summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/abuild/0001-core-abuild-fix-options-order-to-apk-add.patch25
-rw-r--r--core/abuild/APKBUILD9
-rw-r--r--core/alpine-conf/APKBUILD4
-rw-r--r--core/apk-tools/0001-io-move-csumming-away-from-bstream-to-gunzip.patch539
-rw-r--r--core/apk-tools/0002-pkg-fix-package-scanner-to-read-whole-archive.patch36
-rw-r--r--core/apk-tools/APKBUILD23
-rw-r--r--core/apk-tools/fd-leak.patch24
-rw-r--r--core/apk-tools/fd-leak2.patch30
-rw-r--r--core/bash/APKBUILD126
-rw-r--r--core/busybox/APKBUILD16
-rw-r--r--core/busybox/busybox-1.14.1-ash.patch13
-rw-r--r--core/busybox/busybox-1.14.1-ftpd.patch22
-rw-r--r--core/busybox/busybox-1.14.1-httpd.patch655
-rw-r--r--core/busybox/busybox-1.14.1-modprobe.patch132
-rw-r--r--core/busybox/busybox-1.14.1-telnetd.patch85
-rw-r--r--core/e2fsprogs/APKBUILD4
-rw-r--r--core/fakeroot/APKBUILD4
-rw-r--r--core/git/APKBUILD4
-rw-r--r--core/installkernel/APKBUILD17
-rw-r--r--core/iptables/APKBUILD6
-rw-r--r--core/iptables/nocxx.patch15
-rw-r--r--core/iscsitarget-grsec/APKBUILD43
-rw-r--r--core/iscsitarget-grsec/iscsitarget-0.4.17+linux-2.6.28.patch (renamed from core/iscsitarget/iscsitarget-0.4.17+linux-2.6.28.patch)0
-rw-r--r--core/iscsitarget-grsec/iscsitarget-0.4.17+linux-2.6.29.patch40
-rw-r--r--core/iscsitarget/APKBUILD42
-rw-r--r--core/linux-grsec-sources/.gitignore1
-rw-r--r--core/linux-grsec-sources/APKBUILD39
-rw-r--r--core/linux-grsec-sources/linux-2.6.26.8-ipgre-strict-binding.diff124
-rw-r--r--core/linux-grsec/0001-linux-2.6.28.5-ipgre-strict-binding.patch (renamed from core/linux-grsec-sources/0001-linux-2.6.28.5-ipgre-strict-binding.patch)0
-rw-r--r--core/linux-grsec/0002-linux-2.6.28.5-ipgre-optimize-hash-lookup.patch (renamed from core/linux-grsec-sources/0002-linux-2.6.28.5-ipgre-optimize-hash-lookup.patch)0
-rw-r--r--core/linux-grsec/APKBUILD135
-rw-r--r--core/linux-grsec/grsecurity-2.1.14-2.6.29.5-200906152045.patch (renamed from core/linux-grsec-sources/grsecurity-2.1.13-2.6.28.8-200903191958.patch)12132
-rw-r--r--core/linux-grsec/kernelconfig311
-rw-r--r--core/linux-grsec/linux-grsec.post-install7
l---------core/linux-grsec/linux-grsec.post-upgrade1
-rw-r--r--core/linux-grsec/net-next-2.6.git-5ef12d98a19254ee5dc851bd83e214b43ec1f725.patch96
-rw-r--r--core/linux-headers/APKBUILD27
-rw-r--r--core/linux-headers/linux-nbma-mroute-v4-2.6.29.diff321
-rw-r--r--core/linux-sources/APKBUILD26
-rw-r--r--core/lvm2/APKBUILD4
-rw-r--r--core/mkinitfs/APKBUILD5
-rw-r--r--core/openntpd/APKBUILD12
-rw-r--r--core/openntpd/openntpd-3.9p1-ifaddr.patch12
-rw-r--r--core/openrc/APKBUILD4
-rw-r--r--core/openrc/openrc.post-install17
-rw-r--r--core/openssl/APKBUILD18
-rw-r--r--core/openssl/openssl-0.9.8k-padlock-sha.patch897
-rw-r--r--core/parted/APKBUILD5
-rw-r--r--core/readline/APKBUILD48
-rw-r--r--core/sudo/APKBUILD7
-rw-r--r--core/uclibc/APKBUILD8
-rw-r--r--core/uclibc/uclibc-fork-hook.diff36
-rw-r--r--core/uclibc/uclibc-i386-floating-stacks.diff23
-rw-r--r--core/xtables-addons-grsec/APKBUILD39
-rw-r--r--core/xtables-addons/APKBUILD46
-rw-r--r--core/xtables-addons/xtables-addons-1.12-readlink.patch13
-rw-r--r--extra/acf-alpine-baselayout/APKBUILD4
-rw-r--r--extra/acf-alpine-conf/APKBUILD4
-rw-r--r--extra/acf-core/APKBUILD4
-rw-r--r--extra/acf-fetchmail/APKBUILD4
-rw-r--r--extra/acf-postgresql/APKBUILD4
-rw-r--r--extra/acf-samba/APKBUILD4
-rw-r--r--extra/acf-weblog/APKBUILD20
-rw-r--r--extra/apr-util/APKBUILD6
-rw-r--r--extra/apr/APKBUILD6
-rw-r--r--extra/asterisk/APKBUILD8
-rw-r--r--extra/b43-fwcutter/APKBUILD24
-rw-r--r--extra/bc/APKBUILD4
-rw-r--r--extra/ca-certificates/APKBUILD10
-rw-r--r--extra/ca-certificates/ca-certificates-20080514-warn-on-bad-symlinks.patch20
-rw-r--r--extra/clamav/APKBUILD48
-rw-r--r--extra/clamav/clamav.logrotate15
-rw-r--r--extra/clamav/clamav.pre-upgrade16
-rw-r--r--extra/clamav/clamd.confd9
-rw-r--r--extra/clamav/clamd.initd38
-rw-r--r--extra/clamav/freshclam.confd6
-rw-r--r--extra/clamav/freshclam.initd36
-rw-r--r--extra/dahdi-linux-grsec/APKBUILD57
-rw-r--r--extra/dahdi-linux-grsec/dahdi-bri_dchan.patch (renamed from extra/dahdi-linux/dahdi-bri_dchan.patch)4
-rw-r--r--extra/dahdi-linux-grsec/dahdi-depmod.patch (renamed from extra/dahdi-linux/dahdi-depmod.patch)0
-rw-r--r--extra/dahdi-linux-grsec/dahdi-linux-2.2.0-hfc-4s.patch (renamed from extra/dahdi-linux/dahdi-linux-2.1.0.4-hfc-4s.patch)93
-rw-r--r--extra/dahdi-linux-grsec/dahdi-zaphfc.patch (renamed from extra/dahdi-linux/dahdi-zaphfc.patch)0
-rw-r--r--extra/dahdi-linux-grsec/zaphfc-dahdi-flortz.diff (renamed from extra/dahdi-linux/zaphfc-dahdi-flortz.diff)0
-rw-r--r--extra/dahdi-linux/APKBUILD59
-rw-r--r--extra/dahdi-tools/APKBUILD12
-rw-r--r--extra/dahdi-tools/dahdi-tools.initd6
-rw-r--r--extra/dhcpcd/APKBUILD6
-rw-r--r--extra/dovecot/APKBUILD8
-rw-r--r--extra/freetds/APKBUILD7
-rw-r--r--extra/gd/APKBUILD7
-rw-r--r--extra/gdb/APKBUILD8
-rw-r--r--extra/glib/APKBUILD11
-rw-r--r--extra/gross/APKBUILD10
-rw-r--r--extra/gross/gross.initd12
-rw-r--r--extra/gzip/APKBUILD15
-rw-r--r--extra/heimdal/APKBUILD2
-rw-r--r--extra/hylafax/APKBUILD (renamed from testing/hylafax/APKBUILD)0
-rw-r--r--extra/hylafax/hylafax.post-install (renamed from testing/hylafax/hylafax.post-install)0
-rw-r--r--extra/iaxmodem/iaxmodem.confd7
-rw-r--r--extra/iaxmodem/iaxmodem.initd43
-rw-r--r--extra/icu/APKBUILD6
-rw-r--r--extra/imagemagick/APKBUILD10
-rw-r--r--extra/jpeg/APKBUILD35
-rw-r--r--extra/lftp/APKBUILD4
-rw-r--r--extra/libgcrypt/APKBUILD20
-rw-r--r--extra/libidn/APKBUILD6
-rw-r--r--extra/libjpeg/APKBUILD35
-rw-r--r--extra/libtheora/APKBUILD7
-rw-r--r--extra/lighttpd/APKBUILD6
-rw-r--r--extra/lm_sensors/APKBUILD6
-rw-r--r--extra/lua/APKBUILD4
-rw-r--r--extra/luasql-postgres/APKBUILD (renamed from testing/luasql-postgres/APKBUILD)0
-rw-r--r--extra/luasql-postgres/config.new (renamed from testing/luasql-postgres/config.new)0
-rw-r--r--extra/mini_httpd/APKBUILD11
-rw-r--r--extra/mini_httpd/mini_httpd.conf.sample4
-rw-r--r--extra/mini_httpd/mini_httpd.confd26
-rw-r--r--extra/mini_httpd/mini_httpd.initd24
-rw-r--r--extra/mpg123/APKBUILD6
-rw-r--r--extra/mysql/APKBUILD16
-rw-r--r--extra/ngircd/APKBUILD36
-rw-r--r--extra/ngircd/ngircd.initd21
-rw-r--r--extra/ngircd/ngircd.pre-install4
-rw-r--r--extra/pgcluster/APKBUILD2
-rw-r--r--extra/php/APKBUILD302
-rw-r--r--extra/postgresql/APKBUILD8
-rw-r--r--extra/quagga/APKBUILD8
-rw-r--r--extra/quagga/quagga-0.99.11-ipv6.patch19
-rw-r--r--extra/ruby/APKBUILD20
-rw-r--r--extra/run-parts/APKBUILD6
-rw-r--r--extra/samba/APKBUILD8
-rw-r--r--extra/samba/samba.initd6
-rw-r--r--extra/sed/APKBUILD6
-rw-r--r--extra/shorewall-common/APKBUILD4
-rw-r--r--extra/shorewall-lite/APKBUILD4
-rw-r--r--extra/shorewall-perl/APKBUILD6
-rw-r--r--extra/shorewall-shell/APKBUILD6
-rw-r--r--extra/shorewall/APKBUILD2
-rw-r--r--extra/squid/APKBUILD3
-rw-r--r--extra/sysklogd/APKBUILD50
-rw-r--r--extra/sysklogd/LICENSE16
-rw-r--r--extra/sysklogd/sysklogd-1.4.2-caen-owl-klogd-drop-root.diff162
-rw-r--r--extra/sysklogd/sysklogd-1.4.2-caen-owl-syslogd-bind.diff103
-rw-r--r--extra/sysklogd/sysklogd-1.4.2-caen-owl-syslogd-drop-root.diff118
-rw-r--r--extra/sysklogd/sysklogd-1.5-build.patch20
-rw-r--r--extra/sysklogd/sysklogd.confd6
-rw-r--r--extra/sysklogd/sysklogd.initd79
-rw-r--r--extra/sysklogd/sysklogd.logrotate6
-rw-r--r--extra/sysstat/APKBUILD9
-rw-r--r--extra/tmux/APKBUILD27
-rw-r--r--extra/tmux/build.patch23
-rw-r--r--extra/unrar/APKBUILD7
-rw-r--r--extra/xvidcore/APKBUILD5
-rw-r--r--non-free/b43-firmware/APKBUILD21
-rw-r--r--testing/acf-fetch-crl/APKBUILD8
-rw-r--r--testing/acf-lvm2/APKBUILD22
-rw-r--r--testing/apcupsd/APKBUILD4
-rw-r--r--testing/asterisk/APKBUILD41
-rw-r--r--testing/asterisk/asterisk-02-uclibc-daemon.patch (renamed from testing/asterisk/200-uclibc-daemon.patch)0
-rw-r--r--testing/asterisk/asterisk-03-1.6.2.0-beta1-to-r186562.patch41697
-rw-r--r--testing/asterisk/asterisk-03-1.6.2.0-beta3-to-svn-r202568.patch102239
-rw-r--r--testing/asterisk/asterisk-07-issue14068.patch753
-rw-r--r--testing/kvm/APKBUILD36
-rw-r--r--testing/kvm/kvm-82-uclibc.patch14
-rw-r--r--testing/multipath-tools/APKBUILD4
-rw-r--r--x11/aterm/APKBUILD28
-rw-r--r--x11/aterm/uclibc.patch16
-rw-r--r--x11/fontconfig/APKBUILD11
-rw-r--r--x11/gamin/APKBUILD30
-rw-r--r--x11/glproto/APKBUILD4
-rw-r--r--x11/gst-plugins-base/APKBUILD33
-rw-r--r--x11/gstreamer/APKBUILD26
-rw-r--r--x11/intltool/APKBUILD4
-rw-r--r--x11/libdrm/APKBUILD6
-rw-r--r--x11/liboil/APKBUILD22
-rw-r--r--x11/libsoup/APKBUILD8
-rw-r--r--x11/libxau/APKBUILD6
-rw-r--r--x11/libxtst/APKBUILD24
-rw-r--r--x11/mesa/APKBUILD10
-rw-r--r--x11/pango/APKBUILD6
-rw-r--r--x11/recordproto/APKBUILD20
-rw-r--r--x11/ristretto/APKBUILD28
l---------x11/ristretto/ristretto.post-deinstall1
-rw-r--r--x11/ristretto/ristretto.post-install6
l---------x11/ristretto/ristretto.post-upgrade1
-rw-r--r--x11/thunar/APKBUILD (renamed from x11/Thunar/APKBUILD)5
l---------x11/thunar/thunar.post-deinstall (renamed from x11/Thunar/thunar.post-deinstall)0
-rw-r--r--x11/thunar/thunar.post-install (renamed from x11/Thunar/thunar.post-install)0
l---------x11/thunar/thunar.post-upgrade (renamed from x11/Thunar/thunar.post-upgrade)0
-rw-r--r--x11/vte/APKBUILD8
-rw-r--r--x11/webkit/APKBUILD5
-rw-r--r--x11/xcb-util/APKBUILD8
-rw-r--r--x11/xdpyinfo/APKBUILD21
-rw-r--r--x11/xdriinfo/APKBUILD21
-rw-r--r--x11/xev/APKBUILD21
-rw-r--r--x11/xfce4-appfinder/APKBUILD30
l---------x11/xfce4-appfinder/xfce4-appfinder.post-deinstall1
-rw-r--r--x11/xfce4-appfinder/xfce4-appfinder.post-install4
l---------x11/xfce4-appfinder/xfce4-appfinder.post-upgrade1
-rw-r--r--x11/xfce4-mixer/APKBUILD30
l---------x11/xfce4-mixer/xfce4-mixer.post-deinstall1
-rw-r--r--x11/xfce4-mixer/xfce4-mixer.post-install4
l---------x11/xfce4-mixer/xfce4-mixer.post-upgrade1
-rw-r--r--x11/xfce4-taskmanager/APKBUILD24
-rw-r--r--x11/xfce4/APKBUILD22
-rw-r--r--x11/xkeyboard-config/APKBUILD6
-rw-r--r--x11/xvinfo/APKBUILD21
206 files changed, 114925 insertions, 48751 deletions
diff --git a/core/abuild/0001-core-abuild-fix-options-order-to-apk-add.patch b/core/abuild/0001-core-abuild-fix-options-order-to-apk-add.patch
new file mode 100644
index 000000000..7a5c25a81
--- /dev/null
+++ b/core/abuild/0001-core-abuild-fix-options-order-to-apk-add.patch
@@ -0,0 +1,25 @@
+From 7c45a9dcafa1b4cd1f30c6453b76a3a29f6b9c8f Mon Sep 17 00:00:00 2001
+From: Natanael Copa <ncopa@alpinelinux.org>
+Date: Tue, 14 Jul 2009 14:37:33 +0000
+Subject: [PATCH] core/abuild: fix options order to apk add
+
+---
+ abuild.in | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/abuild.in b/abuild.in
+index 6dc2fb4..43cf68e 100755
+--- a/abuild.in
++++ b/abuild.in
+@@ -724,7 +724,7 @@ builddeps() {
+ msg "Entering $dir"
+ cd "$dir" && $0 -k -r apkcache || return 1
+ done
+- $SUDO apk add --repo -u "$apkcache" \
++ $SUDO apk add -u --repo "$apkcache" \
+ --virtual .makedepends-$pkgname $deps
+ }
+
+--
+1.6.3.3
+
diff --git a/core/abuild/APKBUILD b/core/abuild/APKBUILD
index c68050df9..4122b36fd 100644
--- a/core/abuild/APKBUILD
+++ b/core/abuild/APKBUILD
@@ -1,10 +1,11 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgdesc="Script to build Alpine Packages"
pkgname=abuild
-pkgver=1.15.2
+pkgver=1.16
pkgrel=1
url=http://git.alpinelinux.org/cgit/abuild/
source="http://git.alpinelinux.org/cgit/abuild/snapshot/abuild-$pkgver.tar.bz2
+ 0001-core-abuild-fix-options-order-to-apk-add.patch
"
depends="fakeroot file sudo pax-utils"
license=GPL-2
@@ -12,8 +13,12 @@ license=GPL-2
build() {
cd "$srcdir/$pkgname-$pkgver"
+ patch -p1 < ../0001-core-abuild-fix-options-order-to-apk-add.patch \
+ || return 1
+
make install DESTDIR="$pkgdir"
install -m 644 abuild.conf "$pkgdir"/etc/abuild.conf
}
-md5sums="dd03e8e79b3b4fa9bc17a9acc1b4e520 abuild-1.15.2.tar.bz2"
+md5sums="d6aa9ae0b28491c687f6575a6b219780 abuild-1.16.tar.bz2
+13ea88d46143b30d5c4fe261d6e80228 0001-core-abuild-fix-options-order-to-apk-add.patch"
diff --git a/core/alpine-conf/APKBUILD b/core/alpine-conf/APKBUILD
index 8d73dcf94..08e641d02 100644
--- a/core/alpine-conf/APKBUILD
+++ b/core/alpine-conf/APKBUILD
@@ -1,6 +1,6 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=alpine-conf
-pkgver=2.0_beta2
+pkgver=2.0_beta3
pkgrel=0
pkgdesc="Alpine configuration management scripts"
url=http://git.alpinelinux.org/cgit/$pkgname
@@ -18,4 +18,4 @@ build() {
ln -s lbu "$pkgdir"/sbin/lbu_$i
done
}
-md5sums="22dca49a4312dc265cea0ae04e7abc64 alpine-conf-2.0_beta2.tar.bz2"
+md5sums="7786d6d526e96a3fdf51b9284d063caa alpine-conf-2.0_beta3.tar.bz2"
diff --git a/core/apk-tools/0001-io-move-csumming-away-from-bstream-to-gunzip.patch b/core/apk-tools/0001-io-move-csumming-away-from-bstream-to-gunzip.patch
new file mode 100644
index 000000000..05f7d2c97
--- /dev/null
+++ b/core/apk-tools/0001-io-move-csumming-away-from-bstream-to-gunzip.patch
@@ -0,0 +1,539 @@
+From e69b81f5259f532d5f5ae9c0a0f9bbd81240fbaf Mon Sep 17 00:00:00 2001
+From: Timo Teras <timo.teras@iki.fi>
+Date: Mon, 13 Jul 2009 20:37:03 +0300
+Subject: [PATCH] io: move csumming away from bstream to gunzip
+
+in future we want to checksum on gzip boundary basis, not the
+full file.
+---
+ src/apk_io.h | 17 +++++++++++++++--
+ src/archive.c | 4 ++--
+ src/audit.c | 18 +++++-------------
+ src/database.c | 42 +++++++++++++++++++++++++++++-------------
+ src/gunzip.c | 49 +++++++++++++++++++++++++++++++++++++++++--------
+ src/io.c | 48 ++++++++++++++++--------------------------------
+ src/package.c | 28 +++++++++++++++++++++++-----
+ 7 files changed, 131 insertions(+), 75 deletions(-)
+
+diff --git a/src/apk_io.h b/src/apk_io.h
+index b5e984a..629729a 100644
+--- a/src/apk_io.h
++++ b/src/apk_io.h
+@@ -36,7 +36,7 @@ struct apk_istream {
+
+ struct apk_bstream {
+ size_t (*read)(void *stream, void **ptr);
+- void (*close)(void *stream, csum_p csum, size_t *size);
++ void (*close)(void *stream, size_t *size);
+ };
+
+ struct apk_ostream {
+@@ -44,7 +44,20 @@ struct apk_ostream {
+ void (*close)(void *stream);
+ };
+
+-struct apk_istream *apk_bstream_gunzip(struct apk_bstream *, int);
++#define APK_MPART_BEGIN 0
++#define APK_MPART_BOUNDARY 1
++#define APK_MPART_END 2
++
++typedef int (*apk_multipart_cb)(void *ctx, EVP_MD_CTX *mdctx, int part);
++
++struct apk_istream *apk_bstream_gunzip_mpart(struct apk_bstream *, int,
++ apk_multipart_cb cb, void *ctx);
++static inline struct apk_istream *apk_bstream_gunzip(struct apk_bstream *bs,
++ int autoclose)
++{
++ return apk_bstream_gunzip_mpart(bs, autoclose, NULL, NULL);
++}
++
+ struct apk_ostream *apk_ostream_gzip(struct apk_ostream *);
+
+ struct apk_istream *apk_istream_from_fd(int fd);
+diff --git a/src/archive.c b/src/archive.c
+index a05aee2..6681b61 100644
+--- a/src/archive.c
++++ b/src/archive.c
+@@ -4,7 +4,7 @@
+ * Copyright (C) 2008 Timo Teräs <timo.teras@iki.fi>
+ * All rights reserved.
+ *
+- * This program is free software; you can redistribute it and/or modify it
++ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation. See http://www.gnu.org/ for details.
+ */
+@@ -91,7 +91,7 @@ int apk_parse_tar(struct apk_istream *is, apk_archive_entry_parser parser,
+ if (buf.name[0] == '\0') {
+ if (end) {
+ r = 0;
+- break;
++ //break;
+ }
+ end++;
+ continue;
+diff --git a/src/audit.c b/src/audit.c
+index 9ea0f25..3732aac 100644
+--- a/src/audit.c
++++ b/src/audit.c
+@@ -27,12 +27,10 @@ static int audit_directory(apk_hash_item item, void *ctx)
+ struct apk_db_file *dbf;
+ struct apk_database *db = (struct apk_database *) ctx;
+ struct dirent *de;
+- struct stat st;
+- struct apk_bstream *bs;
++ struct apk_file_info fi;
++ apk_blob_t bdir = APK_BLOB_STR(dbd->dirname);
+ char tmp[512], reason;
+ DIR *dir;
+- apk_blob_t bdir = APK_BLOB_STR(dbd->dirname);
+- csum_t csum;
+
+ if (!(dbd->flags & APK_DBDIRF_PROTECTED))
+ return 0;
+@@ -49,10 +47,10 @@ static int audit_directory(apk_hash_item item, void *ctx)
+ snprintf(tmp, sizeof(tmp), "%s/%s",
+ dbd->dirname, de->d_name);
+
+- if (stat(tmp, &st) < 0)
++ if (apk_file_get_info(tmp, &fi) < 0)
+ continue;
+
+- if (S_ISDIR(st.st_mode)) {
++ if (S_ISDIR(fi.mode)) {
+ if (apk_db_dir_query(db, APK_BLOB_STR(tmp)) != NULL)
+ continue;
+
+@@ -60,13 +58,7 @@ static int audit_directory(apk_hash_item item, void *ctx)
+ } else {
+ dbf = apk_db_file_query(db, bdir, APK_BLOB_STR(de->d_name));
+ if (dbf != NULL) {
+- bs = apk_bstream_from_file(tmp);
+- if (bs == NULL)
+- continue;
+-
+- bs->close(bs, csum, NULL);
+-
+- if (apk_blob_compare(APK_BLOB_BUF(csum),
++ if (apk_blob_compare(APK_BLOB_BUF(fi.csum),
+ APK_BLOB_BUF(dbf->csum)) == 0)
+ continue;
+
+diff --git a/src/database.c b/src/database.c
+index 293af4c..10c0b5e 100644
+--- a/src/database.c
++++ b/src/database.c
+@@ -36,6 +36,7 @@ struct install_ctx {
+
+ int script;
+ struct apk_db_dir_instance *diri;
++ csum_t data_csum;
+
+ apk_progress_cb cb;
+ void *cb_ctx;
+@@ -1271,13 +1272,28 @@ static void apk_db_purge_pkg(struct apk_database *db,
+ apk_pkg_set_state(db, pkg, APK_PKG_NOT_INSTALLED);
+ }
+
++static int apk_db_gzip_part(void *pctx, EVP_MD_CTX *mdctx, int part)
++{
++ struct install_ctx *ctx = (struct install_ctx *) pctx;
++
++ switch (part) {
++ case APK_MPART_BEGIN:
++ EVP_DigestInit_ex(mdctx, EVP_md5(), NULL);
++ break;
++ case APK_MPART_END:
++ EVP_DigestFinal_ex(mdctx, ctx->data_csum, NULL);
++ break;
++ }
++ return 0;
++}
++
+ static int apk_db_unpack_pkg(struct apk_database *db,
+ struct apk_package *newpkg,
+- int upgrade, csum_t csum,
+- apk_progress_cb cb, void *cb_ctx)
++ int upgrade, apk_progress_cb cb, void *cb_ctx)
+ {
+ struct install_ctx ctx;
+ struct apk_bstream *bs = NULL;
++ struct apk_istream *tar;
+ char pkgname[256], file[256];
+ int i, need_copy = FALSE;
+ size_t length;
+@@ -1334,10 +1350,17 @@ static int apk_db_unpack_pkg(struct apk_database *db,
+ .cb = cb,
+ .cb_ctx = cb_ctx,
+ };
+- if (apk_parse_tar_gz(bs, apk_db_install_archive_entry, &ctx) != 0)
++
++ tar = apk_bstream_gunzip_mpart(bs, FALSE, apk_db_gzip_part, &ctx);
++ if (apk_parse_tar(tar, apk_db_install_archive_entry, &ctx) != 0)
+ goto err_close;
++ bs->close(bs, &length);
++
++ /* Check the package checksum */
++ if (memcmp(ctx.data_csum, newpkg->csum, sizeof(csum_t)) != 0)
++ apk_warning("%s-%s: checksum does not match",
++ newpkg->name->name, newpkg->version);
+
+- bs->close(bs, csum, &length);
+ if (need_copy) {
+ if (length == newpkg->size) {
+ char file2[256];
+@@ -1351,7 +1374,7 @@ static int apk_db_unpack_pkg(struct apk_database *db,
+
+ return 0;
+ err_close:
+- bs->close(bs, NULL, NULL);
++ bs->close(bs, NULL);
+ return -1;
+ }
+
+@@ -1360,7 +1383,6 @@ int apk_db_install_pkg(struct apk_database *db,
+ struct apk_package *newpkg,
+ apk_progress_cb cb, void *cb_ctx)
+ {
+- csum_t csum;
+ int r;
+
+ if (fchdir(db->root_fd) < 0)
+@@ -1382,19 +1404,13 @@ int apk_db_install_pkg(struct apk_database *db,
+
+ /* Install the new stuff */
+ if (!(newpkg->name->flags & APK_NAME_VIRTUAL)) {
+- r = apk_db_unpack_pkg(db, newpkg, (oldpkg != NULL), csum,
+- cb, cb_ctx);
++ r = apk_db_unpack_pkg(db, newpkg, (oldpkg != NULL), cb, cb_ctx);
+ if (r != 0)
+ return r;
+ }
+
+ apk_pkg_set_state(db, newpkg, APK_PKG_INSTALLED);
+
+- if (!(newpkg->name->flags & APK_NAME_VIRTUAL) &&
+- memcmp(csum, newpkg->csum, sizeof(csum)) != 0)
+- apk_warning("%s-%s: checksum does not match",
+- newpkg->name->name, newpkg->version);
+-
+ if (oldpkg != NULL)
+ apk_db_purge_pkg(db, oldpkg);
+
+diff --git a/src/gunzip.c b/src/gunzip.c
+index 2c7ffc2..1d2881c 100644
+--- a/src/gunzip.c
++++ b/src/gunzip.c
+@@ -23,13 +23,18 @@ struct apk_gzip_istream {
+ z_stream zs;
+ int z_err;
+ int autoclose;
++
++ EVP_MD_CTX mdctx;
++ void *mdblock;
++
++ apk_multipart_cb cb;
++ void *cbctx;
+ };
+
+ static size_t gz_read(void *stream, void *ptr, size_t size)
+ {
+ struct apk_gzip_istream *gis =
+ container_of(stream, struct apk_gzip_istream, is);
+- int restart_count = 0;
+
+ if (gis->z_err == Z_DATA_ERROR || gis->z_err == Z_ERRNO)
+ return -1;
+@@ -44,22 +49,40 @@ static size_t gz_read(void *stream, void *ptr, size_t size)
+
+ while (gis->zs.avail_out != 0 && gis->z_err == Z_OK) {
+ if (gis->zs.avail_in == 0) {
+- gis->zs.avail_in = gis->bs->read(gis->bs, (void **) &gis->zs.next_in);
++ if (gis->cb != NULL && gis->mdblock != NULL) {
++ /* Digest the inflated bytes */
++ EVP_DigestUpdate(&gis->mdctx, gis->mdblock,
++ (void *)gis->zs.next_in - gis->mdblock);
++ }
++ gis->zs.avail_in = gis->bs->read(gis->bs, &gis->mdblock);
++ gis->zs.next_in = (void *) gis->mdblock;
+ if (gis->zs.avail_in < 0) {
+ gis->z_err = Z_DATA_ERROR;
+ return size - gis->zs.avail_out;
++ } else if (gis->zs.avail_in == 0) {
++ if (gis->cb != NULL)
++ gis->cb(gis->cbctx, &gis->mdctx,
++ APK_MPART_END);
++ gis->z_err = Z_STREAM_END;
++ return size - gis->zs.avail_out;
+ }
+ }
+
+ gis->z_err = inflate(&gis->zs, Z_NO_FLUSH);
+- if (restart_count == 0 && gis->z_err == Z_STREAM_END) {
++ if (gis->z_err == Z_STREAM_END) {
++ /* Digest the inflated bytes */
++ if (gis->cb != NULL) {
++ EVP_DigestUpdate(&gis->mdctx, gis->mdblock,
++ (void *)gis->zs.next_in - gis->mdblock);
++ gis->mdblock = gis->zs.next_in;
++ gis->cb(gis->cbctx, &gis->mdctx,
++ APK_MPART_BOUNDARY);
++ }
+ inflateEnd(&gis->zs);
++
+ if (inflateInit2(&gis->zs, 15+32) != Z_OK)
+ return -1;
+ gis->z_err = Z_OK;
+- restart_count++;
+- } else {
+- restart_count = 0;
+ }
+ }
+
+@@ -74,13 +97,16 @@ static void gz_close(void *stream)
+ struct apk_gzip_istream *gis =
+ container_of(stream, struct apk_gzip_istream, is);
+
++ if (gis->cb != NULL)
++ EVP_MD_CTX_cleanup(&gis->mdctx);
+ inflateEnd(&gis->zs);
+ if (gis->autoclose)
+- gis->bs->close(gis->bs, NULL, NULL);
++ gis->bs->close(gis->bs, NULL);
+ free(gis);
+ }
+
+-struct apk_istream *apk_bstream_gunzip(struct apk_bstream *bs, int autoclose)
++struct apk_istream *apk_bstream_gunzip_mpart(struct apk_bstream *bs, int autoclose,
++ apk_multipart_cb cb, void *ctx)
+ {
+ struct apk_gzip_istream *gis;
+
+@@ -97,6 +123,8 @@ struct apk_istream *apk_bstream_gunzip(struct apk_bstream *bs, int autoclose)
+ .bs = bs,
+ .z_err = 0,
+ .autoclose = autoclose,
++ .cb = cb,
++ .cbctx = ctx,
+ };
+
+ if (inflateInit2(&gis->zs, 15+32) != Z_OK) {
+@@ -104,6 +132,11 @@ struct apk_istream *apk_bstream_gunzip(struct apk_bstream *bs, int autoclose)
+ return NULL;
+ }
+
++ if (gis->cb != NULL) {
++ EVP_MD_CTX_init(&gis->mdctx);
++ cb(ctx, &gis->mdctx, APK_MPART_BEGIN);
++ }
++
+ return &gis->is;
+ }
+
+diff --git a/src/io.c b/src/io.c
+index 722bccb..a250b27 100644
+--- a/src/io.c
++++ b/src/io.c
+@@ -150,7 +150,6 @@ err:
+ struct apk_istream_bstream {
+ struct apk_bstream bs;
+ struct apk_istream *is;
+- csum_ctx_t csum_ctx;
+ unsigned char buffer[8*1024];
+ size_t size;
+ };
+@@ -165,31 +164,17 @@ static size_t is_bs_read(void *stream, void **ptr)
+ if (size <= 0)
+ return size;
+
+- csum_process(&isbs->csum_ctx, isbs->buffer, size);
+ isbs->size += size;
+
+ *ptr = isbs->buffer;
+ return size;
+ }
+
+-static void is_bs_close(void *stream, csum_t csum, size_t *size)
++static void is_bs_close(void *stream, size_t *size)
+ {
+ struct apk_istream_bstream *isbs =
+ container_of(stream, struct apk_istream_bstream, bs);
+
+- if (csum != NULL) {
+- size_t size;
+-
+- do {
+- size = isbs->is->read(isbs->is, isbs->buffer,
+- sizeof(isbs->buffer));
+- csum_process(&isbs->csum_ctx, isbs->buffer, size);
+- isbs->size += size;
+- } while (size == sizeof(isbs->buffer));
+-
+- csum_finish(&isbs->csum_ctx, csum);
+- }
+-
+ if (size != NULL)
+ *size = isbs->size;
+
+@@ -210,14 +195,12 @@ struct apk_bstream *apk_bstream_from_istream(struct apk_istream *istream)
+ .close = is_bs_close,
+ };
+ isbs->is = istream;
+- csum_init(&isbs->csum_ctx);
+
+ return &isbs->bs;
+ }
+
+ struct apk_mmap_bstream {
+ struct apk_bstream bs;
+- csum_ctx_t csum_ctx;
+ int fd;
+ size_t size;
+ unsigned char *ptr;
+@@ -235,24 +218,16 @@ static size_t mmap_read(void *stream, void **ptr)
+ size = 1024*1024;
+
+ *ptr = (void *) &mbs->ptr[mbs->pos];
+- csum_process(&mbs->csum_ctx, &mbs->ptr[mbs->pos], size);
+ mbs->pos += size;
+
+ return size;
+ }
+
+-static void mmap_close(void *stream, csum_t csum, size_t *size)
++static void mmap_close(void *stream, size_t *size)
+ {
+ struct apk_mmap_bstream *mbs =
+ container_of(stream, struct apk_mmap_bstream, bs);
+
+- if (csum != NULL) {
+- if (mbs->pos != mbs->size)
+- csum_process(&mbs->csum_ctx, &mbs->ptr[mbs->pos],
+- mbs->size - mbs->pos);
+- csum_finish(&mbs->csum_ctx, csum);
+- }
+-
+ if (size != NULL)
+ *size = mbs->size;
+
+@@ -288,7 +263,6 @@ static struct apk_bstream *apk_mmap_bstream_from_fd(int fd)
+ mbs->size = st.st_size;
+ mbs->ptr = ptr;
+ mbs->pos = 0;
+- csum_init(&mbs->csum_ctx);
+
+ return &mbs->bs;
+ }
+@@ -340,12 +314,12 @@ static size_t tee_read(void *stream, void **ptr)
+ return size;
+ }
+
+-static void tee_close(void *stream, csum_t csum, size_t *size)
++static void tee_close(void *stream, size_t *size)
+ {
+ struct apk_tee_bstream *tbs =
+ container_of(stream, struct apk_tee_bstream, bs);
+
+- tbs->inner_bs->close(tbs->inner_bs, csum, NULL);
++ tbs->inner_bs->close(tbs->inner_bs, NULL);
+ if (size != NULL)
+ *size = tbs->size;
+ close(tbs->fd);
+@@ -431,6 +405,7 @@ int apk_file_get_info(const char *filename, struct apk_file_info *fi)
+ {
+ struct stat st;
+ struct apk_bstream *bs;
++ csum_ctx_t ctx;
+
+ if (stat(filename, &st) != 0)
+ return -1;
+@@ -445,8 +420,17 @@ int apk_file_get_info(const char *filename, struct apk_file_info *fi)
+ };
+
+ bs = apk_bstream_from_file(filename);
+- if (bs != NULL)
+- bs->close(bs, fi->csum, NULL);
++ if (bs != NULL) {
++ ssize_t size;
++ void *ptr;
++
++ csum_init(&ctx);
++ while ((size = bs->read(bs, &ptr)) > 0)
++ csum_process(&ctx, ptr, size);
++ csum_finish(&ctx, fi->csum);
++
++ bs->close(bs, NULL);
++ }
+
+ return 0;
+ }
+diff --git a/src/package.c b/src/package.c
+index 6c51924..30b09b1 100644
+--- a/src/package.c
++++ b/src/package.c
+@@ -4,7 +4,7 @@
+ * Copyright (C) 2008 Timo Teräs <timo.teras@iki.fi>
+ * All rights reserved.
+ *
+- * This program is free software; you can redistribute it and/or modify it
++ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation. See http://www.gnu.org/ for details.
+ */
+@@ -415,10 +415,26 @@ static int read_info_entry(void *ctx, const struct apk_file_info *ae,
+ return 0;
+ }
+
++static int apk_pkg_gzip_part(void *ctx, EVP_MD_CTX *mdctx, int part)
++{
++ struct read_info_ctx *ri = (struct read_info_ctx *) ctx;
++
++ switch (part) {
++ case APK_MPART_BEGIN:
++ EVP_DigestInit_ex(mdctx, EVP_md5(), NULL);
++ break;
++ case APK_MPART_END:
++ EVP_DigestFinal_ex(mdctx, ri->pkg->csum, NULL);
++ break;
++ }
++ return 0;
++}
++
+ struct apk_package *apk_pkg_read(struct apk_database *db, const char *file)
+ {
+ struct read_info_ctx ctx;
+ struct apk_bstream *bs;
++ struct apk_istream *tar;
+ char realfile[PATH_MAX];
+
+ if (realpath(file, realfile) < 0)
+@@ -434,12 +450,14 @@ struct apk_package *apk_pkg_read(struct apk_database *db, const char *file)
+
+ ctx.db = db;
+ ctx.has_install = 0;
+- if (apk_parse_tar_gz(bs, read_info_entry, &ctx) < 0) {
++
++ tar = apk_bstream_gunzip_mpart(bs, FALSE, apk_pkg_gzip_part, &ctx);
++ if (apk_parse_tar(tar, read_info_entry, &ctx) < 0) {
+ apk_error("File %s is not an APK archive", file);
+- bs->close(bs, NULL, NULL);
++ bs->close(bs, NULL);
+ goto err;
+ }
+- bs->close(bs, ctx.pkg->csum, &ctx.pkg->size);
++ bs->close(bs, &ctx.pkg->size);
+
+ if (ctx.pkg->name == NULL) {
+ apk_error("File %s is corrupted", file);
+@@ -682,7 +700,7 @@ struct apk_dependency apk_dep_from_str(struct apk_database *db,
+ mask = apk_version_result_mask(v++);
+ if (*v == '=')
+ v++;
+- }
++ }
+ return (struct apk_dependency) {
+ .name = apk_db_get_name(db, name),
+ .version = v,
+--
+1.6.3.3
+
diff --git a/core/apk-tools/0002-pkg-fix-package-scanner-to-read-whole-archive.patch b/core/apk-tools/0002-pkg-fix-package-scanner-to-read-whole-archive.patch
new file mode 100644
index 000000000..3609a6aa4
--- /dev/null
+++ b/core/apk-tools/0002-pkg-fix-package-scanner-to-read-whole-archive.patch
@@ -0,0 +1,36 @@
+From bfabf8f8d966ab8305212b9730db8fc5eb5e1094 Mon Sep 17 00:00:00 2001
+From: Timo Teras <timo.teras@iki.fi>
+Date: Wed, 15 Jul 2009 08:38:30 +0300
+Subject: [PATCH] pkg: fix package scanner to read whole archive
+
+otherwise we don't get chechksum anymore after the changes to
+support partial gzip checksumming.
+---
+ src/package.c | 4 ++--
+ 1 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/package.c b/src/package.c
+index bb37317..6c050cf 100644
+--- a/src/package.c
++++ b/src/package.c
+@@ -372,7 +372,7 @@ static int read_info_entry(void *ctx, const struct apk_file_info *ae,
+ if (strcmp(ae->name, ".INSTALL") == 0) {
+ apk_warning("Package '%s-%s' contains deprecated .INSTALL",
+ pkg->name->name, pkg->version);
+- return 1;
++ return 0;
+ }
+ } else if (strncmp(ae->name, "var/db/apk/", 11) == 0) {
+ /* APK 1.0 format */
+@@ -407,7 +407,7 @@ static int read_info_entry(void *ctx, const struct apk_file_info *ae,
+ ri->has_install = 1;
+ } else if (ri->version == 2) {
+ /* All metdata of version 2.x package handled */
+- return 1;
++ return 0;
+ } else {
+ /* Version 1.x packages do not contain installed size
+ * in metadata, so we calculate it here */
+--
+1.6.3.3
+
diff --git a/core/apk-tools/APKBUILD b/core/apk-tools/APKBUILD
index 8f4b1718f..4472ce0c5 100644
--- a/core/apk-tools/APKBUILD
+++ b/core/apk-tools/APKBUILD
@@ -1,22 +1,27 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=apk-tools
-pkgver=2.0_pre12
+pkgver=2.0_pre14
pkgrel=2
pkgdesc="Alpine Package Keeper - package manager for alpine"
depends=
-makedepends="zlib-dev"
+makedepends="zlib-dev openssl-dev pkgconfig"
source="http://git.alpinelinux.org/cgit/$pkgname/snapshot/$pkgname-$pkgver.tar.bz2
- fd-leak.patch
- fd-leak2.patch"
+ 0001-io-move-csumming-away-from-bstream-to-gunzip.patch
+ 0002-pkg-fix-package-scanner-to-read-whole-archive.patch
+ "
+
url="http://git.alpinelinux.org/cgit/apk-tools/"
license=GPL-2
build() {
cd "$srcdir/$pkgname-$pkgver"
- patch -p1 < ../fd-leak.patch || return 1
- patch -p1 < ../fd-leak2.patch || return 1
sed -i -e 's:-Werror::' Make.rules
+ for i in ../*.patch; do
+ msg "Applying $i..."
+ patch -p1 < $i || return 1
+ done
+
make || return 1
make DESTDIR="$pkgdir" install
cd "$pkgdir/sbin"
@@ -28,6 +33,6 @@ build() {
ln -s apk apk_version
}
-md5sums="042d28b5cb8ddafe6add63766bc6c17a apk-tools-2.0_pre12.tar.bz2
-66e915fb667e5ac382ecb801decf2c1c fd-leak.patch
-aafaa226c07f97f46cefe42a9335ea35 fd-leak2.patch"
+md5sums="1a00b5fefddd652ed06bc5602e73e409 apk-tools-2.0_pre14.tar.bz2
+8350b25dadf4a2574654af477e7283d2 0001-io-move-csumming-away-from-bstream-to-gunzip.patch
+d0a6358024cb54f79d779a3c8ec4387a 0002-pkg-fix-package-scanner-to-read-whole-archive.patch"
diff --git a/core/apk-tools/fd-leak.patch b/core/apk-tools/fd-leak.patch
deleted file mode 100644
index 5f6a55ff8..000000000
--- a/core/apk-tools/fd-leak.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-commit bd6278fb28d1d87a58a591244fe1069aa4216a6f
-Author: Natanael Copa <ncopa@alpinelinux.org>
-Date: Tue May 26 14:12:02 2009 +0000
-
- fetch: fix fd leak
-
- we should always close the in-stream, not only on failure.
-
-diff --git a/src/fetch.c b/src/fetch.c
-index 9e0d930..f3c651b 100644
---- a/src/fetch.c
-+++ b/src/fetch.c
-@@ -95,10 +95,10 @@ static int fetch_package(struct fetch_ctx *fctx,
- }
-
- r = apk_istream_splice(is, fd, pkg->size, NULL, NULL);
-+ is->close(is);
- if (fd != STDOUT_FILENO)
- close(fd);
- if (r != pkg->size) {
-- is->close(is);
- apk_error("Unable to download '%s'", file);
- unlink(file);
- return -1;
diff --git a/core/apk-tools/fd-leak2.patch b/core/apk-tools/fd-leak2.patch
deleted file mode 100644
index 033bc0dc1..000000000
--- a/core/apk-tools/fd-leak2.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-commit 49c904c993d39cfac7d3373c66f5b910e755f203
-Author: Timo Teras <timo.teras@iki.fi>
-Date: Thu Jun 11 13:03:10 2009 +0300
-
- io: fix mmap bstream fd leak
-
- We need to close the fd on destruction. This is what the corresponding
- istream variant does too.
-
-diff --git a/src/io.c b/src/io.c
-index e0a9c9b..defbe46 100644
---- a/src/io.c
-+++ b/src/io.c
-@@ -4,7 +4,7 @@
- * Copyright (C) 2008 Timo Teräs <timo.teras@iki.fi>
- * All rights reserved.
- *
-- * This program is free software; you can redistribute it and/or modify it
-+ * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation. See http://www.gnu.org/ for details.
- */
-@@ -257,6 +257,7 @@ static void mmap_close(void *stream, csum_t csum, size_t *size)
- *size = mbs->size;
-
- munmap(mbs->ptr, mbs->size);
-+ close(mbs->fd);
- free(mbs);
- }
-
diff --git a/core/bash/APKBUILD b/core/bash/APKBUILD
index 2911ec0aa..886c0c066 100644
--- a/core/bash/APKBUILD
+++ b/core/bash/APKBUILD
@@ -1,35 +1,66 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=bash
-_patchlevel=039
-pkgver=3.2_p$_patchlevel
-pkgrel=3
+_myver=4.0
+_patchbase=40
+_patchlevel=024
+pkgver=${_myver}.${_patchlevel}
+pkgrel=0
pkgdesc="The GNU Bourne Again shell"
license='GPL'
url="http://www.gnu.org/software/bash/bash.html"
-makedepends="readline-dev ncurses-dev"
-depends='readline ncurses uclibc'
-source="http://ftp.gnu.org/gnu/bash/bash-3.2.tar.gz
+makedepends="readline-dev ncurses-dev bison flex"
+depends=
+source="http://ftp.gnu.org/gnu/bash/bash-${_myver}.tar.gz
+ http://ftp.gnu.org/gnu/bash/bash-4.0-patches/bash40-001
+ http://ftp.gnu.org/gnu/bash/bash-4.0-patches/bash40-002
+ http://ftp.gnu.org/gnu/bash/bash-4.0-patches/bash40-003
+ http://ftp.gnu.org/gnu/bash/bash-4.0-patches/bash40-004
+ http://ftp.gnu.org/gnu/bash/bash-4.0-patches/bash40-005
+ http://ftp.gnu.org/gnu/bash/bash-4.0-patches/bash40-006
+ http://ftp.gnu.org/gnu/bash/bash-4.0-patches/bash40-007
+ http://ftp.gnu.org/gnu/bash/bash-4.0-patches/bash40-008
+ http://ftp.gnu.org/gnu/bash/bash-4.0-patches/bash40-009
+ http://ftp.gnu.org/gnu/bash/bash-4.0-patches/bash40-010
+ http://ftp.gnu.org/gnu/bash/bash-4.0-patches/bash40-011
+ http://ftp.gnu.org/gnu/bash/bash-4.0-patches/bash40-012
+ http://ftp.gnu.org/gnu/bash/bash-4.0-patches/bash40-013
+ http://ftp.gnu.org/gnu/bash/bash-4.0-patches/bash40-014
+ http://ftp.gnu.org/gnu/bash/bash-4.0-patches/bash40-015
+ http://ftp.gnu.org/gnu/bash/bash-4.0-patches/bash40-016
+ http://ftp.gnu.org/gnu/bash/bash-4.0-patches/bash40-017
+ http://ftp.gnu.org/gnu/bash/bash-4.0-patches/bash40-018
+ http://ftp.gnu.org/gnu/bash/bash-4.0-patches/bash40-019
+ http://ftp.gnu.org/gnu/bash/bash-4.0-patches/bash40-020
+ http://ftp.gnu.org/gnu/bash/bash-4.0-patches/bash40-021
+ http://ftp.gnu.org/gnu/bash/bash-4.0-patches/bash40-022
+ http://ftp.gnu.org/gnu/bash/bash-4.0-patches/bash40-023
+ http://ftp.gnu.org/gnu/bash/bash-4.0-patches/bash40-024
bash-noinfo.patch
"
-for _i in $(seq 1 $_patchlevel); do
- # seq -w unsupported by busybox
- _p=$(printf "%0.3i" $_i)
- source="$source http://ftp.gnu.org/gnu/bash/bash-3.2-patches/bash32-$_p"
-done
subpackages="$pkgname-doc"
+# run 'abuild _gensrc >> APKBUILD' to generate the patch list
+_gensrc() {
+ for _i in $(seq 1 $_patchlevel); do
+ # seq -w unsupported by busybox
+ _p=$(printf "%0.3i" $_i)
+ echo -e "\thttp://ftp.gnu.org/gnu/bash/bash-${_myver}-patches/bash${_patchbase}-$_p"
+ done
+}
+
build() {
local p
- cd ${startdir}/src/${pkgname}-3.2
- for p in ../bash32-??? ../*.patch; do
+ cd ${startdir}/src/${pkgname}-${_myver}
+ for p in ../bash${_patchbase}-??? ../*.patch; do
msg "applying patch ${p##*/}"
patch -p0 -i $p || return 1
done
./configure --prefix=/usr \
--with-curses \
+ --disable-nls \
--enable-readline \
--without-bash-malloc \
--with-installed-readline \
@@ -39,46 +70,31 @@ build() {
make -j1 || return 1
make DESTDIR=${pkgdir} install
- rm -r "$pkgdir"/usr/share/locale
+ rm -rf "$pkgdir"/usr/share/locale
}
-md5sums="00bfa16d58e034e3c2aa27f390390d30 bash-3.2.tar.gz
-80fec5f3d60a63756a4999c877e31a8e bash-noinfo.patch
-d8e10c754f477e3f3a581af566b89301 bash32-001
-d38a5288b2f0ea6c9ac76b66cc74ef7d bash32-002
-0b90d37911827d8cb95f3b4353cc225e bash32-003
-8062f3a59631f58d78b180d83759b68a bash32-004
-585b5943fadf0875ced243b245adde58 bash32-005
-1d5732e01ea938aeed42f3def131fa4d bash32-006
-dcd0cc5d801607827f7c851e72b0eabc bash32-007
-bb3c7dd11198c0ab93d0e960bebf6256 bash32-008
-434a6f29b0ca5f1ab784b2437ae8eaed bash32-009
-2efff04dd246fcf63bd4b99f77c9a081 bash32-010
-1dd104342f6920dfaf5efb3131e922e0 bash32-011
-4f24b696ab78bdfae4f9cb7eb59b835d bash32-012
-7c40addbf1187a26ae1c8373ed383442 bash32-013
-28e88c9f8679e99ac590d4a4a8227c56 bash32-014
-7c17d29675bd0d49470f162774385f80 bash32-015
-a1edaa98b4449fe2205fa75448b7b105 bash32-016
-889ed119bbf9d363660b9a0127f35efa bash32-017
-a7d3f85fa687d2c1b5a134839f6d395d bash32-018
-f0399da4007e46fc5820ce25d07425b9 bash32-019
-b76602281c3104d904fd064510fe0c21 bash32-020
-923374ae4403c92820f711e62e1d01a5 bash32-021
-c82d3bd14e373878b2a680dce18d1596 bash32-022
-987c949a77b4b0ffe4a2597141e77635 bash32-023
-5a2b976e761ab83f0fc7daae11451b86 bash32-024
-08668dc2825f65eced9cac6b09ce1b45 bash32-025
-f35b2b217f088ff009f956894550d41d bash32-026
-b5ff2b9610c61290f773c4b02cc1a37d bash32-027
-016f5b56c93404d32aea09385f0fc13e bash32-028
-a81420626d4d88d0dce2ffac0ac56341 bash32-029
-11f91baf970c132949f9072ee93f2ea6 bash32-030
-f6bbc1e8ec0246740731c728ef476191 bash32-031
-8180ec936770579bce69f0816c2dd878 bash32-032
-3cec33c3711860c4c6b7614afeec7870 bash32-033
-7bc6c5b5f38b7027152f8db0458a2e14 bash32-034
-a2db61fe90e39371d0e6cd2285ec9208 bash32-035
-95c70c7ae9de5bd3659c86284be7fb76 bash32-036
-62b876a3d7cd192cc8db2476fbb6b7b9 bash32-037
-aca3afc341bd3e5a0d8a3b4ca40dbb3f bash32-038
-e240c34f979b64bcb83c5f6567110bb1 bash32-039"
+md5sums="a90a1b5a6db4838483f05438e05e8eb9 bash-4.0.tar.gz
+bc7f4762443939bd7dccb42370f0d932 bash40-001
+c2a4a4786a83ed4ec366c6a8924369a2 bash40-002
+22e8a824eddba21a8fce10d7984c2aba bash40-003
+ed7cbced8c7c964323265522369a37a2 bash40-004
+8ed86b7d31423d71ecf3148251d63512 bash40-005
+5f447338cb98ff156cabf1fd9879d5f3 bash40-006
+96e946cb66a4ca186cba1da44f1ee163 bash40-007
+d3eb7b6f00d525e032478c33f51d46a8 bash40-008
+340601c997ce569532417a7ae92248b8 bash40-009
+0bd5ab96d514ffb1afbb8c7984b15146 bash40-010
+32cb20f339a20e1e9fb37a5d18f18fca bash40-011
+33fd9e93d30a17988c19554ef26d56e0 bash40-012
+a266b42df5e9ed7e8818a8b00d50e00b bash40-013
+86cac78f191a32cd1404f11264eb9b2a bash40-014
+bb41963d030bc61a20e8185367b337c5 bash40-015
+f75455048a086528971252fd979b8755 bash40-016
+34b2cd57271a452f4a26b39d77ff908f bash40-017
+99318eed8dcc05e10a14ae27043f175d bash40-018
+af3b9aaeadc71a5007bec2b98c751cde bash40-019
+eb7c7ddeb7e8451eb59228dca3329696 bash40-020
+585d701b978ceb63967dc020db3a2234 bash40-021
+7a70f2608f90f6ac0c2051e5f1c6c414 bash40-022
+7a23aa41630dd4fe8d30108a200e2d96 bash40-023
+82ba5fc9eb780eb57d8b7628a17b7d74 bash40-024
+80fec5f3d60a63756a4999c877e31a8e bash-noinfo.patch"
diff --git a/core/busybox/APKBUILD b/core/busybox/APKBUILD
index e086c7270..4eb47a589 100644
--- a/core/busybox/APKBUILD
+++ b/core/busybox/APKBUILD
@@ -1,7 +1,7 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=busybox
-pkgver=1.14.1
-pkgrel=2
+pkgver=1.14.2
+pkgrel=0
pkgdesc="Size optimized toolbox of many common UNIX utilities"
url=http://busybox.net
license=GPL-2
@@ -10,11 +10,6 @@ install="$pkgname.post-install $pkgname.post-upgrade"
source="http://busybox.net/downloads/$pkgname-$pkgver.tar.bz2
$pkgname-1.12.1-vi-path.patch
$pkgname-1.11.1-bb.patch
- busybox-1.14.1-ftpd.patch
- busybox-1.14.1-httpd.patch
- busybox-1.14.1-modprobe.patch
- busybox-1.14.1-telnetd.patch
- busybox-1.14.1-ash.patch
bb-tar-numeric-owner.patch
$install
busyboxconfig"
@@ -45,14 +40,9 @@ build() {
ln -s /bin/busybox "$pkgdir"/bin/sh
}
-md5sums="d5186821d4f4cf6017452c7c8730cf19 busybox-1.14.1.tar.bz2
+md5sums="c13b09b4125688d5fca5c95a79bf814a busybox-1.14.2.tar.bz2
f5a8ae3145aa249868c1a1abc319c228 busybox-1.12.1-vi-path.patch
4c0f3b486eaa0674961b7ddcd0c60a9b busybox-1.11.1-bb.patch
-b49e33a98d7be2a52d772f3600c4aa78 busybox-1.14.1-ftpd.patch
-9bdb6b91d7dd21253b3725c84e21347e busybox-1.14.1-httpd.patch
-11877bde19afe1f6e1f55d9b5c9ee900 busybox-1.14.1-modprobe.patch
-9020600467cdb1a1df7df41a1ba0c6e9 busybox-1.14.1-telnetd.patch
-fa809c927ac3793452fdf521c84e5803 busybox-1.14.1-ash.patch
0b5b2d7db201f90cd08f4a3164ee29a1 bb-tar-numeric-owner.patch
56b78c358797cd15fb64719a48939267 busybox.post-install
56b78c358797cd15fb64719a48939267 busybox.post-upgrade
diff --git a/core/busybox/busybox-1.14.1-ash.patch b/core/busybox/busybox-1.14.1-ash.patch
deleted file mode 100644
index eee054239..000000000
--- a/core/busybox/busybox-1.14.1-ash.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-diff -urpN busybox-1.14.1/shell/ash.c busybox-1.14.1-ash/shell/ash.c
---- busybox-1.14.1/shell/ash.c 2009-05-27 18:00:23.000000000 +0200
-+++ busybox-1.14.1-ash/shell/ash.c 2009-06-14 19:44:24.000000000 +0200
-@@ -11909,7 +11909,8 @@ find_dot_file(char *name)
- */
- return fullname;
- }
-- stunalloc(fullname);
-+ if (fullname != name)
-+ stunalloc(fullname);
- }
-
- /* not found in the PATH */
diff --git a/core/busybox/busybox-1.14.1-ftpd.patch b/core/busybox/busybox-1.14.1-ftpd.patch
deleted file mode 100644
index d33977ff6..000000000
--- a/core/busybox/busybox-1.14.1-ftpd.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-diff -urpN busybox-1.14.1/networking/ftpd.c busybox-1.14.1-ftpd/networking/ftpd.c
---- busybox-1.14.1/networking/ftpd.c 2009-05-27 18:00:23.000000000 +0200
-+++ busybox-1.14.1-ftpd/networking/ftpd.c 2009-06-04 18:59:49.000000000 +0200
-@@ -1320,6 +1320,8 @@ int ftpd_main(int argc UNUSED_PARAM, cha
- handle_appe();
- else if (cmdval == const_STOU) /* "store unique" */
- handle_stou();
-+ else
-+ goto bad_cmd;
- }
- #endif
- #if 0
-@@ -1340,6 +1342,9 @@ int ftpd_main(int argc UNUSED_PARAM, cha
- * (doesn't necessarily mean "we must support them")
- * foo 1.2.3: XXXX - comment
- */
-+#if ENABLE_FEATURE_FTP_WRITE
-+ bad_cmd:
-+#endif
- cmdio_write_raw(STR(FTP_BADCMD)" Unknown command\r\n");
- }
- }
diff --git a/core/busybox/busybox-1.14.1-httpd.patch b/core/busybox/busybox-1.14.1-httpd.patch
deleted file mode 100644
index 3395cf074..000000000
--- a/core/busybox/busybox-1.14.1-httpd.patch
+++ /dev/null
@@ -1,655 +0,0 @@
-diff -urpN busybox-1.14.1/include/libbb.h busybox-1.14.1-httpd/include/libbb.h
---- busybox-1.14.1/include/libbb.h 2009-05-27 18:01:37.000000000 +0200
-+++ busybox-1.14.1-httpd/include/libbb.h 2009-06-12 09:07:39.000000000 +0200
-@@ -1099,6 +1099,8 @@ const char *get_signame(int number) FAST
- void print_signames(void) FAST_FUNC;
-
- char *bb_simplify_path(const char *path) FAST_FUNC;
-+/* Returns ptr to NUL */
-+char *bb_simplify_abs_path_inplace(char *path) FAST_FUNC;
-
- #define FAIL_DELAY 3
- extern void bb_do_delay(int seconds) FAST_FUNC;
-diff -urpN busybox-1.14.1/libbb/simplify_path.c busybox-1.14.1-httpd/libbb/simplify_path.c
---- busybox-1.14.1/libbb/simplify_path.c 2009-05-27 18:00:23.000000000 +0200
-+++ busybox-1.14.1-httpd/libbb/simplify_path.c 2009-06-03 12:50:48.000000000 +0200
-@@ -6,22 +6,13 @@
- *
- * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
- */
--
- #include "libbb.h"
-
--char* FAST_FUNC bb_simplify_path(const char *path)
-+char* FAST_FUNC bb_simplify_abs_path_inplace(char *start)
- {
-- char *s, *start, *p;
-+ char *s, *p;
-
-- if (path[0] == '/')
-- start = xstrdup(path);
-- else {
-- s = xrealloc_getcwd_or_warn(NULL);
-- start = concat_path_file(s, path);
-- free(s);
-- }
- p = s = start;
--
- do {
- if (*p == '/') {
- if (*s == '/') { /* skip duplicate (or initial) slash */
-@@ -47,7 +38,22 @@ char* FAST_FUNC bb_simplify_path(const c
- if ((p == start) || (*p != '/')) { /* not a trailing slash */
- ++p; /* so keep last character */
- }
-- *p = 0;
-+ *p = '\0';
-+ return p;
-+}
-+
-+char* FAST_FUNC bb_simplify_path(const char *path)
-+{
-+ char *s, *p;
-+
-+ if (path[0] == '/')
-+ s = xstrdup(path);
-+ else {
-+ p = xrealloc_getcwd_or_warn(NULL);
-+ s = concat_path_file(p, path);
-+ free(p);
-+ }
-
-- return start;
-+ bb_simplify_abs_path_inplace(s);
-+ return s;
- }
-diff -urpN busybox-1.14.1/networking/httpd.c busybox-1.14.1-httpd/networking/httpd.c
---- busybox-1.14.1/networking/httpd.c 2009-05-27 18:00:23.000000000 +0200
-+++ busybox-1.14.1-httpd/networking/httpd.c 2009-06-12 08:53:46.000000000 +0200
-@@ -32,7 +32,7 @@
- * foo=`httpd -d $foo` # decode "Hello%20World" as "Hello World"
- * bar=`httpd -e "<Hello World>"` # encode as "&#60Hello&#32World&#62"
- * Note that url encoding for arguments is not the same as html encoding for
-- * presentation. -d decodes a url-encoded argument while -e encodes in html
-+ * presentation. -d decodes an url-encoded argument while -e encodes in html
- * for page display.
- *
- * httpd.conf has the following format:
-@@ -54,7 +54,7 @@
- * /adm:admin:setup # Require user admin, pwd setup on urls starting with /adm/
- * /adm:toor:PaSsWd # or user toor, pwd PaSsWd on urls starting with /adm/
- * .au:audio/basic # additional mime type for audio.au files
-- * *.php:/path/php # running cgi.php scripts through an interpreter
-+ * *.php:/path/php # run xxx.php through an interpreter
- *
- * A/D may be as a/d or allow/deny - only first char matters.
- * Deny/Allow IP logic:
-@@ -94,13 +94,13 @@
- * server exits with an error.
- *
- */
-+ /* TODO: use TCP_CORK, parse_config() */
-
- #include "libbb.h"
- #if ENABLE_FEATURE_HTTPD_USE_SENDFILE
- # include <sys/sendfile.h>
- #endif
-
--//#define DEBUG 1
- #define DEBUG 0
-
- #define IOBUF_SIZE 8192 /* IO buffer */
-@@ -115,8 +115,8 @@
-
- #define HEADER_READ_TIMEOUT 60
-
--static const char default_path_httpd_conf[] ALIGN1 = "/etc";
--static const char httpd_conf[] ALIGN1 = "httpd.conf";
-+static const char DEFAULT_PATH_HTTPD_CONF[] ALIGN1 = "/etc";
-+static const char HTTPD_CONF[] ALIGN1 = "httpd.conf";
- static const char HTTP_200[] ALIGN1 = "HTTP/1.0 200 OK\r\n";
-
- typedef struct has_next_ptr {
-@@ -242,7 +242,7 @@ struct globals {
- const char *bind_addr_or_port;
-
- const char *g_query;
-- const char *configFile;
-+ const char *opt_c_configFile;
- const char *home_httpd;
- const char *index_page;
-
-@@ -289,7 +289,7 @@ struct globals {
- #define rmt_ip (G.rmt_ip )
- #define bind_addr_or_port (G.bind_addr_or_port)
- #define g_query (G.g_query )
--#define configFile (G.configFile )
-+#define opt_c_configFile (G.opt_c_configFile )
- #define home_httpd (G.home_httpd )
- #define index_page (G.index_page )
- #define found_mime_type (G.found_mime_type )
-@@ -452,14 +452,6 @@ static int scan_ip_mask(const char *str,
- /*
- * Parse configuration file into in-memory linked list.
- *
-- * The first non-white character is examined to determine if the config line
-- * is one of the following:
-- * .ext:mime/type # new mime type not compiled into httpd
-- * [adAD]:from # ip address allow/deny, * for wildcard
-- * /path:user:pass # username/password
-- * Ennn:error.html # error page for status nnn
-- * P:/url:[http://]hostname[:port]/new/path # reverse proxy
-- *
- * Any previous IP rules are discarded.
- * If the flag argument is not SUBDIR_PARSE then all /path and mime rules
- * are also discarded. That is, previous settings are retained if flag is
-@@ -469,99 +461,150 @@ static int scan_ip_mask(const char *str,
- * path Path where to look for httpd.conf (without filename).
- * flag Type of the parse request.
- */
--/* flag */
--#define FIRST_PARSE 0
--#define SUBDIR_PARSE 1
--#define SIGNALED_PARSE 2
--#define FIND_FROM_HTTPD_ROOT 3
-+/* flag param: */
-+enum {
-+ FIRST_PARSE = 0, /* path will be "/etc" */
-+ SIGNALED_PARSE = 1, /* path will be "/etc" */
-+ SUBDIR_PARSE = 2, /* path will be derived from URL */
-+};
- static void parse_conf(const char *path, int flag)
- {
-+ /* internally used extra flag state */
-+ enum { TRY_CURDIR_PARSE = 3 };
-+
- FILE *f;
--#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
-- Htaccess *prev;
--#endif
-- Htaccess *cur;
-- const char *filename = configFile;
-+ const char *filename;
- char buf[160];
-- char *p, *p0;
-- char *after_colon;
-- Htaccess_IP *pip;
-
- /* discard old rules */
- free_Htaccess_IP_list(&ip_a_d);
- flg_deny_all = 0;
- /* retain previous auth and mime config only for subdir parse */
- if (flag != SUBDIR_PARSE) {
-+ free_Htaccess_list(&mime_a);
- #if ENABLE_FEATURE_HTTPD_BASIC_AUTH
- free_Htaccess_list(&g_auth);
- #endif
-- free_Htaccess_list(&mime_a);
- #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
- free_Htaccess_list(&script_i);
- #endif
- }
-
-+ filename = opt_c_configFile;
- if (flag == SUBDIR_PARSE || filename == NULL) {
-- filename = alloca(strlen(path) + sizeof(httpd_conf) + 2);
-- sprintf((char *)filename, "%s/%s", path, httpd_conf);
-+ filename = alloca(strlen(path) + sizeof(HTTPD_CONF) + 2);
-+ sprintf((char *)filename, "%s/%s", path, HTTPD_CONF);
- }
-
- while ((f = fopen_for_read(filename)) == NULL) {
-- if (flag == SUBDIR_PARSE || flag == FIND_FROM_HTTPD_ROOT) {
-+ if (flag >= SUBDIR_PARSE) { /* SUBDIR or TRY_CURDIR */
- /* config file not found, no changes to config */
- return;
- }
-- if (configFile && flag == FIRST_PARSE) /* if -c option given */
-- bb_simple_perror_msg_and_die(filename);
-- flag = FIND_FROM_HTTPD_ROOT;
-- filename = httpd_conf;
-+ if (flag == FIRST_PARSE) {
-+ /* -c CONFFILE given, but CONFFILE doesn't exist? */
-+ if (opt_c_configFile)
-+ bb_simple_perror_msg_and_die(opt_c_configFile);
-+ /* else: no -c, thus we looked at /etc/httpd.conf,
-+ * and it's not there. try ./httpd.conf: */
-+ }
-+ flag = TRY_CURDIR_PARSE;
-+ filename = HTTPD_CONF;
- }
-
- #if ENABLE_FEATURE_HTTPD_BASIC_AUTH
-- prev = g_auth;
--#endif
-- /* This could stand some work */
-- while ((p0 = fgets(buf, sizeof(buf), f)) != NULL) {
-- after_colon = NULL;
-- for (p = p0; *p0 != '\0' && *p0 != '#'; p0++) {
-- if (!isspace(*p0)) {
-- *p++ = *p0;
-- if (*p0 == ':' && after_colon == NULL)
-- after_colon = p;
-+ /* in "/file:user:pass" lines, we prepend path in subdirs */
-+ if (flag != SUBDIR_PARSE)
-+ path = "";
-+#endif
-+ /* The lines can be:
-+ *
-+ * I:default_index_file
-+ * H:http_home
-+ * [AD]:IP[/mask] # allow/deny, * for wildcard
-+ * Ennn:error.html # error page for status nnn
-+ * P:/url:[http://]hostname[:port]/new/path # reverse proxy
-+ * .ext:mime/type # mime type
-+ * *.php:/path/php # run xxx.php through an interpreter
-+ * /file:user:pass # username and password
-+ */
-+ while (fgets(buf, sizeof(buf), f) != NULL) {
-+ unsigned strlen_buf;
-+ unsigned char ch;
-+ char *after_colon;
-+
-+ { /* remove all whitespace, and # comments */
-+ char *p, *p0;
-+
-+ p0 = buf;
-+ /* skip non-whitespace beginning. Often the whole line
-+ * is non-whitespace. We want this case to work fast,
-+ * without needless copying, therefore we don't merge
-+ * this operation into next while loop. */
-+ while ((ch = *p0) != '\0' && ch != '\n' && ch != '#'
-+ && ch != ' ' && ch != '\t'
-+ ) {
-+ p0++;
-+ }
-+ p = p0;
-+ /* if we enter this loop, we have some whitespace.
-+ * discard it */
-+ while (ch != '\0' && ch != '\n' && ch != '#') {
-+ if (ch != ' ' && ch != '\t') {
-+ *p++ = ch;
-+ }
-+ ch = *++p0;
- }
-+ *p = '\0';
-+ strlen_buf = p - buf;
-+ if (strlen_buf == 0)
-+ continue; /* empty line */
- }
-- *p = '\0';
-
-- /* test for empty or strange line */
-- if (after_colon == NULL || *after_colon == '\0')
-+ after_colon = strchr(buf, ':');
-+ /* strange line? */
-+ if (after_colon == NULL || *++after_colon == '\0')
-+ goto config_error;
-+
-+ ch = (buf[0] & ~0x20); /* toupper if it's a letter */
-+
-+ if (ch == 'I') {
-+ index_page = xstrdup(after_colon);
- continue;
-- p0 = buf;
-- if (*p0 == 'd' || *p0 == 'a')
-- *p0 -= 0x20; /* a/d -> A/D */
-- if (*after_colon == '*') {
-- if (*p0 == 'D') {
-- /* memorize "deny all" */
-- flg_deny_all = 1;
-- }
-- /* skip assumed "A:*", it is a default anyway */
-+ }
-+
-+ /* do not allow jumping around using H in subdir's configs */
-+ if (flag == FIRST_PARSE && ch == 'H') {
-+ home_httpd = xstrdup(after_colon);
-+ xchdir(home_httpd);
- continue;
- }
-
-- if (*p0 == 'A' || *p0 == 'D') {
-- /* storing current config IP line */
-- pip = xzalloc(sizeof(Htaccess_IP));
-- if (scan_ip_mask(after_colon, &(pip->ip), &(pip->mask))) {
-+ if (ch == 'A' || ch == 'D') {
-+ Htaccess_IP *pip;
-+
-+ if (*after_colon == '*') {
-+ if (ch == 'D') {
-+ /* memorize "deny all" */
-+ flg_deny_all = 1;
-+ }
-+ /* skip assumed "A:*", it is a default anyway */
-+ continue;
-+ }
-+ /* store "allow/deny IP/mask" line */
-+ pip = xzalloc(sizeof(*pip));
-+ if (scan_ip_mask(after_colon, &pip->ip, &pip->mask)) {
- /* IP{/mask} syntax error detected, protect all */
-- *p0 = 'D';
-+ ch = 'D';
- pip->mask = 0;
- }
-- pip->allow_deny = *p0;
-- if (*p0 == 'D') {
-+ pip->allow_deny = ch;
-+ if (ch == 'D') {
- /* Deny:from_IP - prepend */
- pip->next = ip_a_d;
- ip_a_d = pip;
- } else {
-- /* A:from_IP - append (thus D precedes A) */
-+ /* A:from_IP - append (thus all D's precedes A's) */
- Htaccess_IP *prev_IP = ip_a_d;
- if (prev_IP == NULL) {
- ip_a_d = pip;
-@@ -575,12 +618,12 @@ static void parse_conf(const char *path,
- }
-
- #if ENABLE_FEATURE_HTTPD_ERROR_PAGES
-- if (flag == FIRST_PARSE && *p0 == 'E') {
-+ if (flag == FIRST_PARSE && ch == 'E') {
- unsigned i;
-- int status = atoi(++p0); /* error status code */
-+ int status = atoi(buf + 1); /* error status code */
-+
- if (status < HTTP_CONTINUE) {
-- bb_error_msg("config error '%s' in '%s'", buf, filename);
-- continue;
-+ goto config_error;
- }
- /* then error page; find matching status */
- for (i = 0; i < ARRAY_SIZE(http_response_type); i++) {
-@@ -597,7 +640,7 @@ static void parse_conf(const char *path,
- #endif
-
- #if ENABLE_FEATURE_HTTPD_PROXY
-- if (flag == FIRST_PARSE && *p0 == 'P') {
-+ if (flag == FIRST_PARSE && ch == 'P') {
- /* P:/url:[http://]hostname[:port]/new/path */
- char *url_from, *host_port, *url_to;
- Htaccess_Proxy *proxy_entry;
-@@ -605,23 +648,20 @@ static void parse_conf(const char *path,
- url_from = after_colon;
- host_port = strchr(after_colon, ':');
- if (host_port == NULL) {
-- bb_error_msg("config error '%s' in '%s'", buf, filename);
-- continue;
-+ goto config_error;
- }
- *host_port++ = '\0';
- if (strncmp(host_port, "http://", 7) == 0)
- host_port += 7;
- if (*host_port == '\0') {
-- bb_error_msg("config error '%s' in '%s'", buf, filename);
-- continue;
-+ goto config_error;
- }
- url_to = strchr(host_port, '/');
- if (url_to == NULL) {
-- bb_error_msg("config error '%s' in '%s'", buf, filename);
-- continue;
-+ goto config_error;
- }
- *url_to = '\0';
-- proxy_entry = xzalloc(sizeof(Htaccess_Proxy));
-+ proxy_entry = xzalloc(sizeof(*proxy_entry));
- proxy_entry->url_from = xstrdup(url_from);
- proxy_entry->host_port = xstrdup(host_port);
- *url_to = '/';
-@@ -631,115 +671,87 @@ static void parse_conf(const char *path,
- continue;
- }
- #endif
-+ /* the rest of directives are non-alphabetic,
-+ * must avoid using "toupper'ed" ch */
-+ ch = buf[0];
-
--#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
-- if (*p0 == '/') {
-- /* make full path from httpd root / current_path / config_line_path */
-- const char *tp = (flag == SUBDIR_PARSE ? path : "");
-- p0 = xmalloc(strlen(tp) + (after_colon - buf) + 2 + strlen(after_colon));
-- after_colon[-1] = '\0';
-- sprintf(p0, "/%s%s", tp, buf);
--
-- /* looks like bb_simplify_path... */
-- tp = p = p0;
-- do {
-- if (*p == '/') {
-- if (*tp == '/') { /* skip duplicate (or initial) slash */
-- continue;
-- }
-- if (*tp == '.') {
-- if (tp[1] == '/' || tp[1] == '\0') { /* remove extra '.' */
-- continue;
-- }
-- if ((tp[1] == '.') && (tp[2] == '/' || tp[2] == '\0')) {
-- ++tp;
-- if (p > p0) {
-- while (*--p != '/') /* omit previous dir */
-- continue;
-- }
-- continue;
-- }
-- }
-- }
-- *++p = *tp;
-- } while (*++tp);
-+ if (ch == '.' /* ".ext:mime/type" */
-+#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
-+ || (ch == '*' && buf[1] == '.') /* "*.php:/path/php" */
-+#endif
-+ ) {
-+ char *p;
-+ Htaccess *cur;
-
-- if ((p == p0) || (*p != '/')) { /* not a trailing slash */
-- ++p; /* so keep last character */
-+ cur = xzalloc(sizeof(*cur) /* includes space for NUL */ + strlen_buf);
-+ strcpy(cur->before_colon, buf);
-+ p = cur->before_colon + (after_colon - buf);
-+ p[-1] = '\0';
-+ cur->after_colon = p;
-+ if (ch == '.') {
-+ /* .mime line: prepend to mime_a list */
-+ cur->next = mime_a;
-+ mime_a = cur;
-+ }
-+#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
-+ else {
-+ /* script interpreter line: prepend to script_i list */
-+ cur->next = script_i;
-+ script_i = cur;
- }
-- *p = ':';
-- strcpy(p + 1, after_colon);
-- }
- #endif
-- if (*p0 == 'I') {
-- index_page = xstrdup(after_colon);
-- continue;
-- }
--
-- /* Do not allow jumping around using H in subdir's configs */
-- if (flag == FIRST_PARSE && *p0 == 'H') {
-- home_httpd = xstrdup(after_colon);
-- xchdir(home_httpd);
- continue;
- }
-
-- /* storing current config line */
-- cur = xzalloc(sizeof(Htaccess) + strlen(p0));
-- strcpy(cur->before_colon, p0);
--#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
-- if (*p0 == '/') /* was malloced - see above */
-- free(p0);
--#endif
-- cur->after_colon = strchr(cur->before_colon, ':');
-- *cur->after_colon++ = '\0';
-- if (cur->before_colon[0] == '.') {
-- /* .mime line: prepend to mime_a list */
-- cur->next = mime_a;
-- mime_a = cur;
-- continue;
-- }
--#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
-- if (cur->before_colon[0] == '*' && cur->before_colon[1] == '.') {
-- /* script interpreter line: prepend to script_i list */
-- cur->next = script_i;
-- script_i = cur;
-- continue;
-- }
--#endif
- #if ENABLE_FEATURE_HTTPD_BASIC_AUTH
--//TODO: we do not test for leading "/"??
--//also, do we leak cur if BASIC_AUTH is off?
-- if (prev == NULL) {
-- /* first line */
-- g_auth = prev = cur;
-- } else {
-- /* sort path, if current length eq or bigger then move up */
-- Htaccess *prev_hti = g_auth;
-- size_t l = strlen(cur->before_colon);
-- Htaccess *hti;
--
-- for (hti = prev_hti; hti; hti = hti->next) {
-- if (l >= strlen(hti->before_colon)) {
-- /* insert before hti */
-- cur->next = hti;
-- if (prev_hti != hti) {
-- prev_hti->next = cur;
-- } else {
-- /* insert as top */
-- g_auth = cur;
-+ if (ch == '/') { /* "/file:user:pass" */
-+ char *p;
-+ Htaccess *cur;
-+ unsigned file_len;
-+
-+ /* note: path is "" unless we are in SUBDIR parse,
-+ * otherwise it does NOT start with "/" */
-+ cur = xzalloc(sizeof(*cur) /* includes space for NUL */
-+ + 1 + strlen(path)
-+ + strlen_buf
-+ );
-+ /* form "/path/file" */
-+ sprintf(cur->before_colon, "/%s%.*s",
-+ path,
-+ (int) (after_colon - buf - 1), /* includes "/", but not ":" */
-+ buf);
-+ /* canonicalize it */
-+ p = bb_simplify_abs_path_inplace(cur->before_colon);
-+ file_len = p - cur->before_colon;
-+ /* add "user:pass" after NUL */
-+ strcpy(++p, after_colon);
-+ cur->after_colon = p;
-+
-+ /* insert cur into g_auth */
-+ /* g_auth is sorted by decreased filename length */
-+ {
-+ Htaccess *auth, **authp;
-+
-+ authp = &g_auth;
-+ while ((auth = *authp) != NULL) {
-+ if (file_len >= strlen(auth->before_colon)) {
-+ /* insert cur before auth */
-+ cur->next = auth;
-+ break;
- }
-- break;
-+ authp = &auth->next;
- }
-- if (prev_hti != hti)
-- prev_hti = prev_hti->next;
-- }
-- if (!hti) { /* not inserted, add to bottom */
-- prev->next = cur;
-- prev = cur;
-+ *authp = cur;
- }
-+ continue;
- }
- #endif /* BASIC_AUTH */
-+
-+ /* the line is not recognized */
-+ config_error:
-+ bb_error_msg("config error '%s' in '%s'", buf, filename);
- } /* while (fgets) */
-+
- fclose(f);
- }
-
-@@ -1527,11 +1539,6 @@ static NOINLINE void send_file_and_exit(
- send_headers_and_exit(HTTP_NOT_FOUND);
- log_and_exit();
- }
--
-- if (DEBUG)
-- bb_error_msg("sending file '%s' content-type: %s",
-- url, found_mime_type);
--
- /* If you want to know about EPIPE below
- * (happens if you abort downloads from local httpd): */
- signal(SIGPIPE, SIG_IGN);
-@@ -1559,6 +1566,11 @@ static NOINLINE void send_file_and_exit(
- }
- }
- }
-+
-+ if (DEBUG)
-+ bb_error_msg("sending file '%s' content-type: %s",
-+ url, found_mime_type);
-+
- #if ENABLE_FEATURE_HTTPD_RANGES
- if (what == SEND_BODY)
- range_start = 0; /* err pages and ranges don't mix */
-@@ -2031,8 +2043,8 @@ static void handle_incoming_and_exit(con
- /* We are done reading headers, disable peer timeout */
- alarm(0);
-
-- if (strcmp(bb_basename(urlcopy), httpd_conf) == 0 || !ip_allowed) {
-- /* protect listing [/path]/httpd_conf or IP deny */
-+ if (strcmp(bb_basename(urlcopy), HTTPD_CONF) == 0 || !ip_allowed) {
-+ /* protect listing [/path]/httpd.conf or IP deny */
- send_headers_and_exit(HTTP_FORBIDDEN);
- }
-
-@@ -2074,7 +2086,7 @@ static void handle_incoming_and_exit(con
- header_ptr += 2;
- write(proxy_fd, header_buf, header_ptr - header_buf);
- free(header_buf); /* on the order of 8k, free it */
-- /* cgi_io_loop_and_exit needs to have two disctinct fds */
-+ /* cgi_io_loop_and_exit needs to have two distinct fds */
- cgi_io_loop_and_exit(proxy_fd, dup(proxy_fd), length);
- }
- #endif
-@@ -2245,7 +2257,7 @@ static void mini_httpd_inetd(void)
-
- static void sighup_handler(int sig UNUSED_PARAM)
- {
-- parse_conf(default_path_httpd_conf, SIGNALED_PARSE);
-+ parse_conf(DEFAULT_PATH_HTTPD_CONF, SIGNALED_PARSE);
- }
-
- enum {
-@@ -2304,7 +2316,7 @@ int httpd_main(int argc UNUSED_PARAM, ch
- USE_FEATURE_HTTPD_AUTH_MD5("m:")
- USE_FEATURE_HTTPD_SETUID("u:")
- "p:ifv",
-- &configFile, &url_for_decode, &home_httpd
-+ &opt_c_configFile, &url_for_decode, &home_httpd
- USE_FEATURE_HTTPD_ENCODE_URL_STR(, &url_for_encode)
- USE_FEATURE_HTTPD_BASIC_AUTH(, &g_realm)
- USE_FEATURE_HTTPD_AUTH_MD5(, &pass)
-@@ -2375,7 +2387,7 @@ int httpd_main(int argc UNUSED_PARAM, ch
- }
- #endif
-
-- parse_conf(default_path_httpd_conf, FIRST_PARSE);
-+ parse_conf(DEFAULT_PATH_HTTPD_CONF, FIRST_PARSE);
- if (!(opt & OPT_INETD))
- signal(SIGHUP, sighup_handler);
-
diff --git a/core/busybox/busybox-1.14.1-modprobe.patch b/core/busybox/busybox-1.14.1-modprobe.patch
deleted file mode 100644
index 96901250f..000000000
--- a/core/busybox/busybox-1.14.1-modprobe.patch
+++ /dev/null
@@ -1,132 +0,0 @@
-diff -urpN busybox-1.14.1/modutils/modprobe.c busybox-1.14.1-modprobe/modutils/modprobe.c
---- busybox-1.14.1/modutils/modprobe.c 2009-05-27 18:01:37.000000000 +0200
-+++ busybox-1.14.1-modprobe/modutils/modprobe.c 2009-06-04 19:01:04.000000000 +0200
-@@ -8,12 +8,17 @@
- * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
- */
-
-+/* Note that unlike older versions of modules.dep/depmod (busybox and m-i-t),
-+ * we expect the full dependency list to be specified in modules.dep. Older
-+ * versions would only export the direct dependency list.
-+ */
-+
- #include "libbb.h"
- #include "modutils.h"
- #include <sys/utsname.h>
- #include <fnmatch.h>
-
--//#define DBG(...) bb_error_msg(__VA_ARGS__)
-+//#define DBG(fmt, ...) bb_error_msg("%s: " fmt, __func__, ## __VA_ARGS__)
- #define DBG(...) ((void)0)
-
- #define MODULE_FLAG_LOADED 0x0001
-@@ -116,6 +121,7 @@ static void add_probe(const char *name)
- return;
- }
-
-+ DBG("queuing %s", name);
- m->probed_name = name;
- m->flags |= MODULE_FLAG_NEED_DEPS;
- llist_add_to_end(&G.probes, m);
-@@ -205,9 +211,10 @@ static int read_config(const char *path)
-
- static int do_modprobe(struct module_entry *m)
- {
-- struct module_entry *m2;
-+ struct module_entry *m2 = m2; /* for compiler */
- char *fn, *options;
-- int rc = -1;
-+ int rc, first;
-+ llist_t *l;
-
- if (!(m->flags & MODULE_FLAG_FOUND_IN_MODDEP)) {
- DBG("skipping %s, not found in modules.dep", m->modname);
-@@ -218,13 +225,25 @@ static int do_modprobe(struct module_ent
- if (!(option_mask32 & MODPROBE_OPT_REMOVE))
- m->deps = llist_rev(m->deps);
-
-+ for (l = m->deps; l != NULL; l = l->link)
-+ DBG("dep: %s", l->data);
-+
-+ first = 1;
- rc = 0;
- while (m->deps && rc == 0) {
- fn = llist_pop(&m->deps);
- m2 = get_or_add_modentry(fn);
- if (option_mask32 & MODPROBE_OPT_REMOVE) {
-- if (bb_delete_module(m->modname, O_EXCL) != 0)
-- rc = errno;
-+ if (m2->flags & MODULE_FLAG_LOADED) {
-+ if (bb_delete_module(m2->modname, O_EXCL) != 0) {
-+ if (first)
-+ rc = errno;
-+ } else {
-+ m2->flags &= ~MODULE_FLAG_LOADED;
-+ }
-+ }
-+ /* do not error out if *deps* fail to unload */
-+ first = 0;
- } else if (!(m2->flags & MODULE_FLAG_LOADED)) {
- options = m2->options;
- m2->options = NULL;
-@@ -242,11 +261,10 @@ static int do_modprobe(struct module_ent
- free(fn);
- }
-
--//FIXME: what if rc < 0?
-- if (rc > 0 && !(option_mask32 & INSMOD_OPT_SILENT)) {
-+ if (rc && !(option_mask32 & INSMOD_OPT_SILENT)) {
- bb_error_msg("failed to %sload module %s: %s",
- (option_mask32 & MODPROBE_OPT_REMOVE) ? "un" : "",
-- m->probed_name ? m->probed_name : m->modname,
-+ m2->probed_name ? m2->probed_name : m2->modname,
- moderror(rc)
- );
- }
-@@ -294,7 +312,8 @@ static void load_modules_dep(void)
- llist_add_to(&m->deps, xstrdup(tokens[0]));
- if (tokens[1])
- string_to_llist(tokens[1], &m->deps, " ");
-- }
-+ } else
-+ DBG("skipping dep line");
- }
- config_close(p);
- }
-@@ -344,10 +363,12 @@ int modprobe_main(int argc UNUSED_PARAM,
- if (opt & (MODPROBE_OPT_INSERT_ALL | MODPROBE_OPT_REMOVE)) {
- /* Each argument is a module name */
- do {
-+ DBG("adding module %s", *argv);
- add_probe(*argv++);
- } while (*argv);
- } else {
- /* First argument is module name, rest are parameters */
-+ DBG("probing just module %s", *argv);
- add_probe(argv[0]);
- G.cmdline_mopts = parse_cmdline_module_options(argv);
- }
-diff -urpN busybox-1.14.1/modutils/modprobe-small.c busybox-1.14.1-modprobe/modutils/modprobe-small.c
---- busybox-1.14.1/modutils/modprobe-small.c 2009-05-27 18:00:23.000000000 +0200
-+++ busybox-1.14.1-modprobe/modutils/modprobe-small.c 2009-06-04 19:01:28.000000000 +0200
-@@ -656,7 +656,7 @@ depmod -[aA] [-n -e -v -q -V -r -u]
- [-b basedirectory] [forced_version]
- depmod [-n -e -v -q -r -u] [-F kernelsyms] module1.ko module2.ko ...
- If no arguments (except options) are given, "depmod -a" is assumed.
--depmod will output a dependancy list suitable for the modprobe utility.
-+depmod will output a dependency list suitable for the modprobe utility.
- Options:
- -a, --all Probe all modules
- -A, --quick Only does the work if there's a new module
-diff -urpN busybox-1.14.1/modutils/modutils.c busybox-1.14.1-modprobe/modutils/modutils.c
---- busybox-1.14.1/modutils/modutils.c 2009-05-27 18:00:23.000000000 +0200
-+++ busybox-1.14.1-modprobe/modutils/modutils.c 2009-06-03 12:50:48.000000000 +0200
-@@ -57,7 +57,7 @@ char * FAST_FUNC filename2modname(const
- from = bb_get_last_path_component_nostrip(filename);
- for (i = 0; i < (MODULE_NAME_LEN-1) && from[i] != '\0' && from[i] != '.'; i++)
- modname[i] = (from[i] == '-') ? '_' : from[i];
-- modname[i] = 0;
-+ modname[i] = '\0';
-
- return modname;
- }
diff --git a/core/busybox/busybox-1.14.1-telnetd.patch b/core/busybox/busybox-1.14.1-telnetd.patch
deleted file mode 100644
index 099e5eb83..000000000
--- a/core/busybox/busybox-1.14.1-telnetd.patch
+++ /dev/null
@@ -1,85 +0,0 @@
-diff -urpN busybox-1.14.1/networking/telnetd.c busybox-1.14.1-telnetd/networking/telnetd.c
---- busybox-1.14.1/networking/telnetd.c 2009-05-27 18:00:23.000000000 +0200
-+++ busybox-1.14.1-telnetd/networking/telnetd.c 2009-06-09 22:54:06.000000000 +0200
-@@ -199,9 +199,17 @@ static size_t iac_safe_write(int fd, con
- return total + rc;
- }
-
-+/* Must match getopt32 string */
-+enum {
-+ OPT_WATCHCHILD = (1 << 2), /* -K */
-+ OPT_INETD = (1 << 3) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -i */
-+ OPT_PORT = (1 << 4) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -p */
-+ OPT_FOREGROUND = (1 << 6) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -F */
-+};
-+
- static struct tsession *
- make_new_session(
-- USE_FEATURE_TELNETD_STANDALONE(int sock)
-+ USE_FEATURE_TELNETD_STANDALONE(int master_fd, int sock)
- SKIP_FEATURE_TELNETD_STANDALONE(void)
- ) {
- const char *login_argv[2];
-@@ -288,9 +296,29 @@ make_new_session(
- /* Restore default signal handling ASAP */
- bb_signals((1 << SIGCHLD) + (1 << SIGPIPE), SIG_DFL);
-
-+#if ENABLE_FEATURE_TELNETD_STANDALONE
-+ if (!(option_mask32 & OPT_INETD)) {
-+ struct tsession *tp = sessions;
-+ while (tp) {
-+ close(tp->ptyfd);
-+ close(tp->sockfd_read);
-+ /* sockfd_write == sockfd_read for standalone telnetd */
-+ /*close(tp->sockfd_write);*/
-+ tp = tp->next;
-+ }
-+ }
-+#endif
-+
- /* Make new session and process group */
- setsid();
-
-+ close(fd);
-+#if ENABLE_FEATURE_TELNETD_STANDALONE
-+ close(sock);
-+ if (master_fd >= 0)
-+ close(master_fd);
-+#endif
-+
- /* Open the child's side of the tty. */
- /* NB: setsid() disconnects from any previous ctty's. Therefore
- * we must open child's side of the tty AFTER setsid! */
-@@ -329,14 +357,6 @@ make_new_session(
- _exit(EXIT_FAILURE); /*bb_perror_msg_and_die("execv %s", loginpath);*/
- }
-
--/* Must match getopt32 string */
--enum {
-- OPT_WATCHCHILD = (1 << 2), /* -K */
-- OPT_INETD = (1 << 3) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -i */
-- OPT_PORT = (1 << 4) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -p */
-- OPT_FOREGROUND = (1 << 6) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -F */
--};
--
- #if ENABLE_FEATURE_TELNETD_STANDALONE
-
- static void
-@@ -465,7 +485,7 @@ int telnetd_main(int argc UNUSED_PARAM,
-
- #if ENABLE_FEATURE_TELNETD_STANDALONE
- if (IS_INETD) {
-- sessions = make_new_session(0);
-+ sessions = make_new_session(-1, 0);
- if (!sessions) /* pty opening or vfork problem, exit */
- return 1; /* make_new_session prints error message */
- } else {
-@@ -553,7 +573,7 @@ int telnetd_main(int argc UNUSED_PARAM,
- if (fd < 0)
- goto again;
- /* Create a new session and link it into our active list */
-- new_ts = make_new_session(fd);
-+ new_ts = make_new_session(master_fd, fd);
- if (new_ts) {
- new_ts->next = sessions;
- sessions = new_ts;
diff --git a/core/e2fsprogs/APKBUILD b/core/e2fsprogs/APKBUILD
index 466f1a0ab..eedabbffa 100644
--- a/core/e2fsprogs/APKBUILD
+++ b/core/e2fsprogs/APKBUILD
@@ -1,6 +1,6 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=e2fsprogs
-pkgver=1.41.6
+pkgver=1.41.8
pkgrel=0
pkgdesc="Standard Ext2/3/4 filesystem utilities"
url="http://e2fsprogs.sourceforge.net"
@@ -40,4 +40,4 @@ libblkid() {
mv "$pkgdir"/lib/libblkid* "$subpkgdir"/lib/
}
-md5sums="732c559db400c8fc994f4f38568c9f1f e2fsprogs-1.41.6.tar.gz"
+md5sums="6708cc8e484809fc5cfb232882e48489 e2fsprogs-1.41.8.tar.gz"
diff --git a/core/fakeroot/APKBUILD b/core/fakeroot/APKBUILD
index ed38a537e..d9bfb67b8 100644
--- a/core/fakeroot/APKBUILD
+++ b/core/fakeroot/APKBUILD
@@ -1,6 +1,6 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=fakeroot
-pkgver=1.12.3
+pkgver=1.12.4
pkgrel=0
pkgdesc="Gives a fake root environment, useful for building packages as a non-privileged user"
license='GPL'
@@ -18,5 +18,5 @@ build() {
make DESTDIR="$pkgdir" install
}
-md5sums="5b482b106e7417a9d7aa5b03a37911cc fakeroot_1.12.3.tar.gz
+md5sums="aaefede2405a40c87438e7e833d69b70 fakeroot_1.12.4.tar.gz
ea7b7e3065090d72804cdf4719dd5832 busybox-compat.patch"
diff --git a/core/git/APKBUILD b/core/git/APKBUILD
index 8d90bee59..2f5d36dba 100644
--- a/core/git/APKBUILD
+++ b/core/git/APKBUILD
@@ -1,6 +1,6 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=git
-pkgver=1.6.3.2
+pkgver=1.6.3.3
pkgrel=0
pkgdesc="GIT - the stupid content tracker"
url="http://git.or.cz/"
@@ -38,5 +38,5 @@ perl() {
}
-md5sums="149948ff33fb7d8cf9eef925e6c08157 git-1.6.3.2.tar.bz2
+md5sums="91ae46ac01dadab1962beb064abd5b60 git-1.6.3.3.tar.bz2
04e1bdf76a0bac568f8488daad07dce7 bb-tar.patch"
diff --git a/core/installkernel/APKBUILD b/core/installkernel/APKBUILD
new file mode 100644
index 000000000..76690b904
--- /dev/null
+++ b/core/installkernel/APKBUILD
@@ -0,0 +1,17 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=installkernel
+pkgver=3.1.3
+pkgrel=0
+pkgdesc="Kernel install script from debianutils"
+url="http://packages.qa.debian.org/d/debianutils.html"
+license="BSD GPL-2 SMAIL"
+subpackages="$pkgname-doc"
+depends=""
+source="http://ftp.debian.org/debian/pool/main/d/debianutils/debianutils_$pkgver.tar.gz"
+
+build() {
+ cd "$srcdir"/debianutils-$pkgver
+ install -Dm755 installkernel "$pkgdir"/sbin/installkernel
+ install -Dm644 installkernel.8 "$pkgdir"/usr/share/man/man8/installkernel.8
+}
+md5sums="42c759ff41851313bb0b9c419598c04c debianutils_3.1.3.tar.gz"
diff --git a/core/iptables/APKBUILD b/core/iptables/APKBUILD
index b673ec006..2a503aca7 100644
--- a/core/iptables/APKBUILD
+++ b/core/iptables/APKBUILD
@@ -2,14 +2,13 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=iptables
-pkgver=1.4.3.2
+pkgver=1.4.4
pkgrel=0
pkgdesc="Linux kernel firewall, NAT and packet mangling tools"
url="http://www.iptables.org/"
license=GPL-2
source="http://iptables.org/projects/iptables/files/$pkgname-$pkgver.tar.bz2
iptables-1.4.2-include-in.patch
- nocxx.patch
iptables.initd
iptables.confd
"
@@ -61,8 +60,7 @@ ip6tables() {
"$subpkgdir"/etc/init.d/ip6tables
}
-md5sums="545698693b636cfc844aafc6729fd48a iptables-1.4.3.2.tar.bz2
+md5sums="08cd9196881657ea0615d926334cb7e9 iptables-1.4.4.tar.bz2
ec3e80a1b0ea3e13e4e60824b7ebd1b9 iptables-1.4.2-include-in.patch
-28513788ba4d556ccd538867dc6205ab nocxx.patch
2202ac150a5dfe32a8363b0ad565ee1d iptables.initd
956ebf5ab69e5a1e1d3983541eab643b iptables.confd"
diff --git a/core/iptables/nocxx.patch b/core/iptables/nocxx.patch
deleted file mode 100644
index beb1ab900..000000000
--- a/core/iptables/nocxx.patch
+++ /dev/null
@@ -1,15 +0,0 @@
---- a/configure 2004-12-07 21:34:23.205172545 +0000
-+++ b/configure 2004-12-07 21:37:17.726654782 +0000
-@@ -5148,10 +5148,8 @@
- :
- else
- { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check
--See \`config.log' for more details." >&5
--echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check
--See \`config.log' for more details." >&2;}
-- { (exit 1); exit 1; }; }
-+See \`config.log' for more details." >&5;}
-+ { echo "C++ sucks, ignoring ..." >&5; }; }
- fi
-
- ac_ext=cc
diff --git a/core/iscsitarget-grsec/APKBUILD b/core/iscsitarget-grsec/APKBUILD
new file mode 100644
index 000000000..a40470475
--- /dev/null
+++ b/core/iscsitarget-grsec/APKBUILD
@@ -0,0 +1,43 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+
+_flavor=grsec
+_realname=iscsitarget
+# source the kernel version
+if [ -f ../linux-$_flavor/APKBUILD ]; then
+ . ../linux-$_flavor/APKBUILD
+fi
+_abi_release=$pkgver-${_flavor}
+
+# get pkgver from iscsitarget
+if [ -f ../iscsitarget/APKBUILD ]; then
+ . ../iscsitarget/APKBUILD
+fi
+pkgname=${_realname}-${_flavor}
+pkgver=${pkgver:-0.4.17}
+pkgrel=2
+pkgdesc="$_flavor kernel modules for iscsitarget"
+url="http://iscsitarget.sourceforge.net/"
+license="GPL-2"
+depends=
+makedepends="linux-${_flavor}-dev"
+subpackages=
+source="http://downloads.sourceforge.net/$_realname/$_realname-$pkgver.tar.gz
+ iscsitarget-0.4.17+linux-2.6.28.patch
+ iscsitarget-0.4.17+linux-2.6.29.patch
+ "
+
+build() {
+ cd "$srcdir"/$_realname-$pkgver
+ for i in ../*.patch; do
+ msg "Applying $i"
+ patch -p1 < $i || return 1
+ done
+
+ unset ARCH
+ local ksrc=/usr/src/linux-headers-${_abi_release}
+ make KSRC="$ksrc" kernel || return 1
+ make KSRC="$ksrc" DISTDIR="$pkgdir" install-kernel || return 1
+}
+md5sums="e79b437695fc50e7d054631855a16b1b iscsitarget-0.4.17.tar.gz
+f58dde50f72b04b7737b33e517e56208 iscsitarget-0.4.17+linux-2.6.28.patch
+a7be10bb04c9014807e39db75c9cd468 iscsitarget-0.4.17+linux-2.6.29.patch"
diff --git a/core/iscsitarget/iscsitarget-0.4.17+linux-2.6.28.patch b/core/iscsitarget-grsec/iscsitarget-0.4.17+linux-2.6.28.patch
index ec35cd526..ec35cd526 100644
--- a/core/iscsitarget/iscsitarget-0.4.17+linux-2.6.28.patch
+++ b/core/iscsitarget-grsec/iscsitarget-0.4.17+linux-2.6.28.patch
diff --git a/core/iscsitarget-grsec/iscsitarget-0.4.17+linux-2.6.29.patch b/core/iscsitarget-grsec/iscsitarget-0.4.17+linux-2.6.29.patch
new file mode 100644
index 000000000..092fdc3fd
--- /dev/null
+++ b/core/iscsitarget-grsec/iscsitarget-0.4.17+linux-2.6.29.patch
@@ -0,0 +1,40 @@
+From 81373580a641732a7e4610c3d39af0c68007b892 Mon Sep 17 00:00:00 2001
+From: =?utf-8?q?Diego=20Elio=20'Flameeyes'=20Petten=C3=B2?= <flameeyes@gmail.com>
+Date: Wed, 25 Mar 2009 16:14:46 +0100
+Subject: [PATCH 2/2] Fix building with Linux kernel 2.6.29 and later.
+
+When building for Linux 2.6.29 or later, instead of using the NIP6
+macro (that has been removed) use the new %p6 format specifier.
+---
+ kernel/conn.c | 6 ++++++
+ 1 files changed, 6 insertions(+), 0 deletions(-)
+
+diff --git a/kernel/conn.c b/kernel/conn.c
+index f96e2b6..ab561f9 100644
+--- a/kernel/conn.c
++++ b/kernel/conn.c
+@@ -6,6 +6,7 @@
+
+ #include <linux/file.h>
+ #include <linux/ip.h>
++#include <linux/version.h>
+ #include <net/tcp.h>
+
+ #include "iscsi.h"
+@@ -47,8 +48,13 @@ void conn_info_show(struct seq_file *seq, struct iscsi_session *session)
+ break;
+ case AF_INET6:
+ snprintf(buf, sizeof(buf),
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
++ "[%p6]",
++ &(inet6_sk(sk)->daddr));
++#else
+ "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]",
+ NIP6(inet6_sk(sk)->daddr));
++#endif
+ break;
+ default:
+ break;
+--
+1.6.2
+
diff --git a/core/iscsitarget/APKBUILD b/core/iscsitarget/APKBUILD
index d6dc27404..3bdf98ee0 100644
--- a/core/iscsitarget/APKBUILD
+++ b/core/iscsitarget/APKBUILD
@@ -1,56 +1,30 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+
pkgname=iscsitarget
pkgver=0.4.17
-pkgrel=1
-pkgdesc="Open Source iSCSI target with professional features"
+pkgrel=2
+pkgdesc="Open Source iSCSI target with professional features - userspace utils"
url="http://iscsitarget.sourceforge.net/"
license="GPL-2"
-depends="uclibc openssl"
+depends=
makedepends="openssl-dev"
-subpackages="$pkgname-doc $pkgname-grsec:mod"
-_kernels="grsec"
+subpackages="$pkgname-doc"
source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz
$pkgname-0.4.15-isns-set-scn-flag.patch
$pkgname-0.4.17-build.patch
- $pkgname-0.4.17+linux-2.6.28.patch
ietd.initd
ietd.confd
"
-for _i in $_kernels; do
- makedepends="$makedepends linux-${_i}-sources linux-${_i}-dev"
-done
-
build() {
cd "$srcdir"/$pkgname-$pkgver
for i in ../*.patch; do
msg "Applying $i"
patch -p1 < $i || return 1
done
-
- unset ARCH
- local k
- for k in $_kernels; do
- msg "Building kernel modules for $k"
- local kout="$srcdir"/$k
- mkdir -p "$kout"
- local ver=$(awk -F': ' '$1 ~ /Linux kernel version/ {print $2}' /boot/config-$k)
-
- cd "$kout"
- cp /boot/config-$k .config
- cp /boot/Module.symvers-$k Module.symvers
- make -C /usr/src/linux-$ver-$k O=$PWD silentoldconfig \
- || return 1
- make modules_prepare
-
- cd "$srcdir"/$pkgname-$pkgver
- make KSRC="$kout" kernel || return 1
- make KSRC="$kout" DISTDIR="$pkgdir" install-kernel || return 1
- done
- msg "Building userspace"
- make KSRC="$kout" usr || return 1
- make KSRC="$kout" DISTDIR="$pkgdir" install-usr install-doc
+ make usr || return 1
+ make DISTDIR="$pkgdir" install-usr install-doc
for i in etc/ietd.conf etc/initiators.*; do
install -Dm640 $i "$pkgdir"/$i || return 1
@@ -58,9 +32,9 @@ build() {
install -Dm755 ../ietd.initd "$pkgdir"/etc/init.d/ietd
install -Dm755 ../ietd.confd "$pkgdir"/etc/conf.d/ietd
}
+
md5sums="e79b437695fc50e7d054631855a16b1b iscsitarget-0.4.17.tar.gz
22512c5cf4cb62127730ce53d74ff28f iscsitarget-0.4.15-isns-set-scn-flag.patch
c9a9b839b3afcdecd1601511ee48a171 iscsitarget-0.4.17-build.patch
-f58dde50f72b04b7737b33e517e56208 iscsitarget-0.4.17+linux-2.6.28.patch
641513492f58a6cb13247d0028a50906 ietd.initd
06ba479d3533d557b8582abe6f182410 ietd.confd"
diff --git a/core/linux-grsec-sources/.gitignore b/core/linux-grsec-sources/.gitignore
deleted file mode 100644
index 201f43de6..000000000
--- a/core/linux-grsec-sources/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-grsecurity*.patch
diff --git a/core/linux-grsec-sources/APKBUILD b/core/linux-grsec-sources/APKBUILD
deleted file mode 100644
index e1a5901bc..000000000
--- a/core/linux-grsec-sources/APKBUILD
+++ /dev/null
@@ -1,39 +0,0 @@
-# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
-_suff=grsec
-pkgname=linux-$_suff-sources
-pkgver=2.6.28.9
-pkgdesc="Linux kernel sources with grsecurity patch"
-_kernver=2.6.28
-_grsecver=2.1.13-$_kernver.8-200903191958
-pkgrel=0
-options="!strip"
-license=GPL-2
-url=http://kernel.org
-source="ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-$_kernver.tar.bz2
- ftp://ftp.kernel.org/pub/linux/kernel/v2.6/patch-$pkgver.bz2
- http://www.grsecurity.net/test/grsecurity-$_grsecver.patch
- 0001-linux-2.6.28.5-ipgre-strict-binding.patch
- 0002-linux-2.6.28.5-ipgre-optimize-hash-lookup.patch
- "
-
-build() {
- cd $srcdir/linux-$_kernver
- if [ "$_kernver" != "$pkgver" ]; then
- bunzip2 -c < ../patch-$pkgver.bz2 | patch -p1 || return 1
- fi
-
- for i in ../*.patch; do
- msg "Applying $i..."
- patch -p1 < $i || return 1
- done
-
- mkdir -p "$pkgdir/usr/src"
- cd "$srcdir"
- mv "linux-$_kernver" "$pkgdir/usr/src/linux-$pkgver-$_suff"
-}
-
-md5sums="d351e44709c9810b85e29b877f50968a linux-2.6.28.tar.bz2
-27a43f76cf4b90db18df6d1c5e72789b patch-2.6.28.9.bz2
-e98fdd8e286579c61822ef264b56dee4 grsecurity-2.1.13-2.6.28.8-200903191958.patch
-7673b4521283ad41434a18ca18b16ad8 0001-linux-2.6.28.5-ipgre-strict-binding.patch
-8f405c738b150c532c46eaad5390cca2 0002-linux-2.6.28.5-ipgre-optimize-hash-lookup.patch"
diff --git a/core/linux-grsec-sources/linux-2.6.26.8-ipgre-strict-binding.diff b/core/linux-grsec-sources/linux-2.6.26.8-ipgre-strict-binding.diff
deleted file mode 100644
index 16f421c58..000000000
--- a/core/linux-grsec-sources/linux-2.6.26.8-ipgre-strict-binding.diff
+++ /dev/null
@@ -1,124 +0,0 @@
-Index: linux-2.6.26.8/net/ipv4/ip_gre.c
-===================================================================
---- linux-2.6.26.8.orig/net/ipv4/ip_gre.c 2009-01-08 12:54:44.000000000 +0200
-+++ linux-2.6.26.8/net/ipv4/ip_gre.c 2009-01-08 15:30:38.000000000 +0200
-@@ -162,41 +162,65 @@
-
- /* Given src, dst and key, find appropriate for input tunnel. */
-
--static struct ip_tunnel * ipgre_tunnel_lookup(struct net *net,
-+static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev,
- __be32 remote, __be32 local, __be32 key)
- {
-+ struct net *net = dev_net(dev);
-+ int link = dev->ifindex;
- unsigned h0 = HASH(remote);
- unsigned h1 = HASH(key);
-- struct ip_tunnel *t;
-+ struct ip_tunnel *t, *tlinkless = NULL;
- struct ipgre_net *ign = net_generic(net, ipgre_net_id);
-
- for (t = ign->tunnels_r_l[h0^h1]; t; t = t->next) {
-- if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) {
-- if (t->parms.i_key == key && (t->dev->flags&IFF_UP))
-+ if (local == t->parms.iph.saddr &&
-+ remote == t->parms.iph.daddr &&
-+ key == t->parms.i_key &&
-+ (t->dev->flags & IFF_UP)) {
-+ if (link == t->parms.link)
- return t;
-+ if (tlinkless == NULL)
-+ tlinkless = t;
- }
- }
- for (t = ign->tunnels_r[h0^h1]; t; t = t->next) {
-- if (remote == t->parms.iph.daddr) {
-- if (t->parms.i_key == key && (t->dev->flags&IFF_UP))
-+ if (remote == t->parms.iph.daddr &&
-+ key == t->parms.i_key &&
-+ (t->dev->flags&IFF_UP)) {
-+ if (link == t->parms.link)
- return t;
-+ if (tlinkless == NULL)
-+ tlinkless = t;
- }
- }
- for (t = ign->tunnels_l[h1]; t; t = t->next) {
-- if (local == t->parms.iph.saddr ||
-- (local == t->parms.iph.daddr &&
-- ipv4_is_multicast(local))) {
-- if (t->parms.i_key == key && (t->dev->flags&IFF_UP))
-+ if ((local == t->parms.iph.saddr ||
-+ (local == t->parms.iph.daddr && ipv4_is_multicast(local))) &&
-+ key == t->parms.i_key &&
-+ (t->dev->flags & IFF_UP)) {
-+ if (link == t->parms.link)
- return t;
-+ if (tlinkless == NULL)
-+ tlinkless = t;
- }
- }
-+
- for (t = ign->tunnels_wc[h1]; t; t = t->next) {
-- if (t->parms.i_key == key && (t->dev->flags&IFF_UP))
-- return t;
-+ if (t->parms.i_key == key &&
-+ (t->dev->flags & IFF_UP)) {
-+ if (link == t->parms.link)
-+ return t;
-+ if (tlinkless == NULL)
-+ tlinkless = t;
-+ }
- }
-
-- if (ign->fb_tunnel_dev->flags&IFF_UP)
-+ if (tlinkless != NULL)
-+ return tlinkless;
-+
-+ if (ign->fb_tunnel_dev->flags & IFF_UP)
- return netdev_priv(ign->fb_tunnel_dev);
-+
- return NULL;
- }
-
-@@ -255,16 +279,18 @@
- __be32 remote = parms->iph.daddr;
- __be32 local = parms->iph.saddr;
- __be32 key = parms->i_key;
-+ int link = parms->link;
- struct ip_tunnel *t, **tp, *nt;
- struct net_device *dev;
- char name[IFNAMSIZ];
- struct ipgre_net *ign = net_generic(net, ipgre_net_id);
-
- for (tp = __ipgre_bucket(ign, parms); (t = *tp) != NULL; tp = &t->next) {
-- if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) {
-- if (key == t->parms.i_key)
-- return t;
-- }
-+ if (local == t->parms.iph.saddr &&
-+ remote == t->parms.iph.daddr &&
-+ key == t->parms.i_key &&
-+ link == t->parms.link)
-+ return t;
- }
- if (!create)
- return NULL;
-@@ -379,7 +405,7 @@
- }
-
- read_lock(&ipgre_lock);
-- t = ipgre_tunnel_lookup(dev_net(skb->dev), iph->daddr, iph->saddr,
-+ t = ipgre_tunnel_lookup(skb->dev, iph->daddr, iph->saddr,
- (flags&GRE_KEY) ?
- *(((__be32*)p) + (grehlen>>2) - 1) : 0);
- if (t == NULL || t->parms.iph.daddr == 0 ||
-@@ -471,7 +497,7 @@
- }
-
- read_lock(&ipgre_lock);
-- if ((tunnel = ipgre_tunnel_lookup(dev_net(skb->dev),
-+ if ((tunnel = ipgre_tunnel_lookup(skb->dev,
- iph->saddr, iph->daddr, key)) != NULL) {
- secpath_reset(skb);
-
diff --git a/core/linux-grsec-sources/0001-linux-2.6.28.5-ipgre-strict-binding.patch b/core/linux-grsec/0001-linux-2.6.28.5-ipgre-strict-binding.patch
index fd0cfeb2a..fd0cfeb2a 100644
--- a/core/linux-grsec-sources/0001-linux-2.6.28.5-ipgre-strict-binding.patch
+++ b/core/linux-grsec/0001-linux-2.6.28.5-ipgre-strict-binding.patch
diff --git a/core/linux-grsec-sources/0002-linux-2.6.28.5-ipgre-optimize-hash-lookup.patch b/core/linux-grsec/0002-linux-2.6.28.5-ipgre-optimize-hash-lookup.patch
index fbfef33b9..fbfef33b9 100644
--- a/core/linux-grsec-sources/0002-linux-2.6.28.5-ipgre-optimize-hash-lookup.patch
+++ b/core/linux-grsec/0002-linux-2.6.28.5-ipgre-optimize-hash-lookup.patch
diff --git a/core/linux-grsec/APKBUILD b/core/linux-grsec/APKBUILD
index fc66f061f..8b9043f4b 100644
--- a/core/linux-grsec/APKBUILD
+++ b/core/linux-grsec/APKBUILD
@@ -1,38 +1,123 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+
_flavor=grsec
-pkgname=linux-$_flavor
-pkgver=2.6.28.9
-pkgrel=4
+pkgname=linux-${_flavor}
+pkgver=2.6.29.6
+_kernver=2.6.29
+pkgrel=0
pkgdesc="Linux kernel with grsecurity"
url=http://grsecurity.net
-arch=i486
-makedepends="$pkgname-sources perl"
-source="kernelconfig"
-subpackages="$pkgname-mod $pkgname-dev"
-license=GPL-2
+depends="mkinitfs"
+makedepends="perl installkernel"
+_config=${config:-kernelconfig}
+install="$pkgname.post-install $pkgname.post-upgrade"
+source="ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-$_kernver.tar.bz2
+ ftp://ftp.kernel.org/pub/linux/kernel/v2.6/patch-$pkgver.bz2
+ grsecurity-2.1.14-2.6.29.5-200906152045.patch
+ 0001-linux-2.6.28.5-ipgre-strict-binding.patch
+ 0002-linux-2.6.28.5-ipgre-optimize-hash-lookup.patch
+ net-next-2.6.git-5ef12d98a19254ee5dc851bd83e214b43ec1f725.patch
+ $_config
+ $install
+ "
+subpackages="$pkgname-dev"
+license="GPL-2"
-build() {
- mkdir -p "$srcdir/$pkgname"
- cd "$srcdir/$pkgname"
- cp ../kernelconfig .config
- make -C /usr/src/linux-$pkgver-grsec "O=$PWD" HOSTCC="$CC" \
+_abi_release=${pkgver}-${_flavor}
+
+_prepare() {
+ cd "$srcdir"/linux-$_kernver
+ if [ "$_kernver" != "$pkgver" ]; then
+ bunzip2 -c < ../patch-$pkgver.bz2 | patch -p1 || return 1
+ fi
+
+ for i in ../*.patch; do
+ msg "Applying $i..."
+ patch -p1 -N < $i || return 1
+ done
+
+ mkdir -p "$srcdir"/build
+ cp "$srcdir"/$_config "$srcdir"/build/.config
+ make -C "$srcdir"/linux-$_kernver O="$srcdir"/build HOSTCC="$CC" \
silentoldconfig
+}
+
+# this is so we can do: 'abuild menuconfig' to reconfigure kernel
+menuconfig() {
+ _prepare
+ cd "$srcdir"/build
+ make menuconfig
+ cp .config "$startdir"/$_config
+}
+
+build() {
+ _prepare || return 1
+ cd "$srcdir"/build
make CC="$CC" || return 1
- mkdir -p $pkgdir/boot $pkgdir/lib/modules
+ mkdir -p "$pkgdir"/boot "$pkgdir"/lib/modules
make modules_install install \
- INSTALL_MOD_PATH=$pkgdir \
- INSTALL_PATH=$pkgdir/boot
- cd "$pkgdir"/boot
- mv vmlinuz $_flavor
+ INSTALL_MOD_PATH="$pkgdir" \
+ INSTALL_PATH="$pkgdir"/boot
+
+ ln -s vmlinuz-${_abi_release} "${pkgdir}"/boot/$_flavor
+
+ rm -f "$pkgdir"/lib/modules/${_abi_release}/build \
+ "$pkgdir"/lib/modules/${_abi_release}/source
}
-dev() {
- install -Dm644 "$srcdir"/$pkgname/Module.symvers \
- "$subpkgdir"/boot/Module.symvers-$_flavor
- install -Dm644 "$srcdir/kernelconfig" \
- "$subpkgdir"/boot/config-$_flavor
- mv "$pkgdir"/boot/System.map "$subpkgdir"/boot/System.map-$_flavor
+dev() {
+ # copy the only the parts that we really need for build 3rd party
+ # kernel modules and install those as /usr/src/linux-headers,
+ # simlar to what ubuntu does
+ #
+ # this way you dont need to install the 300-400 kernel sources to
+ # build a tiny kernel module
+ #
+ pkgdesc="Headers and script for third party modules for grsec kernel"
+ local dir="$subpkgdir"/usr/src/linux-headers-${_abi_release}
+
+ # first we import config, run prepare to set up for building
+ # external modules, and create the scripts
+ mkdir -p "$dir"
+ cp "$srcdir"/kernelconfig "$dir"/.config
+ make -j1 -C "$srcdir"/linux-$_kernver O="$dir" HOSTCC="$CC" \
+ silentoldconfig prepare scripts
+
+ # remove the stuff that poits to real sources. we want 3rd party
+ # modules to believe this is the soruces
+ rm "$dir"/Makefile "$dir"/source
+
+ # copy the needed stuff from real sources
+ #
+ # this is taken from ubuntu kernel build script
+ # http://kernel.ubuntu.com/git?p=ubuntu/ubuntu-jaunty.git;a=blob;f=debian/rules.d/3-binary-indep.mk;hb=HEAD
+ cd "$srcdir"/linux-$_kernver
+ find . -path './include/*' -prune -o -path './scripts/*' -prune \
+ -o -type f \( -name 'Makefile*' -o -name 'Kconfig*' \
+ -o -name 'Kbuild*' -o -name '*.sh' -o -name '*.pl' \
+ -o -name '*.lds' \) | cpio -pdm "$dir"
+ cp -a drivers/media/dvb/dvb-core/*.h "$dir"/drivers/media/dvb/dvb-core
+ cp -a drivers/media/video/*.h "$dir"/drivers/media/video
+ cp -a drivers/media/dvb/frontends/*.h "$dir"/drivers/media/dvb/frontends
+ cp -a scripts include "$dir"
+ find $(find arch -name include -type d -print) -type f \
+ | cpio -pdm "$dir"
+
+ install -Dm644 "$srcdir"/build/Module.symvers \
+ "$dir"/Module.symvers
+
+ mkdir -p "$subpkgdir"/lib/modules/${_abi_release}
+ ln -sf /usr/src/linux-headers-${_abi_release} \
+ "$subpkgdir"/lib/modules/${_abi_release}/build
}
-md5sums="2b13beaff480758b99eba6cb2191952b kernelconfig"
+md5sums="64921b5ff5cdadbccfcd3820f03be7d8 linux-2.6.29.tar.bz2
+0317760b52c9ac7a11de997da19a366e patch-2.6.29.6.bz2
+e2e49a250303720b31c4371905c105e3 grsecurity-2.1.14-2.6.29.5-200906152045.patch
+7673b4521283ad41434a18ca18b16ad8 0001-linux-2.6.28.5-ipgre-strict-binding.patch
+8f405c738b150c532c46eaad5390cca2 0002-linux-2.6.28.5-ipgre-optimize-hash-lookup.patch
+ca05fd252783b82e01610e775cf56498 net-next-2.6.git-5ef12d98a19254ee5dc851bd83e214b43ec1f725.patch
+c9443dcc46eb70267b4cfe6a6694f637 kernelconfig
+2834240b15805b248ef2a973b1ad4416 linux-grsec.post-install
+2834240b15805b248ef2a973b1ad4416 linux-grsec.post-upgrade"
diff --git a/core/linux-grsec-sources/grsecurity-2.1.13-2.6.28.8-200903191958.patch b/core/linux-grsec/grsecurity-2.1.14-2.6.29.5-200906152045.patch
index c4ec6365f..275bbfe7c 100644
--- a/core/linux-grsec-sources/grsecurity-2.1.13-2.6.28.8-200903191958.patch
+++ b/core/linux-grsec/grsecurity-2.1.14-2.6.29.5-200906152045.patch
@@ -1,6 +1,19 @@
-diff -urNp linux-2.6.28.8/arch/alpha/include/asm/elf.h linux-2.6.28.8/arch/alpha/include/asm/elf.h
---- linux-2.6.28.8/arch/alpha/include/asm/elf.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/alpha/include/asm/elf.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/alpha/include/asm/atomic.h linux-2.6.29.5/arch/alpha/include/asm/atomic.h
+--- linux-2.6.29.5/arch/alpha/include/asm/atomic.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/alpha/include/asm/atomic.h 2009-06-12 23:57:31.000000000 -0400
+@@ -246,6 +246,9 @@ static __inline__ int atomic64_add_unles
+ #define atomic64_dec_and_test(v) (atomic64_sub_return(1, (v)) == 0)
+
+ #define atomic_inc(v) atomic_add(1,(v))
++#define atomic_inc_unchecked(v) atomic_inc(v)
++#define atomic_add_unchecked(i,v) atomic_add((i),(v))
++#define atomic_sub_unchecked(i,v) atomic_sub((i),(v))
+ #define atomic64_inc(v) atomic64_add(1,(v))
+
+ #define atomic_dec(v) atomic_sub(1,(v))
+diff -urNp linux-2.6.29.5/arch/alpha/include/asm/elf.h linux-2.6.29.5/arch/alpha/include/asm/elf.h
+--- linux-2.6.29.5/arch/alpha/include/asm/elf.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/alpha/include/asm/elf.h 2009-06-12 23:57:31.000000000 -0400
@@ -91,6 +91,13 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N
#define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x1000000)
@@ -15,9 +28,9 @@ diff -urNp linux-2.6.28.8/arch/alpha/include/asm/elf.h linux-2.6.28.8/arch/alpha
/* $0 is set by ld.so to a pointer to a function which might be
registered using atexit. This provides a mean for the dynamic
linker to call DT_FINI functions for shared libraries that have
-diff -urNp linux-2.6.28.8/arch/alpha/include/asm/kmap_types.h linux-2.6.28.8/arch/alpha/include/asm/kmap_types.h
---- linux-2.6.28.8/arch/alpha/include/asm/kmap_types.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/alpha/include/asm/kmap_types.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/alpha/include/asm/kmap_types.h linux-2.6.29.5/arch/alpha/include/asm/kmap_types.h
+--- linux-2.6.29.5/arch/alpha/include/asm/kmap_types.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/alpha/include/asm/kmap_types.h 2009-06-12 23:57:31.000000000 -0400
@@ -24,7 +24,8 @@ D(9) KM_IRQ0,
D(10) KM_IRQ1,
D(11) KM_SOFTIRQ0,
@@ -28,9 +41,9 @@ diff -urNp linux-2.6.28.8/arch/alpha/include/asm/kmap_types.h linux-2.6.28.8/arc
};
#undef D
-diff -urNp linux-2.6.28.8/arch/alpha/include/asm/pgtable.h linux-2.6.28.8/arch/alpha/include/asm/pgtable.h
---- linux-2.6.28.8/arch/alpha/include/asm/pgtable.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/alpha/include/asm/pgtable.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/alpha/include/asm/pgtable.h linux-2.6.29.5/arch/alpha/include/asm/pgtable.h
+--- linux-2.6.29.5/arch/alpha/include/asm/pgtable.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/alpha/include/asm/pgtable.h 2009-06-12 23:57:31.000000000 -0400
@@ -101,6 +101,17 @@ struct vm_area_struct;
#define PAGE_SHARED __pgprot(_PAGE_VALID | __ACCESS_BITS)
#define PAGE_COPY __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW)
@@ -49,9 +62,9 @@ diff -urNp linux-2.6.28.8/arch/alpha/include/asm/pgtable.h linux-2.6.28.8/arch/a
#define PAGE_KERNEL __pgprot(_PAGE_VALID | _PAGE_ASM | _PAGE_KRE | _PAGE_KWE)
#define _PAGE_NORMAL(x) __pgprot(_PAGE_VALID | __ACCESS_BITS | (x))
-diff -urNp linux-2.6.28.8/arch/alpha/kernel/module.c linux-2.6.28.8/arch/alpha/kernel/module.c
---- linux-2.6.28.8/arch/alpha/kernel/module.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/alpha/kernel/module.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/alpha/kernel/module.c linux-2.6.29.5/arch/alpha/kernel/module.c
+--- linux-2.6.29.5/arch/alpha/kernel/module.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/alpha/kernel/module.c 2009-06-12 23:57:31.000000000 -0400
@@ -182,7 +182,7 @@ apply_relocate_add(Elf64_Shdr *sechdrs,
/* The small sections were sorted to the end of the segment.
@@ -61,10 +74,10 @@ diff -urNp linux-2.6.28.8/arch/alpha/kernel/module.c linux-2.6.28.8/arch/alpha/k
got = sechdrs[me->arch.gotsecindex].sh_addr;
for (i = 0; i < n; i++) {
-diff -urNp linux-2.6.28.8/arch/alpha/kernel/osf_sys.c linux-2.6.28.8/arch/alpha/kernel/osf_sys.c
---- linux-2.6.28.8/arch/alpha/kernel/osf_sys.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/alpha/kernel/osf_sys.c 2009-02-21 09:37:48.000000000 -0500
-@@ -1230,6 +1230,10 @@ arch_get_unmapped_area(struct file *filp
+diff -urNp linux-2.6.29.5/arch/alpha/kernel/osf_sys.c linux-2.6.29.5/arch/alpha/kernel/osf_sys.c
+--- linux-2.6.29.5/arch/alpha/kernel/osf_sys.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/alpha/kernel/osf_sys.c 2009-06-12 23:57:31.000000000 -0400
+@@ -1217,6 +1217,10 @@ arch_get_unmapped_area(struct file *filp
merely specific addresses, but regions of memory -- perhaps
this feature should be incorporated into all ports? */
@@ -75,7 +88,7 @@ diff -urNp linux-2.6.28.8/arch/alpha/kernel/osf_sys.c linux-2.6.28.8/arch/alpha/
if (addr) {
addr = arch_get_unmapped_area_1 (PAGE_ALIGN(addr), len, limit);
if (addr != (unsigned long) -ENOMEM)
-@@ -1237,8 +1241,8 @@ arch_get_unmapped_area(struct file *filp
+@@ -1224,8 +1228,8 @@ arch_get_unmapped_area(struct file *filp
}
/* Next, try allocating at TASK_UNMAPPED_BASE. */
@@ -86,22 +99,9 @@ diff -urNp linux-2.6.28.8/arch/alpha/kernel/osf_sys.c linux-2.6.28.8/arch/alpha/
if (addr != (unsigned long) -ENOMEM)
return addr;
-diff -urNp linux-2.6.28.8/arch/alpha/kernel/ptrace.c linux-2.6.28.8/arch/alpha/kernel/ptrace.c
---- linux-2.6.28.8/arch/alpha/kernel/ptrace.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/alpha/kernel/ptrace.c 2009-02-21 09:37:48.000000000 -0500
-@@ -266,6 +266,9 @@ long arch_ptrace(struct task_struct *chi
- size_t copied;
- long ret;
-
-+ if (gr_handle_ptrace(child, request))
-+ return -EPERM;
-+
- switch (request) {
- /* When I and D space are separate, these will need to be fixed. */
- case PTRACE_PEEKTEXT: /* read word at location addr. */
-diff -urNp linux-2.6.28.8/arch/alpha/mm/fault.c linux-2.6.28.8/arch/alpha/mm/fault.c
---- linux-2.6.28.8/arch/alpha/mm/fault.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/alpha/mm/fault.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/alpha/mm/fault.c linux-2.6.29.5/arch/alpha/mm/fault.c
+--- linux-2.6.29.5/arch/alpha/mm/fault.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/alpha/mm/fault.c 2009-06-12 23:57:31.000000000 -0400
@@ -54,6 +54,124 @@ __load_new_mm_context(struct mm_struct *
__reload_thread(pcb);
}
@@ -258,10 +258,23 @@ diff -urNp linux-2.6.28.8/arch/alpha/mm/fault.c linux-2.6.28.8/arch/alpha/mm/fau
} else if (!cause) {
/* Allow reads even for write-only mappings */
if (!(vma->vm_flags & (VM_READ | VM_WRITE)))
-diff -urNp linux-2.6.28.8/arch/arm/include/asm/elf.h linux-2.6.28.8/arch/arm/include/asm/elf.h
---- linux-2.6.28.8/arch/arm/include/asm/elf.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/arm/include/asm/elf.h 2009-02-21 09:37:48.000000000 -0500
-@@ -99,7 +99,14 @@ extern int arm_elf_read_implies_exec(con
+diff -urNp linux-2.6.29.5/arch/arm/include/asm/atomic.h linux-2.6.29.5/arch/arm/include/asm/atomic.h
+--- linux-2.6.29.5/arch/arm/include/asm/atomic.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/arm/include/asm/atomic.h 2009-06-12 23:57:31.000000000 -0400
+@@ -191,6 +191,9 @@ static inline int atomic_add_unless(atom
+ #define atomic_inc(v) (void) atomic_add_return(1, v)
+ #define atomic_sub(i, v) (void) atomic_sub_return(i, v)
+ #define atomic_dec(v) (void) atomic_sub_return(1, v)
++#define atomic_inc_unchecked(v) (void) atomic_inc(v)
++#define atomic_add_unchecked(i, v) (void) atomic_add(i, v)
++#define atomic_sub_unchecked(i, v) (void) atomic_sub(i, v)
+
+ #define atomic_inc_and_test(v) (atomic_add_return(1, v) == 0)
+ #define atomic_dec_and_test(v) (atomic_sub_return(1, v) == 0)
+diff -urNp linux-2.6.29.5/arch/arm/include/asm/elf.h linux-2.6.29.5/arch/arm/include/asm/elf.h
+--- linux-2.6.29.5/arch/arm/include/asm/elf.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/arm/include/asm/elf.h 2009-06-12 23:57:31.000000000 -0400
+@@ -100,7 +100,14 @@ extern int arm_elf_read_implies_exec(con
the loader. We need to make sure that it is out of the way of the program
that it will "exec", and that there is sufficient room for the brk. */
@@ -277,9 +290,9 @@ diff -urNp linux-2.6.28.8/arch/arm/include/asm/elf.h linux-2.6.28.8/arch/arm/inc
/* When the program starts, a1 contains a pointer to a function to be
registered with atexit, as per the SVR4 ABI. A value of 0 means we
-diff -urNp linux-2.6.28.8/arch/arm/include/asm/kmap_types.h linux-2.6.28.8/arch/arm/include/asm/kmap_types.h
---- linux-2.6.28.8/arch/arm/include/asm/kmap_types.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/arm/include/asm/kmap_types.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/arm/include/asm/kmap_types.h linux-2.6.29.5/arch/arm/include/asm/kmap_types.h
+--- linux-2.6.29.5/arch/arm/include/asm/kmap_types.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/arm/include/asm/kmap_types.h 2009-06-12 23:57:31.000000000 -0400
@@ -18,6 +18,7 @@ enum km_type {
KM_IRQ1,
KM_SOFTIRQ0,
@@ -288,9 +301,21 @@ diff -urNp linux-2.6.28.8/arch/arm/include/asm/kmap_types.h linux-2.6.28.8/arch/
KM_TYPE_NR
};
-diff -urNp linux-2.6.28.8/arch/arm/mm/mmap.c linux-2.6.28.8/arch/arm/mm/mmap.c
---- linux-2.6.28.8/arch/arm/mm/mmap.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/arm/mm/mmap.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/arm/include/asm/uaccess.h linux-2.6.29.5/arch/arm/include/asm/uaccess.h
+--- linux-2.6.29.5/arch/arm/include/asm/uaccess.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/arm/include/asm/uaccess.h 2009-06-13 00:30:48.000000000 -0400
+@@ -400,7 +400,7 @@ static inline unsigned long __must_check
+ {
+ if (access_ok(VERIFY_READ, from, n))
+ n = __copy_from_user(to, from, n);
+- else /* security hole - plug it */
++ else if ((long)n > 0) /* security hole - plug it -- good idea! */
+ memset(to, 0, n);
+ return n;
+ }
+diff -urNp linux-2.6.29.5/arch/arm/mm/mmap.c linux-2.6.29.5/arch/arm/mm/mmap.c
+--- linux-2.6.29.5/arch/arm/mm/mmap.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/arm/mm/mmap.c 2009-06-12 23:57:31.000000000 -0400
@@ -62,6 +62,10 @@ arch_get_unmapped_area(struct file *filp
if (len > TASK_SIZE)
return -ENOMEM;
@@ -327,9 +352,25 @@ diff -urNp linux-2.6.28.8/arch/arm/mm/mmap.c linux-2.6.28.8/arch/arm/mm/mmap.c
mm->cached_hole_size = 0;
goto full_search;
}
-diff -urNp linux-2.6.28.8/arch/avr32/include/asm/elf.h linux-2.6.28.8/arch/avr32/include/asm/elf.h
---- linux-2.6.28.8/arch/avr32/include/asm/elf.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/avr32/include/asm/elf.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/avr32/include/asm/atomic.h linux-2.6.29.5/arch/avr32/include/asm/atomic.h
+--- linux-2.6.29.5/arch/avr32/include/asm/atomic.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/avr32/include/asm/atomic.h 2009-06-12 23:57:31.000000000 -0400
+@@ -176,9 +176,12 @@ static inline int atomic_sub_if_positive
+ #define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n)))
+
+ #define atomic_sub(i, v) (void)atomic_sub_return(i, v)
++#define atomic_sub_unchecked(i, v) atomic_sub((i), (v))
+ #define atomic_add(i, v) (void)atomic_add_return(i, v)
++#define atomic_add_unchecked(i, v) atomic_add((i), (v))
+ #define atomic_dec(v) atomic_sub(1, (v))
+ #define atomic_inc(v) atomic_add(1, (v))
++#define atomic_inc_unchecked(v) atomic_inc(v)
+
+ #define atomic_dec_return(v) atomic_sub_return(1, v)
+ #define atomic_inc_return(v) atomic_add_return(1, v)
+diff -urNp linux-2.6.29.5/arch/avr32/include/asm/elf.h linux-2.6.29.5/arch/avr32/include/asm/elf.h
+--- linux-2.6.29.5/arch/avr32/include/asm/elf.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/avr32/include/asm/elf.h 2009-06-12 23:57:31.000000000 -0400
@@ -85,8 +85,14 @@ typedef struct user_fpu_struct elf_fpreg
the loader. We need to make sure that it is out of the way of the program
that it will "exec", and that there is sufficient room for the brk. */
@@ -346,9 +387,9 @@ diff -urNp linux-2.6.28.8/arch/avr32/include/asm/elf.h linux-2.6.28.8/arch/avr32
/* This yields a mask that user programs can use to figure out what
instruction set this CPU supports. This could be done in user space,
-diff -urNp linux-2.6.28.8/arch/avr32/include/asm/kmap_types.h linux-2.6.28.8/arch/avr32/include/asm/kmap_types.h
---- linux-2.6.28.8/arch/avr32/include/asm/kmap_types.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/avr32/include/asm/kmap_types.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/avr32/include/asm/kmap_types.h linux-2.6.29.5/arch/avr32/include/asm/kmap_types.h
+--- linux-2.6.29.5/arch/avr32/include/asm/kmap_types.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/avr32/include/asm/kmap_types.h 2009-06-12 23:57:31.000000000 -0400
@@ -22,7 +22,8 @@ D(10) KM_IRQ0,
D(11) KM_IRQ1,
D(12) KM_SOFTIRQ0,
@@ -359,9 +400,9 @@ diff -urNp linux-2.6.28.8/arch/avr32/include/asm/kmap_types.h linux-2.6.28.8/arc
};
#undef D
-diff -urNp linux-2.6.28.8/arch/avr32/mm/fault.c linux-2.6.28.8/arch/avr32/mm/fault.c
---- linux-2.6.28.8/arch/avr32/mm/fault.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/avr32/mm/fault.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/avr32/mm/fault.c linux-2.6.29.5/arch/avr32/mm/fault.c
+--- linux-2.6.29.5/arch/avr32/mm/fault.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/avr32/mm/fault.c 2009-06-12 23:57:31.000000000 -0400
@@ -41,6 +41,23 @@ static inline int notify_page_fault(stru
int exception_trace = 1;
@@ -403,9 +444,22 @@ diff -urNp linux-2.6.28.8/arch/avr32/mm/fault.c linux-2.6.28.8/arch/avr32/mm/fau
if (exception_trace && printk_ratelimit())
printk("%s%s[%d]: segfault at %08lx pc %08lx "
"sp %08lx ecr %lu\n",
-diff -urNp linux-2.6.28.8/arch/blackfin/include/asm/kmap_types.h linux-2.6.28.8/arch/blackfin/include/asm/kmap_types.h
---- linux-2.6.28.8/arch/blackfin/include/asm/kmap_types.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/blackfin/include/asm/kmap_types.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/blackfin/include/asm/atomic.h linux-2.6.29.5/arch/blackfin/include/asm/atomic.h
+--- linux-2.6.29.5/arch/blackfin/include/asm/atomic.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/blackfin/include/asm/atomic.h 2009-06-12 23:57:31.000000000 -0400
+@@ -178,6 +178,9 @@ static inline void atomic_set_mask(unsig
+
+ #endif /* !CONFIG_SMP */
+
++#define atomic_add_unchecked(i, v) atomic_add((i), (v))
++#define atomic_sub_unchecked(i, v) atomic_sub((i), (v))
++#define atomic_inc_unchecked(v) atomic_inc((v))
+ #define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0)
+ #define atomic_dec_return(v) atomic_sub_return(1,(v))
+ #define atomic_inc_return(v) atomic_add_return(1,(v))
+diff -urNp linux-2.6.29.5/arch/blackfin/include/asm/kmap_types.h linux-2.6.29.5/arch/blackfin/include/asm/kmap_types.h
+--- linux-2.6.29.5/arch/blackfin/include/asm/kmap_types.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/blackfin/include/asm/kmap_types.h 2009-06-12 23:57:31.000000000 -0400
@@ -15,6 +15,7 @@ enum km_type {
KM_IRQ1,
KM_SOFTIRQ0,
@@ -414,9 +468,23 @@ diff -urNp linux-2.6.28.8/arch/blackfin/include/asm/kmap_types.h linux-2.6.28.8/
KM_TYPE_NR
};
-diff -urNp linux-2.6.28.8/arch/cris/include/asm/kmap_types.h linux-2.6.28.8/arch/cris/include/asm/kmap_types.h
---- linux-2.6.28.8/arch/cris/include/asm/kmap_types.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/cris/include/asm/kmap_types.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/cris/include/asm/atomic.h linux-2.6.29.5/arch/cris/include/asm/atomic.h
+--- linux-2.6.29.5/arch/cris/include/asm/atomic.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/cris/include/asm/atomic.h 2009-06-12 23:57:31.000000000 -0400
+@@ -152,6 +152,10 @@ static inline int atomic_add_unless(atom
+ }
+ #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
+
++#define atomic_inc_unchecked(v) atomic_inc((v))
++#define atomic_add_unchecked(i,v) atomic_add((i),(v))
++#define atomic_sub_unchecked(i,v) atomic_sub((i),(v))
++
+ /* Atomic operations are already serializing */
+ #define smp_mb__before_atomic_dec() barrier()
+ #define smp_mb__after_atomic_dec() barrier()
+diff -urNp linux-2.6.29.5/arch/cris/include/asm/kmap_types.h linux-2.6.29.5/arch/cris/include/asm/kmap_types.h
+--- linux-2.6.29.5/arch/cris/include/asm/kmap_types.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/cris/include/asm/kmap_types.h 2009-06-12 23:57:31.000000000 -0400
@@ -19,6 +19,7 @@ enum km_type {
KM_IRQ1,
KM_SOFTIRQ0,
@@ -425,9 +493,36 @@ diff -urNp linux-2.6.28.8/arch/cris/include/asm/kmap_types.h linux-2.6.28.8/arch
KM_TYPE_NR
};
-diff -urNp linux-2.6.28.8/arch/h8300/include/asm/kmap_types.h linux-2.6.28.8/arch/h8300/include/asm/kmap_types.h
---- linux-2.6.28.8/arch/h8300/include/asm/kmap_types.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/h8300/include/asm/kmap_types.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/h8300/include/asm/atomic.h linux-2.6.29.5/arch/h8300/include/asm/atomic.h
+--- linux-2.6.29.5/arch/h8300/include/asm/atomic.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/h8300/include/asm/atomic.h 2009-06-12 23:57:31.000000000 -0400
+@@ -26,6 +26,7 @@ static __inline__ int atomic_add_return(
+ }
+
+ #define atomic_add(i, v) atomic_add_return(i, v)
++#define atomic_add_unchecked(i, v) atomic_add((i), (v))
+ #define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0)
+
+ static __inline__ int atomic_sub_return(int i, atomic_t *v)
+@@ -38,6 +39,7 @@ static __inline__ int atomic_sub_return(
+ }
+
+ #define atomic_sub(i, v) atomic_sub_return(i, v)
++#define atomic_subUnchecked(i, v) atomic_sub(i, v)
+ #define atomic_sub_and_test(i,v) (atomic_sub_return(i, v) == 0)
+
+ static __inline__ int atomic_inc_return(atomic_t *v)
+@@ -51,6 +53,7 @@ static __inline__ int atomic_inc_return(
+ }
+
+ #define atomic_inc(v) atomic_inc_return(v)
++#define atomic_inc_unchecked(v) atomic_inc(v)
+
+ /*
+ * atomic_inc_and_test - increment and test
+diff -urNp linux-2.6.29.5/arch/h8300/include/asm/kmap_types.h linux-2.6.29.5/arch/h8300/include/asm/kmap_types.h
+--- linux-2.6.29.5/arch/h8300/include/asm/kmap_types.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/h8300/include/asm/kmap_types.h 2009-06-12 23:57:31.000000000 -0400
@@ -15,6 +15,7 @@ enum km_type {
KM_IRQ1,
KM_SOFTIRQ0,
@@ -436,9 +531,9 @@ diff -urNp linux-2.6.28.8/arch/h8300/include/asm/kmap_types.h linux-2.6.28.8/arc
KM_TYPE_NR
};
-diff -urNp linux-2.6.28.8/arch/ia64/ia32/binfmt_elf32.c linux-2.6.28.8/arch/ia64/ia32/binfmt_elf32.c
---- linux-2.6.28.8/arch/ia64/ia32/binfmt_elf32.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/ia64/ia32/binfmt_elf32.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/ia64/ia32/binfmt_elf32.c linux-2.6.29.5/arch/ia64/ia32/binfmt_elf32.c
+--- linux-2.6.29.5/arch/ia64/ia32/binfmt_elf32.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/ia64/ia32/binfmt_elf32.c 2009-06-12 23:57:31.000000000 -0400
@@ -45,6 +45,13 @@ randomize_stack_top(unsigned long stack_
#define elf_read_implies_exec(ex, have_pt_gnu_stack) (!(have_pt_gnu_stack))
@@ -453,9 +548,9 @@ diff -urNp linux-2.6.28.8/arch/ia64/ia32/binfmt_elf32.c linux-2.6.28.8/arch/ia64
/* Ugly but avoids duplication */
#include "../../../fs/binfmt_elf.c"
-diff -urNp linux-2.6.28.8/arch/ia64/ia32/ia32priv.h linux-2.6.28.8/arch/ia64/ia32/ia32priv.h
---- linux-2.6.28.8/arch/ia64/ia32/ia32priv.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/ia64/ia32/ia32priv.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/ia64/ia32/ia32priv.h linux-2.6.29.5/arch/ia64/ia32/ia32priv.h
+--- linux-2.6.29.5/arch/ia64/ia32/ia32priv.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/ia64/ia32/ia32priv.h 2009-06-12 23:57:31.000000000 -0400
@@ -296,7 +296,14 @@ typedef struct compat_siginfo {
#define ELF_DATA ELFDATA2LSB
#define ELF_ARCH EM_386
@@ -472,9 +567,24 @@ diff -urNp linux-2.6.28.8/arch/ia64/ia32/ia32priv.h linux-2.6.28.8/arch/ia64/ia3
#define IA32_GATE_OFFSET IA32_PAGE_OFFSET
#define IA32_GATE_END IA32_PAGE_OFFSET + PAGE_SIZE
-diff -urNp linux-2.6.28.8/arch/ia64/include/asm/elf.h linux-2.6.28.8/arch/ia64/include/asm/elf.h
---- linux-2.6.28.8/arch/ia64/include/asm/elf.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/ia64/include/asm/elf.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/ia64/include/asm/atomic.h linux-2.6.29.5/arch/ia64/include/asm/atomic.h
+--- linux-2.6.29.5/arch/ia64/include/asm/atomic.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/ia64/include/asm/atomic.h 2009-06-12 23:57:31.000000000 -0400
+@@ -201,8 +201,11 @@ atomic64_add_negative (__s64 i, atomic64
+ #define atomic64_inc_and_test(v) (atomic64_add_return(1, (v)) == 0)
+
+ #define atomic_add(i,v) atomic_add_return((i), (v))
++#define atomic_add_unchecked(i,v) atomic_add((i), (v))
+ #define atomic_sub(i,v) atomic_sub_return((i), (v))
++#define atomic_sub_unchecked(i,v) atomic_sub((i), (v))
+ #define atomic_inc(v) atomic_add(1, (v))
++#define atomic_inc_unchecked(v) atomic_inc(v)
+ #define atomic_dec(v) atomic_sub(1, (v))
+
+ #define atomic64_add(i,v) atomic64_add_return((i), (v))
+diff -urNp linux-2.6.29.5/arch/ia64/include/asm/elf.h linux-2.6.29.5/arch/ia64/include/asm/elf.h
+--- linux-2.6.29.5/arch/ia64/include/asm/elf.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/ia64/include/asm/elf.h 2009-06-12 23:57:31.000000000 -0400
@@ -43,6 +43,13 @@
*/
#define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x800000000UL)
@@ -489,9 +599,9 @@ diff -urNp linux-2.6.28.8/arch/ia64/include/asm/elf.h linux-2.6.28.8/arch/ia64/i
#define PT_IA_64_UNWIND 0x70000001
/* IA-64 relocations: */
-diff -urNp linux-2.6.28.8/arch/ia64/include/asm/kmap_types.h linux-2.6.28.8/arch/ia64/include/asm/kmap_types.h
---- linux-2.6.28.8/arch/ia64/include/asm/kmap_types.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/ia64/include/asm/kmap_types.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/ia64/include/asm/kmap_types.h linux-2.6.29.5/arch/ia64/include/asm/kmap_types.h
+--- linux-2.6.29.5/arch/ia64/include/asm/kmap_types.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/ia64/include/asm/kmap_types.h 2009-06-12 23:57:31.000000000 -0400
@@ -22,7 +22,8 @@ D(9) KM_IRQ0,
D(10) KM_IRQ1,
D(11) KM_SOFTIRQ0,
@@ -502,9 +612,9 @@ diff -urNp linux-2.6.28.8/arch/ia64/include/asm/kmap_types.h linux-2.6.28.8/arch
};
#undef D
-diff -urNp linux-2.6.28.8/arch/ia64/include/asm/pgtable.h linux-2.6.28.8/arch/ia64/include/asm/pgtable.h
---- linux-2.6.28.8/arch/ia64/include/asm/pgtable.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/ia64/include/asm/pgtable.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/ia64/include/asm/pgtable.h linux-2.6.29.5/arch/ia64/include/asm/pgtable.h
+--- linux-2.6.29.5/arch/ia64/include/asm/pgtable.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/ia64/include/asm/pgtable.h 2009-06-12 23:57:31.000000000 -0400
@@ -143,6 +143,17 @@
#define PAGE_READONLY __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R)
#define PAGE_COPY __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R)
@@ -523,9 +633,30 @@ diff -urNp linux-2.6.28.8/arch/ia64/include/asm/pgtable.h linux-2.6.28.8/arch/ia
#define PAGE_GATE __pgprot(__ACCESS_BITS | _PAGE_PL_0 | _PAGE_AR_X_RX)
#define PAGE_KERNEL __pgprot(__DIRTY_BITS | _PAGE_PL_0 | _PAGE_AR_RWX)
#define PAGE_KERNELRX __pgprot(__ACCESS_BITS | _PAGE_PL_0 | _PAGE_AR_RX)
-diff -urNp linux-2.6.28.8/arch/ia64/kernel/module.c linux-2.6.28.8/arch/ia64/kernel/module.c
---- linux-2.6.28.8/arch/ia64/kernel/module.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/ia64/kernel/module.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/ia64/include/asm/uaccess.h linux-2.6.29.5/arch/ia64/include/asm/uaccess.h
+--- linux-2.6.29.5/arch/ia64/include/asm/uaccess.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/ia64/include/asm/uaccess.h 2009-06-13 00:25:18.000000000 -0400
+@@ -257,7 +257,7 @@ __copy_from_user (void *to, const void _
+ const void *__cu_from = (from); \
+ long __cu_len = (n); \
+ \
+- if (__access_ok(__cu_to, __cu_len, get_fs())) \
++ if (__cu_len > 0 && __cu_len <= INT_MAX && __access_ok(__cu_to, __cu_len, get_fs())) \
+ __cu_len = __copy_user(__cu_to, (__force void __user *) __cu_from, __cu_len); \
+ __cu_len; \
+ })
+@@ -269,7 +269,7 @@ __copy_from_user (void *to, const void _
+ long __cu_len = (n); \
+ \
+ __chk_user_ptr(__cu_from); \
+- if (__access_ok(__cu_from, __cu_len, get_fs())) \
++ if (__cu_len > 0 && __cu_len <= INT_MAX && __access_ok(__cu_from, __cu_len, get_fs())) \
+ __cu_len = __copy_user((__force void __user *) __cu_to, __cu_from, __cu_len); \
+ __cu_len; \
+ })
+diff -urNp linux-2.6.29.5/arch/ia64/kernel/module.c linux-2.6.29.5/arch/ia64/kernel/module.c
+--- linux-2.6.29.5/arch/ia64/kernel/module.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/ia64/kernel/module.c 2009-06-12 23:57:31.000000000 -0400
@@ -312,8 +312,7 @@ module_alloc (unsigned long size)
void
module_free (struct module *mod, void *module_region)
@@ -614,9 +745,9 @@ diff -urNp linux-2.6.28.8/arch/ia64/kernel/module.c linux-2.6.28.8/arch/ia64/ker
mod->arch.gp = gp;
DEBUGP("%s: placing gp at 0x%lx\n", __func__, gp);
}
-diff -urNp linux-2.6.28.8/arch/ia64/kernel/sys_ia64.c linux-2.6.28.8/arch/ia64/kernel/sys_ia64.c
---- linux-2.6.28.8/arch/ia64/kernel/sys_ia64.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/ia64/kernel/sys_ia64.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/ia64/kernel/sys_ia64.c linux-2.6.29.5/arch/ia64/kernel/sys_ia64.c
+--- linux-2.6.29.5/arch/ia64/kernel/sys_ia64.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/ia64/kernel/sys_ia64.c 2009-06-12 23:57:31.000000000 -0400
@@ -43,6 +43,13 @@ arch_get_unmapped_area (struct file *fil
if (REGION_NUMBER(addr) == RGN_HPAGE)
addr = 0;
@@ -643,9 +774,9 @@ diff -urNp linux-2.6.28.8/arch/ia64/kernel/sys_ia64.c linux-2.6.28.8/arch/ia64/k
goto full_search;
}
return -ENOMEM;
-diff -urNp linux-2.6.28.8/arch/ia64/mm/fault.c linux-2.6.28.8/arch/ia64/mm/fault.c
---- linux-2.6.28.8/arch/ia64/mm/fault.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/ia64/mm/fault.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/ia64/mm/fault.c linux-2.6.29.5/arch/ia64/mm/fault.c
+--- linux-2.6.29.5/arch/ia64/mm/fault.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/ia64/mm/fault.c 2009-06-12 23:57:31.000000000 -0400
@@ -72,6 +72,23 @@ mapped_kernel_page_is_present (unsigned
return pte_present(pte);
}
@@ -695,9 +826,9 @@ diff -urNp linux-2.6.28.8/arch/ia64/mm/fault.c linux-2.6.28.8/arch/ia64/mm/fault
survive:
/*
* If for any reason at all we couldn't handle the fault, make
-diff -urNp linux-2.6.28.8/arch/ia64/mm/init.c linux-2.6.28.8/arch/ia64/mm/init.c
---- linux-2.6.28.8/arch/ia64/mm/init.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/ia64/mm/init.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/ia64/mm/init.c linux-2.6.29.5/arch/ia64/mm/init.c
+--- linux-2.6.29.5/arch/ia64/mm/init.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/ia64/mm/init.c 2009-06-12 23:57:31.000000000 -0400
@@ -121,6 +121,19 @@ ia64_init_addr_space (void)
vma->vm_start = current->thread.rbs_bot & PAGE_MASK;
vma->vm_end = vma->vm_start + PAGE_SIZE;
@@ -718,9 +849,34 @@ diff -urNp linux-2.6.28.8/arch/ia64/mm/init.c linux-2.6.28.8/arch/ia64/mm/init.c
vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
down_write(&current->mm->mmap_sem);
if (insert_vm_struct(current->mm, vma)) {
-diff -urNp linux-2.6.28.8/arch/m68knommu/include/asm/kmap_types.h linux-2.6.28.8/arch/m68knommu/include/asm/kmap_types.h
---- linux-2.6.28.8/arch/m68knommu/include/asm/kmap_types.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/m68knommu/include/asm/kmap_types.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/m32r/lib/usercopy.c linux-2.6.29.5/arch/m32r/lib/usercopy.c
+--- linux-2.6.29.5/arch/m32r/lib/usercopy.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/m32r/lib/usercopy.c 2009-06-13 00:52:32.000000000 -0400
+@@ -26,7 +26,7 @@ __generic_copy_from_user(void *to, const
+ prefetchw(to);
+ if (access_ok(VERIFY_READ, from, n))
+ __copy_user_zeroing(to,from,n);
+- else
++ else if ((long)n > 0)
+ memset(to, 0, n);
+ return n;
+ }
+diff -urNp linux-2.6.29.5/arch/m68k/include/asm/atomic_no.h linux-2.6.29.5/arch/m68k/include/asm/atomic_no.h
+--- linux-2.6.29.5/arch/m68k/include/asm/atomic_no.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/m68k/include/asm/atomic_no.h 2009-06-12 23:57:31.000000000 -0400
+@@ -151,5 +151,9 @@ static __inline__ int atomic_add_unless(
+ #define atomic_dec_return(v) atomic_sub_return(1,(v))
+ #define atomic_inc_return(v) atomic_add_return(1,(v))
+
++#define atomic_inc_unchecked(v) atomic_inc((v))
++#define atomic_add_unchecked(i,v) atomic_add((i),(v))
++#define atomic_sub_unchecked(i,v) atomic_sub((i),(v))
++
+ #include <asm-generic/atomic.h>
+ #endif /* __ARCH_M68KNOMMU_ATOMIC __ */
+diff -urNp linux-2.6.29.5/arch/m68k/include/asm/kmap_types_mm.h linux-2.6.29.5/arch/m68k/include/asm/kmap_types_mm.h
+--- linux-2.6.29.5/arch/m68k/include/asm/kmap_types_mm.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/m68k/include/asm/kmap_types_mm.h 2009-06-12 23:57:31.000000000 -0400
@@ -15,6 +15,7 @@ enum km_type {
KM_IRQ1,
KM_SOFTIRQ0,
@@ -729,9 +885,33 @@ diff -urNp linux-2.6.28.8/arch/m68knommu/include/asm/kmap_types.h linux-2.6.28.8
KM_TYPE_NR
};
-diff -urNp linux-2.6.28.8/arch/mips/include/asm/elf.h linux-2.6.28.8/arch/mips/include/asm/elf.h
---- linux-2.6.28.8/arch/mips/include/asm/elf.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/mips/include/asm/elf.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/m68k/include/asm/kmap_types_no.h linux-2.6.29.5/arch/m68k/include/asm/kmap_types_no.h
+--- linux-2.6.29.5/arch/m68k/include/asm/kmap_types_no.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/m68k/include/asm/kmap_types_no.h 2009-06-12 23:57:31.000000000 -0400
+@@ -15,6 +15,7 @@ enum km_type {
+ KM_IRQ1,
+ KM_SOFTIRQ0,
+ KM_SOFTIRQ1,
++ KM_CLEARPAGE,
+ KM_TYPE_NR
+ };
+
+diff -urNp linux-2.6.29.5/arch/mips/include/asm/atomic.h linux-2.6.29.5/arch/mips/include/asm/atomic.h
+--- linux-2.6.29.5/arch/mips/include/asm/atomic.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/mips/include/asm/atomic.h 2009-06-12 23:57:31.000000000 -0400
+@@ -381,6 +381,9 @@ static __inline__ int atomic_add_unless(
+ * Atomically increments @v by 1.
+ */
+ #define atomic_inc(v) atomic_add(1, (v))
++#define atomic_inc_unchecked(v) atomic_inc(v)
++#define atomic_add_unchecked(i, v) atomic_add((i), (v))
++#define atomic_sub_unchecked(i, v) atomic_sub((i), (v))
+
+ /*
+ * atomic_dec - decrement and test
+diff -urNp linux-2.6.29.5/arch/mips/include/asm/elf.h linux-2.6.29.5/arch/mips/include/asm/elf.h
+--- linux-2.6.29.5/arch/mips/include/asm/elf.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/mips/include/asm/elf.h 2009-06-12 23:57:31.000000000 -0400
@@ -364,4 +364,11 @@ extern int dump_task_fpu(struct task_str
#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2)
#endif
@@ -744,9 +924,9 @@ diff -urNp linux-2.6.28.8/arch/mips/include/asm/elf.h linux-2.6.28.8/arch/mips/i
+#endif
+
#endif /* _ASM_ELF_H */
-diff -urNp linux-2.6.28.8/arch/mips/include/asm/kmap_types.h linux-2.6.28.8/arch/mips/include/asm/kmap_types.h
---- linux-2.6.28.8/arch/mips/include/asm/kmap_types.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/mips/include/asm/kmap_types.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/mips/include/asm/kmap_types.h linux-2.6.29.5/arch/mips/include/asm/kmap_types.h
+--- linux-2.6.29.5/arch/mips/include/asm/kmap_types.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/mips/include/asm/kmap_types.h 2009-06-12 23:57:31.000000000 -0400
@@ -22,7 +22,8 @@ D(9) KM_IRQ0,
D(10) KM_IRQ1,
D(11) KM_SOFTIRQ0,
@@ -757,9 +937,9 @@ diff -urNp linux-2.6.28.8/arch/mips/include/asm/kmap_types.h linux-2.6.28.8/arch
};
#undef D
-diff -urNp linux-2.6.28.8/arch/mips/include/asm/page.h linux-2.6.28.8/arch/mips/include/asm/page.h
---- linux-2.6.28.8/arch/mips/include/asm/page.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/mips/include/asm/page.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/mips/include/asm/page.h linux-2.6.29.5/arch/mips/include/asm/page.h
+--- linux-2.6.29.5/arch/mips/include/asm/page.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/mips/include/asm/page.h 2009-06-12 23:57:31.000000000 -0400
@@ -82,7 +82,7 @@ extern void copy_user_highpage(struct pa
#ifdef CONFIG_CPU_MIPS32
typedef struct { unsigned long pte_low, pte_high; } pte_t;
@@ -769,9 +949,9 @@ diff -urNp linux-2.6.28.8/arch/mips/include/asm/page.h linux-2.6.28.8/arch/mips/
#else
typedef struct { unsigned long long pte; } pte_t;
#define pte_val(x) ((x).pte)
-diff -urNp linux-2.6.28.8/arch/mips/include/asm/system.h linux-2.6.28.8/arch/mips/include/asm/system.h
---- linux-2.6.28.8/arch/mips/include/asm/system.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/mips/include/asm/system.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/mips/include/asm/system.h linux-2.6.29.5/arch/mips/include/asm/system.h
+--- linux-2.6.29.5/arch/mips/include/asm/system.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/mips/include/asm/system.h 2009-06-12 23:57:31.000000000 -0400
@@ -217,6 +217,6 @@ extern void per_cpu_trap_init(void);
*/
#define __ARCH_WANT_UNLOCKED_CTXSW
@@ -780,9 +960,9 @@ diff -urNp linux-2.6.28.8/arch/mips/include/asm/system.h linux-2.6.28.8/arch/mip
+#define arch_align_stack(x) ((x) & ALMASK)
#endif /* _ASM_SYSTEM_H */
-diff -urNp linux-2.6.28.8/arch/mips/kernel/binfmt_elfn32.c linux-2.6.28.8/arch/mips/kernel/binfmt_elfn32.c
---- linux-2.6.28.8/arch/mips/kernel/binfmt_elfn32.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/mips/kernel/binfmt_elfn32.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/mips/kernel/binfmt_elfn32.c linux-2.6.29.5/arch/mips/kernel/binfmt_elfn32.c
+--- linux-2.6.29.5/arch/mips/kernel/binfmt_elfn32.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/mips/kernel/binfmt_elfn32.c 2009-06-12 23:57:31.000000000 -0400
@@ -50,6 +50,13 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N
#undef ELF_ET_DYN_BASE
#define ELF_ET_DYN_BASE (TASK32_SIZE / 3 * 2)
@@ -797,9 +977,9 @@ diff -urNp linux-2.6.28.8/arch/mips/kernel/binfmt_elfn32.c linux-2.6.28.8/arch/m
#include <asm/processor.h>
#include <linux/module.h>
#include <linux/elfcore.h>
-diff -urNp linux-2.6.28.8/arch/mips/kernel/binfmt_elfo32.c linux-2.6.28.8/arch/mips/kernel/binfmt_elfo32.c
---- linux-2.6.28.8/arch/mips/kernel/binfmt_elfo32.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/mips/kernel/binfmt_elfo32.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/mips/kernel/binfmt_elfo32.c linux-2.6.29.5/arch/mips/kernel/binfmt_elfo32.c
+--- linux-2.6.29.5/arch/mips/kernel/binfmt_elfo32.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/mips/kernel/binfmt_elfo32.c 2009-06-12 23:57:31.000000000 -0400
@@ -52,6 +52,13 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N
#undef ELF_ET_DYN_BASE
#define ELF_ET_DYN_BASE (TASK32_SIZE / 3 * 2)
@@ -814,9 +994,9 @@ diff -urNp linux-2.6.28.8/arch/mips/kernel/binfmt_elfo32.c linux-2.6.28.8/arch/m
#include <asm/processor.h>
#include <linux/module.h>
#include <linux/elfcore.h>
-diff -urNp linux-2.6.28.8/arch/mips/kernel/process.c linux-2.6.28.8/arch/mips/kernel/process.c
---- linux-2.6.28.8/arch/mips/kernel/process.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/mips/kernel/process.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/mips/kernel/process.c linux-2.6.29.5/arch/mips/kernel/process.c
+--- linux-2.6.29.5/arch/mips/kernel/process.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/mips/kernel/process.c 2009-06-12 23:57:31.000000000 -0400
@@ -457,15 +457,3 @@ unsigned long get_wchan(struct task_stru
out:
return pc;
@@ -833,9 +1013,9 @@ diff -urNp linux-2.6.28.8/arch/mips/kernel/process.c linux-2.6.28.8/arch/mips/ke
-
- return sp & ALMASK;
-}
-diff -urNp linux-2.6.28.8/arch/mips/kernel/syscall.c linux-2.6.28.8/arch/mips/kernel/syscall.c
---- linux-2.6.28.8/arch/mips/kernel/syscall.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/mips/kernel/syscall.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/mips/kernel/syscall.c linux-2.6.29.5/arch/mips/kernel/syscall.c
+--- linux-2.6.29.5/arch/mips/kernel/syscall.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/mips/kernel/syscall.c 2009-06-12 23:57:31.000000000 -0400
@@ -99,6 +99,11 @@ unsigned long arch_get_unmapped_area(str
do_color_align = 0;
if (filp || (flags & MAP_SHARED))
@@ -857,9 +1037,9 @@ diff -urNp linux-2.6.28.8/arch/mips/kernel/syscall.c linux-2.6.28.8/arch/mips/ke
if (do_color_align)
addr = COLOUR_ALIGN(addr, pgoff);
else
-diff -urNp linux-2.6.28.8/arch/mips/mm/fault.c linux-2.6.28.8/arch/mips/mm/fault.c
---- linux-2.6.28.8/arch/mips/mm/fault.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/mips/mm/fault.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/mips/mm/fault.c linux-2.6.29.5/arch/mips/mm/fault.c
+--- linux-2.6.29.5/arch/mips/mm/fault.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/mips/mm/fault.c 2009-06-12 23:57:31.000000000 -0400
@@ -26,6 +26,23 @@
#include <asm/ptrace.h>
#include <asm/highmem.h> /* For VMALLOC_END */
@@ -884,9 +1064,24 @@ diff -urNp linux-2.6.28.8/arch/mips/mm/fault.c linux-2.6.28.8/arch/mips/mm/fault
/*
* This routine handles page faults. It determines the address,
* and the problem, and then passes it off to one of the appropriate
-diff -urNp linux-2.6.28.8/arch/parisc/include/asm/elf.h linux-2.6.28.8/arch/parisc/include/asm/elf.h
---- linux-2.6.28.8/arch/parisc/include/asm/elf.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/parisc/include/asm/elf.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/parisc/include/asm/atomic.h linux-2.6.29.5/arch/parisc/include/asm/atomic.h
+--- linux-2.6.29.5/arch/parisc/include/asm/atomic.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/parisc/include/asm/atomic.h 2009-06-12 23:57:32.000000000 -0400
+@@ -223,8 +223,11 @@ static __inline__ int atomic_add_unless(
+ #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
+
+ #define atomic_add(i,v) ((void)(__atomic_add_return( ((int)i),(v))))
++#define atomic_add_unchecked(i,v) atomic_add((i), (v))
+ #define atomic_sub(i,v) ((void)(__atomic_add_return(-((int)i),(v))))
++#define atomic_sub_unchecked(i,v) atomic_sub((i), (v))
+ #define atomic_inc(v) ((void)(__atomic_add_return( 1,(v))))
++#define atomic_inc_unchecked(v) atomic_inc(v)
+ #define atomic_dec(v) ((void)(__atomic_add_return( -1,(v))))
+
+ #define atomic_add_return(i,v) (__atomic_add_return( ((int)i),(v)))
+diff -urNp linux-2.6.29.5/arch/parisc/include/asm/elf.h linux-2.6.29.5/arch/parisc/include/asm/elf.h
+--- linux-2.6.29.5/arch/parisc/include/asm/elf.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/parisc/include/asm/elf.h 2009-06-12 23:57:32.000000000 -0400
@@ -333,6 +333,13 @@ struct pt_regs; /* forward declaration..
#define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x01000000)
@@ -901,9 +1096,9 @@ diff -urNp linux-2.6.28.8/arch/parisc/include/asm/elf.h linux-2.6.28.8/arch/pari
/* This yields a mask that user programs can use to figure out what
instruction set this CPU supports. This could be done in user space,
but it's not easy, and we've already done it here. */
-diff -urNp linux-2.6.28.8/arch/parisc/include/asm/kmap_types.h linux-2.6.28.8/arch/parisc/include/asm/kmap_types.h
---- linux-2.6.28.8/arch/parisc/include/asm/kmap_types.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/parisc/include/asm/kmap_types.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/parisc/include/asm/kmap_types.h linux-2.6.29.5/arch/parisc/include/asm/kmap_types.h
+--- linux-2.6.29.5/arch/parisc/include/asm/kmap_types.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/parisc/include/asm/kmap_types.h 2009-06-12 23:57:32.000000000 -0400
@@ -22,7 +22,8 @@ D(9) KM_IRQ0,
D(10) KM_IRQ1,
D(11) KM_SOFTIRQ0,
@@ -914,9 +1109,9 @@ diff -urNp linux-2.6.28.8/arch/parisc/include/asm/kmap_types.h linux-2.6.28.8/ar
};
#undef D
-diff -urNp linux-2.6.28.8/arch/parisc/include/asm/pgtable.h linux-2.6.28.8/arch/parisc/include/asm/pgtable.h
---- linux-2.6.28.8/arch/parisc/include/asm/pgtable.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/parisc/include/asm/pgtable.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/parisc/include/asm/pgtable.h linux-2.6.29.5/arch/parisc/include/asm/pgtable.h
+--- linux-2.6.29.5/arch/parisc/include/asm/pgtable.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/parisc/include/asm/pgtable.h 2009-06-12 23:57:32.000000000 -0400
@@ -202,6 +202,17 @@
#define PAGE_EXECREAD __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_EXEC |_PAGE_ACCESSED)
#define PAGE_COPY PAGE_EXECREAD
@@ -935,10 +1130,10 @@ diff -urNp linux-2.6.28.8/arch/parisc/include/asm/pgtable.h linux-2.6.28.8/arch/
#define PAGE_KERNEL __pgprot(_PAGE_KERNEL)
#define PAGE_KERNEL_RO __pgprot(_PAGE_KERNEL & ~_PAGE_WRITE)
#define PAGE_KERNEL_UNC __pgprot(_PAGE_KERNEL | _PAGE_NO_CACHE)
-diff -urNp linux-2.6.28.8/arch/parisc/kernel/module.c linux-2.6.28.8/arch/parisc/kernel/module.c
---- linux-2.6.28.8/arch/parisc/kernel/module.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/parisc/kernel/module.c 2009-02-21 09:37:48.000000000 -0500
-@@ -75,16 +75,38 @@
+diff -urNp linux-2.6.29.5/arch/parisc/kernel/module.c linux-2.6.29.5/arch/parisc/kernel/module.c
+--- linux-2.6.29.5/arch/parisc/kernel/module.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/parisc/kernel/module.c 2009-06-12 23:57:32.000000000 -0400
+@@ -93,16 +93,38 @@
/* three functions to determine where in the module core
* or init pieces the location is */
@@ -981,7 +1176,7 @@ diff -urNp linux-2.6.28.8/arch/parisc/kernel/module.c linux-2.6.28.8/arch/parisc
}
static inline int in_local(struct module *me, void *loc)
-@@ -298,21 +320,21 @@ int module_frob_arch_sections(CONST Elf_
+@@ -340,13 +362,13 @@ int module_frob_arch_sections(CONST Elf_
}
/* align things a bit */
@@ -992,14 +1187,6 @@ diff -urNp linux-2.6.28.8/arch/parisc/kernel/module.c linux-2.6.28.8/arch/parisc
- me->core_size = ALIGN(me->core_size, 16);
- me->arch.fdesc_offset = me->core_size;
- me->core_size += fdescs * sizeof(Elf_Fdesc);
--
-- me->core_size = ALIGN(me->core_size, 16);
-- me->arch.stub_offset = me->core_size;
-- me->core_size += stubs * sizeof(struct stub_entry);
--
-- me->init_size = ALIGN(me->init_size, 16);
-- me->arch.init_stub_offset = me->init_size;
-- me->init_size += init_stubs * sizeof(struct stub_entry);
+ me->core_size_rw = ALIGN(me->core_size_rw, 16);
+ me->arch.got_offset = me->core_size_rw;
+ me->core_size_rw += gots * sizeof(struct got_entry);
@@ -1007,18 +1194,10 @@ diff -urNp linux-2.6.28.8/arch/parisc/kernel/module.c linux-2.6.28.8/arch/parisc
+ me->core_size_rw = ALIGN(me->core_size_rw, 16);
+ me->arch.fdesc_offset = me->core_size_rw;
+ me->core_size_rw += fdescs * sizeof(Elf_Fdesc);
-+
-+ me->core_size_rx = ALIGN(me->core_size_rx, 16);
-+ me->arch.stub_offset = me->core_size_rx;
-+ me->core_size_rx += stubs * sizeof(struct stub_entry);
-+
-+ me->init_size_rx = ALIGN(me->init_size_rx, 16);
-+ me->arch.init_stub_offset = me->init_size_rx;
-+ me->init_size_rx += init_stubs * sizeof(struct stub_entry);
me->arch.got_max = gots;
me->arch.fdesc_max = fdescs;
-@@ -332,7 +354,7 @@ static Elf64_Word get_got(struct module
+@@ -364,7 +386,7 @@ static Elf64_Word get_got(struct module
BUG_ON(value == 0);
@@ -1027,7 +1206,7 @@ diff -urNp linux-2.6.28.8/arch/parisc/kernel/module.c linux-2.6.28.8/arch/parisc
for (i = 0; got[i].addr; i++)
if (got[i].addr == value)
goto out;
-@@ -350,7 +372,7 @@ static Elf64_Word get_got(struct module
+@@ -382,7 +404,7 @@ static Elf64_Word get_got(struct module
#ifdef CONFIG_64BIT
static Elf_Addr get_fdesc(struct module *me, unsigned long value)
{
@@ -1036,7 +1215,7 @@ diff -urNp linux-2.6.28.8/arch/parisc/kernel/module.c linux-2.6.28.8/arch/parisc
if (!value) {
printk(KERN_ERR "%s: zero OPD requested!\n", me->name);
-@@ -368,7 +390,7 @@ static Elf_Addr get_fdesc(struct module
+@@ -400,7 +422,7 @@ static Elf_Addr get_fdesc(struct module
/* Create new one */
fdesc->addr = value;
@@ -1045,22 +1224,7 @@ diff -urNp linux-2.6.28.8/arch/parisc/kernel/module.c linux-2.6.28.8/arch/parisc
return (Elf_Addr)fdesc;
}
#endif /* CONFIG_64BIT */
-@@ -388,12 +410,12 @@ static Elf_Addr get_stub(struct module *
- if(init_section) {
- i = me->arch.init_stub_count++;
- BUG_ON(me->arch.init_stub_count > me->arch.init_stub_max);
-- stub = me->module_init + me->arch.init_stub_offset +
-+ stub = me->module_init_rx + me->arch.init_stub_offset +
- i * sizeof(struct stub_entry);
- } else {
- i = me->arch.stub_count++;
- BUG_ON(me->arch.stub_count > me->arch.stub_max);
-- stub = me->module_core + me->arch.stub_offset +
-+ stub = me->module_core_rx + me->arch.stub_offset +
- i * sizeof(struct stub_entry);
- }
-
-@@ -761,7 +783,7 @@ register_unwind_table(struct module *me,
+@@ -816,7 +838,7 @@ register_unwind_table(struct module *me,
table = (unsigned char *)sechdrs[me->arch.unwind_section].sh_addr;
end = table + sechdrs[me->arch.unwind_section].sh_size;
@@ -1069,9 +1233,9 @@ diff -urNp linux-2.6.28.8/arch/parisc/kernel/module.c linux-2.6.28.8/arch/parisc
DEBUGP("register_unwind_table(), sect = %d at 0x%p - 0x%p (gp=0x%lx)\n",
me->arch.unwind_section, table, end, gp);
-diff -urNp linux-2.6.28.8/arch/parisc/kernel/sys_parisc.c linux-2.6.28.8/arch/parisc/kernel/sys_parisc.c
---- linux-2.6.28.8/arch/parisc/kernel/sys_parisc.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/parisc/kernel/sys_parisc.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/parisc/kernel/sys_parisc.c linux-2.6.29.5/arch/parisc/kernel/sys_parisc.c
+--- linux-2.6.29.5/arch/parisc/kernel/sys_parisc.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/parisc/kernel/sys_parisc.c 2009-06-12 23:57:32.000000000 -0400
@@ -98,7 +98,7 @@ unsigned long arch_get_unmapped_area(str
if (flags & MAP_FIXED)
return addr;
@@ -1081,9 +1245,9 @@ diff -urNp linux-2.6.28.8/arch/parisc/kernel/sys_parisc.c linux-2.6.28.8/arch/pa
if (filp) {
addr = get_shared_area(filp->f_mapping, addr, len, pgoff);
-diff -urNp linux-2.6.28.8/arch/parisc/kernel/traps.c linux-2.6.28.8/arch/parisc/kernel/traps.c
---- linux-2.6.28.8/arch/parisc/kernel/traps.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/parisc/kernel/traps.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/parisc/kernel/traps.c linux-2.6.29.5/arch/parisc/kernel/traps.c
+--- linux-2.6.29.5/arch/parisc/kernel/traps.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/parisc/kernel/traps.c 2009-06-12 23:57:32.000000000 -0400
@@ -731,9 +731,7 @@ void handle_interruption(int code, struc
down_read(&current->mm->mmap_sem);
@@ -1095,9 +1259,9 @@ diff -urNp linux-2.6.28.8/arch/parisc/kernel/traps.c linux-2.6.28.8/arch/parisc/
fault_address = regs->iaoq[0];
fault_space = regs->iasq[0];
-diff -urNp linux-2.6.28.8/arch/parisc/mm/fault.c linux-2.6.28.8/arch/parisc/mm/fault.c
---- linux-2.6.28.8/arch/parisc/mm/fault.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/parisc/mm/fault.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/parisc/mm/fault.c linux-2.6.29.5/arch/parisc/mm/fault.c
+--- linux-2.6.29.5/arch/parisc/mm/fault.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/parisc/mm/fault.c 2009-06-12 23:57:32.000000000 -0400
@@ -16,6 +16,7 @@
#include <linux/sched.h>
#include <linux/interrupt.h>
@@ -1229,10 +1393,10 @@ diff -urNp linux-2.6.28.8/arch/parisc/mm/fault.c linux-2.6.28.8/arch/parisc/mm/f
+}
+#endif
+
- void do_page_fault(struct pt_regs *regs, unsigned long code,
- unsigned long address)
+ int fixup_exception(struct pt_regs *regs)
{
-@@ -165,8 +276,33 @@ good_area:
+ const struct exception_table_entry *fix;
+@@ -193,8 +304,33 @@ good_area:
acc_type = parisc_acctyp(code,regs->iir);
@@ -1267,9 +1431,23 @@ diff -urNp linux-2.6.28.8/arch/parisc/mm/fault.c linux-2.6.28.8/arch/parisc/mm/f
/*
* If for any reason at all we couldn't handle the fault, make
-diff -urNp linux-2.6.28.8/arch/powerpc/include/asm/elf.h linux-2.6.28.8/arch/powerpc/include/asm/elf.h
---- linux-2.6.28.8/arch/powerpc/include/asm/elf.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/powerpc/include/asm/elf.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/powerpc/include/asm/atomic.h linux-2.6.29.5/arch/powerpc/include/asm/atomic.h
+--- linux-2.6.29.5/arch/powerpc/include/asm/atomic.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/powerpc/include/asm/atomic.h 2009-06-12 23:57:32.000000000 -0400
+@@ -244,6 +244,10 @@ static __inline__ int atomic_dec_if_posi
+ return t;
+ }
+
++#define atomic_inc_unchecked(v) atomic_inc((v))
++#define atomic_add_unchecked(i,v) atomic_add((i),(v))
++#define atomic_sub_unchecked(i,v) atomic_sub((i),(v))
++
+ #define smp_mb__before_atomic_dec() smp_mb()
+ #define smp_mb__after_atomic_dec() smp_mb()
+ #define smp_mb__before_atomic_inc() smp_mb()
+diff -urNp linux-2.6.29.5/arch/powerpc/include/asm/elf.h linux-2.6.29.5/arch/powerpc/include/asm/elf.h
+--- linux-2.6.29.5/arch/powerpc/include/asm/elf.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/powerpc/include/asm/elf.h 2009-06-12 23:57:32.000000000 -0400
@@ -180,6 +180,18 @@ typedef elf_fpreg_t elf_vsrreghalf_t32[E
#define ELF_ET_DYN_BASE (0x20000000)
@@ -1289,9 +1467,9 @@ diff -urNp linux-2.6.28.8/arch/powerpc/include/asm/elf.h linux-2.6.28.8/arch/pow
/*
* Our registers are always unsigned longs, whether we're a 32 bit
* process or 64 bit, on either a 64 bit or 32 bit kernel.
-diff -urNp linux-2.6.28.8/arch/powerpc/include/asm/kmap_types.h linux-2.6.28.8/arch/powerpc/include/asm/kmap_types.h
---- linux-2.6.28.8/arch/powerpc/include/asm/kmap_types.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/powerpc/include/asm/kmap_types.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/powerpc/include/asm/kmap_types.h linux-2.6.29.5/arch/powerpc/include/asm/kmap_types.h
+--- linux-2.6.29.5/arch/powerpc/include/asm/kmap_types.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/powerpc/include/asm/kmap_types.h 2009-06-12 23:57:32.000000000 -0400
@@ -26,6 +26,7 @@ enum km_type {
KM_SOFTIRQ1,
KM_PPC_SYNC_PAGE,
@@ -1300,9 +1478,9 @@ diff -urNp linux-2.6.28.8/arch/powerpc/include/asm/kmap_types.h linux-2.6.28.8/a
KM_TYPE_NR
};
-diff -urNp linux-2.6.28.8/arch/powerpc/include/asm/page_64.h linux-2.6.28.8/arch/powerpc/include/asm/page_64.h
---- linux-2.6.28.8/arch/powerpc/include/asm/page_64.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/powerpc/include/asm/page_64.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/powerpc/include/asm/page_64.h linux-2.6.29.5/arch/powerpc/include/asm/page_64.h
+--- linux-2.6.29.5/arch/powerpc/include/asm/page_64.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/powerpc/include/asm/page_64.h 2009-06-12 23:57:32.000000000 -0400
@@ -170,15 +170,18 @@ do { \
* stack by default, so in the absense of a PT_GNU_STACK program header
* we turn execute permission off.
@@ -1324,10 +1502,10 @@ diff -urNp linux-2.6.28.8/arch/powerpc/include/asm/page_64.h linux-2.6.28.8/arch
#include <asm-generic/page.h>
-diff -urNp linux-2.6.28.8/arch/powerpc/include/asm/page.h linux-2.6.28.8/arch/powerpc/include/asm/page.h
---- linux-2.6.28.8/arch/powerpc/include/asm/page.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/powerpc/include/asm/page.h 2009-02-21 09:37:48.000000000 -0500
-@@ -111,8 +111,9 @@ extern phys_addr_t kernstart_addr;
+diff -urNp linux-2.6.29.5/arch/powerpc/include/asm/page.h linux-2.6.29.5/arch/powerpc/include/asm/page.h
+--- linux-2.6.29.5/arch/powerpc/include/asm/page.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/powerpc/include/asm/page.h 2009-06-12 23:57:32.000000000 -0400
+@@ -114,8 +114,9 @@ extern phys_addr_t kernstart_addr;
* and needs to be executable. This means the whole heap ends
* up being executable.
*/
@@ -1339,10 +1517,33 @@ diff -urNp linux-2.6.28.8/arch/powerpc/include/asm/page.h linux-2.6.28.8/arch/po
#define VM_DATA_DEFAULT_FLAGS64 (VM_READ | VM_WRITE | \
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
-diff -urNp linux-2.6.28.8/arch/powerpc/kernel/module_32.c linux-2.6.28.8/arch/powerpc/kernel/module_32.c
---- linux-2.6.28.8/arch/powerpc/kernel/module_32.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/powerpc/kernel/module_32.c 2009-02-21 09:37:48.000000000 -0500
-@@ -158,7 +158,7 @@ int module_frob_arch_sections(Elf32_Ehdr
+diff -urNp linux-2.6.29.5/arch/powerpc/include/asm/uaccess.h linux-2.6.29.5/arch/powerpc/include/asm/uaccess.h
+--- linux-2.6.29.5/arch/powerpc/include/asm/uaccess.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/powerpc/include/asm/uaccess.h 2009-06-13 00:48:06.000000000 -0400
+@@ -334,6 +334,9 @@ static inline unsigned long copy_from_us
+ {
+ unsigned long over;
+
++ if (((long)n < 0) || (n > INT_MAX))
++ return n;
++
+ if (access_ok(VERIFY_READ, from, n))
+ return __copy_tofrom_user((__force void __user *)to, from, n);
+ if ((unsigned long)from < TASK_SIZE) {
+@@ -349,6 +352,9 @@ static inline unsigned long copy_to_user
+ {
+ unsigned long over;
+
++ if (((long)n < 0) || (n > INT_MAX))
++ return n;
++
+ if (access_ok(VERIFY_WRITE, to, n))
+ return __copy_tofrom_user(to, (__force void __user *)from, n);
+ if ((unsigned long)to < TASK_SIZE) {
+diff -urNp linux-2.6.29.5/arch/powerpc/kernel/module_32.c linux-2.6.29.5/arch/powerpc/kernel/module_32.c
+--- linux-2.6.29.5/arch/powerpc/kernel/module_32.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/powerpc/kernel/module_32.c 2009-06-12 23:57:32.000000000 -0400
+@@ -162,7 +162,7 @@ int module_frob_arch_sections(Elf32_Ehdr
me->arch.core_plt_section = i;
}
if (!me->arch.core_plt_section || !me->arch.init_plt_section) {
@@ -1351,7 +1552,7 @@ diff -urNp linux-2.6.28.8/arch/powerpc/kernel/module_32.c linux-2.6.28.8/arch/po
return -ENOEXEC;
}
-@@ -199,11 +199,16 @@ static uint32_t do_plt_call(void *locati
+@@ -203,11 +203,16 @@ static uint32_t do_plt_call(void *locati
DEBUGP("Doing plt for call to 0x%x at 0x%x\n", val, (unsigned int)location);
/* Init, or core PLT? */
@@ -1371,9 +1572,9 @@ diff -urNp linux-2.6.28.8/arch/powerpc/kernel/module_32.c linux-2.6.28.8/arch/po
/* Find this entry, or if that fails, the next avail. entry */
while (entry->jump[0]) {
-diff -urNp linux-2.6.28.8/arch/powerpc/kernel/signal_32.c linux-2.6.28.8/arch/powerpc/kernel/signal_32.c
---- linux-2.6.28.8/arch/powerpc/kernel/signal_32.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/powerpc/kernel/signal_32.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/powerpc/kernel/signal_32.c linux-2.6.29.5/arch/powerpc/kernel/signal_32.c
+--- linux-2.6.29.5/arch/powerpc/kernel/signal_32.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/powerpc/kernel/signal_32.c 2009-06-12 23:57:32.000000000 -0400
@@ -857,7 +857,7 @@ int handle_rt_signal32(unsigned long sig
/* Save user registers on the stack */
frame = &rt_sf->uc.uc_mcontext;
@@ -1383,9 +1584,9 @@ diff -urNp linux-2.6.28.8/arch/powerpc/kernel/signal_32.c linux-2.6.28.8/arch/po
if (save_user_regs(regs, frame, 0, 1))
goto badframe;
regs->link = current->mm->context.vdso_base + vdso32_rt_sigtramp;
-diff -urNp linux-2.6.28.8/arch/powerpc/kernel/signal_64.c linux-2.6.28.8/arch/powerpc/kernel/signal_64.c
---- linux-2.6.28.8/arch/powerpc/kernel/signal_64.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/powerpc/kernel/signal_64.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/powerpc/kernel/signal_64.c linux-2.6.29.5/arch/powerpc/kernel/signal_64.c
+--- linux-2.6.29.5/arch/powerpc/kernel/signal_64.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/powerpc/kernel/signal_64.c 2009-06-12 23:57:32.000000000 -0400
@@ -429,7 +429,7 @@ int handle_rt_signal64(int signr, struct
current->thread.fpscr.val = 0;
@@ -1395,10 +1596,10 @@ diff -urNp linux-2.6.28.8/arch/powerpc/kernel/signal_64.c linux-2.6.28.8/arch/po
regs->link = current->mm->context.vdso_base + vdso64_rt_sigtramp;
} else {
err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]);
-diff -urNp linux-2.6.28.8/arch/powerpc/kernel/vdso.c linux-2.6.28.8/arch/powerpc/kernel/vdso.c
---- linux-2.6.28.8/arch/powerpc/kernel/vdso.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/powerpc/kernel/vdso.c 2009-02-21 09:37:48.000000000 -0500
-@@ -212,7 +212,7 @@ int arch_setup_additional_pages(struct l
+diff -urNp linux-2.6.29.5/arch/powerpc/kernel/vdso.c linux-2.6.29.5/arch/powerpc/kernel/vdso.c
+--- linux-2.6.29.5/arch/powerpc/kernel/vdso.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/powerpc/kernel/vdso.c 2009-06-12 23:57:32.000000000 -0400
+@@ -211,7 +211,7 @@ int arch_setup_additional_pages(struct l
vdso_base = VDSO32_MBASE;
#endif
@@ -1407,7 +1608,7 @@ diff -urNp linux-2.6.28.8/arch/powerpc/kernel/vdso.c linux-2.6.28.8/arch/powerpc
/* vDSO has a problem and was disabled, just don't "enable" it for the
* process
-@@ -229,7 +229,7 @@ int arch_setup_additional_pages(struct l
+@@ -228,7 +228,7 @@ int arch_setup_additional_pages(struct l
*/
down_write(&mm->mmap_sem);
vdso_base = get_unmapped_area(NULL, vdso_base,
@@ -1416,9 +1617,32 @@ diff -urNp linux-2.6.28.8/arch/powerpc/kernel/vdso.c linux-2.6.28.8/arch/powerpc
if (IS_ERR_VALUE(vdso_base)) {
rc = vdso_base;
goto fail_mmapsem;
-diff -urNp linux-2.6.28.8/arch/powerpc/mm/fault.c linux-2.6.28.8/arch/powerpc/mm/fault.c
---- linux-2.6.28.8/arch/powerpc/mm/fault.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/powerpc/mm/fault.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/powerpc/lib/usercopy_64.c linux-2.6.29.5/arch/powerpc/lib/usercopy_64.c
+--- linux-2.6.29.5/arch/powerpc/lib/usercopy_64.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/powerpc/lib/usercopy_64.c 2009-06-13 00:43:03.000000000 -0400
+@@ -11,6 +11,9 @@
+
+ unsigned long copy_from_user(void *to, const void __user *from, unsigned long n)
+ {
++ if (unlikely(((long)n < 0) || (n > INT_MAX)))
++ return n;
++
+ if (likely(access_ok(VERIFY_READ, from, n)))
+ n = __copy_from_user(to, from, n);
+ else
+@@ -20,6 +23,9 @@ unsigned long copy_from_user(void *to, c
+
+ unsigned long copy_to_user(void __user *to, const void *from, unsigned long n)
+ {
++ if (unlikely(((long)n < 0) || (n > INT_MAX)))
++ return n;
++
+ if (likely(access_ok(VERIFY_WRITE, to, n)))
+ n = __copy_to_user(to, from, n);
+ return n;
+diff -urNp linux-2.6.29.5/arch/powerpc/mm/fault.c linux-2.6.29.5/arch/powerpc/mm/fault.c
+--- linux-2.6.29.5/arch/powerpc/mm/fault.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/powerpc/mm/fault.c 2009-06-12 23:57:32.000000000 -0400
@@ -29,6 +29,10 @@
#include <linux/module.h>
#include <linux/kprobes.h>
@@ -1428,9 +1652,9 @@ diff -urNp linux-2.6.28.8/arch/powerpc/mm/fault.c linux-2.6.28.8/arch/powerpc/mm
+#include <linux/compiler.h>
+#include <linux/unistd.h>
+ #include <asm/firmware.h>
#include <asm/page.h>
- #include <asm/pgtable.h>
-@@ -62,6 +66,363 @@ static inline int notify_page_fault(stru
+@@ -63,6 +67,363 @@ static inline int notify_page_fault(stru
}
#endif
@@ -1794,7 +2018,7 @@ diff -urNp linux-2.6.28.8/arch/powerpc/mm/fault.c linux-2.6.28.8/arch/powerpc/mm
/*
* Check whether the instruction at regs->nip is a store using
* an update addressing form which will update r1.
-@@ -132,7 +493,7 @@ int __kprobes do_page_fault(struct pt_re
+@@ -133,7 +494,7 @@ int __kprobes do_page_fault(struct pt_re
* indicate errors in DSISR but can validly be set in SRR1.
*/
if (trap == 0x400)
@@ -1803,7 +2027,7 @@ diff -urNp linux-2.6.28.8/arch/powerpc/mm/fault.c linux-2.6.28.8/arch/powerpc/mm
else
is_write = error_code & DSISR_ISSTORE;
#else
-@@ -331,6 +692,37 @@ bad_area:
+@@ -339,6 +700,37 @@ bad_area:
bad_area_nosemaphore:
/* User mode accesses cause a SIGSEGV */
if (user_mode(regs)) {
@@ -1841,9 +2065,9 @@ diff -urNp linux-2.6.28.8/arch/powerpc/mm/fault.c linux-2.6.28.8/arch/powerpc/mm
_exception(SIGSEGV, regs, code, address);
return 0;
}
-diff -urNp linux-2.6.28.8/arch/powerpc/mm/mmap.c linux-2.6.28.8/arch/powerpc/mm/mmap.c
---- linux-2.6.28.8/arch/powerpc/mm/mmap.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/powerpc/mm/mmap.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/powerpc/mm/mmap.c linux-2.6.29.5/arch/powerpc/mm/mmap.c
+--- linux-2.6.29.5/arch/powerpc/mm/mmap.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/powerpc/mm/mmap.c 2009-06-12 23:57:32.000000000 -0400
@@ -75,10 +75,22 @@ void arch_pick_mmap_layout(struct mm_str
*/
if (mmap_is_legacy()) {
@@ -1867,9 +2091,31 @@ diff -urNp linux-2.6.28.8/arch/powerpc/mm/mmap.c linux-2.6.28.8/arch/powerpc/mm/
mm->get_unmapped_area = arch_get_unmapped_area_topdown;
mm->unmap_area = arch_unmap_area_topdown;
}
-diff -urNp linux-2.6.28.8/arch/s390/include/asm/kmap_types.h linux-2.6.28.8/arch/s390/include/asm/kmap_types.h
---- linux-2.6.28.8/arch/s390/include/asm/kmap_types.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/s390/include/asm/kmap_types.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/s390/include/asm/atomic.h linux-2.6.29.5/arch/s390/include/asm/atomic.h
+--- linux-2.6.29.5/arch/s390/include/asm/atomic.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/s390/include/asm/atomic.h 2009-06-12 23:57:32.000000000 -0400
+@@ -82,8 +82,10 @@ static __inline__ int atomic_add_return(
+ return __CS_LOOP(v, i, "ar");
+ }
+ #define atomic_add(_i, _v) atomic_add_return(_i, _v)
++#define atomic_add_unchecked(_i, _v) atomic_add((_i), (_v))
+ #define atomic_add_negative(_i, _v) (atomic_add_return(_i, _v) < 0)
+ #define atomic_inc(_v) atomic_add_return(1, _v)
++#define atomic_inc_unchecked(_v) atomic_inc(_v)
+ #define atomic_inc_return(_v) atomic_add_return(1, _v)
+ #define atomic_inc_and_test(_v) (atomic_add_return(1, _v) == 0)
+
+@@ -92,6 +94,7 @@ static __inline__ int atomic_sub_return(
+ return __CS_LOOP(v, i, "sr");
+ }
+ #define atomic_sub(_i, _v) atomic_sub_return(_i, _v)
++#define atomic_sub_unchecked(_i, _v) atomic_sub((_i), (_v))
+ #define atomic_sub_and_test(_i, _v) (atomic_sub_return(_i, _v) == 0)
+ #define atomic_dec(_v) atomic_sub_return(1, _v)
+ #define atomic_dec_return(_v) atomic_sub_return(1, _v)
+diff -urNp linux-2.6.29.5/arch/s390/include/asm/kmap_types.h linux-2.6.29.5/arch/s390/include/asm/kmap_types.h
+--- linux-2.6.29.5/arch/s390/include/asm/kmap_types.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/s390/include/asm/kmap_types.h 2009-06-12 23:57:32.000000000 -0400
@@ -16,6 +16,7 @@ enum km_type {
KM_IRQ1,
KM_SOFTIRQ0,
@@ -1878,9 +2124,21 @@ diff -urNp linux-2.6.28.8/arch/s390/include/asm/kmap_types.h linux-2.6.28.8/arch
KM_TYPE_NR
};
-diff -urNp linux-2.6.28.8/arch/s390/kernel/module.c linux-2.6.28.8/arch/s390/kernel/module.c
---- linux-2.6.28.8/arch/s390/kernel/module.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/s390/kernel/module.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/s390/include/asm/uaccess.h linux-2.6.29.5/arch/s390/include/asm/uaccess.h
+--- linux-2.6.29.5/arch/s390/include/asm/uaccess.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/s390/include/asm/uaccess.h 2009-06-13 00:54:08.000000000 -0400
+@@ -285,7 +285,7 @@ copy_from_user(void *to, const void __us
+ might_sleep();
+ if (access_ok(VERIFY_READ, from, n))
+ n = __copy_from_user(to, from, n);
+- else
++ else if ((long)n > 0)
+ memset(to, 0, n);
+ return n;
+ }
+diff -urNp linux-2.6.29.5/arch/s390/kernel/module.c linux-2.6.29.5/arch/s390/kernel/module.c
+--- linux-2.6.29.5/arch/s390/kernel/module.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/s390/kernel/module.c 2009-06-12 23:57:32.000000000 -0400
@@ -166,11 +166,11 @@ module_frob_arch_sections(Elf_Ehdr *hdr,
/* Increase core size by size of got & plt and set start
@@ -1952,9 +2210,22 @@ diff -urNp linux-2.6.28.8/arch/s390/kernel/module.c linux-2.6.28.8/arch/s390/ker
rela->r_addend - loc;
if (r_type == R_390_GOTPC)
*(unsigned int *) loc = val;
-diff -urNp linux-2.6.28.8/arch/sh/include/asm/kmap_types.h linux-2.6.28.8/arch/sh/include/asm/kmap_types.h
---- linux-2.6.28.8/arch/sh/include/asm/kmap_types.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/sh/include/asm/kmap_types.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/sh/include/asm/atomic.h linux-2.6.29.5/arch/sh/include/asm/atomic.h
+--- linux-2.6.29.5/arch/sh/include/asm/atomic.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/sh/include/asm/atomic.h 2009-06-12 23:57:32.000000000 -0400
+@@ -43,6 +43,9 @@
+ #define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
+
+ #define atomic_inc(v) atomic_add(1,(v))
++#define atomic_inc_unchecked(v) atomic_inc(v)
++#define atomic_add_unchecked(i,v) atomic_add((i),(v))
++#define atomic_sub_unchecked(i,v) atomic_sub((i),(v))
+ #define atomic_dec(v) atomic_sub(1,(v))
+
+ #ifndef CONFIG_GUSA_RB
+diff -urNp linux-2.6.29.5/arch/sh/include/asm/kmap_types.h linux-2.6.29.5/arch/sh/include/asm/kmap_types.h
+--- linux-2.6.29.5/arch/sh/include/asm/kmap_types.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/sh/include/asm/kmap_types.h 2009-06-12 23:57:32.000000000 -0400
@@ -24,7 +24,8 @@ D(9) KM_IRQ0,
D(10) KM_IRQ1,
D(11) KM_SOFTIRQ0,
@@ -1965,9 +2236,46 @@ diff -urNp linux-2.6.28.8/arch/sh/include/asm/kmap_types.h linux-2.6.28.8/arch/s
};
#undef D
-diff -urNp linux-2.6.28.8/arch/sparc/include/asm/elf_32.h linux-2.6.28.8/arch/sparc/include/asm/elf_32.h
---- linux-2.6.28.8/arch/sparc/include/asm/elf_32.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/sparc/include/asm/elf_32.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/sparc/include/asm/atomic_32.h linux-2.6.29.5/arch/sparc/include/asm/atomic_32.h
+--- linux-2.6.29.5/arch/sparc/include/asm/atomic_32.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/sparc/include/asm/atomic_32.h 2009-06-12 23:57:32.000000000 -0400
+@@ -26,8 +26,11 @@ extern void atomic_set(atomic_t *, int);
+ #define atomic_read(v) ((v)->counter)
+
+ #define atomic_add(i, v) ((void)__atomic_add_return( (int)(i), (v)))
++#define atomic_add_unchecked(i, v) atomic_add((i), (v))
+ #define atomic_sub(i, v) ((void)__atomic_add_return(-(int)(i), (v)))
++#define atomic_sub_unchecked(i, v) atomic_sub((i), (v))
+ #define atomic_inc(v) ((void)__atomic_add_return( 1, (v)))
++#define atomic_inc_unchecked(v) atomic_inc(v)
+ #define atomic_dec(v) ((void)__atomic_add_return( -1, (v)))
+
+ #define atomic_add_return(i, v) (__atomic_add_return( (int)(i), (v)))
+diff -urNp linux-2.6.29.5/arch/sparc/include/asm/atomic_64.h linux-2.6.29.5/arch/sparc/include/asm/atomic_64.h
+--- linux-2.6.29.5/arch/sparc/include/asm/atomic_64.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/sparc/include/asm/atomic_64.h 2009-06-12 23:57:32.000000000 -0400
+@@ -20,8 +20,10 @@
+ #define atomic64_set(v, i) (((v)->counter) = i)
+
+ extern void atomic_add(int, atomic_t *);
++#define atomic_add_unchecked(i, v) atomic_add((i), (v))
+ extern void atomic64_add(int, atomic64_t *);
+ extern void atomic_sub(int, atomic_t *);
++#define atomic_sub_unchecked(i, v) atomic_sub((i), (v))
+ extern void atomic64_sub(int, atomic64_t *);
+
+ extern int atomic_add_ret(int, atomic_t *);
+@@ -59,6 +61,7 @@ extern int atomic64_sub_ret(int, atomic6
+ #define atomic64_dec_and_test(v) (atomic64_sub_ret(1, v) == 0)
+
+ #define atomic_inc(v) atomic_add(1, v)
++#define atomic_inc_unchecked(v) atomic_inc(v)
+ #define atomic64_inc(v) atomic64_add(1, v)
+
+ #define atomic_dec(v) atomic_sub(1, v)
+diff -urNp linux-2.6.29.5/arch/sparc/include/asm/elf_32.h linux-2.6.29.5/arch/sparc/include/asm/elf_32.h
+--- linux-2.6.29.5/arch/sparc/include/asm/elf_32.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/sparc/include/asm/elf_32.h 2009-06-12 23:57:32.000000000 -0400
@@ -116,6 +116,13 @@ typedef struct {
#define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE)
@@ -1982,9 +2290,9 @@ diff -urNp linux-2.6.28.8/arch/sparc/include/asm/elf_32.h linux-2.6.28.8/arch/sp
/* This yields a mask that user programs can use to figure out what
instruction set this cpu supports. This can NOT be done in userspace
on Sparc. */
-diff -urNp linux-2.6.28.8/arch/sparc/include/asm/elf_64.h linux-2.6.28.8/arch/sparc/include/asm/elf_64.h
---- linux-2.6.28.8/arch/sparc/include/asm/elf_64.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/sparc/include/asm/elf_64.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/sparc/include/asm/elf_64.h linux-2.6.29.5/arch/sparc/include/asm/elf_64.h
+--- linux-2.6.29.5/arch/sparc/include/asm/elf_64.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/sparc/include/asm/elf_64.h 2009-06-12 23:57:32.000000000 -0400
@@ -163,6 +163,12 @@ typedef struct {
#define ELF_ET_DYN_BASE 0x0000010000000000UL
#define COMPAT_ELF_ET_DYN_BASE 0x0000000070000000UL
@@ -1998,9 +2306,9 @@ diff -urNp linux-2.6.28.8/arch/sparc/include/asm/elf_64.h linux-2.6.28.8/arch/sp
/* This yields a mask that user programs can use to figure out what
instruction set this cpu supports. */
-diff -urNp linux-2.6.28.8/arch/sparc/include/asm/kmap_types.h linux-2.6.28.8/arch/sparc/include/asm/kmap_types.h
---- linux-2.6.28.8/arch/sparc/include/asm/kmap_types.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/sparc/include/asm/kmap_types.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/sparc/include/asm/kmap_types.h linux-2.6.29.5/arch/sparc/include/asm/kmap_types.h
+--- linux-2.6.29.5/arch/sparc/include/asm/kmap_types.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/sparc/include/asm/kmap_types.h 2009-06-12 23:57:32.000000000 -0400
@@ -19,6 +19,7 @@ enum km_type {
KM_IRQ1,
KM_SOFTIRQ0,
@@ -2009,9 +2317,9 @@ diff -urNp linux-2.6.28.8/arch/sparc/include/asm/kmap_types.h linux-2.6.28.8/arc
KM_TYPE_NR
};
-diff -urNp linux-2.6.28.8/arch/sparc/include/asm/pgtable_32.h linux-2.6.28.8/arch/sparc/include/asm/pgtable_32.h
---- linux-2.6.28.8/arch/sparc/include/asm/pgtable_32.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/sparc/include/asm/pgtable_32.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/sparc/include/asm/pgtable_32.h linux-2.6.29.5/arch/sparc/include/asm/pgtable_32.h
+--- linux-2.6.29.5/arch/sparc/include/asm/pgtable_32.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/sparc/include/asm/pgtable_32.h 2009-06-12 23:57:32.000000000 -0400
@@ -43,6 +43,13 @@ BTFIXUPDEF_SIMM13(user_ptrs_per_pgd)
BTFIXUPDEF_INT(page_none)
BTFIXUPDEF_INT(page_copy)
@@ -2043,9 +2351,9 @@ diff -urNp linux-2.6.28.8/arch/sparc/include/asm/pgtable_32.h linux-2.6.28.8/arc
extern unsigned long page_kernel;
#ifdef MODULE
-diff -urNp linux-2.6.28.8/arch/sparc/include/asm/pgtsrmmu.h linux-2.6.28.8/arch/sparc/include/asm/pgtsrmmu.h
---- linux-2.6.28.8/arch/sparc/include/asm/pgtsrmmu.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/sparc/include/asm/pgtsrmmu.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/sparc/include/asm/pgtsrmmu.h linux-2.6.29.5/arch/sparc/include/asm/pgtsrmmu.h
+--- linux-2.6.29.5/arch/sparc/include/asm/pgtsrmmu.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/sparc/include/asm/pgtsrmmu.h 2009-06-12 23:57:32.000000000 -0400
@@ -115,6 +115,13 @@
SRMMU_EXEC | SRMMU_REF)
#define SRMMU_PAGE_RDONLY __pgprot(SRMMU_VALID | SRMMU_CACHE | \
@@ -2060,9 +2368,73 @@ diff -urNp linux-2.6.28.8/arch/sparc/include/asm/pgtsrmmu.h linux-2.6.28.8/arch/
#define SRMMU_PAGE_KERNEL __pgprot(SRMMU_VALID | SRMMU_CACHE | SRMMU_PRIV | \
SRMMU_DIRTY | SRMMU_REF)
-diff -urNp linux-2.6.28.8/arch/sparc/kernel/sys_sparc.c linux-2.6.28.8/arch/sparc/kernel/sys_sparc.c
---- linux-2.6.28.8/arch/sparc/kernel/sys_sparc.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/sparc/kernel/sys_sparc.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/sparc/include/asm/uaccess_32.h linux-2.6.29.5/arch/sparc/include/asm/uaccess_32.h
+--- linux-2.6.29.5/arch/sparc/include/asm/uaccess_32.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/sparc/include/asm/uaccess_32.h 2009-06-13 00:16:38.000000000 -0400
+@@ -246,7 +246,7 @@ extern unsigned long __copy_user(void __
+
+ static inline unsigned long copy_to_user(void __user *to, const void *from, unsigned long n)
+ {
+- if (n && __access_ok((unsigned long) to, n))
++ if (((int)n > 0) && __access_ok((unsigned long) to, n))
+ return __copy_user(to, (__force void __user *) from, n);
+ else
+ return n;
+@@ -259,7 +259,7 @@ static inline unsigned long __copy_to_us
+
+ static inline unsigned long copy_from_user(void *to, const void __user *from, unsigned long n)
+ {
+- if (n && __access_ok((unsigned long) from, n))
++ if (((int)n > 0) && __access_ok((unsigned long) from, n))
+ return __copy_user((__force void __user *) to, from, n);
+ else
+ return n;
+diff -urNp linux-2.6.29.5/arch/sparc/include/asm/uaccess_64.h linux-2.6.29.5/arch/sparc/include/asm/uaccess_64.h
+--- linux-2.6.29.5/arch/sparc/include/asm/uaccess_64.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/sparc/include/asm/uaccess_64.h 2009-06-13 00:22:27.000000000 -0400
+@@ -212,7 +212,12 @@ extern unsigned long copy_from_user_fixu
+ static inline unsigned long __must_check
+ copy_from_user(void *to, const void __user *from, unsigned long size)
+ {
+- unsigned long ret = ___copy_from_user(to, from, size);
++ unsigned long ret;
++
++ if (unlikely(((long)size > INT_MAX) || ((long)size < 0)))
++ return size;
++
++ ret = ___copy_from_user(to, from, size);
+
+ if (unlikely(ret))
+ ret = copy_from_user_fixup(to, from, size);
+@@ -228,7 +233,12 @@ extern unsigned long copy_to_user_fixup(
+ static inline unsigned long __must_check
+ copy_to_user(void __user *to, const void *from, unsigned long size)
+ {
+- unsigned long ret = ___copy_to_user(to, from, size);
++ unsigned long ret;
++
++ if (unlikely(((long)size > INT_MAX) || ((long)size < 0)))
++ return size;
++
++ ret = ___copy_to_user(to, from, size);
+
+ if (unlikely(ret))
+ ret = copy_to_user_fixup(to, from, size);
+diff -urNp linux-2.6.29.5/arch/sparc/kernel/Makefile linux-2.6.29.5/arch/sparc/kernel/Makefile
+--- linux-2.6.29.5/arch/sparc/kernel/Makefile 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/sparc/kernel/Makefile 2009-06-12 23:57:32.000000000 -0400
+@@ -3,7 +3,7 @@
+ #
+
+ asflags-y := -ansi
+-ccflags-y := -Werror
++#ccflags-y := -Werror
+
+ extra-y := head_$(BITS).o
+ extra-y += init_task.o
+diff -urNp linux-2.6.29.5/arch/sparc/kernel/sys_sparc_32.c linux-2.6.29.5/arch/sparc/kernel/sys_sparc_32.c
+--- linux-2.6.29.5/arch/sparc/kernel/sys_sparc_32.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/sparc/kernel/sys_sparc_32.c 2009-06-12 23:57:32.000000000 -0400
@@ -56,7 +56,7 @@ unsigned long arch_get_unmapped_area(str
if (ARCH_SUN4C && len > 0x20000000)
return -ENOMEM;
@@ -2072,21 +2444,102 @@ diff -urNp linux-2.6.28.8/arch/sparc/kernel/sys_sparc.c linux-2.6.28.8/arch/spar
if (flags & MAP_SHARED)
addr = COLOUR_ALIGN(addr);
-diff -urNp linux-2.6.28.8/arch/sparc/Makefile linux-2.6.28.8/arch/sparc/Makefile
---- linux-2.6.28.8/arch/sparc/Makefile 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/sparc/Makefile 2009-02-21 09:37:48.000000000 -0500
-@@ -37,7 +37,7 @@ drivers-$(CONFIG_OPROFILE) += arch/sparc
- # Renaming is done to avoid confusing pattern matching rules in 2.5.45 (multy-)
- INIT_Y := $(patsubst %/, %/built-in.o, $(init-y))
- CORE_Y := $(core-y)
--CORE_Y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
-+CORE_Y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ grsecurity/
- CORE_Y := $(patsubst %/, %/built-in.o, $(CORE_Y))
- DRIVERS_Y := $(patsubst %/, %/built-in.o, $(drivers-y))
- NET_Y := $(patsubst %/, %/built-in.o, $(net-y))
-diff -urNp linux-2.6.28.8/arch/sparc/mm/fault.c linux-2.6.28.8/arch/sparc/mm/fault.c
---- linux-2.6.28.8/arch/sparc/mm/fault.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/sparc/mm/fault.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/sparc/kernel/sys_sparc_64.c linux-2.6.29.5/arch/sparc/kernel/sys_sparc_64.c
+--- linux-2.6.29.5/arch/sparc/kernel/sys_sparc_64.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/sparc/kernel/sys_sparc_64.c 2009-06-12 23:57:32.000000000 -0400
+@@ -125,7 +125,7 @@ unsigned long arch_get_unmapped_area(str
+ /* We do not accept a shared mapping if it would violate
+ * cache aliasing constraints.
+ */
+- if ((flags & MAP_SHARED) &&
++ if ((filp || (flags & MAP_SHARED)) &&
+ ((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1)))
+ return -EINVAL;
+ return addr;
+@@ -140,6 +140,10 @@ unsigned long arch_get_unmapped_area(str
+ if (filp || (flags & MAP_SHARED))
+ do_color_align = 1;
+
++#ifdef CONFIG_PAX_RANDMMAP
++ if (!(mm->pax_flags & MF_PAX_RANDMMAP))
++#endif
++
+ if (addr) {
+ if (do_color_align)
+ addr = COLOUR_ALIGN(addr, pgoff);
+@@ -153,9 +157,9 @@ unsigned long arch_get_unmapped_area(str
+ }
+
+ if (len > mm->cached_hole_size) {
+- start_addr = addr = mm->free_area_cache;
++ start_addr = addr = mm->free_area_cache;
+ } else {
+- start_addr = addr = TASK_UNMAPPED_BASE;
+++ start_addr = addr = mm->mmap_base;
+ mm->cached_hole_size = 0;
+ }
+
+@@ -175,8 +179,8 @@ full_search:
+ vma = find_vma(mm, VA_EXCLUDE_END);
+ }
+ if (unlikely(task_size < addr)) {
+- if (start_addr != TASK_UNMAPPED_BASE) {
+- start_addr = addr = TASK_UNMAPPED_BASE;
++ if (start_addr != mm->mmap_base) {
++ start_addr = addr = mm->mmap_base;
+ mm->cached_hole_size = 0;
+ goto full_search;
+ }
+@@ -216,7 +220,7 @@ arch_get_unmapped_area_topdown(struct fi
+ /* We do not accept a shared mapping if it would violate
+ * cache aliasing constraints.
+ */
+- if ((flags & MAP_SHARED) &&
++ if ((filp || (flags & MAP_SHARED)) &&
+ ((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1)))
+ return -EINVAL;
+ return addr;
+@@ -380,6 +384,12 @@ void arch_pick_mmap_layout(struct mm_str
+ current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY ||
+ sysctl_legacy_va_layout) {
+ mm->mmap_base = TASK_UNMAPPED_BASE + random_factor;
++
++#ifdef CONFIG_PAX_RANDMMAP
++ if (mm->pax_flags & MF_PAX_RANDMMAP)
++ mm->mmap_base += mm->delta_mmap;
++#endif
++
+ mm->get_unmapped_area = arch_get_unmapped_area;
+ mm->unmap_area = arch_unmap_area;
+ } else {
+@@ -394,6 +404,12 @@ void arch_pick_mmap_layout(struct mm_str
+ gap = (task_size / 6 * 5);
+
+ mm->mmap_base = PAGE_ALIGN(task_size - gap - random_factor);
++
++#ifdef CONFIG_PAX_RANDMMAP
++ if (mm->pax_flags & MF_PAX_RANDMMAP)
++ mm->mmap_base -= mm->delta_mmap + mm->delta_stack;
++#endif
++
+ mm->get_unmapped_area = arch_get_unmapped_area_topdown;
+ mm->unmap_area = arch_unmap_area_topdown;
+ }
+diff -urNp linux-2.6.29.5/arch/sparc/Makefile linux-2.6.29.5/arch/sparc/Makefile
+--- linux-2.6.29.5/arch/sparc/Makefile 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/sparc/Makefile 2009-06-12 23:57:32.000000000 -0400
+@@ -81,7 +81,7 @@ drivers-$(CONFIG_OPROFILE) += arch/sparc
+ # Export what is needed by arch/sparc/boot/Makefile
+ export VMLINUX_INIT VMLINUX_MAIN
+ VMLINUX_INIT := $(head-y) $(init-y)
+-VMLINUX_MAIN := $(core-y) kernel/ mm/ fs/ ipc/ security/ crypto/ block/
++VMLINUX_MAIN := $(core-y) kernel/ mm/ fs/ ipc/ security/ crypto/ block/ grsecurity/
+ VMLINUX_MAIN += $(patsubst %/, %/lib.a, $(libs-y)) $(libs-y)
+ VMLINUX_MAIN += $(drivers-y) $(net-y)
+
+diff -urNp linux-2.6.29.5/arch/sparc/mm/fault_32.c linux-2.6.29.5/arch/sparc/mm/fault_32.c
+--- linux-2.6.29.5/arch/sparc/mm/fault_32.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/sparc/mm/fault_32.c 2009-06-12 23:57:32.000000000 -0400
@@ -21,6 +21,9 @@
#include <linux/interrupt.h>
#include <linux/module.h>
@@ -2372,168 +2825,21 @@ diff -urNp linux-2.6.28.8/arch/sparc/mm/fault.c linux-2.6.28.8/arch/sparc/mm/fau
/* Allow reads even for write-only mappings */
if(!(vma->vm_flags & (VM_READ | VM_EXEC)))
goto bad_area;
-diff -urNp linux-2.6.28.8/arch/sparc/mm/init.c linux-2.6.28.8/arch/sparc/mm/init.c
---- linux-2.6.28.8/arch/sparc/mm/init.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/sparc/mm/init.c 2009-02-21 09:37:48.000000000 -0500
-@@ -313,6 +313,9 @@ extern void device_scan(void);
- pgprot_t PAGE_SHARED __read_mostly;
- EXPORT_SYMBOL(PAGE_SHARED);
-
-+pgprot_t PAGE_SHARED_NOEXEC __read_mostly;
-+EXPORT_SYMBOL(PAGE_SHARED_NOEXEC);
-+
- void __init paging_init(void)
- {
- switch(sparc_cpu_model) {
-@@ -338,17 +341,17 @@ void __init paging_init(void)
-
- /* Initialize the protection map with non-constant, MMU dependent values. */
- protection_map[0] = PAGE_NONE;
-- protection_map[1] = PAGE_READONLY;
-- protection_map[2] = PAGE_COPY;
-- protection_map[3] = PAGE_COPY;
-+ protection_map[1] = PAGE_READONLY_NOEXEC;
-+ protection_map[2] = PAGE_COPY_NOEXEC;
-+ protection_map[3] = PAGE_COPY_NOEXEC;
- protection_map[4] = PAGE_READONLY;
- protection_map[5] = PAGE_READONLY;
- protection_map[6] = PAGE_COPY;
- protection_map[7] = PAGE_COPY;
- protection_map[8] = PAGE_NONE;
-- protection_map[9] = PAGE_READONLY;
-- protection_map[10] = PAGE_SHARED;
-- protection_map[11] = PAGE_SHARED;
-+ protection_map[9] = PAGE_READONLY_NOEXEC;
-+ protection_map[10] = PAGE_SHARED_NOEXEC;
-+ protection_map[11] = PAGE_SHARED_NOEXEC;
- protection_map[12] = PAGE_READONLY;
- protection_map[13] = PAGE_READONLY;
- protection_map[14] = PAGE_SHARED;
-diff -urNp linux-2.6.28.8/arch/sparc/mm/srmmu.c linux-2.6.28.8/arch/sparc/mm/srmmu.c
---- linux-2.6.28.8/arch/sparc/mm/srmmu.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/sparc/mm/srmmu.c 2009-02-21 09:37:48.000000000 -0500
-@@ -2162,6 +2162,13 @@ void __init ld_mmu_srmmu(void)
- PAGE_SHARED = pgprot_val(SRMMU_PAGE_SHARED);
- BTFIXUPSET_INT(page_copy, pgprot_val(SRMMU_PAGE_COPY));
- BTFIXUPSET_INT(page_readonly, pgprot_val(SRMMU_PAGE_RDONLY));
-+
-+#ifdef CONFIG_PAX_PAGEEXEC
-+ PAGE_SHARED_NOEXEC = pgprot_val(SRMMU_PAGE_SHARED_NOEXEC);
-+ BTFIXUPSET_INT(page_copy_noexec, pgprot_val(SRMMU_PAGE_COPY_NOEXEC));
-+ BTFIXUPSET_INT(page_readonly_noexec, pgprot_val(SRMMU_PAGE_RDONLY_NOEXEC));
-+#endif
-+
- BTFIXUPSET_INT(page_kernel, pgprot_val(SRMMU_PAGE_KERNEL));
- page_kernel = pgprot_val(SRMMU_PAGE_KERNEL);
-
-diff -urNp linux-2.6.28.8/arch/sparc64/kernel/Makefile linux-2.6.28.8/arch/sparc64/kernel/Makefile
---- linux-2.6.28.8/arch/sparc64/kernel/Makefile 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/sparc64/kernel/Makefile 2009-02-21 09:37:48.000000000 -0500
-@@ -3,7 +3,7 @@
- #
-
- EXTRA_AFLAGS := -ansi
--EXTRA_CFLAGS := -Werror
-+#EXTRA_CFLAGS := -Werror
-
- CFLAGS_REMOVE_ftrace.o = -pg
-
-diff -urNp linux-2.6.28.8/arch/sparc64/kernel/sys_sparc.c linux-2.6.28.8/arch/sparc64/kernel/sys_sparc.c
---- linux-2.6.28.8/arch/sparc64/kernel/sys_sparc.c 2009-02-08 00:54:27.000000000 -0500
-+++ linux-2.6.28.8/arch/sparc64/kernel/sys_sparc.c 2009-02-21 09:37:48.000000000 -0500
-@@ -124,7 +124,7 @@ unsigned long arch_get_unmapped_area(str
- /* We do not accept a shared mapping if it would violate
- * cache aliasing constraints.
- */
-- if ((flags & MAP_SHARED) &&
-+ if ((filp || (flags & MAP_SHARED)) &&
- ((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1)))
- return -EINVAL;
- return addr;
-@@ -139,6 +139,10 @@ unsigned long arch_get_unmapped_area(str
- if (filp || (flags & MAP_SHARED))
- do_color_align = 1;
-
-+#ifdef CONFIG_PAX_RANDMMAP
-+ if (!(mm->pax_flags & MF_PAX_RANDMMAP))
-+#endif
-+
- if (addr) {
- if (do_color_align)
- addr = COLOUR_ALIGN(addr, pgoff);
-@@ -152,9 +156,9 @@ unsigned long arch_get_unmapped_area(str
- }
-
- if (len > mm->cached_hole_size) {
-- start_addr = addr = mm->free_area_cache;
-+ start_addr = addr = mm->free_area_cache;
- } else {
-- start_addr = addr = TASK_UNMAPPED_BASE;
-+ start_addr = addr = mm->mmap_base;
- mm->cached_hole_size = 0;
- }
-
-@@ -174,8 +178,8 @@ full_search:
- vma = find_vma(mm, VA_EXCLUDE_END);
- }
- if (unlikely(task_size < addr)) {
-- if (start_addr != TASK_UNMAPPED_BASE) {
-- start_addr = addr = TASK_UNMAPPED_BASE;
-+ if (start_addr != mm->mmap_base) {
-+ start_addr = addr = mm->mmap_base;
- mm->cached_hole_size = 0;
- goto full_search;
- }
-@@ -215,7 +219,7 @@ arch_get_unmapped_area_topdown(struct fi
- /* We do not accept a shared mapping if it would violate
- * cache aliasing constraints.
- */
-- if ((flags & MAP_SHARED) &&
-+ if ((filp || (flags & MAP_SHARED)) &&
- ((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1)))
- return -EINVAL;
- return addr;
-@@ -378,6 +382,12 @@ void arch_pick_mmap_layout(struct mm_str
- current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY ||
- sysctl_legacy_va_layout) {
- mm->mmap_base = TASK_UNMAPPED_BASE + random_factor;
-+
-+#ifdef CONFIG_PAX_RANDMMAP
-+ if (mm->pax_flags & MF_PAX_RANDMMAP)
-+ mm->mmap_base += mm->delta_mmap;
-+#endif
-+
- mm->get_unmapped_area = arch_get_unmapped_area;
- mm->unmap_area = arch_unmap_area;
- } else {
-@@ -392,6 +402,12 @@ void arch_pick_mmap_layout(struct mm_str
- gap = (task_size / 6 * 5);
-
- mm->mmap_base = PAGE_ALIGN(task_size - gap - random_factor);
-+
-+#ifdef CONFIG_PAX_RANDMMAP
-+ if (mm->pax_flags & MF_PAX_RANDMMAP)
-+ mm->mmap_base -= mm->delta_mmap + mm->delta_stack;
-+#endif
-+
- mm->get_unmapped_area = arch_get_unmapped_area_topdown;
- mm->unmap_area = arch_unmap_area_topdown;
- }
-diff -urNp linux-2.6.28.8/arch/sparc64/mm/fault.c linux-2.6.28.8/arch/sparc64/mm/fault.c
---- linux-2.6.28.8/arch/sparc64/mm/fault.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/sparc64/mm/fault.c 2009-02-21 09:37:48.000000000 -0500
-@@ -19,6 +19,9 @@
- #include <linux/interrupt.h>
+diff -urNp linux-2.6.29.5/arch/sparc/mm/fault_64.c linux-2.6.29.5/arch/sparc/mm/fault_64.c
+--- linux-2.6.29.5/arch/sparc/mm/fault_64.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/sparc/mm/fault_64.c 2009-06-12 23:57:32.000000000 -0400
+@@ -20,6 +20,9 @@
#include <linux/kprobes.h>
#include <linux/kdebug.h>
+ #include <linux/percpu.h>
+#include <linux/slab.h>
+#include <linux/pagemap.h>
+#include <linux/compiler.h>
#include <asm/page.h>
#include <asm/pgtable.h>
-@@ -224,6 +227,367 @@ cannot_handle:
- unhandled_fault (address, current, regs);
+@@ -249,6 +252,367 @@ static void noinline bogus_32bit_fault_a
+ show_regs(regs);
}
+#ifdef CONFIG_PAX_PAGEEXEC
@@ -2900,19 +3206,7 @@ diff -urNp linux-2.6.28.8/arch/sparc64/mm/fault.c linux-2.6.28.8/arch/sparc64/mm
asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
{
struct mm_struct *mm = current->mm;
-@@ -265,8 +629,10 @@ asmlinkage void __kprobes do_sparc64_fau
- goto intr_or_no_mm;
-
- if (test_thread_flag(TIF_32BIT)) {
-- if (!(regs->tstate & TSTATE_PRIV))
-+ if (!(regs->tstate & TSTATE_PRIV)) {
- regs->tpc &= 0xffffffff;
-+ regs->tnpc &= 0xffffffff;
-+ }
- address &= 0xffffffff;
- }
-
-@@ -283,6 +649,29 @@ asmlinkage void __kprobes do_sparc64_fau
+@@ -315,6 +679,29 @@ asmlinkage void __kprobes do_sparc64_fau
if (!vma)
goto bad_area;
@@ -2942,21 +3236,75 @@ diff -urNp linux-2.6.28.8/arch/sparc64/mm/fault.c linux-2.6.28.8/arch/sparc64/mm
/* Pure DTLB misses do not tell us whether the fault causing
* load/store/atomic was a write or not, it only says that there
* was no match. So in such a case we (carefully) read the
-diff -urNp linux-2.6.28.8/arch/sparc64/mm/Makefile linux-2.6.28.8/arch/sparc64/mm/Makefile
---- linux-2.6.28.8/arch/sparc64/mm/Makefile 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/sparc64/mm/Makefile 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/sparc/mm/init_32.c linux-2.6.29.5/arch/sparc/mm/init_32.c
+--- linux-2.6.29.5/arch/sparc/mm/init_32.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/sparc/mm/init_32.c 2009-06-12 23:57:32.000000000 -0400
+@@ -316,6 +316,9 @@ extern void device_scan(void);
+ pgprot_t PAGE_SHARED __read_mostly;
+ EXPORT_SYMBOL(PAGE_SHARED);
+
++pgprot_t PAGE_SHARED_NOEXEC __read_mostly;
++EXPORT_SYMBOL(PAGE_SHARED_NOEXEC);
++
+ void __init paging_init(void)
+ {
+ switch(sparc_cpu_model) {
+@@ -341,17 +344,17 @@ void __init paging_init(void)
+
+ /* Initialize the protection map with non-constant, MMU dependent values. */
+ protection_map[0] = PAGE_NONE;
+- protection_map[1] = PAGE_READONLY;
+- protection_map[2] = PAGE_COPY;
+- protection_map[3] = PAGE_COPY;
++ protection_map[1] = PAGE_READONLY_NOEXEC;
++ protection_map[2] = PAGE_COPY_NOEXEC;
++ protection_map[3] = PAGE_COPY_NOEXEC;
+ protection_map[4] = PAGE_READONLY;
+ protection_map[5] = PAGE_READONLY;
+ protection_map[6] = PAGE_COPY;
+ protection_map[7] = PAGE_COPY;
+ protection_map[8] = PAGE_NONE;
+- protection_map[9] = PAGE_READONLY;
+- protection_map[10] = PAGE_SHARED;
+- protection_map[11] = PAGE_SHARED;
++ protection_map[9] = PAGE_READONLY_NOEXEC;
++ protection_map[10] = PAGE_SHARED_NOEXEC;
++ protection_map[11] = PAGE_SHARED_NOEXEC;
+ protection_map[12] = PAGE_READONLY;
+ protection_map[13] = PAGE_READONLY;
+ protection_map[14] = PAGE_SHARED;
+diff -urNp linux-2.6.29.5/arch/sparc/mm/Makefile linux-2.6.29.5/arch/sparc/mm/Makefile
+--- linux-2.6.29.5/arch/sparc/mm/Makefile 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/sparc/mm/Makefile 2009-06-12 23:57:32.000000000 -0400
@@ -2,7 +2,7 @@
#
- EXTRA_AFLAGS := -ansi
--EXTRA_CFLAGS := -Werror
-+#EXTRA_CFLAGS := -Werror
+ asflags-y := -ansi
+-ccflags-y := -Werror
++#ccflags-y := -Werror
- obj-y := ultra.o tlb.o tsb.o fault.o init.o generic.o
+ obj-$(CONFIG_SPARC64) += ultra.o tlb.o tsb.o
+ obj-y += fault_$(BITS).o
+diff -urNp linux-2.6.29.5/arch/sparc/mm/srmmu.c linux-2.6.29.5/arch/sparc/mm/srmmu.c
+--- linux-2.6.29.5/arch/sparc/mm/srmmu.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/sparc/mm/srmmu.c 2009-06-12 23:57:32.000000000 -0400
+@@ -2148,6 +2148,13 @@ void __init ld_mmu_srmmu(void)
+ PAGE_SHARED = pgprot_val(SRMMU_PAGE_SHARED);
+ BTFIXUPSET_INT(page_copy, pgprot_val(SRMMU_PAGE_COPY));
+ BTFIXUPSET_INT(page_readonly, pgprot_val(SRMMU_PAGE_RDONLY));
++
++#ifdef CONFIG_PAX_PAGEEXEC
++ PAGE_SHARED_NOEXEC = pgprot_val(SRMMU_PAGE_SHARED_NOEXEC);
++ BTFIXUPSET_INT(page_copy_noexec, pgprot_val(SRMMU_PAGE_COPY_NOEXEC));
++ BTFIXUPSET_INT(page_readonly_noexec, pgprot_val(SRMMU_PAGE_RDONLY_NOEXEC));
++#endif
++
+ BTFIXUPSET_INT(page_kernel, pgprot_val(SRMMU_PAGE_KERNEL));
+ page_kernel = pgprot_val(SRMMU_PAGE_KERNEL);
-diff -urNp linux-2.6.28.8/arch/um/include/asm/kmap_types.h linux-2.6.28.8/arch/um/include/asm/kmap_types.h
---- linux-2.6.28.8/arch/um/include/asm/kmap_types.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/um/include/asm/kmap_types.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/um/include/asm/kmap_types.h linux-2.6.29.5/arch/um/include/asm/kmap_types.h
+--- linux-2.6.29.5/arch/um/include/asm/kmap_types.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/um/include/asm/kmap_types.h 2009-06-12 23:57:32.000000000 -0400
@@ -23,6 +23,7 @@ enum km_type {
KM_IRQ1,
KM_SOFTIRQ0,
@@ -2965,9 +3313,9 @@ diff -urNp linux-2.6.28.8/arch/um/include/asm/kmap_types.h linux-2.6.28.8/arch/u
KM_TYPE_NR
};
-diff -urNp linux-2.6.28.8/arch/um/include/asm/page.h linux-2.6.28.8/arch/um/include/asm/page.h
---- linux-2.6.28.8/arch/um/include/asm/page.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/um/include/asm/page.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/um/include/asm/page.h linux-2.6.29.5/arch/um/include/asm/page.h
+--- linux-2.6.29.5/arch/um/include/asm/page.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/um/include/asm/page.h 2009-06-12 23:57:32.000000000 -0400
@@ -14,6 +14,9 @@
#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
@@ -2978,9 +3326,9 @@ diff -urNp linux-2.6.28.8/arch/um/include/asm/page.h linux-2.6.28.8/arch/um/incl
#ifndef __ASSEMBLY__
struct page;
-diff -urNp linux-2.6.28.8/arch/um/sys-i386/syscalls.c linux-2.6.28.8/arch/um/sys-i386/syscalls.c
---- linux-2.6.28.8/arch/um/sys-i386/syscalls.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/um/sys-i386/syscalls.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/um/sys-i386/syscalls.c linux-2.6.29.5/arch/um/sys-i386/syscalls.c
+--- linux-2.6.29.5/arch/um/sys-i386/syscalls.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/um/sys-i386/syscalls.c 2009-06-12 23:57:32.000000000 -0400
@@ -11,6 +11,21 @@
#include "asm/uaccess.h"
#include "asm/unistd.h"
@@ -3003,9 +3351,9 @@ diff -urNp linux-2.6.28.8/arch/um/sys-i386/syscalls.c linux-2.6.28.8/arch/um/sys
/*
* Perform the select(nd, in, out, ex, tv) and mmap() system
* calls. Linux/i386 didn't use to be able to handle more than
-diff -urNp linux-2.6.28.8/arch/x86/boot/bitops.h linux-2.6.28.8/arch/x86/boot/bitops.h
---- linux-2.6.28.8/arch/x86/boot/bitops.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/boot/bitops.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/boot/bitops.h linux-2.6.29.5/arch/x86/boot/bitops.h
+--- linux-2.6.29.5/arch/x86/boot/bitops.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/boot/bitops.h 2009-06-12 23:57:32.000000000 -0400
@@ -26,7 +26,7 @@ static inline int variable_test_bit(int
u8 v;
const u32 *p = (const u32 *)addr;
@@ -3024,9 +3372,9 @@ diff -urNp linux-2.6.28.8/arch/x86/boot/bitops.h linux-2.6.28.8/arch/x86/boot/bi
}
#endif /* BOOT_BITOPS_H */
-diff -urNp linux-2.6.28.8/arch/x86/boot/boot.h linux-2.6.28.8/arch/x86/boot/boot.h
---- linux-2.6.28.8/arch/x86/boot/boot.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/boot/boot.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/boot/boot.h linux-2.6.29.5/arch/x86/boot/boot.h
+--- linux-2.6.29.5/arch/x86/boot/boot.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/boot/boot.h 2009-06-12 23:57:32.000000000 -0400
@@ -80,7 +80,7 @@ static inline void io_delay(void)
static inline u16 ds(void)
{
@@ -3045,9 +3393,9 @@ diff -urNp linux-2.6.28.8/arch/x86/boot/boot.h linux-2.6.28.8/arch/x86/boot/boot
: "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len));
return diff;
}
-diff -urNp linux-2.6.28.8/arch/x86/boot/compressed/head_32.S linux-2.6.28.8/arch/x86/boot/compressed/head_32.S
---- linux-2.6.28.8/arch/x86/boot/compressed/head_32.S 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/boot/compressed/head_32.S 2009-03-07 10:28:24.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/boot/compressed/head_32.S linux-2.6.29.5/arch/x86/boot/compressed/head_32.S
+--- linux-2.6.29.5/arch/x86/boot/compressed/head_32.S 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/boot/compressed/head_32.S 2009-06-12 23:57:32.000000000 -0400
@@ -70,7 +70,7 @@ startup_32:
addl $(CONFIG_PHYSICAL_ALIGN - 1), %ebx
andl $(~(CONFIG_PHYSICAL_ALIGN - 1)), %ebx
@@ -3097,9 +3445,9 @@ diff -urNp linux-2.6.28.8/arch/x86/boot/compressed/head_32.S linux-2.6.28.8/arch
addl %ebx, -__PAGE_OFFSET(%ebx, %ecx)
jmp 1b
2:
-diff -urNp linux-2.6.28.8/arch/x86/boot/compressed/misc.c linux-2.6.28.8/arch/x86/boot/compressed/misc.c
---- linux-2.6.28.8/arch/x86/boot/compressed/misc.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/boot/compressed/misc.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/boot/compressed/misc.c linux-2.6.29.5/arch/x86/boot/compressed/misc.c
+--- linux-2.6.29.5/arch/x86/boot/compressed/misc.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/boot/compressed/misc.c 2009-06-12 23:57:32.000000000 -0400
@@ -373,7 +373,7 @@ static void parse_elf(void *output)
case PT_LOAD:
#ifdef CONFIG_RELOCATABLE
@@ -3118,9 +3466,9 @@ diff -urNp linux-2.6.28.8/arch/x86/boot/compressed/misc.c linux-2.6.28.8/arch/x8
error("Wrong destination address");
#endif
#endif
-diff -urNp linux-2.6.28.8/arch/x86/boot/compressed/relocs.c linux-2.6.28.8/arch/x86/boot/compressed/relocs.c
---- linux-2.6.28.8/arch/x86/boot/compressed/relocs.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/boot/compressed/relocs.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/boot/compressed/relocs.c linux-2.6.29.5/arch/x86/boot/compressed/relocs.c
+--- linux-2.6.29.5/arch/x86/boot/compressed/relocs.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/boot/compressed/relocs.c 2009-06-12 23:57:32.000000000 -0400
@@ -10,8 +10,11 @@
#define USE_BSD
#include <endian.h>
@@ -3231,9 +3579,9 @@ diff -urNp linux-2.6.28.8/arch/x86/boot/compressed/relocs.c linux-2.6.28.8/arch/
read_shdrs(fp);
read_strtabs(fp);
read_symtabs(fp);
-diff -urNp linux-2.6.28.8/arch/x86/boot/cpucheck.c linux-2.6.28.8/arch/x86/boot/cpucheck.c
---- linux-2.6.28.8/arch/x86/boot/cpucheck.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/boot/cpucheck.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/boot/cpucheck.c linux-2.6.29.5/arch/x86/boot/cpucheck.c
+--- linux-2.6.29.5/arch/x86/boot/cpucheck.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/boot/cpucheck.c 2009-06-12 23:57:32.000000000 -0400
@@ -74,7 +74,7 @@ static int has_fpu(void)
u16 fcw = -1, fsw = -1;
u32 cr0;
@@ -3329,9 +3677,9 @@ diff -urNp linux-2.6.28.8/arch/x86/boot/cpucheck.c linux-2.6.28.8/arch/x86/boot/
err = check_flags();
}
-diff -urNp linux-2.6.28.8/arch/x86/boot/edd.c linux-2.6.28.8/arch/x86/boot/edd.c
---- linux-2.6.28.8/arch/x86/boot/edd.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/boot/edd.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/boot/edd.c linux-2.6.29.5/arch/x86/boot/edd.c
+--- linux-2.6.29.5/arch/x86/boot/edd.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/boot/edd.c 2009-06-12 23:57:32.000000000 -0400
@@ -81,7 +81,7 @@ static int get_edd_info(u8 devno, struct
ax = 0x4100;
bx = EDDMAGIC1;
@@ -3359,9 +3707,9 @@ diff -urNp linux-2.6.28.8/arch/x86/boot/edd.c linux-2.6.28.8/arch/x86/boot/edd.c
"movw %%di,%%es; "
"pushfl; stc; int $0x13; setc %%al; popfl; "
"popw %%es"
-diff -urNp linux-2.6.28.8/arch/x86/boot/main.c linux-2.6.28.8/arch/x86/boot/main.c
---- linux-2.6.28.8/arch/x86/boot/main.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/boot/main.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/boot/main.c linux-2.6.29.5/arch/x86/boot/main.c
+--- linux-2.6.29.5/arch/x86/boot/main.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/boot/main.c 2009-06-12 23:57:32.000000000 -0400
@@ -78,7 +78,7 @@ static void query_ist(void)
if (cpu.level < 6)
return;
@@ -3371,9 +3719,9 @@ diff -urNp linux-2.6.28.8/arch/x86/boot/main.c linux-2.6.28.8/arch/x86/boot/main
: "=a" (boot_params.ist_info.signature),
"=b" (boot_params.ist_info.command),
"=c" (boot_params.ist_info.event),
-diff -urNp linux-2.6.28.8/arch/x86/boot/mca.c linux-2.6.28.8/arch/x86/boot/mca.c
---- linux-2.6.28.8/arch/x86/boot/mca.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/boot/mca.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/boot/mca.c linux-2.6.29.5/arch/x86/boot/mca.c
+--- linux-2.6.29.5/arch/x86/boot/mca.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/boot/mca.c 2009-06-12 23:57:32.000000000 -0400
@@ -19,7 +19,7 @@ int query_mca(void)
u8 err;
u16 es, bx, len;
@@ -3383,19 +3731,19 @@ diff -urNp linux-2.6.28.8/arch/x86/boot/mca.c linux-2.6.28.8/arch/x86/boot/mca.c
"int $0x15 ; "
"setc %0 ; "
"movw %%es, %1 ; "
-diff -urNp linux-2.6.28.8/arch/x86/boot/memory.c linux-2.6.28.8/arch/x86/boot/memory.c
---- linux-2.6.28.8/arch/x86/boot/memory.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/boot/memory.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/boot/memory.c linux-2.6.29.5/arch/x86/boot/memory.c
+--- linux-2.6.29.5/arch/x86/boot/memory.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/boot/memory.c 2009-06-12 23:57:32.000000000 -0400
@@ -30,7 +30,7 @@ static int detect_memory_e820(void)
- /* Important: %edx is clobbered by some BIOSes,
- so it must be either used for the error output
+ /* Important: %edx and %esi are clobbered by some BIOSes,
+ so they must be either used for the error output
or explicitly marked clobbered. */
- asm("int $0x15; setc %0"
+ asm volatile("int $0x15; setc %0"
: "=d" (err), "+b" (next), "=a" (id), "+c" (size),
"=m" (*desc)
- : "D" (desc), "d" (SMAP), "a" (0xe820));
-@@ -65,7 +65,7 @@ static int detect_memory_e801(void)
+ : "D" (desc), "d" (SMAP), "a" (0xe820)
+@@ -66,7 +66,7 @@ static int detect_memory_e801(void)
bx = cx = dx = 0;
ax = 0xe801;
@@ -3404,7 +3752,7 @@ diff -urNp linux-2.6.28.8/arch/x86/boot/memory.c linux-2.6.28.8/arch/x86/boot/me
: "=m" (err), "+a" (ax), "+b" (bx), "+c" (cx), "+d" (dx));
if (err)
-@@ -95,7 +95,7 @@ static int detect_memory_88(void)
+@@ -96,7 +96,7 @@ static int detect_memory_88(void)
u8 err;
ax = 0x8800;
@@ -3413,9 +3761,9 @@ diff -urNp linux-2.6.28.8/arch/x86/boot/memory.c linux-2.6.28.8/arch/x86/boot/me
boot_params.screen_info.ext_mem_k = ax;
-diff -urNp linux-2.6.28.8/arch/x86/boot/video.c linux-2.6.28.8/arch/x86/boot/video.c
---- linux-2.6.28.8/arch/x86/boot/video.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/boot/video.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/boot/video.c linux-2.6.29.5/arch/x86/boot/video.c
+--- linux-2.6.29.5/arch/x86/boot/video.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/boot/video.c 2009-06-12 23:57:32.000000000 -0400
@@ -23,7 +23,7 @@ static void store_cursor_position(void)
ax = 0x0300;
@@ -3434,9 +3782,9 @@ diff -urNp linux-2.6.28.8/arch/x86/boot/video.c linux-2.6.28.8/arch/x86/boot/vid
: "+a" (ax), "=b" (page)
: : "ecx", "edx", "esi", "edi");
-diff -urNp linux-2.6.28.8/arch/x86/boot/video-vesa.c linux-2.6.28.8/arch/x86/boot/video-vesa.c
---- linux-2.6.28.8/arch/x86/boot/video-vesa.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/boot/video-vesa.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/boot/video-vesa.c linux-2.6.29.5/arch/x86/boot/video-vesa.c
+--- linux-2.6.29.5/arch/x86/boot/video-vesa.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/boot/video-vesa.c 2009-06-12 23:57:32.000000000 -0400
@@ -41,7 +41,7 @@ static int vesa_probe(void)
ax = 0x4f00;
@@ -3496,21 +3844,21 @@ diff -urNp linux-2.6.28.8/arch/x86/boot/video-vesa.c linux-2.6.28.8/arch/x86/boo
- asm("pushw %%es; movw %2,%%es; "INT10"; popw %%es"
+ asm volatile("pushw %%es; movw %2,%%es; "INT10"; popw %%es"
- : "+a" (ax), "+b" (bx)
- : "c" (cx), "D" (di)
- : "esi");
-@@ -284,7 +285,7 @@ void vesa_store_edid(void)
+ : "+a" (ax), "+b" (bx), "+c" (cx), "+D" (di)
+ : : "esi", "edx");
+
+@@ -283,7 +284,7 @@ void vesa_store_edid(void)
cx = 0; /* Controller 0 */
dx = 0; /* EDID block number */
di =(size_t) &boot_params.edid_info; /* (ES:)Pointer to block */
- asm(INT10
+ asm volatile(INT10
- : "+a" (ax), "+b" (bx), "+d" (dx), "=m" (boot_params.edid_info)
- : "c" (cx), "D" (di)
- : "esi");
-diff -urNp linux-2.6.28.8/arch/x86/boot/video-vga.c linux-2.6.28.8/arch/x86/boot/video-vga.c
---- linux-2.6.28.8/arch/x86/boot/video-vga.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/boot/video-vga.c 2009-02-21 09:37:48.000000000 -0500
+ : "+a" (ax), "+b" (bx), "+d" (dx), "=m" (boot_params.edid_info),
+ "+c" (cx), "+D" (di)
+ : : "esi");
+diff -urNp linux-2.6.29.5/arch/x86/boot/video-vga.c linux-2.6.29.5/arch/x86/boot/video-vga.c
+--- linux-2.6.29.5/arch/x86/boot/video-vga.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/boot/video-vga.c 2009-06-12 23:57:32.000000000 -0400
@@ -225,7 +225,7 @@ static int vga_probe(void)
};
u8 vga_flag;
@@ -3529,9 +3877,9 @@ diff -urNp linux-2.6.28.8/arch/x86/boot/video-vga.c linux-2.6.28.8/arch/x86/boot
: "=a" (vga_flag)
: "a" (0x1a00)
: "ebx", "ecx", "edx", "esi", "edi");
-diff -urNp linux-2.6.28.8/arch/x86/boot/voyager.c linux-2.6.28.8/arch/x86/boot/voyager.c
---- linux-2.6.28.8/arch/x86/boot/voyager.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/boot/voyager.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/boot/voyager.c linux-2.6.29.5/arch/x86/boot/voyager.c
+--- linux-2.6.29.5/arch/x86/boot/voyager.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/boot/voyager.c 2009-06-12 23:57:32.000000000 -0400
@@ -23,7 +23,7 @@ int query_voyager(void)
data_ptr[0] = 0xff; /* Flag on config not found(?) */
@@ -3541,20 +3889,48 @@ diff -urNp linux-2.6.28.8/arch/x86/boot/voyager.c linux-2.6.28.8/arch/x86/boot/v
"int $0x15 ; "
"setc %0 ; "
"movw %%es, %1 ; "
-diff -urNp linux-2.6.28.8/arch/x86/ia32/ia32_signal.c linux-2.6.28.8/arch/x86/ia32/ia32_signal.c
---- linux-2.6.28.8/arch/x86/ia32/ia32_signal.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/ia32/ia32_signal.c 2009-02-21 09:37:48.000000000 -0500
-@@ -518,6 +518,7 @@ int ia32_setup_rt_frame(int sig, struct
+diff -urNp linux-2.6.29.5/arch/x86/ia32/ia32_signal.c linux-2.6.29.5/arch/x86/ia32/ia32_signal.c
+--- linux-2.6.29.5/arch/x86/ia32/ia32_signal.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/ia32/ia32_signal.c 2009-06-12 23:57:32.000000000 -0400
+@@ -387,7 +387,7 @@ static void __user *get_sigframe(struct
+ sp -= frame_size;
+ /* Align the stack pointer according to the i386 ABI,
+ * i.e. so that on function entry ((sp + 4) & 15) == 0. */
+- sp = ((sp + 4) & -16ul) - 4;
++ sp = ((sp - 12) & -16ul) - 4;
+ return (void __user *) sp;
+ }
+
+@@ -464,7 +464,7 @@ int ia32_setup_frame(int sig, struct k_s
+
+ #if DEBUG_SIG
+ printk(KERN_DEBUG "SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n",
+- current->comm, current->pid, frame, regs->ip, frame->pretcode);
++ current->comm, task_pid_nr(current), frame, regs->ip, frame->pretcode);
+ #endif
+
+ return 0;
+@@ -488,7 +488,7 @@ int ia32_setup_rt_frame(int sig, struct
+ 0xb8,
__NR_ia32_rt_sigreturn,
0x80cd,
- 0,
+- 0,
+ 0
};
frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate);
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/alternative.h linux-2.6.28.8/arch/x86/include/asm/alternative.h
---- linux-2.6.28.8/arch/x86/include/asm/alternative.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/alternative.h 2009-02-21 09:37:48.000000000 -0500
+@@ -551,7 +551,7 @@ int ia32_setup_rt_frame(int sig, struct
+
+ #if DEBUG_SIG
+ printk(KERN_DEBUG "SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n",
+- current->comm, current->pid, frame, regs->ip, frame->pretcode);
++ current->comm, task_pid_nr(current), frame, regs->ip, frame->pretcode);
+ #endif
+
+ return 0;
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/alternative.h linux-2.6.29.5/arch/x86/include/asm/alternative.h
+--- linux-2.6.29.5/arch/x86/include/asm/alternative.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/alternative.h 2009-06-12 23:57:32.000000000 -0400
@@ -96,7 +96,7 @@ const unsigned char *const *find_nop_tab
" .byte 662b-661b\n" /* sourcelen */ \
" .byte 664f-663f\n" /* replacementlen */ \
@@ -3582,10 +3958,10 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/alternative.h linux-2.6.28.8/arch
"663:\n\t" newinstr "\n664:\n" /* replacement */ \
".previous" : output : [feat] "i" (feature), ##input)
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/atomic_32.h linux-2.6.28.8/arch/x86/include/asm/atomic_32.h
---- linux-2.6.28.8/arch/x86/include/asm/atomic_32.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/atomic_32.h 2009-02-21 09:37:48.000000000 -0500
-@@ -47,7 +47,29 @@ typedef struct {
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/atomic_32.h linux-2.6.29.5/arch/x86/include/asm/atomic_32.h
+--- linux-2.6.29.5/arch/x86/include/asm/atomic_32.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/atomic_32.h 2009-06-12 23:57:32.000000000 -0400
+@@ -39,7 +39,29 @@
*/
static inline void atomic_add(int i, atomic_t *v)
{
@@ -3610,13 +3986,13 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/atomic_32.h linux-2.6.28.8/arch/x
+ *
+ * Atomically adds @i to @v.
+ */
-+static inline void atomic_add_unchecked(int i, atomic_t *v)
++static inline void atomic_add_unchecked(int i, atomic_unchecked_t *v)
+{
+ asm volatile(LOCK_PREFIX "addl %1,%0\n"
: "+m" (v->counter)
: "ir" (i));
}
-@@ -61,7 +83,15 @@ static inline void atomic_add(int i, ato
+@@ -53,7 +75,29 @@ static inline void atomic_add(int i, ato
*/
static inline void atomic_sub(int i, atomic_t *v)
{
@@ -3630,10 +4006,24 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/atomic_32.h linux-2.6.28.8/arch/x
+ _ASM_EXTABLE(0b, 0b)
+#endif
+
++ : "+m" (v->counter)
++ : "ir" (i));
++}
++
++/**
++ * atomic_sub_unchecked - subtract integer from atomic variable
++ * @i: integer value to subtract
++ * @v: pointer of type atomic_t
++ *
++ * Atomically subtracts @i from @v.
++ */
++static inline void atomic_sub_unchecked(int i, atomic_unchecked_t *v)
++{
++ asm volatile(LOCK_PREFIX "subl %1,%0\n"
: "+m" (v->counter)
: "ir" (i));
}
-@@ -79,7 +109,16 @@ static inline int atomic_sub_and_test(in
+@@ -71,7 +115,16 @@ static inline int atomic_sub_and_test(in
{
unsigned char c;
@@ -3651,7 +4041,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/atomic_32.h linux-2.6.28.8/arch/x
: "+m" (v->counter), "=qm" (c)
: "ir" (i) : "memory");
return c;
-@@ -93,7 +132,18 @@ static inline int atomic_sub_and_test(in
+@@ -85,7 +138,30 @@ static inline int atomic_sub_and_test(in
*/
static inline void atomic_inc(atomic_t *v)
{
@@ -3668,10 +4058,22 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/atomic_32.h linux-2.6.28.8/arch/x
+ _ASM_EXTABLE(0b, 1b)
+#endif
+
++ : "+m" (v->counter));
++}
++
++/**
++ * atomic_inc_unchecked - increment atomic variable
++ * @v: pointer of type atomic_t
++ *
++ * Atomically increments @v by 1.
++ */
++static inline void atomic_inc_unchecked(atomic_unchecked_t *v)
++{
++ asm volatile(LOCK_PREFIX "incl %0\n"
: "+m" (v->counter));
}
-@@ -105,7 +155,18 @@ static inline void atomic_inc(atomic_t *
+@@ -97,7 +173,18 @@ static inline void atomic_inc(atomic_t *
*/
static inline void atomic_dec(atomic_t *v)
{
@@ -3691,7 +4093,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/atomic_32.h linux-2.6.28.8/arch/x
: "+m" (v->counter));
}
-@@ -121,7 +182,19 @@ static inline int atomic_dec_and_test(at
+@@ -113,7 +200,19 @@ static inline int atomic_dec_and_test(at
{
unsigned char c;
@@ -3712,7 +4114,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/atomic_32.h linux-2.6.28.8/arch/x
: "+m" (v->counter), "=qm" (c)
: : "memory");
return c != 0;
-@@ -139,7 +212,19 @@ static inline int atomic_inc_and_test(at
+@@ -131,7 +230,19 @@ static inline int atomic_inc_and_test(at
{
unsigned char c;
@@ -3733,7 +4135,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/atomic_32.h linux-2.6.28.8/arch/x
: "+m" (v->counter), "=qm" (c)
: : "memory");
return c != 0;
-@@ -158,7 +243,16 @@ static inline int atomic_add_negative(in
+@@ -150,7 +261,16 @@ static inline int atomic_add_negative(in
{
unsigned char c;
@@ -3751,7 +4153,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/atomic_32.h linux-2.6.28.8/arch/x
: "+m" (v->counter), "=qm" (c)
: "ir" (i) : "memory");
return c;
-@@ -181,7 +275,15 @@ static inline int atomic_add_return(int
+@@ -173,7 +293,15 @@ static inline int atomic_add_return(int
#endif
/* Modern 486+ processor */
__i = i;
@@ -3768,10 +4170,43 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/atomic_32.h linux-2.6.28.8/arch/x
: "+r" (i), "+m" (v->counter)
: : "memory");
return i + __i;
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/atomic_64.h linux-2.6.28.8/arch/x86/include/asm/atomic_64.h
---- linux-2.6.28.8/arch/x86/include/asm/atomic_64.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/atomic_64.h 2009-02-21 09:37:48.000000000 -0500
-@@ -48,7 +48,29 @@ typedef struct {
+@@ -214,17 +342,28 @@ static inline int atomic_sub_return(int
+ */
+ static inline int atomic_add_unless(atomic_t *v, int a, int u)
+ {
+- int c, old;
++ int c, old, new;
+ c = atomic_read(v);
+ for (;;) {
+- if (unlikely(c == (u)))
++ if (unlikely(c == u))
+ break;
+- old = atomic_cmpxchg((v), c, c + (a));
++
++ asm volatile("addl %2,%0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "into\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
++ : "=r" (new)
++ : "0" (c), "ir" (a));
++
++ old = atomic_cmpxchg(v, c, new);
+ if (likely(old == c))
+ break;
+ c = old;
+ }
+- return c != (u);
++ return c != u;
+ }
+
+ #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/atomic_64.h linux-2.6.29.5/arch/x86/include/asm/atomic_64.h
+--- linux-2.6.29.5/arch/x86/include/asm/atomic_64.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/atomic_64.h 2009-06-12 23:57:32.000000000 -0400
+@@ -38,7 +38,29 @@
*/
static inline void atomic_add(int i, atomic_t *v)
{
@@ -3796,13 +4231,13 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/atomic_64.h linux-2.6.28.8/arch/x
+ *
+ * Atomically adds @i to @v.
+ */
-+static inline void atomic_add_unchecked(int i, atomic_t *v)
++static inline void atomic_add_unchecked(int i, atomic_unchecked_t *v)
+{
+ asm volatile(LOCK_PREFIX "addl %1,%0\n"
: "=m" (v->counter)
: "ir" (i), "m" (v->counter));
}
-@@ -62,7 +84,15 @@ static inline void atomic_add(int i, ato
+@@ -52,7 +74,29 @@ static inline void atomic_add(int i, ato
*/
static inline void atomic_sub(int i, atomic_t *v)
{
@@ -3816,10 +4251,24 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/atomic_64.h linux-2.6.28.8/arch/x
+ _ASM_EXTABLE(0b, 0b)
+#endif
+
++ : "=m" (v->counter)
++ : "ir" (i), "m" (v->counter));
++}
++
++/**
++ * atomic_sub_unchecked - subtract the atomic variable
++ * @i: integer value to subtract
++ * @v: pointer of type atomic_t
++ *
++ * Atomically subtracts @i from @v.
++ */
++static inline void atomic_sub_unchecked(int i, atomic_unchecked_t *v)
++{
++ asm volatile(LOCK_PREFIX "subl %1,%0\n"
: "=m" (v->counter)
: "ir" (i), "m" (v->counter));
}
-@@ -80,7 +110,16 @@ static inline int atomic_sub_and_test(in
+@@ -70,7 +114,16 @@ static inline int atomic_sub_and_test(in
{
unsigned char c;
@@ -3837,7 +4286,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/atomic_64.h linux-2.6.28.8/arch/x
: "=m" (v->counter), "=qm" (c)
: "ir" (i), "m" (v->counter) : "memory");
return c;
-@@ -94,7 +133,19 @@ static inline int atomic_sub_and_test(in
+@@ -84,7 +137,32 @@ static inline int atomic_sub_and_test(in
*/
static inline void atomic_inc(atomic_t *v)
{
@@ -3855,10 +4304,23 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/atomic_64.h linux-2.6.28.8/arch/x
+ _ASM_EXTABLE(0b, 1b)
+#endif
+
++ : "=m" (v->counter)
++ : "m" (v->counter));
++}
++
++/**
++ * atomic_inc_unchecked - increment atomic variable
++ * @v: pointer of type atomic_t
++ *
++ * Atomically increments @v by 1.
++ */
++static inline void atomic_inc_unchecked(atomic_unchecked_t *v)
++{
++ asm volatile(LOCK_PREFIX "incl %0\n"
: "=m" (v->counter)
: "m" (v->counter));
}
-@@ -107,7 +158,19 @@ static inline void atomic_inc(atomic_t *
+@@ -97,7 +175,19 @@ static inline void atomic_inc(atomic_t *
*/
static inline void atomic_dec(atomic_t *v)
{
@@ -3879,7 +4341,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/atomic_64.h linux-2.6.28.8/arch/x
: "=m" (v->counter)
: "m" (v->counter));
}
-@@ -124,7 +187,20 @@ static inline int atomic_dec_and_test(at
+@@ -114,7 +204,20 @@ static inline int atomic_dec_and_test(at
{
unsigned char c;
@@ -3901,7 +4363,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/atomic_64.h linux-2.6.28.8/arch/x
: "=m" (v->counter), "=qm" (c)
: "m" (v->counter) : "memory");
return c != 0;
-@@ -142,7 +218,20 @@ static inline int atomic_inc_and_test(at
+@@ -132,7 +235,20 @@ static inline int atomic_inc_and_test(at
{
unsigned char c;
@@ -3923,7 +4385,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/atomic_64.h linux-2.6.28.8/arch/x
: "=m" (v->counter), "=qm" (c)
: "m" (v->counter) : "memory");
return c != 0;
-@@ -161,7 +250,16 @@ static inline int atomic_add_negative(in
+@@ -151,7 +267,16 @@ static inline int atomic_add_negative(in
{
unsigned char c;
@@ -3941,7 +4403,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/atomic_64.h linux-2.6.28.8/arch/x
: "=m" (v->counter), "=qm" (c)
: "ir" (i), "m" (v->counter) : "memory");
return c;
-@@ -177,7 +275,15 @@ static inline int atomic_add_negative(in
+@@ -167,7 +292,15 @@ static inline int atomic_add_negative(in
static inline int atomic_add_return(int i, atomic_t *v)
{
int __i = i;
@@ -3958,7 +4420,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/atomic_64.h linux-2.6.28.8/arch/x
: "+r" (i), "+m" (v->counter)
: : "memory");
return i + __i;
-@@ -226,7 +332,15 @@ typedef struct {
+@@ -212,7 +345,15 @@ static inline int atomic_sub_return(int
*/
static inline void atomic64_add(long i, atomic64_t *v)
{
@@ -3975,7 +4437,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/atomic_64.h linux-2.6.28.8/arch/x
: "=m" (v->counter)
: "er" (i), "m" (v->counter));
}
-@@ -240,7 +354,15 @@ static inline void atomic64_add(long i,
+@@ -226,7 +367,15 @@ static inline void atomic64_add(long i,
*/
static inline void atomic64_sub(long i, atomic64_t *v)
{
@@ -3992,7 +4454,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/atomic_64.h linux-2.6.28.8/arch/x
: "=m" (v->counter)
: "er" (i), "m" (v->counter));
}
-@@ -258,7 +380,16 @@ static inline int atomic64_sub_and_test(
+@@ -244,7 +393,16 @@ static inline int atomic64_sub_and_test(
{
unsigned char c;
@@ -4010,7 +4472,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/atomic_64.h linux-2.6.28.8/arch/x
: "=m" (v->counter), "=qm" (c)
: "er" (i), "m" (v->counter) : "memory");
return c;
-@@ -272,7 +403,19 @@ static inline int atomic64_sub_and_test(
+@@ -258,7 +416,19 @@ static inline int atomic64_sub_and_test(
*/
static inline void atomic64_inc(atomic64_t *v)
{
@@ -4031,7 +4493,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/atomic_64.h linux-2.6.28.8/arch/x
: "=m" (v->counter)
: "m" (v->counter));
}
-@@ -285,7 +428,19 @@ static inline void atomic64_inc(atomic64
+@@ -271,7 +441,19 @@ static inline void atomic64_inc(atomic64
*/
static inline void atomic64_dec(atomic64_t *v)
{
@@ -4052,7 +4514,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/atomic_64.h linux-2.6.28.8/arch/x
: "=m" (v->counter)
: "m" (v->counter));
}
-@@ -302,7 +457,20 @@ static inline int atomic64_dec_and_test(
+@@ -288,7 +470,20 @@ static inline int atomic64_dec_and_test(
{
unsigned char c;
@@ -4074,7 +4536,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/atomic_64.h linux-2.6.28.8/arch/x
: "=m" (v->counter), "=qm" (c)
: "m" (v->counter) : "memory");
return c != 0;
-@@ -320,7 +488,20 @@ static inline int atomic64_inc_and_test(
+@@ -306,7 +501,20 @@ static inline int atomic64_inc_and_test(
{
unsigned char c;
@@ -4096,7 +4558,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/atomic_64.h linux-2.6.28.8/arch/x
: "=m" (v->counter), "=qm" (c)
: "m" (v->counter) : "memory");
return c != 0;
-@@ -339,7 +520,16 @@ static inline int atomic64_add_negative(
+@@ -325,7 +533,16 @@ static inline int atomic64_add_negative(
{
unsigned char c;
@@ -4114,7 +4576,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/atomic_64.h linux-2.6.28.8/arch/x
: "=m" (v->counter), "=qm" (c)
: "er" (i), "m" (v->counter) : "memory");
return c;
-@@ -355,7 +545,15 @@ static inline int atomic64_add_negative(
+@@ -341,7 +558,15 @@ static inline int atomic64_add_negative(
static inline long atomic64_add_return(long i, atomic64_t *v)
{
long __i = i;
@@ -4131,9 +4593,77 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/atomic_64.h linux-2.6.28.8/arch/x
: "+r" (i), "+m" (v->counter)
: : "memory");
return i + __i;
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/boot.h linux-2.6.28.8/arch/x86/include/asm/boot.h
---- linux-2.6.28.8/arch/x86/include/asm/boot.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/boot.h 2009-02-21 09:37:48.000000000 -0500
+@@ -372,17 +597,29 @@ static inline long atomic64_sub_return(l
+ */
+ static inline int atomic_add_unless(atomic_t *v, int a, int u)
+ {
+- int c, old;
++ int c, old, new;
+ c = atomic_read(v);
+ for (;;) {
+- if (unlikely(c == (u)))
++ if (unlikely(c == u))
+ break;
+- old = atomic_cmpxchg((v), c, c + (a));
++
++ asm volatile("addl %2,%0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
++ : "=r" (new)
++ : "0" (c), "ir" (a));
++
++ old = atomic_cmpxchg(v, c, new);
+ if (likely(old == c))
+ break;
+ c = old;
+ }
+- return c != (u);
++ return c != u;
+ }
+
+ #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
+@@ -398,17 +635,29 @@ static inline int atomic_add_unless(atom
+ */
+ static inline int atomic64_add_unless(atomic64_t *v, long a, long u)
+ {
+- long c, old;
++ long c, old, new;
+ c = atomic64_read(v);
+ for (;;) {
+- if (unlikely(c == (u)))
++ if (unlikely(c == u))
+ break;
+- old = atomic64_cmpxchg((v), c, c + (a));
++
++ asm volatile("addq %2,%0\n"
++
++#ifdef CONFIG_PAX_REFCOUNT
++ "jno 0f\n"
++ "int $4\n0:\n"
++ _ASM_EXTABLE(0b, 0b)
++#endif
++
++ : "=r" (new)
++ : "0" (c), "er" (a));
++
++ old = atomic64_cmpxchg((v), c, new);
+ if (likely(old == c))
+ break;
+ c = old;
+ }
+- return c != (u);
++ return c != u;
+ }
+
+ /**
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/boot.h linux-2.6.29.5/arch/x86/include/asm/boot.h
+--- linux-2.6.29.5/arch/x86/include/asm/boot.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/boot.h 2009-06-12 23:57:32.000000000 -0400
@@ -11,10 +11,15 @@
#define ASK_VGA 0xfffd /* ask for it at bootup */
@@ -4151,9 +4681,9 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/boot.h linux-2.6.28.8/arch/x86/in
#ifdef CONFIG_X86_64
#define BOOT_HEAP_SIZE 0x7000
#define BOOT_STACK_SIZE 0x4000
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/cache.h linux-2.6.28.8/arch/x86/include/asm/cache.h
---- linux-2.6.28.8/arch/x86/include/asm/cache.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/cache.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/cache.h linux-2.6.29.5/arch/x86/include/asm/cache.h
+--- linux-2.6.29.5/arch/x86/include/asm/cache.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/cache.h 2009-06-12 23:57:32.000000000 -0400
@@ -6,6 +6,7 @@
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
@@ -4162,9 +4692,9 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/cache.h linux-2.6.28.8/arch/x86/i
#ifdef CONFIG_X86_VSMP
/* vSMP Internode cacheline shift */
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/checksum_32.h linux-2.6.28.8/arch/x86/include/asm/checksum_32.h
---- linux-2.6.28.8/arch/x86/include/asm/checksum_32.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/checksum_32.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/checksum_32.h linux-2.6.29.5/arch/x86/include/asm/checksum_32.h
+--- linux-2.6.29.5/arch/x86/include/asm/checksum_32.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/checksum_32.h 2009-06-12 23:57:32.000000000 -0400
@@ -31,6 +31,14 @@ asmlinkage __wsum csum_partial_copy_gene
int len, __wsum sum,
int *src_err_ptr, int *dst_err_ptr);
@@ -4198,20 +4728,9 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/checksum_32.h linux-2.6.28.8/arch
len, sum, NULL, err_ptr);
if (len)
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/cpufeature.h linux-2.6.28.8/arch/x86/include/asm/cpufeature.h
---- linux-2.6.28.8/arch/x86/include/asm/cpufeature.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/cpufeature.h 2009-02-21 09:37:48.000000000 -0500
-@@ -80,7 +80,6 @@
- #define X86_FEATURE_UP (3*32+ 9) /* smp kernel running on up */
- #define X86_FEATURE_FXSAVE_LEAK (3*32+10) /* "" FXSAVE leaks FOP/FIP/FOP */
- #define X86_FEATURE_ARCH_PERFMON (3*32+11) /* Intel Architectural PerfMon */
--#define X86_FEATURE_NOPL (3*32+20) /* The NOPL (0F 1F) instructions */
- #define X86_FEATURE_PEBS (3*32+12) /* Precise-Event Based Sampling */
- #define X86_FEATURE_BTS (3*32+13) /* Branch Trace Store */
- #define X86_FEATURE_SYSCALL32 (3*32+14) /* "" syscall in ia32 userspace */
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/desc.h linux-2.6.28.8/arch/x86/include/asm/desc.h
---- linux-2.6.28.8/arch/x86/include/asm/desc.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/desc.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/desc.h linux-2.6.29.5/arch/x86/include/asm/desc.h
+--- linux-2.6.29.5/arch/x86/include/asm/desc.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/desc.h 2009-06-12 23:57:32.000000000 -0400
@@ -16,6 +16,7 @@ static inline void fill_ldt(struct desc_
desc->base1 = (info->base_addr & 0x00ff0000) >> 16;
desc->type = (info->read_exec_only ^ 1) << 1;
@@ -4347,7 +4866,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/desc.h linux-2.6.28.8/arch/x86/in
}
#define _LDT_empty(info) \
-@@ -381,6 +440,18 @@ static inline void set_system_intr_gate_
+@@ -379,6 +438,18 @@ static inline void set_system_intr_gate_
_set_gate(n, GATE_INTERRUPT, addr, 0x3, ist, __KERNEL_CS);
}
@@ -4366,10 +4885,10 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/desc.h linux-2.6.28.8/arch/x86/in
#else
/*
* GET_DESC_BASE reads the descriptor base of the specified segment.
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/e820.h linux-2.6.28.8/arch/x86/include/asm/e820.h
---- linux-2.6.28.8/arch/x86/include/asm/e820.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/e820.h 2009-02-21 09:37:48.000000000 -0500
-@@ -134,7 +134,7 @@ extern char *memory_setup(void);
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/e820.h linux-2.6.29.5/arch/x86/include/asm/e820.h
+--- linux-2.6.29.5/arch/x86/include/asm/e820.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/e820.h 2009-06-12 23:57:32.000000000 -0400
+@@ -135,7 +135,7 @@ extern char *memory_setup(void);
#define ISA_END_ADDRESS 0x100000
#define is_ISA_range(s, e) ((s) >= ISA_START_ADDRESS && (e) < ISA_END_ADDRESS)
@@ -4378,9 +4897,9 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/e820.h linux-2.6.28.8/arch/x86/in
#define BIOS_END 0x00100000
#ifdef __KERNEL__
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/elf.h linux-2.6.28.8/arch/x86/include/asm/elf.h
---- linux-2.6.28.8/arch/x86/include/asm/elf.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/elf.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/elf.h linux-2.6.29.5/arch/x86/include/asm/elf.h
+--- linux-2.6.29.5/arch/x86/include/asm/elf.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/elf.h 2009-06-12 23:57:32.000000000 -0400
@@ -252,7 +252,25 @@ extern int force_personality32;
the loader. We need to make sure that it is out of the way of the program
that it will "exec", and that there is sufficient room for the brk. */
@@ -4434,9 +4953,9 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/elf.h linux-2.6.28.8/arch/x86/inc
-#define arch_randomize_brk arch_randomize_brk
-
#endif /* _ASM_X86_ELF_H */
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/futex.h linux-2.6.28.8/arch/x86/include/asm/futex.h
---- linux-2.6.28.8/arch/x86/include/asm/futex.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/futex.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/futex.h linux-2.6.29.5/arch/x86/include/asm/futex.h
+--- linux-2.6.29.5/arch/x86/include/asm/futex.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/futex.h 2009-06-12 23:57:32.000000000 -0400
@@ -11,6 +11,40 @@
#include <asm/processor.h>
#include <asm/system.h>
@@ -4548,10 +5067,10 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/futex.h linux-2.6.28.8/arch/x86/i
: "memory"
);
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/i387.h linux-2.6.28.8/arch/x86/include/asm/i387.h
---- linux-2.6.28.8/arch/x86/include/asm/i387.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/i387.h 2009-02-21 09:37:48.000000000 -0500
-@@ -197,13 +197,8 @@ static inline void restore_fpu(struct ta
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/i387.h linux-2.6.29.5/arch/x86/include/asm/i387.h
+--- linux-2.6.29.5/arch/x86/include/asm/i387.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/i387.h 2009-06-12 23:57:32.000000000 -0400
+@@ -203,13 +203,8 @@ static inline void restore_fpu(struct ta
}
/* We need a safe address that is cheap to find and that is already
@@ -4567,9 +5086,9 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/i387.h linux-2.6.28.8/arch/x86/in
/*
* These must be called with preempt disabled
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/io_64.h linux-2.6.28.8/arch/x86/include/asm/io_64.h
---- linux-2.6.28.8/arch/x86/include/asm/io_64.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/io_64.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/io_64.h linux-2.6.29.5/arch/x86/include/asm/io_64.h
+--- linux-2.6.29.5/arch/x86/include/asm/io_64.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/io_64.h 2009-06-12 23:57:32.000000000 -0400
@@ -158,6 +158,17 @@ static inline void *phys_to_virt(unsigne
}
#endif
@@ -4588,9 +5107,9 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/io_64.h linux-2.6.28.8/arch/x86/i
/*
* Change "struct page" to physical address.
*/
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/irqflags.h linux-2.6.28.8/arch/x86/include/asm/irqflags.h
---- linux-2.6.28.8/arch/x86/include/asm/irqflags.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/irqflags.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/irqflags.h linux-2.6.29.5/arch/x86/include/asm/irqflags.h
+--- linux-2.6.29.5/arch/x86/include/asm/irqflags.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/irqflags.h 2009-06-12 23:57:32.000000000 -0400
@@ -141,6 +141,8 @@ static inline unsigned long __raw_local_
#define INTERRUPT_RETURN iret
#define ENABLE_INTERRUPTS_SYSEXIT sti; sysexit
@@ -4600,9 +5119,9 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/irqflags.h linux-2.6.28.8/arch/x8
#endif
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/kmap_types.h linux-2.6.28.8/arch/x86/include/asm/kmap_types.h
---- linux-2.6.28.8/arch/x86/include/asm/kmap_types.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/kmap_types.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/kmap_types.h linux-2.6.29.5/arch/x86/include/asm/kmap_types.h
+--- linux-2.6.29.5/arch/x86/include/asm/kmap_types.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/kmap_types.h 2009-06-12 23:57:32.000000000 -0400
@@ -21,7 +21,8 @@ D(9) KM_IRQ0,
D(10) KM_IRQ1,
D(11) KM_SOFTIRQ0,
@@ -4613,11 +5132,11 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/kmap_types.h linux-2.6.28.8/arch/
};
#undef D
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/kvm_host.h linux-2.6.28.8/arch/x86/include/asm/kvm_host.h
---- linux-2.6.28.8/arch/x86/include/asm/kvm_host.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/kvm_host.h 2009-02-21 09:37:48.000000000 -0500
-@@ -479,7 +479,7 @@ struct kvm_x86_ops {
- int (*get_tdp_level)(void);
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/kvm_host.h linux-2.6.29.5/arch/x86/include/asm/kvm_host.h
+--- linux-2.6.29.5/arch/x86/include/asm/kvm_host.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/kvm_host.h 2009-06-12 23:57:32.000000000 -0400
+@@ -494,7 +494,7 @@ struct kvm_x86_ops {
+ int (*get_mt_mask_shift)(void);
};
-extern struct kvm_x86_ops *kvm_x86_ops;
@@ -4625,9 +5144,9 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/kvm_host.h linux-2.6.28.8/arch/x8
int kvm_mmu_module_init(void);
void kvm_mmu_module_exit(void);
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/linkage.h linux-2.6.28.8/arch/x86/include/asm/linkage.h
---- linux-2.6.28.8/arch/x86/include/asm/linkage.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/linkage.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/linkage.h linux-2.6.29.5/arch/x86/include/asm/linkage.h
+--- linux-2.6.29.5/arch/x86/include/asm/linkage.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/linkage.h 2009-06-12 23:57:32.000000000 -0400
@@ -7,6 +7,11 @@
#ifdef CONFIG_X86_64
#define __ALIGN .p2align 4,,15
@@ -4640,7 +5159,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/linkage.h linux-2.6.28.8/arch/x86
#endif
#ifdef CONFIG_X86_32
-@@ -52,10 +57,5 @@
+@@ -52,11 +57,6 @@
#endif
@@ -4649,11 +5168,12 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/linkage.h linux-2.6.28.8/arch/x86
-#define __ALIGN_STR ".align 16,0x90"
-#endif
-
- #endif /* _ASM_X86_LINKAGE_H */
-
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/local.h linux-2.6.28.8/arch/x86/include/asm/local.h
---- linux-2.6.28.8/arch/x86/include/asm/local.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/local.h 2009-02-21 09:37:48.000000000 -0500
+ /*
+ * to check ENTRY_X86/END_X86 and
+ * KPROBE_ENTRY_X86/KPROBE_END_X86
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/local.h linux-2.6.29.5/arch/x86/include/asm/local.h
+--- linux-2.6.29.5/arch/x86/include/asm/local.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/local.h 2009-06-12 23:57:32.000000000 -0400
@@ -18,26 +18,90 @@ typedef struct {
static inline void local_inc(local_t *l)
@@ -4878,9 +5398,9 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/local.h linux-2.6.28.8/arch/x86/i
: "+r" (i), "+m" (l->a.counter)
: : "memory");
return i + __i;
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/mach-default/apm.h linux-2.6.28.8/arch/x86/include/asm/mach-default/apm.h
---- linux-2.6.28.8/arch/x86/include/asm/mach-default/apm.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/mach-default/apm.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/mach-default/apm.h linux-2.6.29.5/arch/x86/include/asm/mach-default/apm.h
+--- linux-2.6.29.5/arch/x86/include/asm/mach-default/apm.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/mach-default/apm.h 2009-06-12 23:57:32.000000000 -0400
@@ -34,7 +34,7 @@ static inline void apm_bios_call_asm(u32
__asm__ __volatile__(APM_DO_ZERO_SEGS
"pushl %%edi\n\t"
@@ -4899,9 +5419,9 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/mach-default/apm.h linux-2.6.28.8
"setc %%bl\n\t"
"popl %%ebp\n\t"
"popl %%edi\n\t"
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/mman.h linux-2.6.28.8/arch/x86/include/asm/mman.h
---- linux-2.6.28.8/arch/x86/include/asm/mman.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/mman.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/mman.h linux-2.6.29.5/arch/x86/include/asm/mman.h
+--- linux-2.6.29.5/arch/x86/include/asm/mman.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/mman.h 2009-06-12 23:57:32.000000000 -0400
@@ -17,4 +17,14 @@
#define MCL_CURRENT 1 /* lock all current mappings */
#define MCL_FUTURE 2 /* lock all future mappings */
@@ -4917,10 +5437,26 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/mman.h linux-2.6.28.8/arch/x86/in
+#endif
+
#endif /* _ASM_X86_MMAN_H */
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/mmu_context_32.h linux-2.6.28.8/arch/x86/include/asm/mmu_context_32.h
---- linux-2.6.28.8/arch/x86/include/asm/mmu_context_32.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/mmu_context_32.h 2009-02-21 09:37:48.000000000 -0500
-@@ -33,6 +33,22 @@ static inline void switch_mm(struct mm_s
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/mmu_context_32.h linux-2.6.29.5/arch/x86/include/asm/mmu_context_32.h
+--- linux-2.6.29.5/arch/x86/include/asm/mmu_context_32.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/mmu_context_32.h 2009-06-12 23:57:32.000000000 -0400
+@@ -14,11 +14,15 @@ static inline void switch_mm(struct mm_s
+ struct task_struct *tsk)
+ {
+ int cpu = smp_processor_id();
++#ifdef CONFIG_SMP
++ int tlbstate = TLBSTATE_OK;
++#endif
+
+ if (likely(prev != next)) {
+ /* stop flush ipis for the previous mm */
+ cpu_clear(cpu, prev->cpu_vm_mask);
+ #ifdef CONFIG_SMP
++ tlbstate = x86_read_percpu(cpu_tlbstate.state);
+ x86_write_percpu(cpu_tlbstate.state, TLBSTATE_OK);
+ x86_write_percpu(cpu_tlbstate.active_mm, next);
+ #endif
+@@ -32,6 +36,26 @@ static inline void switch_mm(struct mm_s
*/
if (unlikely(prev->context.ldt != next->context.ldt))
load_LDT_nolock(&next->context);
@@ -4936,14 +5472,18 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/mmu_context_32.h linux-2.6.28.8/a
+
+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
+ if (unlikely(prev->context.user_cs_base != next->context.user_cs_base ||
-+ prev->context.user_cs_limit != next->context.user_cs_limit))
++ prev->context.user_cs_limit != next->context.user_cs_limit
++#ifdef CONFIG_SMP
++ || tlbstate != TLBSTATE_OK
++#endif
++ ))
+ set_user_cs(next->context.user_cs_base, next->context.user_cs_limit, cpu);
+#endif
+
}
#ifdef CONFIG_SMP
else {
-@@ -45,6 +61,19 @@ static inline void switch_mm(struct mm_s
+@@ -44,6 +68,19 @@ static inline void switch_mm(struct mm_s
*/
load_cr3(next->pgd);
load_LDT_nolock(&next->context);
@@ -4963,9 +5503,9 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/mmu_context_32.h linux-2.6.28.8/a
}
}
#endif
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/mmu.h linux-2.6.28.8/arch/x86/include/asm/mmu.h
---- linux-2.6.28.8/arch/x86/include/asm/mmu.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/mmu.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/mmu.h linux-2.6.29.5/arch/x86/include/asm/mmu.h
+--- linux-2.6.29.5/arch/x86/include/asm/mmu.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/mmu.h 2009-06-12 23:57:32.000000000 -0400
@@ -9,10 +9,23 @@
* we put the segment information here.
*/
@@ -4992,9 +5532,9 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/mmu.h linux-2.6.28.8/arch/x86/inc
} mm_context_t;
#ifdef CONFIG_SMP
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/module.h linux-2.6.28.8/arch/x86/include/asm/module.h
---- linux-2.6.28.8/arch/x86/include/asm/module.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/module.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/module.h linux-2.6.29.5/arch/x86/include/asm/module.h
+--- linux-2.6.29.5/arch/x86/include/asm/module.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/module.h 2009-06-12 23:57:32.000000000 -0400
@@ -74,7 +74,12 @@ struct mod_arch_specific {};
# else
# define MODULE_STACKSIZE ""
@@ -5009,9 +5549,9 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/module.h linux-2.6.28.8/arch/x86/
#endif
#endif /* _ASM_X86_MODULE_H */
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/page_32.h linux-2.6.28.8/arch/x86/include/asm/page_32.h
---- linux-2.6.28.8/arch/x86/include/asm/page_32.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/page_32.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/page_32.h linux-2.6.29.5/arch/x86/include/asm/page_32.h
+--- linux-2.6.29.5/arch/x86/include/asm/page_32.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/page_32.h 2009-06-12 23:57:32.000000000 -0400
@@ -13,6 +13,23 @@
*/
#define __PAGE_OFFSET _AC(CONFIG_PAGE_OFFSET, UL)
@@ -5036,9 +5576,9 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/page_32.h linux-2.6.28.8/arch/x86
#ifdef CONFIG_4KSTACKS
#define THREAD_ORDER 0
#else
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/page_64.h linux-2.6.28.8/arch/x86/include/asm/page_64.h
---- linux-2.6.28.8/arch/x86/include/asm/page_64.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/page_64.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/page_64.h linux-2.6.29.5/arch/x86/include/asm/page_64.h
+--- linux-2.6.29.5/arch/x86/include/asm/page_64.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/page_64.h 2009-06-12 23:57:32.000000000 -0400
@@ -49,6 +49,9 @@
#define __START_KERNEL (__START_KERNEL_map + __PHYSICAL_START)
#define __START_KERNEL_map _AC(0xffffffff80000000, UL)
@@ -5056,10 +5596,10 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/page_64.h linux-2.6.28.8/arch/x86
+#define nx_enabled (1)
#endif /* _ASM_X86_PAGE_64_H */
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/paravirt.h linux-2.6.28.8/arch/x86/include/asm/paravirt.h
---- linux-2.6.28.8/arch/x86/include/asm/paravirt.h 2009-03-07 10:24:49.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/paravirt.h 2009-03-07 10:29:51.000000000 -0500
-@@ -1557,7 +1557,7 @@ static inline unsigned long __raw_local_
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/paravirt.h linux-2.6.29.5/arch/x86/include/asm/paravirt.h
+--- linux-2.6.29.5/arch/x86/include/asm/paravirt.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/paravirt.h 2009-06-12 23:57:32.000000000 -0400
+@@ -1558,7 +1558,7 @@ static inline unsigned long __raw_local_
#define PV_RESTORE_REGS popl %edx; popl %ecx; popl %edi; popl %eax
#define PARA_PATCH(struct, off) ((PARAVIRT_PATCH_##struct + (off)) / 4)
#define PARA_SITE(ptype, clobbers, ops) _PVSITE(ptype, clobbers, ops, .long, 4)
@@ -5068,9 +5608,9 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/paravirt.h linux-2.6.28.8/arch/x8
#endif
#define INTERRUPT_RETURN \
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/pda.h linux-2.6.28.8/arch/x86/include/asm/pda.h
---- linux-2.6.28.8/arch/x86/include/asm/pda.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/pda.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/pda.h linux-2.6.29.5/arch/x86/include/asm/pda.h
+--- linux-2.6.29.5/arch/x86/include/asm/pda.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/pda.h 2009-06-12 23:57:32.000000000 -0400
@@ -16,11 +16,9 @@ struct x8664_pda {
unsigned long oldrsp; /* 24 user rsp for system call */
int irqcount; /* 32 Irq nesting counter. Starts -1 */
@@ -5083,9 +5623,9 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/pda.h linux-2.6.28.8/arch/x86/inc
char *irqstackptr;
short nodenumber; /* number of current node (32k max) */
short in_bootmem; /* pda lives in bootmem */
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/percpu.h linux-2.6.28.8/arch/x86/include/asm/percpu.h
---- linux-2.6.28.8/arch/x86/include/asm/percpu.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/percpu.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/percpu.h linux-2.6.29.5/arch/x86/include/asm/percpu.h
+--- linux-2.6.29.5/arch/x86/include/asm/percpu.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/percpu.h 2009-06-12 23:57:32.000000000 -0400
@@ -93,6 +93,12 @@ DECLARE_PER_CPU(struct x8664_pda, pda);
#define __my_cpu_offset x86_read_percpu(this_cpu_off)
@@ -5099,9 +5639,9 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/percpu.h linux-2.6.28.8/arch/x86/
/* fs segment starts at (positive) offset == __per_cpu_offset[cpu] */
#define __percpu_seg "%%fs:"
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/pgalloc.h linux-2.6.28.8/arch/x86/include/asm/pgalloc.h
---- linux-2.6.28.8/arch/x86/include/asm/pgalloc.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/pgalloc.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/pgalloc.h linux-2.6.29.5/arch/x86/include/asm/pgalloc.h
+--- linux-2.6.29.5/arch/x86/include/asm/pgalloc.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/pgalloc.h 2009-06-12 23:57:32.000000000 -0400
@@ -52,7 +52,7 @@ static inline void pmd_populate_kernel(s
pmd_t *pmd, pte_t *pte)
{
@@ -5111,9 +5651,9 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/pgalloc.h linux-2.6.28.8/arch/x86
}
static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/pgtable-2level.h linux-2.6.28.8/arch/x86/include/asm/pgtable-2level.h
---- linux-2.6.28.8/arch/x86/include/asm/pgtable-2level.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/pgtable-2level.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/pgtable-2level.h linux-2.6.29.5/arch/x86/include/asm/pgtable-2level.h
+--- linux-2.6.29.5/arch/x86/include/asm/pgtable-2level.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/pgtable-2level.h 2009-06-12 23:57:32.000000000 -0400
@@ -18,7 +18,19 @@ static inline void native_set_pte(pte_t
static inline void native_set_pmd(pmd_t *pmdp, pmd_t pmd)
@@ -5134,9 +5674,9 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/pgtable-2level.h linux-2.6.28.8/a
}
static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte)
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/pgtable_32.h linux-2.6.28.8/arch/x86/include/asm/pgtable_32.h
---- linux-2.6.28.8/arch/x86/include/asm/pgtable_32.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/pgtable_32.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/pgtable_32.h linux-2.6.29.5/arch/x86/include/asm/pgtable_32.h
+--- linux-2.6.29.5/arch/x86/include/asm/pgtable_32.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/pgtable_32.h 2009-06-12 23:57:32.000000000 -0400
@@ -25,8 +25,6 @@
struct mm_struct;
struct vm_area_struct;
@@ -5167,7 +5707,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/pgtable_32.h linux-2.6.28.8/arch/
#define pte_present(x) ((x).pte_low & (_PAGE_PRESENT | _PAGE_PROTNONE))
-@@ -175,6 +178,9 @@ do { \
+@@ -166,6 +169,9 @@ do { \
#endif /* !__ASSEMBLY__ */
@@ -5177,9 +5717,9 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/pgtable_32.h linux-2.6.28.8/arch/
/*
* kern_addr_valid() is (1) for FLATMEM and (0) for
* SPARSEMEM and DISCONTIGMEM
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/pgtable-3level.h linux-2.6.28.8/arch/x86/include/asm/pgtable-3level.h
---- linux-2.6.28.8/arch/x86/include/asm/pgtable-3level.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/pgtable-3level.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/pgtable-3level.h linux-2.6.29.5/arch/x86/include/asm/pgtable-3level.h
+--- linux-2.6.29.5/arch/x86/include/asm/pgtable-3level.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/pgtable-3level.h 2009-06-12 23:57:32.000000000 -0400
@@ -70,12 +70,36 @@ static inline void native_set_pte_atomic
static inline void native_set_pmd(pmd_t *pmdp, pmd_t pmd)
@@ -5217,9 +5757,9 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/pgtable-3level.h linux-2.6.28.8/a
}
/*
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/pgtable_64.h linux-2.6.28.8/arch/x86/include/asm/pgtable_64.h
---- linux-2.6.28.8/arch/x86/include/asm/pgtable_64.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/pgtable_64.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/pgtable_64.h linux-2.6.29.5/arch/x86/include/asm/pgtable_64.h
+--- linux-2.6.29.5/arch/x86/include/asm/pgtable_64.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/pgtable_64.h 2009-06-12 23:57:32.000000000 -0400
@@ -15,9 +15,12 @@
extern pud_t level3_kernel_pgt[512];
@@ -5275,10 +5815,10 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/pgtable_64.h linux-2.6.28.8/arch/
}
#define pte_none(x) (!pte_val((x)))
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/pgtable.h linux-2.6.28.8/arch/x86/include/asm/pgtable.h
---- linux-2.6.28.8/arch/x86/include/asm/pgtable.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/pgtable.h 2009-02-21 09:37:48.000000000 -0500
-@@ -14,12 +14,11 @@
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/pgtable.h linux-2.6.29.5/arch/x86/include/asm/pgtable.h
+--- linux-2.6.29.5/arch/x86/include/asm/pgtable.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/pgtable.h 2009-06-12 23:57:32.000000000 -0400
+@@ -13,12 +13,11 @@
#define _PAGE_BIT_PSE 7 /* 4 MB (or 2MB) page */
#define _PAGE_BIT_PAT 7 /* on 4KB pages */
#define _PAGE_BIT_GLOBAL 8 /* Global TLB entry PPro+ */
@@ -5292,8 +5832,8 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/pgtable.h linux-2.6.28.8/arch/x86
+#define _PAGE_BIT_CPA_TEST _PAGE_BIT_SPECIAL
#define _PAGE_BIT_NX 63 /* No execute: only valid after cpuid check */
- #define _PAGE_PRESENT (_AT(pteval_t, 1) << _PAGE_BIT_PRESENT)
-@@ -31,7 +30,6 @@
+ /* If _PAGE_BIT_PRESENT is clear, we use these: */
+@@ -36,7 +35,6 @@
#define _PAGE_DIRTY (_AT(pteval_t, 1) << _PAGE_BIT_DIRTY)
#define _PAGE_PSE (_AT(pteval_t, 1) << _PAGE_BIT_PSE)
#define _PAGE_GLOBAL (_AT(pteval_t, 1) << _PAGE_BIT_GLOBAL)
@@ -5301,7 +5841,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/pgtable.h linux-2.6.28.8/arch/x86
#define _PAGE_IOMAP (_AT(pteval_t, 1) << _PAGE_BIT_IOMAP)
#define _PAGE_UNUSED3 (_AT(pteval_t, 1) << _PAGE_BIT_UNUSED3)
#define _PAGE_PAT (_AT(pteval_t, 1) << _PAGE_BIT_PAT)
-@@ -43,7 +41,7 @@
+@@ -48,7 +46,7 @@
#if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
#define _PAGE_NX (_AT(pteval_t, 1) << _PAGE_BIT_NX)
#else
@@ -5309,8 +5849,8 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/pgtable.h linux-2.6.28.8/arch/x86
+#define _PAGE_NX (_AT(pteval_t, 1) << _PAGE_BIT_UNUSED3)
#endif
- /* If _PAGE_PRESENT is clear, we use these: */
-@@ -83,6 +81,9 @@
+ #define _PAGE_FILE (_AT(pteval_t, 1) << _PAGE_BIT_FILE)
+@@ -85,6 +83,9 @@
#define PAGE_READONLY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | \
_PAGE_ACCESSED)
@@ -5320,16 +5860,18 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/pgtable.h linux-2.6.28.8/arch/x86
#define __PAGE_KERNEL_EXEC \
(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_GLOBAL)
#define __PAGE_KERNEL (__PAGE_KERNEL_EXEC | _PAGE_NX)
-@@ -94,7 +95,7 @@
+@@ -95,8 +96,8 @@
+ #define __PAGE_KERNEL_WC (__PAGE_KERNEL | _PAGE_CACHE_WC)
#define __PAGE_KERNEL_NOCACHE (__PAGE_KERNEL | _PAGE_PCD | _PAGE_PWT)
#define __PAGE_KERNEL_UC_MINUS (__PAGE_KERNEL | _PAGE_PCD)
- #define __PAGE_KERNEL_VSYSCALL (__PAGE_KERNEL_RX | _PAGE_USER)
+-#define __PAGE_KERNEL_VSYSCALL (__PAGE_KERNEL_RX | _PAGE_USER)
-#define __PAGE_KERNEL_VSYSCALL_NOCACHE (__PAGE_KERNEL_VSYSCALL | _PAGE_PCD | _PAGE_PWT)
++#define __PAGE_KERNEL_VSYSCALL (__PAGE_KERNEL_RO | _PAGE_USER)
+#define __PAGE_KERNEL_VSYSCALL_NOCACHE (__PAGE_KERNEL_RO | _PAGE_PCD | _PAGE_PWT | _PAGE_USER)
#define __PAGE_KERNEL_LARGE (__PAGE_KERNEL | _PAGE_PSE)
#define __PAGE_KERNEL_LARGE_NOCACHE (__PAGE_KERNEL | _PAGE_CACHE_UC | _PAGE_PSE)
#define __PAGE_KERNEL_LARGE_EXEC (__PAGE_KERNEL_EXEC | _PAGE_PSE)
-@@ -153,7 +154,7 @@
+@@ -155,7 +156,7 @@
* bits are combined, this will alow user to access the high address mapped
* VDSO in the presence of CONFIG_COMPAT_VDSO
*/
@@ -5338,7 +5880,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/pgtable.h linux-2.6.28.8/arch/x86
#define PDE_IDENT_ATTR 0x067 /* PRESENT+RW+USER+DIRTY+ACCESSED */
#define PGD_IDENT_ATTR 0x001 /* PRESENT (no other attributes) */
#endif
-@@ -170,10 +171,17 @@ extern unsigned long empty_zero_page[PAG
+@@ -183,10 +184,17 @@ extern unsigned long empty_zero_page[PAG
extern spinlock_t pgd_lock;
extern struct list_head pgd_list;
@@ -5356,7 +5898,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/pgtable.h linux-2.6.28.8/arch/x86
static inline int pte_dirty(pte_t pte)
{
return pte_flags(pte) & _PAGE_DIRTY;
-@@ -242,9 +250,29 @@ static inline pte_t pte_wrprotect(pte_t
+@@ -255,9 +263,29 @@ static inline pte_t pte_wrprotect(pte_t
return __pte(pte_val(pte) & ~_PAGE_RW);
}
@@ -5387,16 +5929,16 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/pgtable.h linux-2.6.28.8/arch/x86
}
static inline pte_t pte_mkdirty(pte_t pte)
-@@ -287,8 +315,6 @@ static inline pte_t pte_mkspecial(pte_t
+@@ -300,8 +328,6 @@ static inline pte_t pte_mkspecial(pte_t
return __pte(pte_val(pte) | _PAGE_SPECIAL);
}
-extern pteval_t __supported_pte_mask;
-
- static inline pte_t pfn_pte(unsigned long page_nr, pgprot_t pgprot)
- {
- return __pte((((phys_addr_t)page_nr << PAGE_SHIFT) |
-@@ -552,7 +578,19 @@ static inline void ptep_set_wrprotect(st
+ /*
+ * Mask out unsupported bits in a present pgprot. Non-present pgprots
+ * can use those bits for other purposes, so leave them be.
+@@ -601,7 +627,19 @@ static inline void ptep_set_wrprotect(st
*/
static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count)
{
@@ -5417,10 +5959,10 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/pgtable.h linux-2.6.28.8/arch/x86
}
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/processor.h linux-2.6.28.8/arch/x86/include/asm/processor.h
---- linux-2.6.28.8/arch/x86/include/asm/processor.h 2009-03-07 10:24:49.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/processor.h 2009-03-07 10:29:51.000000000 -0500
-@@ -271,7 +271,7 @@ struct tss_struct {
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/processor.h linux-2.6.29.5/arch/x86/include/asm/processor.h
+--- linux-2.6.29.5/arch/x86/include/asm/processor.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/processor.h 2009-06-12 23:57:32.000000000 -0400
+@@ -275,7 +275,7 @@ struct tss_struct {
} ____cacheline_aligned;
@@ -5429,7 +5971,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/processor.h linux-2.6.28.8/arch/x
/*
* Save the original ist values for checking stack pointers during debugging
-@@ -822,11 +822,20 @@ static inline void spin_lock_prefetch(co
+@@ -839,11 +839,20 @@ static inline void spin_lock_prefetch(co
* User space process size: 3GB (default).
*/
#define TASK_SIZE PAGE_OFFSET
@@ -5452,7 +5994,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/processor.h linux-2.6.28.8/arch/x
.vm86_info = NULL, \
.sysenter_cs = __KERNEL_CS, \
.io_bitmap_ptr = NULL, \
-@@ -841,7 +850,7 @@ static inline void spin_lock_prefetch(co
+@@ -858,7 +867,7 @@ static inline void spin_lock_prefetch(co
*/
#define INIT_TSS { \
.x86_tss = { \
@@ -5461,7 +6003,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/processor.h linux-2.6.28.8/arch/x
.ss0 = __KERNEL_DS, \
.ss1 = __KERNEL_CS, \
.io_bitmap_base = INVALID_IO_BITMAP_OFFSET, \
-@@ -852,11 +861,7 @@ static inline void spin_lock_prefetch(co
+@@ -869,11 +878,7 @@ static inline void spin_lock_prefetch(co
extern unsigned long thread_saved_pc(struct task_struct *tsk);
#define THREAD_SIZE_LONGS (THREAD_SIZE/sizeof(unsigned long))
@@ -5474,7 +6016,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/processor.h linux-2.6.28.8/arch/x
/*
* The below -8 is to reserve 8 bytes on top of the ring0 stack.
-@@ -871,7 +876,7 @@ extern unsigned long thread_saved_pc(str
+@@ -888,7 +893,7 @@ extern unsigned long thread_saved_pc(str
#define task_pt_regs(task) \
({ \
struct pt_regs *__regs__; \
@@ -5483,7 +6025,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/processor.h linux-2.6.28.8/arch/x
__regs__ - 1; \
})
-@@ -887,7 +892,7 @@ extern unsigned long thread_saved_pc(str
+@@ -904,7 +909,7 @@ extern unsigned long thread_saved_pc(str
* space during mmap's.
*/
#define IA32_PAGE_OFFSET ((current->personality & ADDR_LIMIT_3GB) ? \
@@ -5492,7 +6034,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/processor.h linux-2.6.28.8/arch/x
#define TASK_SIZE (test_thread_flag(TIF_IA32) ? \
IA32_PAGE_OFFSET : TASK_SIZE64)
-@@ -924,6 +929,10 @@ extern void start_thread(struct pt_regs
+@@ -941,6 +946,10 @@ extern void start_thread(struct pt_regs
*/
#define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 3))
@@ -5503,10 +6045,10 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/processor.h linux-2.6.28.8/arch/x
#define KSTK_EIP(task) (task_pt_regs(task)->ip)
/* Get/set a process' ability to use the timestamp counter instruction */
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/ptrace.h linux-2.6.28.8/arch/x86/include/asm/ptrace.h
---- linux-2.6.28.8/arch/x86/include/asm/ptrace.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/ptrace.h 2009-02-21 09:37:48.000000000 -0500
-@@ -187,28 +187,29 @@ static inline unsigned long regs_return_
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/ptrace.h linux-2.6.29.5/arch/x86/include/asm/ptrace.h
+--- linux-2.6.29.5/arch/x86/include/asm/ptrace.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/ptrace.h 2009-06-12 23:57:32.000000000 -0400
+@@ -151,28 +151,29 @@ static inline unsigned long regs_return_
}
/*
@@ -5542,20 +6084,21 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/ptrace.h linux-2.6.28.8/arch/x86/
#endif
}
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/reboot.h linux-2.6.28.8/arch/x86/include/asm/reboot.h
---- linux-2.6.28.8/arch/x86/include/asm/reboot.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/reboot.h 2009-02-21 09:37:48.000000000 -0500
-@@ -16,6 +16,6 @@ extern struct machine_ops machine_ops;
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/reboot.h linux-2.6.29.5/arch/x86/include/asm/reboot.h
+--- linux-2.6.29.5/arch/x86/include/asm/reboot.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/reboot.h 2009-06-12 23:57:32.000000000 -0400
+@@ -18,7 +18,7 @@ extern struct machine_ops machine_ops;
void native_machine_crash_shutdown(struct pt_regs *regs);
void native_machine_shutdown(void);
-void machine_real_restart(const unsigned char *code, int length);
+void machine_real_restart(const unsigned char *code, unsigned int length);
- #endif /* _ASM_X86_REBOOT_H */
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/rwsem.h linux-2.6.28.8/arch/x86/include/asm/rwsem.h
---- linux-2.6.28.8/arch/x86/include/asm/rwsem.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/rwsem.h 2009-02-21 09:37:48.000000000 -0500
+ typedef void (*nmi_shootdown_cb)(int, struct die_args*);
+ void nmi_shootdown_cpus(nmi_shootdown_cb callback);
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/rwsem.h linux-2.6.29.5/arch/x86/include/asm/rwsem.h
+--- linux-2.6.29.5/arch/x86/include/asm/rwsem.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/rwsem.h 2009-06-12 23:57:32.000000000 -0400
@@ -106,10 +106,26 @@ static inline void __down_read(struct rw
{
asm volatile("# beginning down_read\n\t"
@@ -5788,9 +6331,9 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/rwsem.h linux-2.6.28.8/arch/x86/i
: "+r" (tmp), "+m" (sem->count)
: : "memory");
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/segment.h linux-2.6.28.8/arch/x86/include/asm/segment.h
---- linux-2.6.28.8/arch/x86/include/asm/segment.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/segment.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/segment.h linux-2.6.29.5/arch/x86/include/asm/segment.h
+--- linux-2.6.29.5/arch/x86/include/asm/segment.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/segment.h 2009-06-12 23:57:32.000000000 -0400
@@ -88,13 +88,19 @@
#define GDT_ENTRY_ESPFIX_SS (GDT_ENTRY_KERNEL_BASE + 14)
#define __ESPFIX_SS (GDT_ENTRY_ESPFIX_SS * 8)
@@ -5821,10 +6364,10 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/segment.h linux-2.6.28.8/arch/x86
#else
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/spinlock.h linux-2.6.28.8/arch/x86/include/asm/spinlock.h
---- linux-2.6.28.8/arch/x86/include/asm/spinlock.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/spinlock.h 2009-02-21 09:37:48.000000000 -0500
-@@ -310,18 +310,50 @@ static inline int __raw_write_can_lock(r
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/spinlock.h linux-2.6.29.5/arch/x86/include/asm/spinlock.h
+--- linux-2.6.29.5/arch/x86/include/asm/spinlock.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/spinlock.h 2009-06-12 23:57:32.000000000 -0400
+@@ -311,18 +311,50 @@ static inline int __raw_write_can_lock(r
static inline void __raw_read_lock(raw_rwlock_t *rw)
{
asm volatile(LOCK_PREFIX " subl $1,(%0)\n\t"
@@ -5879,7 +6422,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/spinlock.h linux-2.6.28.8/arch/x8
::LOCK_PTR_REG (rw), "i" (RW_LOCK_BIAS) : "memory");
}
-@@ -348,12 +380,45 @@ static inline int __raw_write_trylock(ra
+@@ -349,12 +381,45 @@ static inline int __raw_write_trylock(ra
static inline void __raw_read_unlock(raw_rwlock_t *rw)
{
@@ -5927,9 +6470,9 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/spinlock.h linux-2.6.28.8/arch/x8
: "+m" (rw->lock) : "i" (RW_LOCK_BIAS) : "memory");
}
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/system.h linux-2.6.28.8/arch/x86/include/asm/system.h
---- linux-2.6.28.8/arch/x86/include/asm/system.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/system.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/system.h linux-2.6.29.5/arch/x86/include/asm/system.h
+--- linux-2.6.29.5/arch/x86/include/asm/system.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/system.h 2009-06-12 23:57:32.000000000 -0400
@@ -95,6 +95,8 @@ do { \
".globl thread_return\n" \
"thread_return:\n\t" \
@@ -5990,9 +6533,92 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/system.h linux-2.6.28.8/arch/x86/
extern void free_init_pages(char *what, unsigned long begin, unsigned long end);
void default_idle(void);
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/uaccess_64.h linux-2.6.28.8/arch/x86/include/asm/uaccess_64.h
---- linux-2.6.28.8/arch/x86/include/asm/uaccess_64.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/uaccess_64.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/uaccess_32.h linux-2.6.29.5/arch/x86/include/asm/uaccess_32.h
+--- linux-2.6.29.5/arch/x86/include/asm/uaccess_32.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/uaccess_32.h 2009-06-12 23:57:32.000000000 -0400
+@@ -62,6 +62,8 @@ __copy_to_user_inatomic(void __user *to,
+ return ret;
+ }
+ }
++ if (!__builtin_constant_p(n))
++ check_object_size(from, n, true);
+ return __copy_to_user_ll(to, from, n);
+ }
+
+@@ -153,6 +155,8 @@ __copy_from_user(void *to, const void __
+ return ret;
+ }
+ }
++ if (!__builtin_constant_p(n))
++ check_object_size(to, n, false);
+ return __copy_from_user_ll(to, from, n);
+ }
+
+@@ -185,11 +189,56 @@ __copy_from_user_inatomic_nocache(void *
+ return __copy_from_user_ll_nocache_nozero(to, from, n);
+ }
+
+-unsigned long __must_check copy_to_user(void __user *to,
+- const void *from, unsigned long n);
+-unsigned long __must_check copy_from_user(void *to,
+- const void __user *from,
+- unsigned long n);
++/**
++ * copy_to_user: - Copy a block of data into user space.
++ * @to: Destination address, in user space.
++ * @from: Source address, in kernel space.
++ * @n: Number of bytes to copy.
++ *
++ * Context: User context only. This function may sleep.
++ *
++ * Copy data from kernel space to user space.
++ *
++ * Returns number of bytes that could not be copied.
++ * On success, this will be zero.
++ */
++static __always_inline unsigned long __must_check
++copy_to_user(void __user *to, const void *from, unsigned long n)
++{
++ if (access_ok(VERIFY_WRITE, to, n))
++ n = __copy_to_user(to, from, n);
++ return n;
++}
++
++/**
++ * copy_from_user: - Copy a block of data from user space.
++ * @to: Destination address, in kernel space.
++ * @from: Source address, in user space.
++ * @n: Number of bytes to copy.
++ *
++ * Context: User context only. This function may sleep.
++ *
++ * Copy data from user space to kernel space.
++ *
++ * Returns number of bytes that could not be copied.
++ * On success, this will be zero.
++ *
++ * If some data could not be copied, this function will pad the copied
++ * data to the requested size using zero bytes.
++ */
++static __always_inline unsigned long __must_check
++copy_from_user(void *to, const void __user *from, unsigned long n)
++{
++ if (access_ok(VERIFY_READ, from, n))
++ n = __copy_from_user(to, from, n);
++ else if ((long)n > 0) {
++ if (!__builtin_constant_p(n))
++ check_object_size(to, n, false);
++ memset(to, 0, n);
++ }
++ return n;
++}
++
+ long __must_check strncpy_from_user(char *dst, const char __user *src,
+ long count);
+ long __must_check __strncpy_from_user(char *dst,
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/uaccess_64.h linux-2.6.29.5/arch/x86/include/asm/uaccess_64.h
+--- linux-2.6.29.5/arch/x86/include/asm/uaccess_64.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/uaccess_64.h 2009-06-12 23:57:32.000000000 -0400
@@ -10,6 +10,8 @@
#include <linux/lockdep.h>
#include <asm/page.h>
@@ -6002,18 +6628,135 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/uaccess_64.h linux-2.6.28.8/arch/
/*
* Copy To/From Userspace
*/
-diff -urNp linux-2.6.28.8/arch/x86/include/asm/uaccess.h linux-2.6.28.8/arch/x86/include/asm/uaccess.h
---- linux-2.6.28.8/arch/x86/include/asm/uaccess.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/include/asm/uaccess.h 2009-02-21 09:37:48.000000000 -0500
-@@ -10,6 +10,7 @@
+@@ -19,20 +21,18 @@ __must_check unsigned long
+ copy_user_generic(void *to, const void *from, unsigned len);
+
+ __must_check unsigned long
+-copy_to_user(void __user *to, const void *from, unsigned len);
+-__must_check unsigned long
+-copy_from_user(void *to, const void __user *from, unsigned len);
+-__must_check unsigned long
+ copy_in_user(void __user *to, const void __user *from, unsigned len);
+
+ static __always_inline __must_check
+-int __copy_from_user(void *dst, const void __user *src, unsigned size)
++unsigned long __copy_from_user(void *dst, const void __user *src, unsigned size)
+ {
+- int ret = 0;
++ unsigned ret = 0;
+
+ might_fault();
+- if (!__builtin_constant_p(size))
++ if (!__builtin_constant_p(size)) {
++ check_object_size(dst, size, false);
+ return copy_user_generic(dst, (__force void *)src, size);
++ }
+ switch (size) {
+ case 1:__get_user_asm(*(u8 *)dst, (u8 __user *)src,
+ ret, "b", "b", "=q", 1);
+@@ -70,13 +70,15 @@ int __copy_from_user(void *dst, const vo
+ }
+
+ static __always_inline __must_check
+-int __copy_to_user(void __user *dst, const void *src, unsigned size)
++unsigned long __copy_to_user(void __user *dst, const void *src, unsigned size)
+ {
+- int ret = 0;
++ unsigned ret = 0;
+
+ might_fault();
+- if (!__builtin_constant_p(size))
++ if (!__builtin_constant_p(size)) {
++ check_object_size(src, size, true);
+ return copy_user_generic((__force void *)dst, src, size);
++ }
+ switch (size) {
+ case 1:__put_user_asm(*(u8 *)src, (u8 __user *)dst,
+ ret, "b", "b", "iq", 1);
+@@ -114,9 +116,30 @@ int __copy_to_user(void __user *dst, con
+ }
+
+ static __always_inline __must_check
+-int __copy_in_user(void __user *dst, const void __user *src, unsigned size)
++unsigned long copy_to_user(void __user *to, const void *from, unsigned len)
++{
++ if (access_ok(VERIFY_WRITE, to, len))
++ len = __copy_to_user(to, from, len);
++ return len;
++}
++
++static __always_inline __must_check
++unsigned long copy_from_user(void *to, const void __user *from, unsigned len)
++{
++ if (access_ok(VERIFY_READ, from, len))
++ len = __copy_from_user(to, from, len);
++ else if ((int)len > 0) {
++ if (!__builtin_constant_p(len))
++ check_object_size(to, len, false);
++ memset(to, 0, len);
++ }
++ return len;
++}
++
++static __always_inline __must_check
++unsigned long __copy_in_user(void __user *dst, const void __user *src, unsigned size)
+ {
+- int ret = 0;
++ unsigned ret = 0;
+
+ might_fault();
+ if (!__builtin_constant_p(size))
+@@ -179,30 +202,30 @@ __must_check unsigned long __clear_user(
+ __must_check long __copy_from_user_inatomic(void *dst, const void __user *src,
+ unsigned size);
+
+-static __must_check __always_inline int
++static __must_check __always_inline unsigned long
+ __copy_to_user_inatomic(void __user *dst, const void *src, unsigned size)
+ {
+ return copy_user_generic((__force void *)dst, src, size);
+ }
+
+-extern long __copy_user_nocache(void *dst, const void __user *src,
++extern unsigned __copy_user_nocache(void *dst, const void __user *src,
+ unsigned size, int zerorest);
+
+-static inline int __copy_from_user_nocache(void *dst, const void __user *src,
++static inline unsigned long __copy_from_user_nocache(void *dst, const void __user *src,
+ unsigned size)
+ {
+ might_sleep();
+ return __copy_user_nocache(dst, src, size, 1);
+ }
+
+-static inline int __copy_from_user_inatomic_nocache(void *dst,
++static inline unsigned long __copy_from_user_inatomic_nocache(void *dst,
+ const void __user *src,
+ unsigned size)
+ {
+ return __copy_user_nocache(dst, src, size, 0);
+ }
+
+-unsigned long
++extern unsigned long
+ copy_user_handle_tail(char *to, char *from, unsigned len, unsigned zerorest);
+
+ #endif /* _ASM_X86_UACCESS_64_H */
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/uaccess.h linux-2.6.29.5/arch/x86/include/asm/uaccess.h
+--- linux-2.6.29.5/arch/x86/include/asm/uaccess.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/uaccess.h 2009-06-12 23:57:32.000000000 -0400
+@@ -8,8 +8,10 @@
+ #include <linux/thread_info.h>
+ #include <linux/prefetch.h>
#include <linux/string.h>
++#include <linux/slab.h>
#include <asm/asm.h>
#include <asm/page.h>
+#include <asm/segment.h>
#define VERIFY_READ 0
#define VERIFY_WRITE 1
-@@ -29,7 +30,12 @@
+@@ -29,7 +31,12 @@
#define get_ds() (KERNEL_DS)
#define get_fs() (current_thread_info()->addr_limit)
@@ -6026,7 +6769,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/uaccess.h linux-2.6.28.8/arch/x86
#define segment_eq(a, b) ((a).seg == (b).seg)
-@@ -186,9 +192,12 @@ extern int __get_user_bad(void);
+@@ -187,9 +194,12 @@ extern int __get_user_bad(void);
#ifdef CONFIG_X86_32
#define __put_user_u64(x, addr, err) \
@@ -6041,7 +6784,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/uaccess.h linux-2.6.28.8/arch/x86
".section .fixup,\"ax\"\n" \
"4: movl %3,%0\n" \
" jmp 3b\n" \
-@@ -196,7 +205,8 @@ extern int __get_user_bad(void);
+@@ -197,7 +207,8 @@ extern int __get_user_bad(void);
_ASM_EXTABLE(1b, 4b) \
_ASM_EXTABLE(2b, 4b) \
: "=r" (err) \
@@ -6051,7 +6794,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/uaccess.h linux-2.6.28.8/arch/x86
#define __put_user_x8(x, ptr, __ret_pu) \
asm volatile("call __put_user_8" : "=a" (__ret_pu) \
-@@ -336,6 +346,22 @@ do { \
+@@ -338,6 +349,22 @@ do { \
} \
} while (0)
@@ -6074,7 +6817,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/uaccess.h linux-2.6.28.8/arch/x86
#define __get_user_asm(x, addr, err, itype, rtype, ltype, errret) \
asm volatile("1: mov"itype" %2,%"rtype"1\n" \
"2:\n" \
-@@ -347,6 +373,7 @@ do { \
+@@ -349,6 +376,7 @@ do { \
_ASM_EXTABLE(1b, 3b) \
: "=r" (err), ltype(x) \
: "m" (__m(addr)), "i" (errret), "0" (err))
@@ -6082,7 +6825,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/uaccess.h linux-2.6.28.8/arch/x86
#define __put_user_nocheck(x, ptr, size) \
({ \
-@@ -373,6 +400,22 @@ struct __large_struct { unsigned long bu
+@@ -375,6 +403,22 @@ struct __large_struct { unsigned long bu
* we do not write to any memory gcc knows about, so there are no
* aliasing issues.
*/
@@ -6105,7 +6848,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/uaccess.h linux-2.6.28.8/arch/x86
#define __put_user_asm(x, addr, err, itype, rtype, ltype, errret) \
asm volatile("1: mov"itype" %"rtype"1,%2\n" \
"2:\n" \
-@@ -383,6 +426,7 @@ struct __large_struct { unsigned long bu
+@@ -385,6 +429,7 @@ struct __large_struct { unsigned long bu
_ASM_EXTABLE(1b, 3b) \
: "=r"(err) \
: ltype(x), "m" (__m(addr)), "i" (errret), "0" (err))
@@ -6113,7 +6856,7 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/uaccess.h linux-2.6.28.8/arch/x86
/**
* __get_user: - Get a simple variable from user space, with less checking.
* @x: Variable to store result.
-@@ -443,6 +487,7 @@ extern struct movsl_mask {
+@@ -445,6 +490,7 @@ extern struct movsl_mask {
#define ARCH_HAS_NOCACHE_UACCESS 1
@@ -6121,10 +6864,54 @@ diff -urNp linux-2.6.28.8/arch/x86/include/asm/uaccess.h linux-2.6.28.8/arch/x86
#ifdef CONFIG_X86_32
# include "uaccess_32.h"
#else
-diff -urNp linux-2.6.28.8/arch/x86/Kconfig linux-2.6.28.8/arch/x86/Kconfig
---- linux-2.6.28.8/arch/x86/Kconfig 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/Kconfig 2009-02-21 09:37:48.000000000 -0500
-@@ -935,7 +935,7 @@ config PAGE_OFFSET
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/vgtod.h linux-2.6.29.5/arch/x86/include/asm/vgtod.h
+--- linux-2.6.29.5/arch/x86/include/asm/vgtod.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/vgtod.h 2009-06-12 23:57:32.000000000 -0400
+@@ -14,6 +14,7 @@ struct vsyscall_gtod_data {
+ int sysctl_enabled;
+ struct timezone sys_tz;
+ struct { /* extract of a clocksource struct */
++ char name[8];
+ cycle_t (*vread)(void);
+ cycle_t cycle_last;
+ cycle_t mask;
+diff -urNp linux-2.6.29.5/arch/x86/include/asm/vsyscall.h linux-2.6.29.5/arch/x86/include/asm/vsyscall.h
+--- linux-2.6.29.5/arch/x86/include/asm/vsyscall.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/include/asm/vsyscall.h 2009-06-12 23:57:32.000000000 -0400
+@@ -15,9 +15,10 @@ enum vsyscall_num {
+
+ #ifdef __KERNEL__
+ #include <linux/seqlock.h>
++#include <linux/getcpu.h>
++#include <linux/time.h>
+
+ #define __section_vgetcpu_mode __attribute__ ((unused, __section__ (".vgetcpu_mode"), aligned(16)))
+-#define __section_jiffies __attribute__ ((unused, __section__ (".jiffies"), aligned(16)))
+
+ /* Definitions for CONFIG_GENERIC_TIME definitions */
+ #define __section_vsyscall_gtod_data __attribute__ \
+@@ -31,7 +32,6 @@ enum vsyscall_num {
+ #define VGETCPU_LSL 2
+
+ extern int __vgetcpu_mode;
+-extern volatile unsigned long __jiffies;
+
+ /* kernel space (writeable) */
+ extern int vgetcpu_mode;
+@@ -39,6 +39,9 @@ extern struct timezone sys_tz;
+
+ extern void map_vsyscall(void);
+
++extern int vgettimeofday(struct timeval * tv, struct timezone * tz);
++extern time_t vtime(time_t *t);
++extern long vgetcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache);
+ #endif /* __KERNEL__ */
+
+ #endif /* _ASM_X86_VSYSCALL_H */
+diff -urNp linux-2.6.29.5/arch/x86/Kconfig linux-2.6.29.5/arch/x86/Kconfig
+--- linux-2.6.29.5/arch/x86/Kconfig 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/Kconfig 2009-06-12 23:57:32.000000000 -0400
+@@ -993,7 +993,7 @@ config PAGE_OFFSET
hex
default 0xB0000000 if VMSPLIT_3G_OPT
default 0x80000000 if VMSPLIT_2G
@@ -6133,7 +6920,7 @@ diff -urNp linux-2.6.28.8/arch/x86/Kconfig linux-2.6.28.8/arch/x86/Kconfig
default 0x40000000 if VMSPLIT_1G
default 0xC0000000
depends on X86_32
-@@ -1337,8 +1337,7 @@ config KEXEC_JUMP
+@@ -1408,8 +1408,7 @@ config KEXEC_JUMP
config PHYSICAL_START
hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP)
default "0x1000000" if X86_NUMAQ
@@ -6143,7 +6930,7 @@ diff -urNp linux-2.6.28.8/arch/x86/Kconfig linux-2.6.28.8/arch/x86/Kconfig
help
This gives the physical address where the kernel is loaded.
-@@ -1430,9 +1429,9 @@ config HOTPLUG_CPU
+@@ -1501,9 +1500,9 @@ config HOTPLUG_CPU
Say N if you want to disable CPU hotplug.
config COMPAT_VDSO
@@ -6155,10 +6942,10 @@ diff -urNp linux-2.6.28.8/arch/x86/Kconfig linux-2.6.28.8/arch/x86/Kconfig
help
Map the 32-bit VDSO to the predictable old-style address too.
---help---
-diff -urNp linux-2.6.28.8/arch/x86/Kconfig.cpu linux-2.6.28.8/arch/x86/Kconfig.cpu
---- linux-2.6.28.8/arch/x86/Kconfig.cpu 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/Kconfig.cpu 2009-02-21 09:37:48.000000000 -0500
-@@ -331,7 +331,7 @@ config X86_PPRO_FENCE
+diff -urNp linux-2.6.29.5/arch/x86/Kconfig.cpu linux-2.6.29.5/arch/x86/Kconfig.cpu
+--- linux-2.6.29.5/arch/x86/Kconfig.cpu 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/Kconfig.cpu 2009-06-12 23:57:32.000000000 -0400
+@@ -333,7 +333,7 @@ config X86_PPRO_FENCE
config X86_F00F_BUG
def_bool y
@@ -6167,7 +6954,7 @@ diff -urNp linux-2.6.28.8/arch/x86/Kconfig.cpu linux-2.6.28.8/arch/x86/Kconfig.c
config X86_WP_WORKS_OK
def_bool y
-@@ -351,7 +351,7 @@ config X86_POPAD_OK
+@@ -353,7 +353,7 @@ config X86_POPAD_OK
config X86_ALIGNMENT_16
def_bool y
@@ -6176,7 +6963,7 @@ diff -urNp linux-2.6.28.8/arch/x86/Kconfig.cpu linux-2.6.28.8/arch/x86/Kconfig.c
config X86_INTEL_USERCOPY
def_bool y
-@@ -397,7 +397,7 @@ config X86_CMPXCHG64
+@@ -399,7 +399,7 @@ config X86_CMPXCHG64
# generates cmov.
config X86_CMOV
def_bool y
@@ -6185,9 +6972,9 @@ diff -urNp linux-2.6.28.8/arch/x86/Kconfig.cpu linux-2.6.28.8/arch/x86/Kconfig.c
config X86_MINIMUM_CPU_FAMILY
int
-diff -urNp linux-2.6.28.8/arch/x86/Kconfig.debug linux-2.6.28.8/arch/x86/Kconfig.debug
---- linux-2.6.28.8/arch/x86/Kconfig.debug 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/Kconfig.debug 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/Kconfig.debug linux-2.6.29.5/arch/x86/Kconfig.debug
+--- linux-2.6.29.5/arch/x86/Kconfig.debug 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/Kconfig.debug 2009-06-12 23:57:32.000000000 -0400
@@ -107,7 +107,7 @@ config X86_PTDUMP
config DEBUG_RODATA
bool "Write protect kernel read-only data structures"
@@ -6197,10 +6984,10 @@ diff -urNp linux-2.6.28.8/arch/x86/Kconfig.debug linux-2.6.28.8/arch/x86/Kconfig
help
Mark the kernel read-only data as write-protected in the pagetables,
in order to catch accidental (and incorrect) writes to such const
-diff -urNp linux-2.6.28.8/arch/x86/kernel/acpi/boot.c linux-2.6.28.8/arch/x86/kernel/acpi/boot.c
---- linux-2.6.28.8/arch/x86/kernel/acpi/boot.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/acpi/boot.c 2009-02-21 09:37:48.000000000 -0500
-@@ -1645,7 +1645,7 @@ static struct dmi_system_id __initdata a
+diff -urNp linux-2.6.29.5/arch/x86/kernel/acpi/boot.c linux-2.6.29.5/arch/x86/kernel/acpi/boot.c
+--- linux-2.6.29.5/arch/x86/kernel/acpi/boot.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/acpi/boot.c 2009-06-12 23:57:32.000000000 -0400
+@@ -1705,7 +1705,7 @@ static struct dmi_system_id __initdata a
DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6715b"),
},
},
@@ -6209,9 +6996,9 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/acpi/boot.c linux-2.6.28.8/arch/x86/ke
};
/*
-diff -urNp linux-2.6.28.8/arch/x86/kernel/acpi/realmode/wakeup.S linux-2.6.28.8/arch/x86/kernel/acpi/realmode/wakeup.S
---- linux-2.6.28.8/arch/x86/kernel/acpi/realmode/wakeup.S 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/acpi/realmode/wakeup.S 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/kernel/acpi/realmode/wakeup.S linux-2.6.29.5/arch/x86/kernel/acpi/realmode/wakeup.S
+--- linux-2.6.29.5/arch/x86/kernel/acpi/realmode/wakeup.S 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/acpi/realmode/wakeup.S 2009-06-12 23:57:32.000000000 -0400
@@ -104,7 +104,7 @@ _start:
movl %eax, %ecx
orl %edx, %ecx
@@ -6221,10 +7008,24 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/acpi/realmode/wakeup.S linux-2.6.28.8/
wrmsr
1:
-diff -urNp linux-2.6.28.8/arch/x86/kernel/acpi/sleep.c linux-2.6.28.8/arch/x86/kernel/acpi/sleep.c
---- linux-2.6.28.8/arch/x86/kernel/acpi/sleep.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/acpi/sleep.c 2009-02-21 09:37:48.000000000 -0500
-@@ -37,6 +37,10 @@ int acpi_save_state_mem(void)
+diff -urNp linux-2.6.29.5/arch/x86/kernel/acpi/sleep.c linux-2.6.29.5/arch/x86/kernel/acpi/sleep.c
+--- linux-2.6.29.5/arch/x86/kernel/acpi/sleep.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/acpi/sleep.c 2009-06-12 23:57:32.000000000 -0400
+@@ -11,11 +11,12 @@
+ #include <linux/cpumask.h>
+ #include <asm/segment.h>
+ #include <asm/desc.h>
++#include <asm/e820.h>
+
+ #include "realmode/wakeup.h"
+ #include "sleep.h"
+
+-unsigned long acpi_wakeup_address;
++unsigned long acpi_wakeup_address = 0x2000;
+ unsigned long acpi_realmode_flags;
+
+ /* address in low memory of the wakeup routine. */
+@@ -37,6 +38,10 @@ int acpi_save_state_mem(void)
{
struct wakeup_header *header;
@@ -6235,7 +7036,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/acpi/sleep.c linux-2.6.28.8/arch/x86/k
if (!acpi_realmode) {
printk(KERN_ERR "Could not allocate memory during boot, "
"S3 disabled\n");
-@@ -99,8 +103,18 @@ int acpi_save_state_mem(void)
+@@ -99,8 +104,18 @@ int acpi_save_state_mem(void)
header->trampoline_segment = setup_trampoline() >> 4;
#ifdef CONFIG_SMP
stack_start.sp = temp_stack + sizeof(temp_stack);
@@ -6254,9 +7055,26 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/acpi/sleep.c linux-2.6.28.8/arch/x86/k
#endif
initial_code = (unsigned long)wakeup_long64;
saved_magic = 0x123456789abcdef0;
-diff -urNp linux-2.6.28.8/arch/x86/kernel/acpi/wakeup_32.S linux-2.6.28.8/arch/x86/kernel/acpi/wakeup_32.S
---- linux-2.6.28.8/arch/x86/kernel/acpi/wakeup_32.S 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/acpi/wakeup_32.S 2009-02-21 09:37:48.000000000 -0500
+@@ -133,14 +148,8 @@ void __init acpi_reserve_bootmem(void)
+ return;
+ }
+
+- acpi_realmode = (unsigned long)alloc_bootmem_low(WAKEUP_SIZE);
+-
+- if (!acpi_realmode) {
+- printk(KERN_ERR "ACPI: Cannot allocate lowmem, S3 disabled.\n");
+- return;
+- }
+-
+- acpi_wakeup_address = virt_to_phys((void *)acpi_realmode);
++ reserve_early(acpi_wakeup_address, acpi_wakeup_address + WAKEUP_SIZE, "ACPI Wakeup Code");
++ acpi_realmode = (unsigned long)__va(acpi_wakeup_address);;
+ }
+
+
+diff -urNp linux-2.6.29.5/arch/x86/kernel/acpi/wakeup_32.S linux-2.6.29.5/arch/x86/kernel/acpi/wakeup_32.S
+--- linux-2.6.29.5/arch/x86/kernel/acpi/wakeup_32.S 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/acpi/wakeup_32.S 2009-06-12 23:57:32.000000000 -0400
@@ -30,13 +30,11 @@ wakeup_pmode_return:
# and restore the stack ... but you need gdt for this to work
movl saved_context_esp, %esp
@@ -6273,9 +7091,9 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/acpi/wakeup_32.S linux-2.6.28.8/arch/x
bogus_magic:
jmp bogus_magic
-diff -urNp linux-2.6.28.8/arch/x86/kernel/alternative.c linux-2.6.28.8/arch/x86/kernel/alternative.c
---- linux-2.6.28.8/arch/x86/kernel/alternative.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/alternative.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/kernel/alternative.c linux-2.6.29.5/arch/x86/kernel/alternative.c
+--- linux-2.6.29.5/arch/x86/kernel/alternative.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/alternative.c 2009-06-12 23:57:32.000000000 -0400
@@ -393,7 +393,7 @@ void apply_paravirt(struct paravirt_patc
BUG_ON(p->len > MAX_PATCH_LEN);
@@ -6363,10 +7181,10 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/alternative.c linux-2.6.28.8/arch/x86/
+ BUG_ON((vaddr)[i] != ((unsigned char *)opcode)[i]);
return addr;
}
-diff -urNp linux-2.6.28.8/arch/x86/kernel/apm_32.c linux-2.6.28.8/arch/x86/kernel/apm_32.c
---- linux-2.6.28.8/arch/x86/kernel/apm_32.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/apm_32.c 2009-02-21 09:37:48.000000000 -0500
-@@ -407,7 +407,7 @@ static DECLARE_WAIT_QUEUE_HEAD(apm_waitq
+diff -urNp linux-2.6.29.5/arch/x86/kernel/apm_32.c linux-2.6.29.5/arch/x86/kernel/apm_32.c
+--- linux-2.6.29.5/arch/x86/kernel/apm_32.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/apm_32.c 2009-06-12 23:57:32.000000000 -0400
+@@ -403,7 +403,7 @@ static DECLARE_WAIT_QUEUE_HEAD(apm_waitq
static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
static struct apm_user *user_list;
static DEFINE_SPINLOCK(user_list_lock);
@@ -6375,7 +7193,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/apm_32.c linux-2.6.28.8/arch/x86/kerne
static const char driver_version[] = "1.16ac"; /* no spaces */
-@@ -602,19 +602,42 @@ static u8 apm_bios_call(u32 func, u32 eb
+@@ -598,19 +598,42 @@ static u8 apm_bios_call(u32 func, u32 eb
struct desc_struct save_desc_40;
struct desc_struct *gdt;
@@ -6418,7 +7236,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/apm_32.c linux-2.6.28.8/arch/x86/kerne
put_cpu();
apm_restore_cpus(cpus);
-@@ -645,19 +668,42 @@ static u8 apm_bios_call_simple(u32 func,
+@@ -641,19 +664,42 @@ static u8 apm_bios_call_simple(u32 func,
struct desc_struct save_desc_40;
struct desc_struct *gdt;
@@ -6461,7 +7279,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/apm_32.c linux-2.6.28.8/arch/x86/kerne
put_cpu();
apm_restore_cpus(cpus);
return error;
-@@ -929,7 +975,7 @@ recalc:
+@@ -925,7 +971,7 @@ recalc:
static void apm_power_off(void)
{
@@ -6544,9 +7362,9 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/apm_32.c linux-2.6.28.8/arch/x86/kerne
proc_create("apm", 0, NULL, &apm_file_ops);
kapmd_task = kthread_create(apm, NULL, "kapmd");
-diff -urNp linux-2.6.28.8/arch/x86/kernel/asm-offsets_32.c linux-2.6.28.8/arch/x86/kernel/asm-offsets_32.c
---- linux-2.6.28.8/arch/x86/kernel/asm-offsets_32.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/asm-offsets_32.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/kernel/asm-offsets_32.c linux-2.6.29.5/arch/x86/kernel/asm-offsets_32.c
+--- linux-2.6.29.5/arch/x86/kernel/asm-offsets_32.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/asm-offsets_32.c 2009-06-12 23:57:32.000000000 -0400
@@ -100,6 +100,7 @@ void foo(void)
DEFINE(PTRS_PER_PTE, PTRS_PER_PTE);
DEFINE(PTRS_PER_PMD, PTRS_PER_PMD);
@@ -6563,10 +7381,10 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/asm-offsets_32.c linux-2.6.28.8/arch/x
#endif
#ifdef CONFIG_XEN
-diff -urNp linux-2.6.28.8/arch/x86/kernel/asm-offsets_64.c linux-2.6.28.8/arch/x86/kernel/asm-offsets_64.c
---- linux-2.6.28.8/arch/x86/kernel/asm-offsets_64.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/asm-offsets_64.c 2009-02-21 09:37:48.000000000 -0500
-@@ -122,6 +122,7 @@ int main(void)
+diff -urNp linux-2.6.29.5/arch/x86/kernel/asm-offsets_64.c linux-2.6.29.5/arch/x86/kernel/asm-offsets_64.c
+--- linux-2.6.29.5/arch/x86/kernel/asm-offsets_64.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/asm-offsets_64.c 2009-06-12 23:57:32.000000000 -0400
+@@ -124,6 +124,7 @@ int main(void)
ENTRY(cr8);
BLANK();
#undef ENTRY
@@ -6574,9 +7392,9 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/asm-offsets_64.c linux-2.6.28.8/arch/x
DEFINE(TSS_ist, offsetof(struct tss_struct, x86_tss.ist));
BLANK();
DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx));
-diff -urNp linux-2.6.28.8/arch/x86/kernel/cpu/common.c linux-2.6.28.8/arch/x86/kernel/cpu/common.c
---- linux-2.6.28.8/arch/x86/kernel/cpu/common.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/cpu/common.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/kernel/cpu/common.c linux-2.6.29.5/arch/x86/kernel/cpu/common.c
+--- linux-2.6.29.5/arch/x86/kernel/cpu/common.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/cpu/common.c 2009-06-12 23:57:32.000000000 -0400
@@ -2,7 +2,6 @@
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -6585,7 +7403,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/cpu/common.c linux-2.6.28.8/arch/x86/k
#include <linux/bitops.h>
#include <linux/module.h>
#include <linux/kgdb.h>
-@@ -41,59 +40,6 @@
+@@ -62,59 +61,6 @@ cpumask_t cpu_sibling_setup_map;
static struct cpu_dev *this_cpu __cpuinitdata;
@@ -6645,7 +7463,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/cpu/common.c linux-2.6.28.8/arch/x86/k
#ifdef CONFIG_X86_32
static int cachesize_override __cpuinitdata = -1;
static int disable_x86_serial_nr __cpuinitdata = 1;
-@@ -227,7 +173,7 @@ void switch_to_new_gdt(void)
+@@ -248,7 +194,7 @@ void switch_to_new_gdt(void)
{
struct desc_ptr gdt_descr;
@@ -6654,7 +7472,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/cpu/common.c linux-2.6.28.8/arch/x86/k
gdt_descr.size = GDT_SIZE - 1;
load_gdt(&gdt_descr);
#ifdef CONFIG_X86_32
-@@ -687,6 +633,10 @@ static void __cpuinit identify_cpu(struc
+@@ -708,6 +654,10 @@ static void __cpuinit identify_cpu(struc
* we do "generic changes."
*/
@@ -6665,23 +7483,16 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/cpu/common.c linux-2.6.28.8/arch/x86/k
/* If the model name is still unset, do table lookup. */
if (!c->x86_model_id[0]) {
char *p;
-@@ -854,13 +804,13 @@ static __init int setup_disablecpuid(cha
- }
- __setup("clearcpuid=", setup_disablecpuid);
-
--cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE;
-+cpumask_t cpu_initialized = CPU_MASK_NONE;
-
- #ifdef CONFIG_X86_64
+@@ -880,7 +830,7 @@ __setup("clearcpuid=", setup_disablecpui
struct x8664_pda **_cpu_pda __read_mostly;
EXPORT_SYMBOL(_cpu_pda);
-struct desc_ptr idt_descr = { 256 * 16 - 1, (unsigned long) idt_table };
+struct desc_ptr idt_descr __read_only = { 256 * 16 - 1, (unsigned long) idt_table };
- char boot_cpu_stack[IRQSTACKSIZE] __page_aligned_bss;
+ static char boot_cpu_stack[IRQSTACKSIZE] __page_aligned_bss;
-@@ -959,7 +909,7 @@ struct pt_regs * __cpuinit idle_regs(str
+@@ -979,7 +929,7 @@ struct pt_regs * __cpuinit idle_regs(str
void __cpuinit cpu_init(void)
{
int cpu = stack_smp_processor_id();
@@ -6690,7 +7501,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/cpu/common.c linux-2.6.28.8/arch/x86/k
struct orig_ist *orig_ist = &per_cpu(orig_ist, cpu);
unsigned long v;
char *estacks = NULL;
-@@ -1080,7 +1030,7 @@ void __cpuinit cpu_init(void)
+@@ -1100,7 +1050,7 @@ void __cpuinit cpu_init(void)
{
int cpu = smp_processor_id();
struct task_struct *curr = current;
@@ -6698,11 +7509,11 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/cpu/common.c linux-2.6.28.8/arch/x86/k
+ struct tss_struct *t = init_tss + cpu;
struct thread_struct *thread = &curr->thread;
- if (cpu_test_and_set(cpu, cpu_initialized)) {
-diff -urNp linux-2.6.28.8/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c linux-2.6.28.8/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
---- linux-2.6.28.8/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c 2009-02-21 09:37:48.000000000 -0500
-@@ -561,7 +561,7 @@ static const struct dmi_system_id sw_any
+ if (cpumask_test_and_set_cpu(cpu, cpu_initialized_mask)) {
+diff -urNp linux-2.6.29.5/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c linux-2.6.29.5/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
+--- linux-2.6.29.5/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c 2009-06-12 23:57:32.000000000 -0400
+@@ -581,7 +581,7 @@ static const struct dmi_system_id sw_any
DMI_MATCH(DMI_PRODUCT_NAME, "X6DLP"),
},
},
@@ -6711,9 +7522,9 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c linux-2.6.2
};
#endif
-diff -urNp linux-2.6.28.8/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c linux-2.6.28.8/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c
---- linux-2.6.28.8/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c linux-2.6.29.5/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c
+--- linux-2.6.29.5/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c 2009-06-12 23:57:32.000000000 -0400
@@ -225,7 +225,7 @@ static struct cpu_model models[] =
{ &cpu_ids[CPU_MP4HT_D0], NULL, 0, NULL },
{ &cpu_ids[CPU_MP4HT_E0], NULL, 0, NULL },
@@ -6723,10 +7534,10 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c linux
};
#undef _BANIAS
#undef BANIAS
-diff -urNp linux-2.6.28.8/arch/x86/kernel/cpu/intel.c linux-2.6.28.8/arch/x86/kernel/cpu/intel.c
---- linux-2.6.28.8/arch/x86/kernel/cpu/intel.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/cpu/intel.c 2009-02-21 09:37:48.000000000 -0500
-@@ -72,7 +72,7 @@ static void __cpuinit trap_init_f00f_bug
+diff -urNp linux-2.6.29.5/arch/x86/kernel/cpu/intel.c linux-2.6.29.5/arch/x86/kernel/cpu/intel.c
+--- linux-2.6.29.5/arch/x86/kernel/cpu/intel.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/cpu/intel.c 2009-06-12 23:57:32.000000000 -0400
+@@ -94,7 +94,7 @@ static void __cpuinit trap_init_f00f_bug
* Update the IDT descriptor and reload the IDT so that
* it uses the read-only mapped virtual address.
*/
@@ -6735,9 +7546,9 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/cpu/intel.c linux-2.6.28.8/arch/x86/ke
load_idt(&idt_descr);
}
#endif
-diff -urNp linux-2.6.28.8/arch/x86/kernel/cpu/mcheck/mce_64.c linux-2.6.28.8/arch/x86/kernel/cpu/mcheck/mce_64.c
---- linux-2.6.28.8/arch/x86/kernel/cpu/mcheck/mce_64.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/cpu/mcheck/mce_64.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/kernel/cpu/mcheck/mce_64.c linux-2.6.29.5/arch/x86/kernel/cpu/mcheck/mce_64.c
+--- linux-2.6.29.5/arch/x86/kernel/cpu/mcheck/mce_64.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/cpu/mcheck/mce_64.c 2009-06-12 23:57:32.000000000 -0400
@@ -678,6 +678,7 @@ static struct miscdevice mce_log_device
MISC_MCELOG_MINOR,
"mcelog",
@@ -6746,10 +7557,10 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/cpu/mcheck/mce_64.c linux-2.6.28.8/arc
};
static unsigned long old_cr4 __initdata;
-diff -urNp linux-2.6.28.8/arch/x86/kernel/cpu/mtrr/generic.c linux-2.6.28.8/arch/x86/kernel/cpu/mtrr/generic.c
---- linux-2.6.28.8/arch/x86/kernel/cpu/mtrr/generic.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/cpu/mtrr/generic.c 2009-02-21 09:37:48.000000000 -0500
-@@ -31,11 +31,11 @@ static struct fixed_range_block fixed_ra
+diff -urNp linux-2.6.29.5/arch/x86/kernel/cpu/mtrr/generic.c linux-2.6.29.5/arch/x86/kernel/cpu/mtrr/generic.c
+--- linux-2.6.29.5/arch/x86/kernel/cpu/mtrr/generic.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/cpu/mtrr/generic.c 2009-06-12 23:57:32.000000000 -0400
+@@ -23,14 +23,14 @@ static struct fixed_range_block fixed_ra
{ MTRRfix64K_00000_MSR, 1 }, /* one 64k MTRR */
{ MTRRfix16K_80000_MSR, 2 }, /* two 16k MTRRs */
{ MTRRfix4K_C0000_MSR, 8 }, /* eight 4k MTRRs */
@@ -6758,16 +7569,19 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/cpu/mtrr/generic.c linux-2.6.28.8/arch
};
static unsigned long smp_changes_mask;
--static struct mtrr_state mtrr_state = {};
-+static struct mtrr_state mtrr_state;
static int mtrr_state_set;
u64 mtrr_tom2;
-diff -urNp linux-2.6.28.8/arch/x86/kernel/crash.c linux-2.6.28.8/arch/x86/kernel/crash.c
---- linux-2.6.28.8/arch/x86/kernel/crash.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/crash.c 2009-02-21 09:37:48.000000000 -0500
-@@ -59,7 +59,7 @@ static int crash_nmi_callback(struct not
- local_irq_disable();
+-struct mtrr_state_type mtrr_state = {};
++struct mtrr_state_type mtrr_state;
+ EXPORT_SYMBOL_GPL(mtrr_state);
+
+ static int __initdata mtrr_show;
+diff -urNp linux-2.6.29.5/arch/x86/kernel/crash.c linux-2.6.29.5/arch/x86/kernel/crash.c
+--- linux-2.6.29.5/arch/x86/kernel/crash.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/crash.c 2009-06-12 23:57:32.000000000 -0400
+@@ -43,7 +43,7 @@ static void kdump_nmi_callback(int cpu,
+ regs = args->regs;
#ifdef CONFIG_X86_32
- if (!user_mode_vm(regs)) {
@@ -6775,9 +7589,9 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/crash.c linux-2.6.28.8/arch/x86/kernel
crash_fixup_ss_esp(&fixed_regs, regs);
regs = &fixed_regs;
}
-diff -urNp linux-2.6.28.8/arch/x86/kernel/doublefault_32.c linux-2.6.28.8/arch/x86/kernel/doublefault_32.c
---- linux-2.6.28.8/arch/x86/kernel/doublefault_32.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/doublefault_32.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/kernel/doublefault_32.c linux-2.6.29.5/arch/x86/kernel/doublefault_32.c
+--- linux-2.6.29.5/arch/x86/kernel/doublefault_32.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/doublefault_32.c 2009-06-12 23:57:32.000000000 -0400
@@ -11,7 +11,7 @@
#define DOUBLEFAULT_STACKSIZE (1024)
@@ -6809,10 +7623,10 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/doublefault_32.c linux-2.6.28.8/arch/x
.fs = __KERNEL_PERCPU,
.__cr3 = __pa_nodebug(swapper_pg_dir),
-diff -urNp linux-2.6.28.8/arch/x86/kernel/dumpstack_32.c linux-2.6.28.8/arch/x86/kernel/dumpstack_32.c
---- linux-2.6.28.8/arch/x86/kernel/dumpstack_32.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/dumpstack_32.c 2009-02-21 09:37:48.000000000 -0500
-@@ -238,11 +238,12 @@ void show_registers(struct pt_regs *regs
+diff -urNp linux-2.6.29.5/arch/x86/kernel/dumpstack_32.c linux-2.6.29.5/arch/x86/kernel/dumpstack_32.c
+--- linux-2.6.29.5/arch/x86/kernel/dumpstack_32.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/dumpstack_32.c 2009-06-12 23:57:32.000000000 -0400
+@@ -107,11 +107,12 @@ void show_registers(struct pt_regs *regs
* When in-kernel, we also print out the stack and code at the
* time of the fault..
*/
@@ -6826,7 +7640,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/dumpstack_32.c linux-2.6.28.8/arch/x86
printk(KERN_EMERG "Stack:\n");
show_stack_log_lvl(NULL, regs, &regs->sp,
-@@ -250,10 +251,10 @@ void show_registers(struct pt_regs *regs
+@@ -119,10 +120,10 @@ void show_registers(struct pt_regs *regs
printk(KERN_EMERG "Code: ");
@@ -6839,7 +7653,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/dumpstack_32.c linux-2.6.28.8/arch/x86
code_len = code_len - code_prologue + 1;
}
for (i = 0; i < code_len; i++, ip++) {
-@@ -262,7 +263,7 @@ void show_registers(struct pt_regs *regs
+@@ -131,7 +132,7 @@ void show_registers(struct pt_regs *regs
printk(" Bad EIP value.");
break;
}
@@ -6848,7 +7662,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/dumpstack_32.c linux-2.6.28.8/arch/x86
printk("<%02x> ", c);
else
printk("%02x ", c);
-@@ -275,6 +276,7 @@ int is_valid_bugaddr(unsigned long ip)
+@@ -144,6 +145,7 @@ int is_valid_bugaddr(unsigned long ip)
{
unsigned short ud2;
@@ -6856,18 +7670,45 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/dumpstack_32.c linux-2.6.28.8/arch/x86
if (ip < PAGE_OFFSET)
return 0;
if (probe_kernel_address((unsigned short *)ip, ud2))
-@@ -410,7 +412,7 @@ die_nmi(char *str, struct pt_regs *regs,
- * If we are in kernel we are probably nested up pretty bad
- * and might aswell get out now while we still can:
- */
-- if (!user_mode_vm(regs)) {
-+ if (!user_mode(regs)) {
- current->thread.trap_no = 2;
- crash_kexec(regs);
- }
-diff -urNp linux-2.6.28.8/arch/x86/kernel/efi_32.c linux-2.6.28.8/arch/x86/kernel/efi_32.c
---- linux-2.6.28.8/arch/x86/kernel/efi_32.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/efi_32.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/kernel/dumpstack.c linux-2.6.29.5/arch/x86/kernel/dumpstack.c
+--- linux-2.6.29.5/arch/x86/kernel/dumpstack.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/dumpstack.c 2009-06-12 23:57:32.000000000 -0400
+@@ -178,7 +178,7 @@ void dump_stack(void)
+ #endif
+
+ printk("Pid: %d, comm: %.20s %s %s %.*s\n",
+- current->pid, current->comm, print_tainted(),
++ task_pid_nr(current), current->comm, print_tainted(),
+ init_utsname()->release,
+ (int)strcspn(init_utsname()->version, " "),
+ init_utsname()->version);
+@@ -288,7 +288,7 @@ void die(const char *str, struct pt_regs
+ unsigned long flags = oops_begin();
+ int sig = SIGSEGV;
+
+- if (!user_mode_vm(regs))
++ if (!user_mode(regs))
+ report_bug(regs->ip, regs);
+
+ if (__die(str, regs, err))
+diff -urNp linux-2.6.29.5/arch/x86/kernel/e820.c linux-2.6.29.5/arch/x86/kernel/e820.c
+--- linux-2.6.29.5/arch/x86/kernel/e820.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/e820.c 2009-06-12 23:57:32.000000000 -0400
+@@ -698,7 +698,10 @@ struct early_res {
+ };
+ static struct early_res early_res[MAX_EARLY_RES] __initdata = {
+ { 0, PAGE_SIZE, "BIOS data page" }, /* BIOS data page */
+- {}
++#ifdef CONFIG_VM86
++ { PAGE_SIZE, ISA_START_ADDRESS, "V86 mode memory", 1 },
++#endif
++ { 0, 0, {0}, 0 }
+ };
+
+ static int __init find_overlapped_early(u64 start, u64 end)
+diff -urNp linux-2.6.29.5/arch/x86/kernel/efi_32.c linux-2.6.29.5/arch/x86/kernel/efi_32.c
+--- linux-2.6.29.5/arch/x86/kernel/efi_32.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/efi_32.c 2009-06-12 23:57:32.000000000 -0400
@@ -38,70 +38,38 @@
*/
@@ -6948,9 +7789,9 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/efi_32.c linux-2.6.28.8/arch/x86/kerne
/*
* After the lock is released, the original page table is restored.
-diff -urNp linux-2.6.28.8/arch/x86/kernel/efi_stub_32.S linux-2.6.28.8/arch/x86/kernel/efi_stub_32.S
---- linux-2.6.28.8/arch/x86/kernel/efi_stub_32.S 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/efi_stub_32.S 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/kernel/efi_stub_32.S linux-2.6.29.5/arch/x86/kernel/efi_stub_32.S
+--- linux-2.6.29.5/arch/x86/kernel/efi_stub_32.S 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/efi_stub_32.S 2009-06-12 23:57:32.000000000 -0400
@@ -6,6 +6,7 @@
*/
@@ -7048,9 +7889,9 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/efi_stub_32.S linux-2.6.28.8/arch/x86/
saved_return_addr:
.long 0
efi_rt_function_ptr:
-diff -urNp linux-2.6.28.8/arch/x86/kernel/entry_32.S linux-2.6.28.8/arch/x86/kernel/entry_32.S
---- linux-2.6.28.8/arch/x86/kernel/entry_32.S 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/entry_32.S 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/kernel/entry_32.S linux-2.6.29.5/arch/x86/kernel/entry_32.S
+--- linux-2.6.29.5/arch/x86/kernel/entry_32.S 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/entry_32.S 2009-06-12 23:57:32.000000000 -0400
@@ -101,7 +101,7 @@
#define resume_userspace_sig resume_userspace
#endif
@@ -7281,16 +8122,15 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/entry_32.S linux-2.6.28.8/arch/x86/ker
#define UNWIND_ESPFIX_STACK \
movl %ss, %eax; \
/* see if on espfix stack */ \
-@@ -622,7 +686,7 @@ END(syscall_badsys)
- * Build the entry stubs and pointer table with
- * some assembler magic.
- */
+@@ -1052,7 +1116,6 @@ return_to_handler:
+ ret
+ #endif
+
-.section .rodata,"a"
-+.section .rodata,"a",@progbits
- ENTRY(interrupt)
- .text
+ #include "syscall_table_32.S"
-@@ -722,12 +786,21 @@ error_code:
+ syscall_table_size=(.-sys_call_table)
+@@ -1106,12 +1169,21 @@ error_code:
popl %ecx
CFI_ADJUST_CFA_OFFSET -4
/*CFI_REGISTER es, ecx*/
@@ -7313,7 +8153,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/entry_32.S linux-2.6.28.8/arch/x86/ker
movl %ecx, %ds
movl %ecx, %es
TRACE_IRQS_OFF
-@@ -853,6 +926,13 @@ nmi_stack_correct:
+@@ -1206,6 +1278,13 @@ nmi_stack_correct:
xorl %edx,%edx # zero error code
movl %esp,%eax # pt_regs pointer
call do_nmi
@@ -7327,7 +8167,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/entry_32.S linux-2.6.28.8/arch/x86/ker
jmp restore_nocheck_notrace
CFI_ENDPROC
-@@ -894,6 +974,13 @@ nmi_espfix_stack:
+@@ -1246,6 +1325,13 @@ nmi_espfix_stack:
FIXUP_ESPFIX_STACK # %eax == %esp
xorl %edx,%edx # zero error code
call do_nmi
@@ -7341,45 +8181,28 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/entry_32.S linux-2.6.28.8/arch/x86/ker
RESTORE_REGS
lss 12+4(%esp), %esp # back to espfix stack
CFI_ADJUST_CFA_OFFSET -24
-@@ -1206,7 +1293,6 @@ END(mcount)
- #endif /* CONFIG_DYNAMIC_FTRACE */
- #endif /* CONFIG_FUNCTION_TRACER */
-
--.section .rodata,"a"
- #include "syscall_table_32.S"
-
- syscall_table_size=(.-sys_call_table)
-diff -urNp linux-2.6.28.8/arch/x86/kernel/entry_64.S linux-2.6.28.8/arch/x86/kernel/entry_64.S
---- linux-2.6.28.8/arch/x86/kernel/entry_64.S 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/entry_64.S 2009-02-21 09:37:48.000000000 -0500
-@@ -911,7 +911,8 @@ END(spurious_interrupt)
- xorl %ebx,%ebx
- 1:
- .if \ist
-- movq %gs:pda_data_offset, %rbp
-+ imul $TSS_size, %gs:pda_cpunumber, %ebp
-+ lea init_tss(%rbp), %rbp
- .endif
- .if \irqtrace
+diff -urNp linux-2.6.29.5/arch/x86/kernel/entry_64.S linux-2.6.29.5/arch/x86/kernel/entry_64.S
+--- linux-2.6.29.5/arch/x86/kernel/entry_64.S 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/entry_64.S 2009-06-12 23:57:32.000000000 -0400
+@@ -1073,10 +1073,11 @@ ENTRY(\sym)
TRACE_IRQS_OFF
-@@ -920,11 +921,11 @@ END(spurious_interrupt)
- movq ORIG_RAX(%rsp),%rsi
- movq $-1,ORIG_RAX(%rsp)
- .if \ist
-- subq $EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp)
-+ subq $EXCEPTION_STKSZ, TSS_ist + (\ist - 1) * 8(%rbp)
- .endif
- call \sym
- .if \ist
-- addq $EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp)
-+ addq $EXCEPTION_STKSZ, TSS_ist + (\ist - 1) * 8(%rbp)
- .endif
- DISABLE_INTERRUPTS(CLBR_NONE)
- .if \irqtrace
-diff -urNp linux-2.6.28.8/arch/x86/kernel/ftrace.c linux-2.6.28.8/arch/x86/kernel/ftrace.c
---- linux-2.6.28.8/arch/x86/kernel/ftrace.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/ftrace.c 2009-02-21 09:37:48.000000000 -0500
-@@ -95,9 +95,9 @@ int ftrace_update_ftrace_func(ftrace_fun
+ movq %rsp,%rdi /* pt_regs pointer */
+ xorl %esi,%esi /* no error code */
+- movq %gs:pda_data_offset, %rbp
+- subq $EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp)
++ imul $TSS_size, %gs:pda_cpunumber, %ebp
++ lea init_tss(%rbp), %rbp
++ subq $EXCEPTION_STKSZ, TSS_ist + (\ist - 1) * 8(%rbp)
+ call \do_sym
+- addq $EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp)
++ addq $EXCEPTION_STKSZ, TSS_ist + (\ist - 1) * 8(%rbp)
+ jmp paranoid_exit /* %ebx: no swapgs flag */
+ CFI_ENDPROC
+ END(\sym)
+diff -urNp linux-2.6.29.5/arch/x86/kernel/ftrace.c linux-2.6.29.5/arch/x86/kernel/ftrace.c
+--- linux-2.6.29.5/arch/x86/kernel/ftrace.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/ftrace.c 2009-06-12 23:57:32.000000000 -0400
+@@ -250,9 +250,9 @@ int ftrace_update_ftrace_func(ftrace_fun
unsigned char old[MCOUNT_INSN_SIZE], *new;
int ret;
@@ -7391,25 +8214,27 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/ftrace.c linux-2.6.28.8/arch/x86/kerne
return ret;
}
-diff -urNp linux-2.6.28.8/arch/x86/kernel/head32.c linux-2.6.28.8/arch/x86/kernel/head32.c
---- linux-2.6.28.8/arch/x86/kernel/head32.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/head32.c 2009-02-21 09:37:48.000000000 -0500
-@@ -12,10 +12,11 @@
- #include <asm/sections.h>
+diff -urNp linux-2.6.29.5/arch/x86/kernel/head32.c linux-2.6.29.5/arch/x86/kernel/head32.c
+--- linux-2.6.29.5/arch/x86/kernel/head32.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/head32.c 2009-06-12 23:57:32.000000000 -0400
+@@ -13,12 +13,13 @@
#include <asm/e820.h>
#include <asm/bios_ebda.h>
+ #include <asm/trampoline.h>
+#include <asm/boot.h>
void __init i386_start_kernel(void)
{
+ reserve_trampoline_memory();
+
- reserve_early(__pa_symbol(&_text), __pa_symbol(&_end), "TEXT DATA BSS");
+ reserve_early(LOAD_PHYSICAL_ADDR, __pa_symbol(&_end), "TEXT DATA BSS");
#ifdef CONFIG_BLK_DEV_INITRD
/* Reserve INITRD */
-diff -urNp linux-2.6.28.8/arch/x86/kernel/head_32.S linux-2.6.28.8/arch/x86/kernel/head_32.S
---- linux-2.6.28.8/arch/x86/kernel/head_32.S 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/head_32.S 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/kernel/head_32.S linux-2.6.29.5/arch/x86/kernel/head_32.S
+--- linux-2.6.29.5/arch/x86/kernel/head_32.S 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/head_32.S 2009-06-12 23:57:32.000000000 -0400
@@ -19,6 +19,7 @@
#include <asm/asm-offsets.h>
#include <asm/setup.h>
@@ -7819,10 +8644,10 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/head_32.S linux-2.6.28.8/arch/x86/kern
+ /* Be sure this is zeroed to avoid false validations in Xen */
+ .fill PAGE_SIZE_asm - GDT_SIZE,1,0
+ .endr
-diff -urNp linux-2.6.28.8/arch/x86/kernel/head64.c linux-2.6.28.8/arch/x86/kernel/head64.c
---- linux-2.6.28.8/arch/x86/kernel/head64.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/head64.c 2009-02-21 09:37:48.000000000 -0500
-@@ -93,6 +93,8 @@ void __init x86_64_start_kernel(char * r
+diff -urNp linux-2.6.29.5/arch/x86/kernel/head64.c linux-2.6.29.5/arch/x86/kernel/head64.c
+--- linux-2.6.29.5/arch/x86/kernel/head64.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/head64.c 2009-06-12 23:57:32.000000000 -0400
+@@ -94,6 +94,8 @@ void __init x86_64_start_kernel(char * r
/* clear bss before set_intr_gate with early_idt_handler */
clear_bss();
@@ -7831,7 +8656,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/head64.c linux-2.6.28.8/arch/x86/kerne
/* Make NULL pointers segfault */
zap_identity_mappings();
-@@ -111,8 +113,6 @@ void __init x86_64_start_kernel(char * r
+@@ -112,8 +114,6 @@ void __init x86_64_start_kernel(char * r
if (console_loglevel == 10)
early_printk("Kernel alive\n");
@@ -7840,9 +8665,9 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/head64.c linux-2.6.28.8/arch/x86/kerne
x86_64_start_reservations(real_mode_data);
}
-diff -urNp linux-2.6.28.8/arch/x86/kernel/head_64.S linux-2.6.28.8/arch/x86/kernel/head_64.S
---- linux-2.6.28.8/arch/x86/kernel/head_64.S 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/head_64.S 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/kernel/head_64.S linux-2.6.29.5/arch/x86/kernel/head_64.S
+--- linux-2.6.29.5/arch/x86/kernel/head_64.S 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/head_64.S 2009-06-12 23:57:32.000000000 -0400
@@ -38,6 +38,10 @@ L4_PAGE_OFFSET = pgd_index(__PAGE_OFFSET
L3_PAGE_OFFSET = pud_index(__PAGE_OFFSET)
L4_START_KERNEL = pgd_index(__START_KERNEL_map)
@@ -8076,9 +8901,9 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/head_64.S linux-2.6.28.8/arch/x86/kern
.section .bss.page_aligned, "aw", @nobits
.align PAGE_SIZE
-diff -urNp linux-2.6.28.8/arch/x86/kernel/i386_ksyms_32.c linux-2.6.28.8/arch/x86/kernel/i386_ksyms_32.c
---- linux-2.6.28.8/arch/x86/kernel/i386_ksyms_32.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/i386_ksyms_32.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/kernel/i386_ksyms_32.c linux-2.6.29.5/arch/x86/kernel/i386_ksyms_32.c
+--- linux-2.6.29.5/arch/x86/kernel/i386_ksyms_32.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/i386_ksyms_32.c 2009-06-12 23:57:32.000000000 -0400
@@ -10,8 +10,12 @@
EXPORT_SYMBOL(mcount);
#endif
@@ -8100,10 +8925,10 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/i386_ksyms_32.c linux-2.6.28.8/arch/x8
+#ifdef CONFIG_PAX_KERNEXEC
+EXPORT_SYMBOL(KERNEL_TEXT_OFFSET);
+#endif
-diff -urNp linux-2.6.28.8/arch/x86/kernel/init_task.c linux-2.6.28.8/arch/x86/kernel/init_task.c
---- linux-2.6.28.8/arch/x86/kernel/init_task.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/init_task.c 2009-02-21 09:37:48.000000000 -0500
-@@ -42,5 +42,5 @@ EXPORT_SYMBOL(init_task);
+diff -urNp linux-2.6.29.5/arch/x86/kernel/init_task.c linux-2.6.29.5/arch/x86/kernel/init_task.c
+--- linux-2.6.29.5/arch/x86/kernel/init_task.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/init_task.c 2009-06-12 23:57:32.000000000 -0400
+@@ -40,5 +40,5 @@ EXPORT_SYMBOL(init_task);
* section. Since TSS's are completely CPU-local, we want them
* on exact cacheline boundaries, to eliminate cacheline ping-pong.
*/
@@ -8111,9 +8936,9 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/init_task.c linux-2.6.28.8/arch/x86/ke
-
+struct tss_struct init_tss[NR_CPUS] ____cacheline_internodealigned_in_smp = { [0 ... NR_CPUS-1] = INIT_TSS };
+EXPORT_SYMBOL(init_tss);
-diff -urNp linux-2.6.28.8/arch/x86/kernel/ioport.c linux-2.6.28.8/arch/x86/kernel/ioport.c
---- linux-2.6.28.8/arch/x86/kernel/ioport.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/ioport.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/kernel/ioport.c linux-2.6.29.5/arch/x86/kernel/ioport.c
+--- linux-2.6.29.5/arch/x86/kernel/ioport.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/ioport.c 2009-06-12 23:57:32.000000000 -0400
@@ -6,6 +6,7 @@
#include <linux/sched.h>
#include <linux/kernel.h>
@@ -8158,15 +8983,15 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/ioport.c linux-2.6.28.8/arch/x86/kerne
}
regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12);
-diff -urNp linux-2.6.28.8/arch/x86/kernel/irq_32.c linux-2.6.28.8/arch/x86/kernel/irq_32.c
---- linux-2.6.28.8/arch/x86/kernel/irq_32.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/irq_32.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/kernel/irq_32.c linux-2.6.29.5/arch/x86/kernel/irq_32.c
+--- linux-2.6.29.5/arch/x86/kernel/irq_32.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/irq_32.c 2009-06-12 23:57:32.000000000 -0400
@@ -93,7 +93,7 @@ execute_on_irq_stack(int overflow, struc
return 0;
/* build the stack frame on the IRQ stack */
-- isp = (u32 *) ((char*)irqctx + sizeof(*irqctx));
-+ isp = (u32 *) ((char*)irqctx + sizeof(*irqctx) - 8);
+- isp = (u32 *) ((char *)irqctx + sizeof(*irqctx));
++ isp = (u32 *) ((char *)irqctx + sizeof(*irqctx) - 8);
irqctx->tinfo.task = curctx->tinfo.task;
irqctx->tinfo.previous_esp = current_stack_pointer;
@@ -8174,14 +8999,14 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/irq_32.c linux-2.6.28.8/arch/x86/kerne
irqctx->tinfo.previous_esp = current_stack_pointer;
/* build the stack frame on the softirq stack */
-- isp = (u32*) ((char*)irqctx + sizeof(*irqctx));
-+ isp = (u32*) ((char*)irqctx + sizeof(*irqctx) - 8);
+- isp = (u32 *) ((char *)irqctx + sizeof(*irqctx));
++ isp = (u32 *) ((char *)irqctx + sizeof(*irqctx) - 8);
call_on_stack(__do_softirq, isp);
/*
-diff -urNp linux-2.6.28.8/arch/x86/kernel/kprobes.c linux-2.6.28.8/arch/x86/kernel/kprobes.c
---- linux-2.6.28.8/arch/x86/kernel/kprobes.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/kprobes.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/kernel/kprobes.c linux-2.6.29.5/arch/x86/kernel/kprobes.c
+--- linux-2.6.29.5/arch/x86/kernel/kprobes.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/kprobes.c 2009-06-12 23:57:32.000000000 -0400
@@ -166,9 +166,24 @@ static void __kprobes set_jmp_op(void *f
char op;
s32 raddr;
@@ -8208,7 +9033,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/kprobes.c linux-2.6.28.8/arch/x86/kern
}
/*
-@@ -342,16 +357,29 @@ static void __kprobes fix_riprel(struct
+@@ -345,16 +360,29 @@ static void __kprobes fix_riprel(struct
static void __kprobes arch_copy_kprobe(struct kprobe *p)
{
@@ -8241,7 +9066,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/kprobes.c linux-2.6.28.8/arch/x86/kern
}
int __kprobes arch_prepare_kprobe(struct kprobe *p)
-@@ -428,7 +456,7 @@ static void __kprobes prepare_singlestep
+@@ -432,7 +460,7 @@ static void __kprobes prepare_singlestep
if (p->opcode == BREAKPOINT_INSTRUCTION)
regs->ip = (unsigned long)p->addr;
else
@@ -8250,7 +9075,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/kprobes.c linux-2.6.28.8/arch/x86/kern
}
void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
-@@ -449,7 +477,7 @@ static void __kprobes setup_singlestep(s
+@@ -453,7 +481,7 @@ static void __kprobes setup_singlestep(s
if (p->ainsn.boostable == 1 && !p->post_handler) {
/* Boost up -- we can execute copied instructions directly */
reset_current_kprobe();
@@ -8259,7 +9084,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/kprobes.c linux-2.6.28.8/arch/x86/kern
preempt_enable_no_resched();
return;
}
-@@ -519,7 +547,7 @@ static int __kprobes kprobe_handler(stru
+@@ -523,7 +551,7 @@ static int __kprobes kprobe_handler(stru
struct kprobe_ctlblk *kcb;
addr = (kprobe_opcode_t *)(regs->ip - sizeof(kprobe_opcode_t));
@@ -8268,7 +9093,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/kprobes.c linux-2.6.28.8/arch/x86/kern
/*
* The breakpoint instruction was removed right
* after we hit it. Another cpu has removed
-@@ -770,7 +798,7 @@ static void __kprobes resume_execution(s
+@@ -774,7 +802,7 @@ static void __kprobes resume_execution(s
struct pt_regs *regs, struct kprobe_ctlblk *kcb)
{
unsigned long *tos = stack_addr(regs);
@@ -8277,7 +9102,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/kprobes.c linux-2.6.28.8/arch/x86/kern
unsigned long orig_ip = (unsigned long)p->addr;
kprobe_opcode_t *insn = p->ainsn.insn;
-@@ -953,7 +981,7 @@ int __kprobes kprobe_exceptions_notify(s
+@@ -957,7 +985,7 @@ int __kprobes kprobe_exceptions_notify(s
struct die_args *args = data;
int ret = NOTIFY_DONE;
@@ -8286,9 +9111,9 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/kprobes.c linux-2.6.28.8/arch/x86/kern
return ret;
switch (val) {
-diff -urNp linux-2.6.28.8/arch/x86/kernel/ldt.c linux-2.6.28.8/arch/x86/kernel/ldt.c
---- linux-2.6.28.8/arch/x86/kernel/ldt.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/ldt.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/kernel/ldt.c linux-2.6.29.5/arch/x86/kernel/ldt.c
+--- linux-2.6.29.5/arch/x86/kernel/ldt.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/ldt.c 2009-06-12 23:57:32.000000000 -0400
@@ -66,13 +66,13 @@ static int alloc_ldt(mm_context_t *pc, i
if (reload) {
#ifdef CONFIG_SMP
@@ -8308,7 +9133,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/ldt.c linux-2.6.28.8/arch/x86/kernel/l
@@ -94,7 +94,7 @@ static inline int copy_ldt(mm_context_t
return err;
- for(i = 0; i < old->size; i++)
+ for (i = 0; i < old->size; i++)
- write_ldt_entry(new->ldt, i, old->ldt + i * LDT_ENTRY_SIZE);
+ write_ldt_entry(new->ldt, i, old->ldt + i);
return 0;
@@ -8353,19 +9178,19 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/ldt.c linux-2.6.28.8/arch/x86/kernel/l
fill_ldt(&ldt, &ldt_info);
if (oldmode)
ldt.avl = 0;
-diff -urNp linux-2.6.28.8/arch/x86/kernel/machine_kexec_32.c linux-2.6.28.8/arch/x86/kernel/machine_kexec_32.c
---- linux-2.6.28.8/arch/x86/kernel/machine_kexec_32.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/machine_kexec_32.c 2009-02-21 09:37:48.000000000 -0500
-@@ -34,7 +34,7 @@ static u32 kexec_pmd1[1024] PAGE_ALIGNED
- static u32 kexec_pte0[1024] PAGE_ALIGNED;
- static u32 kexec_pte1[1024] PAGE_ALIGNED;
+diff -urNp linux-2.6.29.5/arch/x86/kernel/machine_kexec_32.c linux-2.6.29.5/arch/x86/kernel/machine_kexec_32.c
+--- linux-2.6.29.5/arch/x86/kernel/machine_kexec_32.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/machine_kexec_32.c 2009-06-12 23:57:32.000000000 -0400
+@@ -26,7 +26,7 @@
+ #include <asm/system.h>
+ #include <asm/cacheflush.h>
-static void set_idt(void *newidt, __u16 limit)
+static void set_idt(struct desc_struct *newidt, __u16 limit)
{
struct desc_ptr curidt;
-@@ -46,7 +46,7 @@ static void set_idt(void *newidt, __u16
+@@ -38,7 +38,7 @@ static void set_idt(void *newidt, __u16
}
@@ -8374,7 +9199,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/machine_kexec_32.c linux-2.6.28.8/arch
{
struct desc_ptr curgdt;
-@@ -145,7 +145,7 @@ void machine_kexec(struct kimage *image)
+@@ -216,7 +216,7 @@ void machine_kexec(struct kimage *image)
}
control_page = page_address(image->control_code_page);
@@ -8383,9 +9208,9 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/machine_kexec_32.c linux-2.6.28.8/arch
relocate_kernel_ptr = control_page;
page_list[PA_CONTROL_PAGE] = __pa(control_page);
-diff -urNp linux-2.6.28.8/arch/x86/kernel/module_32.c linux-2.6.28.8/arch/x86/kernel/module_32.c
---- linux-2.6.28.8/arch/x86/kernel/module_32.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/module_32.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/kernel/module_32.c linux-2.6.29.5/arch/x86/kernel/module_32.c
+--- linux-2.6.29.5/arch/x86/kernel/module_32.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/module_32.c 2009-06-12 23:57:32.000000000 -0400
@@ -23,6 +23,9 @@
#include <linux/kernel.h>
#include <linux/bug.h>
@@ -8533,9 +9358,9 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/module_32.c linux-2.6.28.8/arch/x86/ke
break;
default:
printk(KERN_ERR "module %s: Unknown relocation: %u\n",
-diff -urNp linux-2.6.28.8/arch/x86/kernel/module_64.c linux-2.6.28.8/arch/x86/kernel/module_64.c
---- linux-2.6.28.8/arch/x86/kernel/module_64.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/module_64.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/kernel/module_64.c linux-2.6.29.5/arch/x86/kernel/module_64.c
+--- linux-2.6.29.5/arch/x86/kernel/module_64.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/module_64.c 2009-06-12 23:57:32.000000000 -0400
@@ -40,7 +40,7 @@ void module_free(struct module *mod, voi
table entries. */
}
@@ -8653,9 +9478,9 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/module_64.c linux-2.6.28.8/arch/x86/ke
#if 0
if ((s64)val != *(s32 *)loc)
goto overflow;
-diff -urNp linux-2.6.28.8/arch/x86/kernel/paravirt.c linux-2.6.28.8/arch/x86/kernel/paravirt.c
---- linux-2.6.28.8/arch/x86/kernel/paravirt.c 2009-03-07 10:24:49.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/paravirt.c 2009-03-07 10:34:42.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/kernel/paravirt.c linux-2.6.29.5/arch/x86/kernel/paravirt.c
+--- linux-2.6.29.5/arch/x86/kernel/paravirt.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/paravirt.c 2009-06-12 23:57:32.000000000 -0400
@@ -44,7 +44,7 @@ void _paravirt_nop(void)
{
}
@@ -8674,7 +9499,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/paravirt.c linux-2.6.28.8/arch/x86/ker
return insn_len;
}
-@@ -292,21 +292,21 @@ void arch_flush_lazy_cpu_mode(void)
+@@ -294,21 +294,21 @@ void arch_flush_lazy_cpu_mode(void)
preempt_enable();
}
@@ -8699,7 +9524,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/paravirt.c linux-2.6.28.8/arch/x86/ker
.time_init = hpet_time_init,
.get_wallclock = native_get_wallclock,
.set_wallclock = native_set_wallclock,
-@@ -314,7 +314,7 @@ struct pv_time_ops pv_time_ops = {
+@@ -316,7 +316,7 @@ struct pv_time_ops pv_time_ops = {
.get_tsc_khz = native_calibrate_tsc,
};
@@ -8708,7 +9533,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/paravirt.c linux-2.6.28.8/arch/x86/ker
.init_IRQ = native_init_IRQ,
.save_fl = native_save_fl,
.restore_fl = native_restore_fl,
-@@ -327,7 +327,7 @@ struct pv_irq_ops pv_irq_ops = {
+@@ -329,7 +329,7 @@ struct pv_irq_ops pv_irq_ops = {
#endif
};
@@ -8717,7 +9542,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/paravirt.c linux-2.6.28.8/arch/x86/ker
.cpuid = native_cpuid,
.get_debugreg = native_get_debugreg,
.set_debugreg = native_set_debugreg,
-@@ -389,7 +389,7 @@ struct pv_cpu_ops pv_cpu_ops = {
+@@ -391,7 +391,7 @@ struct pv_cpu_ops pv_cpu_ops = {
},
};
@@ -8726,7 +9551,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/paravirt.c linux-2.6.28.8/arch/x86/ker
#ifdef CONFIG_X86_LOCAL_APIC
.setup_boot_clock = setup_boot_APIC_clock,
.setup_secondary_clock = setup_secondary_APIC_clock,
-@@ -397,7 +397,7 @@ struct pv_apic_ops pv_apic_ops = {
+@@ -399,7 +399,7 @@ struct pv_apic_ops pv_apic_ops = {
#endif
};
@@ -8735,9 +9560,9 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/paravirt.c linux-2.6.28.8/arch/x86/ker
#ifndef CONFIG_X86_64
.pagetable_setup_start = native_pagetable_setup_start,
.pagetable_setup_done = native_pagetable_setup_done,
-diff -urNp linux-2.6.28.8/arch/x86/kernel/paravirt-spinlocks.c linux-2.6.28.8/arch/x86/kernel/paravirt-spinlocks.c
---- linux-2.6.28.8/arch/x86/kernel/paravirt-spinlocks.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/paravirt-spinlocks.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/kernel/paravirt-spinlocks.c linux-2.6.29.5/arch/x86/kernel/paravirt-spinlocks.c
+--- linux-2.6.29.5/arch/x86/kernel/paravirt-spinlocks.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/paravirt-spinlocks.c 2009-06-12 23:57:32.000000000 -0400
@@ -13,7 +13,7 @@ default_spin_lock_flags(raw_spinlock_t *
__raw_spin_lock(lock);
}
@@ -8747,10 +9572,10 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/paravirt-spinlocks.c linux-2.6.28.8/ar
#ifdef CONFIG_SMP
.spin_is_locked = __ticket_spin_is_locked,
.spin_is_contended = __ticket_spin_is_contended,
-diff -urNp linux-2.6.28.8/arch/x86/kernel/process_32.c linux-2.6.28.8/arch/x86/kernel/process_32.c
---- linux-2.6.28.8/arch/x86/kernel/process_32.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/process_32.c 2009-02-21 09:37:48.000000000 -0500
-@@ -65,8 +65,10 @@ asmlinkage void ret_from_fork(void) __as
+diff -urNp linux-2.6.29.5/arch/x86/kernel/process_32.c linux-2.6.29.5/arch/x86/kernel/process_32.c
+--- linux-2.6.29.5/arch/x86/kernel/process_32.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/process_32.c 2009-06-12 23:57:32.000000000 -0400
+@@ -66,8 +66,10 @@ asmlinkage void ret_from_fork(void) __as
DEFINE_PER_CPU(struct task_struct *, current_task) = &init_task;
EXPORT_PER_CPU_SYMBOL(current_task);
@@ -8761,7 +9586,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/process_32.c linux-2.6.28.8/arch/x86/k
/*
* Return saved PC of a blocked thread.
-@@ -74,6 +76,7 @@ EXPORT_PER_CPU_SYMBOL(cpu_number);
+@@ -75,6 +77,7 @@ EXPORT_PER_CPU_SYMBOL(cpu_number);
unsigned long thread_saved_pc(struct task_struct *tsk)
{
return ((unsigned long *)tsk->thread.sp)[3];
@@ -8769,7 +9594,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/process_32.c linux-2.6.28.8/arch/x86/k
}
#ifndef CONFIG_SMP
-@@ -131,7 +134,7 @@ void __show_regs(struct pt_regs *regs, i
+@@ -129,7 +132,7 @@ void __show_regs(struct pt_regs *regs, i
unsigned short ss, gs;
const char *board;
@@ -8778,7 +9603,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/process_32.c linux-2.6.28.8/arch/x86/k
sp = regs->sp;
ss = regs->ss & 0xffff;
savesegment(gs, gs);
-@@ -212,8 +215,8 @@ int kernel_thread(int (*fn)(void *), voi
+@@ -210,8 +213,8 @@ int kernel_thread(int (*fn)(void *), voi
regs.bx = (unsigned long) fn;
regs.dx = (unsigned long) arg;
@@ -8789,7 +9614,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/process_32.c linux-2.6.28.8/arch/x86/k
regs.fs = __KERNEL_PERCPU;
regs.orig_ax = -1;
regs.ip = (unsigned long) kernel_thread_helper;
-@@ -235,7 +238,7 @@ void exit_thread(void)
+@@ -233,7 +236,7 @@ void exit_thread(void)
struct task_struct *tsk = current;
struct thread_struct *t = &tsk->thread;
int cpu = get_cpu();
@@ -8798,7 +9623,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/process_32.c linux-2.6.28.8/arch/x86/k
kfree(t->io_bitmap_ptr);
t->io_bitmap_ptr = NULL;
-@@ -264,6 +267,7 @@ void flush_thread(void)
+@@ -256,6 +259,7 @@ void flush_thread(void)
{
struct task_struct *tsk = current;
@@ -8806,7 +9631,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/process_32.c linux-2.6.28.8/arch/x86/k
tsk->thread.debugreg0 = 0;
tsk->thread.debugreg1 = 0;
tsk->thread.debugreg2 = 0;
-@@ -303,7 +307,7 @@ int copy_thread(int nr, unsigned long cl
+@@ -295,7 +299,7 @@ int copy_thread(int nr, unsigned long cl
struct task_struct *tsk;
int err;
@@ -8815,7 +9640,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/process_32.c linux-2.6.28.8/arch/x86/k
*childregs = *regs;
childregs->ax = 0;
childregs->sp = sp;
-@@ -332,6 +336,7 @@ int copy_thread(int nr, unsigned long cl
+@@ -324,6 +328,7 @@ int copy_thread(int nr, unsigned long cl
* Set a new TLS for the child thread?
*/
if (clone_flags & CLONE_SETTLS)
@@ -8823,7 +9648,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/process_32.c linux-2.6.28.8/arch/x86/k
err = do_set_thread_area(p, -1,
(struct user_desc __user *)childregs->si, 0);
-@@ -553,7 +558,7 @@ struct task_struct * __switch_to(struct
+@@ -514,7 +519,7 @@ __switch_to(struct task_struct *prev_p,
struct thread_struct *prev = &prev_p->thread,
*next = &next_p->thread;
int cpu = smp_processor_id();
@@ -8832,7 +9657,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/process_32.c linux-2.6.28.8/arch/x86/k
/* never put a printk in __switch_to... printk() calls wake_up*() indirectly */
-@@ -581,6 +586,11 @@ struct task_struct * __switch_to(struct
+@@ -542,6 +547,11 @@ __switch_to(struct task_struct *prev_p,
*/
savesegment(gs, prev->gs);
@@ -8844,7 +9669,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/process_32.c linux-2.6.28.8/arch/x86/k
/*
* Load the per-thread Thread-Local Storage descriptor.
*/
-@@ -719,15 +729,27 @@ unsigned long get_wchan(struct task_stru
+@@ -680,15 +690,27 @@ unsigned long get_wchan(struct task_stru
return 0;
}
@@ -8881,10 +9706,19 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/process_32.c linux-2.6.28.8/arch/x86/k
+ load_sp0(init_tss + smp_processor_id(), thread);
}
+#endif
-diff -urNp linux-2.6.28.8/arch/x86/kernel/process_64.c linux-2.6.28.8/arch/x86/kernel/process_64.c
---- linux-2.6.28.8/arch/x86/kernel/process_64.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/process_64.c 2009-02-21 09:37:48.000000000 -0500
-@@ -109,6 +109,8 @@ static inline void play_dead(void)
+diff -urNp linux-2.6.29.5/arch/x86/kernel/process_64.c linux-2.6.29.5/arch/x86/kernel/process_64.c
+--- linux-2.6.29.5/arch/x86/kernel/process_64.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/process_64.c 2009-06-12 23:57:32.000000000 -0400
+@@ -91,7 +91,7 @@ static void __exit_idle(void)
+ void exit_idle(void)
+ {
+ /* idle loop has pid 0 */
+- if (current->pid)
++ if (task_pid_nr(current))
+ return;
+ __exit_idle();
+ }
+@@ -112,6 +112,8 @@ static inline void play_dead(void)
void cpu_idle(void)
{
current_thread_info()->status |= TS_POLLING;
@@ -8893,7 +9727,16 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/process_64.c linux-2.6.28.8/arch/x86/k
/* endless idle loop with no priority at all */
while (1) {
tick_nohz_stop_sched_tick(1);
-@@ -223,7 +225,7 @@ void exit_thread(void)
+@@ -160,7 +162,7 @@ void __show_regs(struct pt_regs *regs, i
+ if (!board)
+ board = "";
+ printk(KERN_INFO "Pid: %d, comm: %.20s %s %s %.*s %s\n",
+- current->pid, current->comm, print_tainted(),
++ task_pid_nr(current), current->comm, print_tainted(),
+ init_utsname()->release,
+ (int)strcspn(init_utsname()->version, " "),
+ init_utsname()->version, board);
+@@ -230,7 +232,7 @@ void exit_thread(void)
struct thread_struct *t = &me->thread;
if (me->thread.io_bitmap_ptr) {
@@ -8902,7 +9745,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/process_64.c linux-2.6.28.8/arch/x86/k
kfree(t->io_bitmap_ptr);
t->io_bitmap_ptr = NULL;
-@@ -558,7 +560,7 @@ __switch_to(struct task_struct *prev_p,
+@@ -537,7 +539,7 @@ __switch_to(struct task_struct *prev_p,
struct thread_struct *prev = &prev_p->thread;
struct thread_struct *next = &next_p->thread;
int cpu = smp_processor_id();
@@ -8911,7 +9754,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/process_64.c linux-2.6.28.8/arch/x86/k
unsigned fsindex, gsindex;
/* we're going to use this soon, after a few expensive things */
-@@ -647,7 +649,6 @@ __switch_to(struct task_struct *prev_p,
+@@ -626,7 +628,6 @@ __switch_to(struct task_struct *prev_p,
(unsigned long)task_stack_page(next_p) +
THREAD_SIZE - PDA_STACKOFFSET);
#ifdef CONFIG_CC_STACKPROTECTOR
@@ -8919,7 +9762,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/process_64.c linux-2.6.28.8/arch/x86/k
/*
* Build time only check to make sure the stack_canary is at
* offset 40 in the pda; this is a gcc ABI requirement
-@@ -746,12 +747,11 @@ unsigned long get_wchan(struct task_stru
+@@ -725,12 +726,11 @@ unsigned long get_wchan(struct task_stru
if (!p || p == current || p->state == TASK_RUNNING)
return 0;
stack = (unsigned long)task_stack_page(p);
@@ -8934,7 +9777,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/process_64.c linux-2.6.28.8/arch/x86/k
return 0;
ip = *(u64 *)(fp+8);
if (!in_sched_functions(ip))
-@@ -860,16 +860,3 @@ long sys_arch_prctl(int code, unsigned l
+@@ -839,16 +839,3 @@ long sys_arch_prctl(int code, unsigned l
{
return do_arch_prctl(current, code, addr);
}
@@ -8951,10 +9794,10 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/process_64.c linux-2.6.28.8/arch/x86/k
- unsigned long range_end = mm->brk + 0x02000000;
- return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
-}
-diff -urNp linux-2.6.28.8/arch/x86/kernel/ptrace.c linux-2.6.28.8/arch/x86/kernel/ptrace.c
---- linux-2.6.28.8/arch/x86/kernel/ptrace.c 2009-03-07 10:24:49.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/ptrace.c 2009-03-07 10:29:51.000000000 -0500
-@@ -1502,7 +1502,7 @@ void send_sigtrap(struct task_struct *ts
+diff -urNp linux-2.6.29.5/arch/x86/kernel/ptrace.c linux-2.6.29.5/arch/x86/kernel/ptrace.c
+--- linux-2.6.29.5/arch/x86/kernel/ptrace.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/ptrace.c 2009-06-12 23:57:32.000000000 -0400
+@@ -1377,7 +1377,7 @@ void send_sigtrap(struct task_struct *ts
info.si_code = si_code;
/* User-mode ip? */
@@ -8963,10 +9806,10 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/ptrace.c linux-2.6.28.8/arch/x86/kerne
/* Send us the fake SIGTRAP */
force_sig_info(SIGTRAP, &info, tsk);
-diff -urNp linux-2.6.28.8/arch/x86/kernel/reboot.c linux-2.6.28.8/arch/x86/kernel/reboot.c
---- linux-2.6.28.8/arch/x86/kernel/reboot.c 2009-03-07 10:24:49.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/reboot.c 2009-03-07 10:32:37.000000000 -0500
-@@ -28,7 +28,7 @@ void (*pm_power_off)(void);
+diff -urNp linux-2.6.29.5/arch/x86/kernel/reboot.c linux-2.6.29.5/arch/x86/kernel/reboot.c
+--- linux-2.6.29.5/arch/x86/kernel/reboot.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/reboot.c 2009-06-12 23:57:32.000000000 -0400
+@@ -32,7 +32,7 @@ void (*pm_power_off)(void);
EXPORT_SYMBOL(pm_power_off);
static const struct desc_ptr no_idt = {};
@@ -8975,7 +9818,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/reboot.c linux-2.6.28.8/arch/x86/kerne
enum reboot_type reboot_type = BOOT_KBD;
int reboot_force;
-@@ -210,7 +210,7 @@ static struct dmi_system_id __initdata r
+@@ -225,7 +225,7 @@ static struct dmi_system_id __initdata r
DMI_MATCH(DMI_PRODUCT_NAME, "Dell XPS710"),
},
},
@@ -8984,7 +9827,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/reboot.c linux-2.6.28.8/arch/x86/kerne
};
static int __init reboot_init(void)
-@@ -226,12 +226,12 @@ core_initcall(reboot_init);
+@@ -241,12 +241,12 @@ core_initcall(reboot_init);
controller to pulse the CPU reset line, which is more thorough, but
doesn't work with at least one type of 486 motherboard. It is easy
to stop this code working; hence the copious comments. */
@@ -9002,7 +9845,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/reboot.c linux-2.6.28.8/arch/x86/kerne
};
static const struct desc_ptr
-@@ -280,7 +280,7 @@ static const unsigned char jump_to_bios
+@@ -295,7 +295,7 @@ static const unsigned char jump_to_bios
* specified by the code and length parameters.
* We assume that length will aways be less that 100!
*/
@@ -9011,7 +9854,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/reboot.c linux-2.6.28.8/arch/x86/kerne
{
local_irq_disable();
-@@ -300,8 +300,8 @@ void machine_real_restart(const unsigned
+@@ -315,8 +315,8 @@ void machine_real_restart(const unsigned
/* Remap the kernel at virtual address zero, as well as offset zero
from the kernel segment. This assumes the kernel segment starts at
virtual address PAGE_OFFSET. */
@@ -9022,7 +9865,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/reboot.c linux-2.6.28.8/arch/x86/kerne
/*
* Use `swapper_pg_dir' as our page directory.
-@@ -313,16 +313,15 @@ void machine_real_restart(const unsigned
+@@ -328,16 +328,15 @@ void machine_real_restart(const unsigned
boot)". This seems like a fairly standard thing that gets set by
REBOOT.COM programs, and the previous reset routine did this
too. */
@@ -9042,26 +9885,10 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/reboot.c linux-2.6.28.8/arch/x86/kerne
/* Set up the IDT for real mode. */
load_idt(&real_mode_idt);
-diff -urNp linux-2.6.28.8/arch/x86/kernel/setup.c linux-2.6.28.8/arch/x86/kernel/setup.c
---- linux-2.6.28.8/arch/x86/kernel/setup.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/setup.c 2009-02-21 09:37:48.000000000 -0500
-@@ -738,6 +738,7 @@ void start_periodic_check_for_corruption
- }
- #endif
-
-+#ifdef CONFIG_X86_RESERVE_LOW_64K
- static int __init dmi_low_memory_corruption(const struct dmi_system_id *d)
- {
- printk(KERN_NOTICE
-@@ -749,6 +750,7 @@ static int __init dmi_low_memory_corrupt
-
- return 0;
- }
-+#endif
-
- /* List of systems that have known low memory corruption BIOS problems */
- static struct dmi_system_id __initdata bad_bios_dmi_table[] = {
-@@ -845,8 +847,8 @@ void __init setup_arch(char **cmdline_p)
+diff -urNp linux-2.6.29.5/arch/x86/kernel/setup.c linux-2.6.29.5/arch/x86/kernel/setup.c
+--- linux-2.6.29.5/arch/x86/kernel/setup.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/setup.c 2009-06-12 23:57:32.000000000 -0400
+@@ -712,8 +712,8 @@ void __init setup_arch(char **cmdline_p)
if (!boot_params.hdr.root_flags)
root_mountflags &= ~MS_RDONLY;
@@ -9072,7 +9899,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/setup.c linux-2.6.28.8/arch/x86/kernel
init_mm.end_data = (unsigned long) _edata;
#ifdef CONFIG_X86_32
init_mm.brk = init_pg_tables_end + PAGE_OFFSET;
-@@ -854,9 +856,9 @@ void __init setup_arch(char **cmdline_p)
+@@ -721,9 +721,9 @@ void __init setup_arch(char **cmdline_p)
init_mm.brk = (unsigned long) &_end;
#endif
@@ -9085,11 +9912,11 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/setup.c linux-2.6.28.8/arch/x86/kernel
data_resource.end = virt_to_phys(_edata)-1;
bss_resource.start = virt_to_phys(&__bss_start);
bss_resource.end = virt_to_phys(&__bss_stop)-1;
-diff -urNp linux-2.6.28.8/arch/x86/kernel/setup_percpu.c linux-2.6.28.8/arch/x86/kernel/setup_percpu.c
---- linux-2.6.28.8/arch/x86/kernel/setup_percpu.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/setup_percpu.c 2009-02-21 09:37:48.000000000 -0500
-@@ -179,7 +179,11 @@ void __init setup_per_cpu_areas(void)
- cpu, node, __pa(ptr));
+diff -urNp linux-2.6.29.5/arch/x86/kernel/setup_percpu.c linux-2.6.29.5/arch/x86/kernel/setup_percpu.c
+--- linux-2.6.29.5/arch/x86/kernel/setup_percpu.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/setup_percpu.c 2009-06-12 23:57:32.000000000 -0400
+@@ -197,7 +197,11 @@ void __init setup_per_cpu_areas(void)
+ cpu, node, __pa(ptr));
}
#endif
+#ifdef CONFIG_X86_32
@@ -9100,10 +9927,19 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/setup_percpu.c linux-2.6.28.8/arch/x86
memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
}
-diff -urNp linux-2.6.28.8/arch/x86/kernel/signal_32.c linux-2.6.28.8/arch/x86/kernel/signal_32.c
---- linux-2.6.28.8/arch/x86/kernel/signal_32.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/signal_32.c 2009-02-21 09:37:48.000000000 -0500
-@@ -367,9 +367,9 @@ __setup_frame(int sig, struct k_sigactio
+diff -urNp linux-2.6.29.5/arch/x86/kernel/signal.c linux-2.6.29.5/arch/x86/kernel/signal.c
+--- linux-2.6.29.5/arch/x86/kernel/signal.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/signal.c 2009-06-12 23:57:32.000000000 -0400
+@@ -255,7 +255,7 @@ get_sigframe(struct k_sigaction *ka, str
+ * Align the stack pointer according to the i386 ABI,
+ * i.e. so that on function entry ((sp + 4) & 15) == 0.
+ */
+- sp = ((sp + 4) & -16ul) - 4;
++ sp = ((sp - 12) & -16ul) - 4;
+
+ return (void __user *) sp;
+ }
+@@ -287,9 +287,9 @@ __setup_frame(int sig, struct k_sigactio
}
if (current->mm->context.vdso)
@@ -9115,7 +9951,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/signal_32.c linux-2.6.28.8/arch/x86/ke
if (ka->sa.sa_flags & SA_RESTORER)
restorer = ka->sa.sa_restorer;
-@@ -442,7 +442,7 @@ static int __setup_rt_frame(int sig, str
+@@ -360,7 +360,7 @@ static int __setup_rt_frame(int sig, str
return -EFAULT;
/* Set up to return from userspace. */
@@ -9124,7 +9960,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/signal_32.c linux-2.6.28.8/arch/x86/ke
if (ka->sa.sa_flags & SA_RESTORER)
restorer = ka->sa.sa_restorer;
err |= __put_user(restorer, &frame->pretcode);
-@@ -612,7 +612,7 @@ static void do_signal(struct pt_regs *re
+@@ -811,7 +811,7 @@ static void do_signal(struct pt_regs *re
* X86_32: vm86 regs switched out by assembly code before reaching
* here, so testing against kernel CS suffices.
*/
@@ -9133,24 +9969,10 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/signal_32.c linux-2.6.28.8/arch/x86/ke
return;
if (current_thread_info()->status & TS_RESTORE_SIGMASK)
-diff -urNp linux-2.6.28.8/arch/x86/kernel/signal_64.c linux-2.6.28.8/arch/x86/kernel/signal_64.c
---- linux-2.6.28.8/arch/x86/kernel/signal_64.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/signal_64.c 2009-02-21 09:37:48.000000000 -0500
-@@ -239,8 +239,8 @@ static int __setup_rt_frame(int sig, str
- err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0], me);
- err |= __put_user(fp, &frame->uc.uc_mcontext.fpstate);
- if (sizeof(*set) == 16) {
-- __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]);
-- __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]);
-+ err |= __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]);
-+ err |= __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]);
- } else
- err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
-
-diff -urNp linux-2.6.28.8/arch/x86/kernel/smpboot.c linux-2.6.28.8/arch/x86/kernel/smpboot.c
---- linux-2.6.28.8/arch/x86/kernel/smpboot.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/smpboot.c 2009-02-21 09:37:48.000000000 -0500
-@@ -814,6 +814,11 @@ static int __cpuinit do_boot_cpu(int api
+diff -urNp linux-2.6.29.5/arch/x86/kernel/smpboot.c linux-2.6.29.5/arch/x86/kernel/smpboot.c
+--- linux-2.6.29.5/arch/x86/kernel/smpboot.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/smpboot.c 2009-06-12 23:57:32.000000000 -0400
+@@ -806,6 +806,11 @@ static int __cpuinit do_boot_cpu(int api
.cpu = cpu,
.done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done),
};
@@ -9162,7 +9984,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/smpboot.c linux-2.6.28.8/arch/x86/kern
INIT_WORK(&c_idle.work, do_fork_idle);
#ifdef CONFIG_X86_64
-@@ -864,7 +869,17 @@ do_rest:
+@@ -856,7 +861,17 @@ do_rest:
cpu_pda(cpu)->pcurrent = c_idle.idle;
clear_tsk_thread_flag(c_idle.idle, TIF_FORK);
#endif
@@ -9180,9 +10002,9 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/smpboot.c linux-2.6.28.8/arch/x86/kern
initial_code = (unsigned long)start_secondary;
stack_start.sp = (void *) c_idle.idle->thread.sp;
-diff -urNp linux-2.6.28.8/arch/x86/kernel/smpcommon.c linux-2.6.28.8/arch/x86/kernel/smpcommon.c
---- linux-2.6.28.8/arch/x86/kernel/smpcommon.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/smpcommon.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/kernel/smpcommon.c linux-2.6.29.5/arch/x86/kernel/smpcommon.c
+--- linux-2.6.29.5/arch/x86/kernel/smpcommon.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/smpcommon.c 2009-06-12 23:57:32.000000000 -0400
@@ -3,9 +3,10 @@
*/
#include <linux/module.h>
@@ -9222,9 +10044,9 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/smpcommon.c linux-2.6.28.8/arch/x86/ke
per_cpu(cpu_number, cpu) = cpu;
}
#endif
-diff -urNp linux-2.6.28.8/arch/x86/kernel/step.c linux-2.6.28.8/arch/x86/kernel/step.c
---- linux-2.6.28.8/arch/x86/kernel/step.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/step.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/kernel/step.c linux-2.6.29.5/arch/x86/kernel/step.c
+--- linux-2.6.29.5/arch/x86/kernel/step.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/step.c 2009-06-12 23:57:32.000000000 -0400
@@ -23,22 +23,20 @@ unsigned long convert_ip_to_linear(struc
* and APM bios ones we just ignore here.
*/
@@ -9274,17 +10096,17 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/step.c linux-2.6.28.8/arch/x86/kernel/
/* 32-bit mode: register increment */
return 0;
/* 64-bit mode: REX prefix */
-diff -urNp linux-2.6.28.8/arch/x86/kernel/syscall_table_32.S linux-2.6.28.8/arch/x86/kernel/syscall_table_32.S
---- linux-2.6.28.8/arch/x86/kernel/syscall_table_32.S 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/syscall_table_32.S 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/kernel/syscall_table_32.S linux-2.6.29.5/arch/x86/kernel/syscall_table_32.S
+--- linux-2.6.29.5/arch/x86/kernel/syscall_table_32.S 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/syscall_table_32.S 2009-06-12 23:57:32.000000000 -0400
@@ -1,3 +1,4 @@
+.section .rodata,"a",@progbits
ENTRY(sys_call_table)
.long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */
.long sys_exit
-diff -urNp linux-2.6.28.8/arch/x86/kernel/sys_i386_32.c linux-2.6.28.8/arch/x86/kernel/sys_i386_32.c
---- linux-2.6.28.8/arch/x86/kernel/sys_i386_32.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/sys_i386_32.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/kernel/sys_i386_32.c linux-2.6.29.5/arch/x86/kernel/sys_i386_32.c
+--- linux-2.6.29.5/arch/x86/kernel/sys_i386_32.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/sys_i386_32.c 2009-06-12 23:57:32.000000000 -0400
@@ -24,6 +24,21 @@
#include <asm/syscalls.h>
@@ -9513,9 +10335,9 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/sys_i386_32.c linux-2.6.28.8/arch/x86/
struct sel_arg_struct {
unsigned long n;
-diff -urNp linux-2.6.28.8/arch/x86/kernel/sys_x86_64.c linux-2.6.28.8/arch/x86/kernel/sys_x86_64.c
---- linux-2.6.28.8/arch/x86/kernel/sys_x86_64.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/sys_x86_64.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/kernel/sys_x86_64.c linux-2.6.29.5/arch/x86/kernel/sys_x86_64.c
+--- linux-2.6.29.5/arch/x86/kernel/sys_x86_64.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/sys_x86_64.c 2009-06-12 23:57:32.000000000 -0400
@@ -47,8 +47,8 @@ out:
return error;
}
@@ -9597,9 +10419,9 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/sys_x86_64.c linux-2.6.28.8/arch/x86/k
mm->cached_hole_size = ~0UL;
return addr;
-diff -urNp linux-2.6.28.8/arch/x86/kernel/time_32.c linux-2.6.28.8/arch/x86/kernel/time_32.c
---- linux-2.6.28.8/arch/x86/kernel/time_32.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/time_32.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/kernel/time_32.c linux-2.6.29.5/arch/x86/kernel/time_32.c
+--- linux-2.6.29.5/arch/x86/kernel/time_32.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/time_32.c 2009-06-12 23:57:32.000000000 -0400
@@ -47,22 +47,32 @@ unsigned long profile_pc(struct pt_regs
unsigned long pc = instruction_pointer(regs);
@@ -9635,10 +10457,19 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/time_32.c linux-2.6.28.8/arch/x86/kern
return pc;
}
EXPORT_SYMBOL(profile_pc);
-diff -urNp linux-2.6.28.8/arch/x86/kernel/time_64.c linux-2.6.28.8/arch/x86/kernel/time_64.c
---- linux-2.6.28.8/arch/x86/kernel/time_64.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/time_64.c 2009-02-21 09:37:48.000000000 -0500
-@@ -34,7 +34,7 @@ unsigned long profile_pc(struct pt_regs
+diff -urNp linux-2.6.29.5/arch/x86/kernel/time_64.c linux-2.6.29.5/arch/x86/kernel/time_64.c
+--- linux-2.6.29.5/arch/x86/kernel/time_64.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/time_64.c 2009-06-12 23:57:32.000000000 -0400
+@@ -25,8 +25,6 @@
+ #include <asm/time.h>
+ #include <asm/timer.h>
+
+-volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES;
+-
+ unsigned long profile_pc(struct pt_regs *regs)
+ {
+ unsigned long pc = instruction_pointer(regs);
+@@ -34,7 +32,7 @@ unsigned long profile_pc(struct pt_regs
/* Assume the lock function has either no stack frame or a copy
of flags from PUSHF
Eflags always has bits 22 and up cleared unlike kernel addresses. */
@@ -9647,9 +10478,9 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/time_64.c linux-2.6.28.8/arch/x86/kern
#ifdef CONFIG_FRAME_POINTER
return *(unsigned long *)(regs->bp + sizeof(long));
#else
-diff -urNp linux-2.6.28.8/arch/x86/kernel/tlb_32.c linux-2.6.28.8/arch/x86/kernel/tlb_32.c
---- linux-2.6.28.8/arch/x86/kernel/tlb_32.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/tlb_32.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/kernel/tlb_32.c linux-2.6.29.5/arch/x86/kernel/tlb_32.c
+--- linux-2.6.29.5/arch/x86/kernel/tlb_32.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/tlb_32.c 2009-06-12 23:57:32.000000000 -0400
@@ -5,7 +5,7 @@
#include <asm/tlbflush.h>
@@ -9659,9 +10490,9 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/tlb_32.c linux-2.6.28.8/arch/x86/kerne
/* must come after the send_IPI functions above for inlining */
#include <mach_ipi.h>
-diff -urNp linux-2.6.28.8/arch/x86/kernel/tls.c linux-2.6.28.8/arch/x86/kernel/tls.c
---- linux-2.6.28.8/arch/x86/kernel/tls.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/tls.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/kernel/tls.c linux-2.6.29.5/arch/x86/kernel/tls.c
+--- linux-2.6.29.5/arch/x86/kernel/tls.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/tls.c 2009-06-12 23:57:32.000000000 -0400
@@ -85,6 +85,11 @@ int do_set_thread_area(struct task_struc
if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
return -EINVAL;
@@ -9674,10 +10505,10 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/tls.c linux-2.6.28.8/arch/x86/kernel/t
set_tls_desc(p, idx, &info, 1);
return 0;
-diff -urNp linux-2.6.28.8/arch/x86/kernel/traps.c linux-2.6.28.8/arch/x86/kernel/traps.c
---- linux-2.6.28.8/arch/x86/kernel/traps.c 2009-03-07 10:24:49.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/traps.c 2009-03-07 10:29:51.000000000 -0500
-@@ -79,14 +79,6 @@ asmlinkage int system_call(void);
+diff -urNp linux-2.6.29.5/arch/x86/kernel/traps.c linux-2.6.29.5/arch/x86/kernel/traps.c
+--- linux-2.6.29.5/arch/x86/kernel/traps.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/traps.c 2009-06-12 23:57:32.000000000 -0400
+@@ -71,14 +71,6 @@ asmlinkage int system_call(void);
/* Do we ignore FPU interrupts ? */
char ignore_fpu_irq;
@@ -9691,8 +10522,8 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/traps.c linux-2.6.28.8/arch/x86/kernel
- __attribute__((__section__(".data.idt"))) = { { { { 0, 0 } } }, };
#endif
- static int ignore_nmis;
-@@ -121,7 +113,7 @@ static inline void preempt_conditional_c
+ DECLARE_BITMAP(used_vectors, NR_VECTORS);
+@@ -116,7 +108,7 @@ static inline void preempt_conditional_c
static inline void
die_if_kernel(const char *str, struct pt_regs *regs, long err)
{
@@ -9701,7 +10532,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/traps.c linux-2.6.28.8/arch/x86/kernel
die(str, regs, err);
}
-@@ -138,7 +130,7 @@ static int lazy_iobitmap_copy(void)
+@@ -133,7 +125,7 @@ static int lazy_iobitmap_copy(void)
int cpu;
cpu = get_cpu();
@@ -9710,7 +10541,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/traps.c linux-2.6.28.8/arch/x86/kernel
thread = &current->thread;
if (tss->x86_tss.io_bitmap_base == INVALID_IO_BITMAP_OFFSET_LAZY &&
-@@ -174,7 +166,7 @@ do_trap(int trapnr, int signr, char *str
+@@ -169,7 +161,7 @@ do_trap(int trapnr, int signr, char *str
struct task_struct *tsk = current;
#ifdef CONFIG_X86_32
@@ -9719,7 +10550,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/traps.c linux-2.6.28.8/arch/x86/kernel
/*
* traps 0, 1, 3, 4, and 5 should be forwarded to vm86.
* On nmi (interrupt 2), do_trap should not be called.
-@@ -185,7 +177,7 @@ do_trap(int trapnr, int signr, char *str
+@@ -180,7 +172,7 @@ do_trap(int trapnr, int signr, char *str
}
#endif
@@ -9728,7 +10559,16 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/traps.c linux-2.6.28.8/arch/x86/kernel
goto kernel_trap;
#ifdef CONFIG_X86_32
-@@ -227,6 +219,12 @@ kernel_trap:
+@@ -203,7 +195,7 @@ trap_signal:
+ printk_ratelimit()) {
+ printk(KERN_INFO
+ "%s[%d] trap %s ip:%lx sp:%lx error:%lx",
+- tsk->comm, tsk->pid, str,
++ tsk->comm, task_pid_nr(tsk), str,
+ regs->ip, regs->sp, error_code);
+ print_vma_addr(" in ", regs->ip);
+ printk("\n");
+@@ -222,6 +214,12 @@ kernel_trap:
tsk->thread.trap_no = trapnr;
die(str, regs, error_code);
}
@@ -9741,7 +10581,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/traps.c linux-2.6.28.8/arch/x86/kernel
return;
#ifdef CONFIG_X86_32
-@@ -318,14 +316,30 @@ do_general_protection(struct pt_regs *re
+@@ -315,14 +313,30 @@ do_general_protection(struct pt_regs *re
return;
}
@@ -9774,7 +10614,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/traps.c linux-2.6.28.8/arch/x86/kernel
tsk->thread.error_code = error_code;
tsk->thread.trap_no = 13;
-@@ -358,6 +372,13 @@ gp_in_kernel:
+@@ -355,6 +369,13 @@ gp_in_kernel:
if (notify_die(DIE_GPF, "general protection fault", regs,
error_code, 13, SIGSEGV) == NOTIFY_STOP)
return;
@@ -9788,7 +10628,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/traps.c linux-2.6.28.8/arch/x86/kernel
die("general protection fault", regs, error_code);
}
-@@ -604,7 +625,7 @@ dotraplinkage void __kprobes do_debug(st
+@@ -601,7 +622,7 @@ dotraplinkage void __kprobes do_debug(st
}
#ifdef CONFIG_X86_32
@@ -9797,7 +10637,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/traps.c linux-2.6.28.8/arch/x86/kernel
goto debug_vm86;
#endif
-@@ -616,7 +637,7 @@ dotraplinkage void __kprobes do_debug(st
+@@ -613,7 +634,7 @@ dotraplinkage void __kprobes do_debug(st
* kernel space (but re-enable TF when returning to user mode).
*/
if (condition & DR_STEP) {
@@ -9806,7 +10646,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/traps.c linux-2.6.28.8/arch/x86/kernel
goto clear_TF_reenable;
}
-@@ -808,7 +829,7 @@ do_simd_coprocessor_error(struct pt_regs
+@@ -800,7 +821,7 @@ do_simd_coprocessor_error(struct pt_regs
* Handle strange cache flush from user space exception
* in all other cases. This is undocumented behaviour.
*/
@@ -9815,7 +10655,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/traps.c linux-2.6.28.8/arch/x86/kernel
handle_vm86_fault((struct kernel_vm86_regs *)regs, error_code);
return;
}
-@@ -837,19 +858,14 @@ do_spurious_interrupt_bug(struct pt_regs
+@@ -829,19 +850,14 @@ do_spurious_interrupt_bug(struct pt_regs
#ifdef CONFIG_X86_32
unsigned long patch_espfix_desc(unsigned long uesp, unsigned long kesp)
{
@@ -9838,10 +10678,10 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/traps.c linux-2.6.28.8/arch/x86/kernel
return new_kesp;
}
-diff -urNp linux-2.6.28.8/arch/x86/kernel/tsc.c linux-2.6.28.8/arch/x86/kernel/tsc.c
---- linux-2.6.28.8/arch/x86/kernel/tsc.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/tsc.c 2009-02-21 09:37:48.000000000 -0500
-@@ -728,7 +728,7 @@ static struct dmi_system_id __initdata b
+diff -urNp linux-2.6.29.5/arch/x86/kernel/tsc.c linux-2.6.29.5/arch/x86/kernel/tsc.c
+--- linux-2.6.29.5/arch/x86/kernel/tsc.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/tsc.c 2009-06-12 23:57:32.000000000 -0400
+@@ -765,7 +765,7 @@ static struct dmi_system_id __initdata b
DMI_MATCH(DMI_BOARD_NAME, "2635FA0"),
},
},
@@ -9849,10 +10689,10 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/tsc.c linux-2.6.28.8/arch/x86/kernel/t
+ { NULL, NULL, {{0, {0}}}, NULL}
};
- /*
-diff -urNp linux-2.6.28.8/arch/x86/kernel/vm86_32.c linux-2.6.28.8/arch/x86/kernel/vm86_32.c
---- linux-2.6.28.8/arch/x86/kernel/vm86_32.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/vm86_32.c 2009-02-21 09:37:48.000000000 -0500
+ static void __init check_system_tsc_reliable(void)
+diff -urNp linux-2.6.29.5/arch/x86/kernel/vm86_32.c linux-2.6.29.5/arch/x86/kernel/vm86_32.c
+--- linux-2.6.29.5/arch/x86/kernel/vm86_32.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/vm86_32.c 2009-06-12 23:57:32.000000000 -0400
@@ -148,7 +148,7 @@ struct pt_regs *save_v86_state(struct ke
do_exit(SIGSEGV);
}
@@ -9871,9 +10711,9 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/vm86_32.c linux-2.6.28.8/arch/x86/kern
tsk->thread.sp0 = (unsigned long) &info->VM86_TSS_ESP0;
if (cpu_has_sep)
tsk->thread.sysenter_cs = 0;
-diff -urNp linux-2.6.28.8/arch/x86/kernel/vmi_32.c linux-2.6.28.8/arch/x86/kernel/vmi_32.c
---- linux-2.6.28.8/arch/x86/kernel/vmi_32.c 2009-02-08 00:54:27.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/vmi_32.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/kernel/vmi_32.c linux-2.6.29.5/arch/x86/kernel/vmi_32.c
+--- linux-2.6.29.5/arch/x86/kernel/vmi_32.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/vmi_32.c 2009-06-12 23:57:32.000000000 -0400
@@ -102,18 +102,43 @@ static unsigned patch_internal(int call,
{
u64 reloc;
@@ -9918,13 +10758,12 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/vmi_32.c linux-2.6.28.8/arch/x86/kerne
return 5;
case VMI_RELOCATION_NOP:
-@@ -526,14 +551,14 @@ static void vmi_set_pud(pud_t *pudp, pud
+@@ -409,13 +434,13 @@ static void vmi_set_pud(pud_t *pudp, pud
static void vmi_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
- const pte_t pte = { .pte = 0 };
+ const pte_t pte = __pte(0ULL);
- vmi_check_page_type(__pa(ptep) >> PAGE_SHIFT, VMI_PAGE_PTE);
vmi_ops.set_pte(pte, ptep, vmi_flags_addr(mm, addr, VMI_PAGE_PT, 0));
}
@@ -9932,10 +10771,10 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/vmi_32.c linux-2.6.28.8/arch/x86/kerne
{
- const pte_t pte = { .pte = 0 };
+ const pte_t pte = __pte(0ULL);
- vmi_check_page_type(__pa(pmd) >> PAGE_SHIFT, VMI_PAGE_PMD);
vmi_ops.set_pte(pte, (pte_t *)pmd, VMI_PAGE_PD);
}
-@@ -562,8 +587,8 @@ vmi_startup_ipi_hook(int phys_apicid, un
+ #endif
+@@ -443,8 +468,8 @@ vmi_startup_ipi_hook(int phys_apicid, un
ap.ss = __KERNEL_DS;
ap.esp = (unsigned long) start_esp;
@@ -9946,7 +10785,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/vmi_32.c linux-2.6.28.8/arch/x86/kerne
ap.fs = __KERNEL_PERCPU;
ap.gs = 0;
-@@ -758,12 +783,20 @@ static inline int __init activate_vmi(vo
+@@ -639,12 +664,20 @@ static inline int __init activate_vmi(vo
u64 reloc;
const struct vmi_relocation_info *rel = (struct vmi_relocation_info *)&reloc;
@@ -9967,7 +10806,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/vmi_32.c linux-2.6.28.8/arch/x86/kerne
pv_info.paravirt_enabled = 1;
pv_info.kernel_rpl = kernel_cs & SEGMENT_RPL_MASK;
pv_info.name = "vmi";
-@@ -954,6 +987,10 @@ static inline int __init activate_vmi(vo
+@@ -835,6 +868,10 @@ static inline int __init activate_vmi(vo
para_fill(pv_irq_ops.safe_halt, Halt);
@@ -9978,9 +10817,9 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/vmi_32.c linux-2.6.28.8/arch/x86/kerne
/*
* Alternative instruction rewriting doesn't happen soon enough
* to convert VMI_IRET to a call instead of a jump; so we have
-diff -urNp linux-2.6.28.8/arch/x86/kernel/vmlinux_32.lds.S linux-2.6.28.8/arch/x86/kernel/vmlinux_32.lds.S
---- linux-2.6.28.8/arch/x86/kernel/vmlinux_32.lds.S 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/vmlinux_32.lds.S 2009-03-07 10:35:39.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/kernel/vmlinux_32.lds.S linux-2.6.29.5/arch/x86/kernel/vmlinux_32.lds.S
+--- linux-2.6.29.5/arch/x86/kernel/vmlinux_32.lds.S 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/vmlinux_32.lds.S 2009-06-12 23:57:32.000000000 -0400
@@ -15,6 +15,20 @@
#include <asm/page.h>
#include <asm/cache.h>
@@ -10002,7 +10841,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/vmlinux_32.lds.S linux-2.6.28.8/arch/x
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH(i386)
-@@ -22,81 +36,23 @@ ENTRY(phys_startup_32)
+@@ -22,82 +36,23 @@ ENTRY(phys_startup_32)
jiffies = jiffies_64;
PHDRS {
@@ -10035,13 +10874,15 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/vmlinux_32.lds.S linux-2.6.28.8/arch/x
- SCHED_TEXT
- LOCK_TEXT
- KPROBES_TEXT
+- IRQENTRY_TEXT
- *(.fixup)
- *(.gnu.warning)
- _etext = .; /* End of text section */
- } :text = 0x9090
-
- NOTES :text :note
--
++ . = LOAD_OFFSET + ____LOAD_PHYSICAL_ADDR;
+
- . = ALIGN(16); /* Exception table */
- __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) {
- __start___ex_table = .;
@@ -10065,8 +10906,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/vmlinux_32.lds.S linux-2.6.28.8/arch/x
- . = ALIGN(PAGE_SIZE);
- __nosave_end = .;
- }
-+ . = LOAD_OFFSET + ____LOAD_PHYSICAL_ADDR;
-
+-
- . = ALIGN(PAGE_SIZE);
- .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) {
- *(.data.page_aligned)
@@ -10097,7 +10937,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/vmlinux_32.lds.S linux-2.6.28.8/arch/x
/* might get freed after init */
. = ALIGN(PAGE_SIZE);
-@@ -114,14 +70,8 @@ SECTIONS
+@@ -115,14 +70,8 @@ SECTIONS
. = ALIGN(PAGE_SIZE);
/* will be freed after init */
@@ -10113,7 +10953,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/vmlinux_32.lds.S linux-2.6.28.8/arch/x
INIT_DATA
}
. = ALIGN(16);
-@@ -161,11 +111,6 @@ SECTIONS
+@@ -162,11 +111,6 @@ SECTIONS
*(.parainstructions)
__parainstructions_end = .;
}
@@ -10125,7 +10965,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/vmlinux_32.lds.S linux-2.6.28.8/arch/x
.exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) {
EXIT_DATA
}
-@@ -178,18 +123,138 @@ SECTIONS
+@@ -179,18 +123,139 @@ SECTIONS
}
#endif
. = ALIGN(PAGE_SIZE);
@@ -10183,6 +11023,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/vmlinux_32.lds.S linux-2.6.28.8/arch/x
+ SCHED_TEXT
+ LOCK_TEXT
+ KPROBES_TEXT
++ IRQENTRY_TEXT
+ *(.fixup)
+ *(.gnu.warning)
+ _etext = .; /* End of text section */
@@ -10270,19 +11111,26 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/vmlinux_32.lds.S linux-2.6.28.8/arch/x
__bss_start = .; /* BSS */
*(.bss.page_aligned)
*(.bss)
-diff -urNp linux-2.6.28.8/arch/x86/kernel/vmlinux_64.lds.S linux-2.6.28.8/arch/x86/kernel/vmlinux_64.lds.S
---- linux-2.6.28.8/arch/x86/kernel/vmlinux_64.lds.S 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/vmlinux_64.lds.S 2009-02-21 09:37:48.000000000 -0500
-@@ -16,7 +16,7 @@ jiffies_64 = jiffies;
+diff -urNp linux-2.6.29.5/arch/x86/kernel/vmlinux_64.lds.S linux-2.6.29.5/arch/x86/kernel/vmlinux_64.lds.S
+--- linux-2.6.29.5/arch/x86/kernel/vmlinux_64.lds.S 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/vmlinux_64.lds.S 2009-06-12 23:57:32.000000000 -0400
+@@ -12,12 +12,12 @@
+ OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
+ OUTPUT_ARCH(i386:x86-64)
+ ENTRY(phys_startup_64)
+-jiffies_64 = jiffies;
++jiffies = jiffies_64;
_proxy_pda = 1;
PHDRS {
text PT_LOAD FLAGS(5); /* R_E */
- data PT_LOAD FLAGS(7); /* RWE */
+- user PT_LOAD FLAGS(7); /* RWE */
++ user PT_LOAD FLAGS(5); /* R_E */
+ data PT_LOAD FLAGS(6); /* RW_ */
- user PT_LOAD FLAGS(7); /* RWE */
data.init PT_LOAD FLAGS(7); /* RWE */
note PT_NOTE FLAGS(0); /* ___ */
-@@ -49,17 +49,20 @@ SECTIONS
+ }
+@@ -50,17 +50,20 @@ SECTIONS
__stop___ex_table = .;
} :text = 0x9090
@@ -10306,20 +11154,29 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/vmlinux_64.lds.S linux-2.6.28.8/arch/x
. = ALIGN(PAGE_SIZE);
. = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
.data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) {
-@@ -70,9 +73,27 @@ SECTIONS
- *(.data.read_mostly)
+@@ -104,10 +107,6 @@ SECTIONS
+ .vgetcpu_mode : AT(VLOAD(.vgetcpu_mode)) { *(.vgetcpu_mode) }
+ vgetcpu_mode = VVIRT(.vgetcpu_mode);
+
+- . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
+- .jiffies : AT(VLOAD(.jiffies)) { *(.jiffies) }
+- jiffies = VVIRT(.jiffies);
+-
+ .vsyscall_3 ADDR(.vsyscall_0) + 3072: AT(VLOAD(.vsyscall_3))
+ { *(.vsyscall_3) }
+
+@@ -124,20 +123,28 @@ SECTIONS
+ . = ALIGN(THREAD_SIZE); /* init_task */
+ .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
+ *(.data.init_task)
+- }:data.init
++ }:data
+
+ . = ALIGN(PAGE_SIZE);
+ .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) {
+ *(.data.page_aligned)
}
-+ . = ALIGN(THREAD_SIZE); /* init_task */
-+ .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
-+ *(.data.init_task)
-+ }
-+
-+ . = ALIGN(PAGE_SIZE);
-+ .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) {
-+ *(.data.page_aligned)
-+ }
-+
+ . = ALIGN(PAGE_SIZE);
+ __nosave_begin = .;
+ .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { *(.data.nosave) }
@@ -10328,28 +11185,6 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/vmlinux_64.lds.S linux-2.6.28.8/arch/x
+
+ _edata = .; /* End of data section */
+
- #define VSYSCALL_ADDR (-10*1024*1024)
--#define VSYSCALL_PHYS_ADDR ((LOADADDR(.data.read_mostly) + SIZEOF(.data.read_mostly) + 4095) & ~(4095))
--#define VSYSCALL_VIRT_ADDR ((ADDR(.data.read_mostly) + SIZEOF(.data.read_mostly) + 4095) & ~(4095))
-+#define VSYSCALL_PHYS_ADDR ((LOADADDR(.data_nosave) + SIZEOF(.data_nosave) + 4095) & ~(4095))
-+#define VSYSCALL_VIRT_ADDR ((ADDR(.data_nosave) + SIZEOF(.data_nosave) + 4095) & ~(4095))
-
- #define VLOAD_OFFSET (VSYSCALL_ADDR - VSYSCALL_PHYS_ADDR)
- #define VLOAD(x) (ADDR(x) - VLOAD_OFFSET)
-@@ -120,23 +141,13 @@ SECTIONS
- #undef VVIRT_OFFSET
- #undef VVIRT
-
-- . = ALIGN(THREAD_SIZE); /* init_task */
-- .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
-- *(.data.init_task)
-- }:data.init
--
-- . = ALIGN(PAGE_SIZE);
-- .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) {
-- *(.data.page_aligned)
-- }
--
/* might get freed after init */
. = ALIGN(PAGE_SIZE);
__smp_alt_begin = .;
@@ -10357,11 +11192,11 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/vmlinux_64.lds.S linux-2.6.28.8/arch/x
.smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) {
*(.smp_locks)
- }
-+ } :data.init
++ }:data.init
__smp_locks_end = .;
. = ALIGN(PAGE_SIZE);
__smp_alt_end = .;
-@@ -212,16 +223,11 @@ SECTIONS
+@@ -213,16 +220,11 @@ SECTIONS
. = ALIGN(PAGE_SIZE);
__init_end = .;
@@ -10379,10 +11214,27 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/vmlinux_64.lds.S linux-2.6.28.8/arch/x
}
__bss_stop = .;
-diff -urNp linux-2.6.28.8/arch/x86/kernel/vsyscall_64.c linux-2.6.28.8/arch/x86/kernel/vsyscall_64.c
---- linux-2.6.28.8/arch/x86/kernel/vsyscall_64.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kernel/vsyscall_64.c 2009-02-21 09:37:48.000000000 -0500
-@@ -236,13 +236,13 @@ static ctl_table kernel_table2[] = {
+diff -urNp linux-2.6.29.5/arch/x86/kernel/vsyscall_64.c linux-2.6.29.5/arch/x86/kernel/vsyscall_64.c
+--- linux-2.6.29.5/arch/x86/kernel/vsyscall_64.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/vsyscall_64.c 2009-06-12 23:57:32.000000000 -0400
+@@ -79,6 +79,7 @@ void update_vsyscall(struct timespec *wa
+
+ write_seqlock_irqsave(&vsyscall_gtod_data.lock, flags);
+ /* copy vsyscall data */
++ strlcpy(vsyscall_gtod_data.clock.name, clock->name, sizeof vsyscall_gtod_data.clock.name);
+ vsyscall_gtod_data.clock.vread = clock->vread;
+ vsyscall_gtod_data.clock.cycle_last = clock->cycle_last;
+ vsyscall_gtod_data.clock.mask = clock->mask;
+@@ -209,7 +210,7 @@ vgetcpu(unsigned *cpu, unsigned *node, s
+ We do this here because otherwise user space would do it on
+ its own in a likely inferior way (no access to jiffies).
+ If you don't like it pass NULL. */
+- if (tcache && tcache->blob[0] == (j = __jiffies)) {
++ if (tcache && tcache->blob[0] == (j = jiffies)) {
+ p = tcache->blob[1];
+ } else if (__vgetcpu_mode == VGETCPU_RDTSCP) {
+ /* Load per CPU data from RDTSCP */
+@@ -248,13 +249,13 @@ static ctl_table kernel_table2[] = {
.data = &vsyscall_gtod_data.sysctl_enabled, .maxlen = sizeof(int),
.mode = 0644,
.proc_handler = vsyscall_sysctl_change },
@@ -10398,10 +11250,22 @@ diff -urNp linux-2.6.28.8/arch/x86/kernel/vsyscall_64.c linux-2.6.28.8/arch/x86/
};
#endif
-diff -urNp linux-2.6.28.8/arch/x86/kvm/svm.c linux-2.6.28.8/arch/x86/kvm/svm.c
---- linux-2.6.28.8/arch/x86/kvm/svm.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kvm/svm.c 2009-02-21 09:37:48.000000000 -0500
-@@ -1505,7 +1505,19 @@ static void reload_tss(struct kvm_vcpu *
+diff -urNp linux-2.6.29.5/arch/x86/kernel/x8664_ksyms_64.c linux-2.6.29.5/arch/x86/kernel/x8664_ksyms_64.c
+--- linux-2.6.29.5/arch/x86/kernel/x8664_ksyms_64.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kernel/x8664_ksyms_64.c 2009-06-12 23:57:32.000000000 -0400
+@@ -30,8 +30,6 @@ EXPORT_SYMBOL(__put_user_8);
+
+ EXPORT_SYMBOL(copy_user_generic);
+ EXPORT_SYMBOL(__copy_user_nocache);
+-EXPORT_SYMBOL(copy_from_user);
+-EXPORT_SYMBOL(copy_to_user);
+ EXPORT_SYMBOL(__copy_from_user_inatomic);
+
+ EXPORT_SYMBOL(copy_page);
+diff -urNp linux-2.6.29.5/arch/x86/kvm/svm.c linux-2.6.29.5/arch/x86/kvm/svm.c
+--- linux-2.6.29.5/arch/x86/kvm/svm.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kvm/svm.c 2009-06-12 23:57:32.000000000 -0400
+@@ -1525,7 +1525,19 @@ static void reload_tss(struct kvm_vcpu *
int cpu = raw_smp_processor_id();
struct svm_cpu_data *svm_data = per_cpu(svm_data, cpu);
@@ -10421,8 +11285,8 @@ diff -urNp linux-2.6.28.8/arch/x86/kvm/svm.c linux-2.6.28.8/arch/x86/kvm/svm.c
load_TR_desc();
}
-@@ -1912,7 +1924,7 @@ static int get_npt_level(void)
- #endif
+@@ -1936,7 +1948,7 @@ static int svm_get_mt_mask_shift(void)
+ return 0;
}
-static struct kvm_x86_ops svm_x86_ops = {
@@ -10430,19 +11294,10 @@ diff -urNp linux-2.6.28.8/arch/x86/kvm/svm.c linux-2.6.28.8/arch/x86/kvm/svm.c
.cpu_has_kvm_support = has_svm,
.disabled_by_bios = is_disabled,
.hardware_setup = svm_hardware_setup,
-diff -urNp linux-2.6.28.8/arch/x86/kvm/vmx.c linux-2.6.28.8/arch/x86/kvm/vmx.c
---- linux-2.6.28.8/arch/x86/kvm/vmx.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kvm/vmx.c 2009-02-21 09:37:48.000000000 -0500
-@@ -122,7 +122,7 @@ static struct vmcs_config {
- u32 vmentry_ctrl;
- } vmcs_config;
-
--struct vmx_capability {
-+static struct vmx_capability {
- u32 ept;
- u32 vpid;
- } vmx_capability;
-@@ -491,9 +491,23 @@ static void reload_tss(void)
+diff -urNp linux-2.6.29.5/arch/x86/kvm/vmx.c linux-2.6.29.5/arch/x86/kvm/vmx.c
+--- linux-2.6.29.5/arch/x86/kvm/vmx.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kvm/vmx.c 2009-06-12 23:57:32.000000000 -0400
+@@ -497,9 +497,23 @@ static void reload_tss(void)
struct descriptor_table gdt;
struct desc_struct *descs;
@@ -10466,7 +11321,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kvm/vmx.c linux-2.6.28.8/arch/x86/kvm/vmx.c
load_TR_desc();
}
-@@ -2164,7 +2178,7 @@ static int vmx_vcpu_setup(struct vcpu_vm
+@@ -2182,7 +2196,7 @@ static int vmx_vcpu_setup(struct vcpu_vm
vmcs_writel(HOST_IDTR_BASE, dt.base); /* 22.2.4 */
asm("mov $.Lkvm_vmx_return, %0" : "=r"(kvm_vmx_return));
@@ -10475,7 +11330,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kvm/vmx.c linux-2.6.28.8/arch/x86/kvm/vmx.c
vmcs_write32(VM_EXIT_MSR_STORE_COUNT, 0);
vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, 0);
vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, 0);
-@@ -3267,6 +3281,12 @@ static void vmx_vcpu_run(struct kvm_vcpu
+@@ -3379,6 +3393,12 @@ static void vmx_vcpu_run(struct kvm_vcpu
"jmp .Lkvm_vmx_return \n\t"
".Llaunched: " __ex(ASM_VMX_VMRESUME) "\n\t"
".Lkvm_vmx_return: "
@@ -10488,7 +11343,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kvm/vmx.c linux-2.6.28.8/arch/x86/kvm/vmx.c
/* Save guest registers, load host registers, keep flags */
"xchg %0, (%%"R"sp) \n\t"
"mov %%"R"ax, %c[rax](%0) \n\t"
-@@ -3313,6 +3333,11 @@ static void vmx_vcpu_run(struct kvm_vcpu
+@@ -3425,6 +3445,11 @@ static void vmx_vcpu_run(struct kvm_vcpu
[r15]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R15])),
#endif
[cr2]"i"(offsetof(struct vcpu_vmx, vcpu.arch.cr2))
@@ -10500,17 +11355,17 @@ diff -urNp linux-2.6.28.8/arch/x86/kvm/vmx.c linux-2.6.28.8/arch/x86/kvm/vmx.c
: "cc", "memory"
, R"bx", R"di", R"si"
#ifdef CONFIG_X86_64
-@@ -3331,7 +3356,7 @@ static void vmx_vcpu_run(struct kvm_vcpu
- (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) &
- (GUEST_INTR_STATE_STI | GUEST_INTR_STATE_MOV_SS)) == 0;
+@@ -3441,7 +3466,7 @@ static void vmx_vcpu_run(struct kvm_vcpu
+
+ vmx_update_window_states(vcpu);
- asm("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS));
+ asm("mov %0, %%ds; mov %0, %%es" : : "r"(__KERNEL_DS));
vmx->launched = 1;
intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
-@@ -3455,7 +3480,7 @@ static int get_ept_level(void)
- return VMX_EPT_DEFAULT_GAW + 1;
+@@ -3570,7 +3595,7 @@ static int vmx_get_mt_mask_shift(void)
+ return VMX_EPT_MT_EPTE_SHIFT;
}
-static struct kvm_x86_ops vmx_x86_ops = {
@@ -10518,10 +11373,10 @@ diff -urNp linux-2.6.28.8/arch/x86/kvm/vmx.c linux-2.6.28.8/arch/x86/kvm/vmx.c
.cpu_has_kvm_support = cpu_has_kvm_support,
.disabled_by_bios = vmx_disabled_by_bios,
.hardware_setup = hardware_setup,
-diff -urNp linux-2.6.28.8/arch/x86/kvm/x86.c linux-2.6.28.8/arch/x86/kvm/x86.c
---- linux-2.6.28.8/arch/x86/kvm/x86.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/kvm/x86.c 2009-02-21 09:37:48.000000000 -0500
-@@ -68,41 +68,41 @@ static u64 __read_mostly efer_reserved_b
+diff -urNp linux-2.6.29.5/arch/x86/kvm/x86.c linux-2.6.29.5/arch/x86/kvm/x86.c
+--- linux-2.6.29.5/arch/x86/kvm/x86.c 2009-06-12 23:55:00.000000000 -0400
++++ linux-2.6.29.5/arch/x86/kvm/x86.c 2009-06-12 23:57:32.000000000 -0400
+@@ -70,44 +70,44 @@ static u64 __read_mostly efer_reserved_b
static int kvm_dev_ioctl_get_supported_cpuid(struct kvm_cpuid2 *cpuid,
struct kvm_cpuid_entry2 __user *entries);
@@ -10544,6 +11399,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kvm/x86.c linux-2.6.28.8/arch/x86/kvm/x86.c
- { "halt_wakeup", VCPU_STAT(halt_wakeup) },
- { "hypercalls", VCPU_STAT(hypercalls) },
- { "request_irq", VCPU_STAT(request_irq_exits) },
+- { "request_nmi", VCPU_STAT(request_nmi_exits) },
- { "irq_exits", VCPU_STAT(irq_exits) },
- { "host_state_reload", VCPU_STAT(host_state_reload) },
- { "efer_reload", VCPU_STAT(efer_reload) },
@@ -10551,6 +11407,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kvm/x86.c linux-2.6.28.8/arch/x86/kvm/x86.c
- { "insn_emulation", VCPU_STAT(insn_emulation) },
- { "insn_emulation_fail", VCPU_STAT(insn_emulation_fail) },
- { "irq_injections", VCPU_STAT(irq_injections) },
+- { "nmi_injections", VCPU_STAT(nmi_injections) },
- { "mmu_shadow_zapped", VM_STAT(mmu_shadow_zapped) },
- { "mmu_pte_write", VM_STAT(mmu_pte_write) },
- { "mmu_pte_updated", VM_STAT(mmu_pte_updated) },
@@ -10559,6 +11416,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kvm/x86.c linux-2.6.28.8/arch/x86/kvm/x86.c
- { "mmu_recycled", VM_STAT(mmu_recycled) },
- { "mmu_cache_miss", VM_STAT(mmu_cache_miss) },
- { "mmu_unsync", VM_STAT(mmu_unsync) },
+- { "mmu_unsync_global", VM_STAT(mmu_unsync_global) },
- { "remote_tlb_flush", VM_STAT(remote_tlb_flush) },
- { "largepages", VM_STAT(lpages) },
+ { "pf_fixed", VCPU_STAT(pf_fixed), NULL },
@@ -10575,6 +11433,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kvm/x86.c linux-2.6.28.8/arch/x86/kvm/x86.c
+ { "halt_wakeup", VCPU_STAT(halt_wakeup), NULL },
+ { "hypercalls", VCPU_STAT(hypercalls), NULL },
+ { "request_irq", VCPU_STAT(request_irq_exits), NULL },
++ { "request_nmi", VCPU_STAT(request_nmi_exits), NULL },
+ { "irq_exits", VCPU_STAT(irq_exits), NULL },
+ { "host_state_reload", VCPU_STAT(host_state_reload), NULL },
+ { "efer_reload", VCPU_STAT(efer_reload), NULL },
@@ -10582,6 +11441,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kvm/x86.c linux-2.6.28.8/arch/x86/kvm/x86.c
+ { "insn_emulation", VCPU_STAT(insn_emulation), NULL },
+ { "insn_emulation_fail", VCPU_STAT(insn_emulation_fail), NULL },
+ { "irq_injections", VCPU_STAT(irq_injections), NULL },
++ { "nmi_injections", VCPU_STAT(nmi_injections), NULL },
+ { "mmu_shadow_zapped", VM_STAT(mmu_shadow_zapped), NULL },
+ { "mmu_pte_write", VM_STAT(mmu_pte_write), NULL },
+ { "mmu_pte_updated", VM_STAT(mmu_pte_updated), NULL },
@@ -10590,12 +11450,13 @@ diff -urNp linux-2.6.28.8/arch/x86/kvm/x86.c linux-2.6.28.8/arch/x86/kvm/x86.c
+ { "mmu_recycled", VM_STAT(mmu_recycled), NULL },
+ { "mmu_cache_miss", VM_STAT(mmu_cache_miss), NULL },
+ { "mmu_unsync", VM_STAT(mmu_unsync), NULL },
++ { "mmu_unsync_global", VM_STAT(mmu_unsync_global), NULL },
+ { "remote_tlb_flush", VM_STAT(remote_tlb_flush), NULL },
+ { "largepages", VM_STAT(lpages), NULL },
{ NULL }
};
-@@ -1304,7 +1304,7 @@ static int kvm_vcpu_ioctl_set_lapic(stru
+@@ -1372,7 +1372,7 @@ static int kvm_vcpu_ioctl_set_lapic(stru
static int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu,
struct kvm_interrupt *irq)
{
@@ -10604,7 +11465,7 @@ diff -urNp linux-2.6.28.8/arch/x86/kvm/x86.c linux-2.6.28.8/arch/x86/kvm/x86.c
return -EINVAL;
if (irqchip_in_kernel(vcpu->kvm))
return -ENXIO;
-@@ -2509,10 +2509,10 @@ int kvm_emulate_pio_string(struct kvm_vc
+@@ -2591,10 +2591,10 @@ int kvm_emulate_pio_string(struct kvm_vc
}
EXPORT_SYMBOL_GPL(kvm_emulate_pio_string);
@@ -10617,9 +11478,9 @@ diff -urNp linux-2.6.28.8/arch/x86/kvm/x86.c linux-2.6.28.8/arch/x86/kvm/x86.c
if (kvm_x86_ops) {
printk(KERN_ERR "kvm: already loaded the other module\n");
-diff -urNp linux-2.6.28.8/arch/x86/lib/checksum_32.S linux-2.6.28.8/arch/x86/lib/checksum_32.S
---- linux-2.6.28.8/arch/x86/lib/checksum_32.S 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/lib/checksum_32.S 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/lib/checksum_32.S linux-2.6.29.5/arch/x86/lib/checksum_32.S
+--- linux-2.6.29.5/arch/x86/lib/checksum_32.S 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/lib/checksum_32.S 2009-06-12 23:57:32.000000000 -0400
@@ -28,7 +28,8 @@
#include <linux/linkage.h>
#include <asm/dwarf2.h>
@@ -10865,9 +11726,9 @@ diff -urNp linux-2.6.28.8/arch/x86/lib/checksum_32.S linux-2.6.28.8/arch/x86/lib
#undef ROUND
#undef ROUND1
-diff -urNp linux-2.6.28.8/arch/x86/lib/clear_page_64.S linux-2.6.28.8/arch/x86/lib/clear_page_64.S
---- linux-2.6.28.8/arch/x86/lib/clear_page_64.S 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/lib/clear_page_64.S 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/lib/clear_page_64.S linux-2.6.29.5/arch/x86/lib/clear_page_64.S
+--- linux-2.6.29.5/arch/x86/lib/clear_page_64.S 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/lib/clear_page_64.S 2009-06-12 23:57:32.000000000 -0400
@@ -44,7 +44,7 @@ ENDPROC(clear_page)
#include <asm/cpufeature.h>
@@ -10877,9 +11738,9 @@ diff -urNp linux-2.6.28.8/arch/x86/lib/clear_page_64.S linux-2.6.28.8/arch/x86/l
1: .byte 0xeb /* jmp <disp8> */
.byte (clear_page_c - clear_page) - (2f - 1b) /* offset */
2:
-diff -urNp linux-2.6.28.8/arch/x86/lib/copy_page_64.S linux-2.6.28.8/arch/x86/lib/copy_page_64.S
---- linux-2.6.28.8/arch/x86/lib/copy_page_64.S 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/lib/copy_page_64.S 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/lib/copy_page_64.S linux-2.6.29.5/arch/x86/lib/copy_page_64.S
+--- linux-2.6.29.5/arch/x86/lib/copy_page_64.S 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/lib/copy_page_64.S 2009-06-12 23:57:32.000000000 -0400
@@ -104,7 +104,7 @@ ENDPROC(copy_page)
#include <asm/cpufeature.h>
@@ -10889,9 +11750,9 @@ diff -urNp linux-2.6.28.8/arch/x86/lib/copy_page_64.S linux-2.6.28.8/arch/x86/li
1: .byte 0xeb /* jmp <disp8> */
.byte (copy_page_c - copy_page) - (2f - 1b) /* offset */
2:
-diff -urNp linux-2.6.28.8/arch/x86/lib/copy_user_64.S linux-2.6.28.8/arch/x86/lib/copy_user_64.S
---- linux-2.6.28.8/arch/x86/lib/copy_user_64.S 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/lib/copy_user_64.S 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/lib/copy_user_64.S linux-2.6.29.5/arch/x86/lib/copy_user_64.S
+--- linux-2.6.29.5/arch/x86/lib/copy_user_64.S 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/lib/copy_user_64.S 2009-06-12 23:57:32.000000000 -0400
@@ -21,7 +21,7 @@
.byte 0xe9 /* 32bit jump */
.long \orig-1f /* by default jump to orig */
@@ -10901,7 +11762,39 @@ diff -urNp linux-2.6.28.8/arch/x86/lib/copy_user_64.S linux-2.6.28.8/arch/x86/li
2: .byte 0xe9 /* near jump with 32bit immediate */
.long \alt-1b /* offset */ /* or alternatively to alt */
.previous
-@@ -106,6 +106,8 @@ ENDPROC(__copy_from_user_inatomic)
+@@ -64,31 +64,6 @@
+ #endif
+ .endm
+
+-/* Standard copy_to_user with segment limit checking */
+-ENTRY(copy_to_user)
+- CFI_STARTPROC
+- GET_THREAD_INFO(%rax)
+- movq %rdi,%rcx
+- addq %rdx,%rcx
+- jc bad_to_user
+- cmpq TI_addr_limit(%rax),%rcx
+- jae bad_to_user
+- ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
+- CFI_ENDPROC
+-
+-/* Standard copy_from_user with segment limit checking */
+-ENTRY(copy_from_user)
+- CFI_STARTPROC
+- GET_THREAD_INFO(%rax)
+- movq %rsi,%rcx
+- addq %rdx,%rcx
+- jc bad_from_user
+- cmpq TI_addr_limit(%rax),%rcx
+- jae bad_from_user
+- ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
+- CFI_ENDPROC
+-ENDPROC(copy_from_user)
+-
+ ENTRY(copy_user_generic)
+ CFI_STARTPROC
+ ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
+@@ -106,6 +81,8 @@ ENDPROC(__copy_from_user_inatomic)
ENTRY(bad_from_user)
bad_from_user:
CFI_STARTPROC
@@ -10910,9 +11803,9 @@ diff -urNp linux-2.6.28.8/arch/x86/lib/copy_user_64.S linux-2.6.28.8/arch/x86/li
movl %edx,%ecx
xorl %eax,%eax
rep
-diff -urNp linux-2.6.28.8/arch/x86/lib/getuser.S linux-2.6.28.8/arch/x86/lib/getuser.S
---- linux-2.6.28.8/arch/x86/lib/getuser.S 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/lib/getuser.S 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/lib/getuser.S linux-2.6.29.5/arch/x86/lib/getuser.S
+--- linux-2.6.29.5/arch/x86/lib/getuser.S 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/lib/getuser.S 2009-06-12 23:57:32.000000000 -0400
@@ -33,6 +33,7 @@
#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
@@ -10994,9 +11887,9 @@ diff -urNp linux-2.6.28.8/arch/x86/lib/getuser.S linux-2.6.28.8/arch/x86/lib/get
xor %edx,%edx
mov $(-EFAULT),%_ASM_AX
ret
-diff -urNp linux-2.6.28.8/arch/x86/lib/memcpy_64.S linux-2.6.28.8/arch/x86/lib/memcpy_64.S
---- linux-2.6.28.8/arch/x86/lib/memcpy_64.S 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/lib/memcpy_64.S 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/lib/memcpy_64.S linux-2.6.29.5/arch/x86/lib/memcpy_64.S
+--- linux-2.6.29.5/arch/x86/lib/memcpy_64.S 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/lib/memcpy_64.S 2009-06-12 23:57:32.000000000 -0400
@@ -114,7 +114,7 @@ ENDPROC(__memcpy)
/* Some CPUs run faster using the string copy instructions.
It is also a lot simpler. Use this when possible */
@@ -11006,9 +11899,9 @@ diff -urNp linux-2.6.28.8/arch/x86/lib/memcpy_64.S linux-2.6.28.8/arch/x86/lib/m
1: .byte 0xeb /* jmp <disp8> */
.byte (memcpy_c - memcpy) - (2f - 1b) /* offset */
2:
-diff -urNp linux-2.6.28.8/arch/x86/lib/memset_64.S linux-2.6.28.8/arch/x86/lib/memset_64.S
---- linux-2.6.28.8/arch/x86/lib/memset_64.S 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/lib/memset_64.S 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/lib/memset_64.S linux-2.6.29.5/arch/x86/lib/memset_64.S
+--- linux-2.6.29.5/arch/x86/lib/memset_64.S 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/lib/memset_64.S 2009-06-12 23:57:32.000000000 -0400
@@ -118,7 +118,7 @@ ENDPROC(__memset)
#include <asm/cpufeature.h>
@@ -11018,9 +11911,9 @@ diff -urNp linux-2.6.28.8/arch/x86/lib/memset_64.S linux-2.6.28.8/arch/x86/lib/m
1: .byte 0xeb /* jmp <disp8> */
.byte (memset_c - memset) - (2f - 1b) /* offset */
2:
-diff -urNp linux-2.6.28.8/arch/x86/lib/mmx_32.c linux-2.6.28.8/arch/x86/lib/mmx_32.c
---- linux-2.6.28.8/arch/x86/lib/mmx_32.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/lib/mmx_32.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/lib/mmx_32.c linux-2.6.29.5/arch/x86/lib/mmx_32.c
+--- linux-2.6.29.5/arch/x86/lib/mmx_32.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/lib/mmx_32.c 2009-06-12 23:57:32.000000000 -0400
@@ -29,6 +29,7 @@ void *_mmx_memcpy(void *to, const void *
{
void *p;
@@ -11336,9 +12229,9 @@ diff -urNp linux-2.6.28.8/arch/x86/lib/mmx_32.c linux-2.6.28.8/arch/x86/lib/mmx_
from += 64;
to += 64;
-diff -urNp linux-2.6.28.8/arch/x86/lib/putuser.S linux-2.6.28.8/arch/x86/lib/putuser.S
---- linux-2.6.28.8/arch/x86/lib/putuser.S 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/lib/putuser.S 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/lib/putuser.S linux-2.6.29.5/arch/x86/lib/putuser.S
+--- linux-2.6.29.5/arch/x86/lib/putuser.S 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/lib/putuser.S 2009-06-12 23:57:32.000000000 -0400
@@ -15,6 +15,7 @@
#include <asm/thread_info.h>
#include <asm/errno.h>
@@ -11442,9 +12335,9 @@ diff -urNp linux-2.6.28.8/arch/x86/lib/putuser.S linux-2.6.28.8/arch/x86/lib/put
movl $-EFAULT,%eax
EXIT
END(bad_put_user)
-diff -urNp linux-2.6.28.8/arch/x86/lib/usercopy_32.c linux-2.6.28.8/arch/x86/lib/usercopy_32.c
---- linux-2.6.28.8/arch/x86/lib/usercopy_32.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/lib/usercopy_32.c 2009-02-21 09:39:27.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/lib/usercopy_32.c linux-2.6.29.5/arch/x86/lib/usercopy_32.c
+--- linux-2.6.29.5/arch/x86/lib/usercopy_32.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/lib/usercopy_32.c 2009-06-12 23:57:32.000000000 -0400
@@ -36,31 +36,38 @@ static inline int __movsl_is_ok(unsigned
* Copy a null terminated string from userspace.
*/
@@ -11452,7 +12345,7 @@ diff -urNp linux-2.6.28.8/arch/x86/lib/usercopy_32.c linux-2.6.28.8/arch/x86/lib
-#define __do_strncpy_from_user(dst, src, count, res) \
-do { \
- int __d0, __d1, __d2; \
-- might_sleep(); \
+- might_fault(); \
- __asm__ __volatile__( \
- " testl %1,%1\n" \
- " jz 2f\n" \
@@ -11479,7 +12372,7 @@ diff -urNp linux-2.6.28.8/arch/x86/lib/usercopy_32.c linux-2.6.28.8/arch/x86/lib
+ int __d0, __d1, __d2;
+ long res = -EFAULT;
+
-+ might_sleep();
++ might_fault();
+ __asm__ __volatile__(
+ " movw %w10,%%ds\n"
+ " testl %1,%1\n"
@@ -11536,7 +12429,7 @@ diff -urNp linux-2.6.28.8/arch/x86/lib/usercopy_32.c linux-2.6.28.8/arch/x86/lib
-#define __do_clear_user(addr,size) \
-do { \
- int __d0; \
-- might_sleep(); \
+- might_fault(); \
- __asm__ __volatile__( \
- "0: rep; stosl\n" \
- " movl %2,%0\n" \
@@ -11555,7 +12448,7 @@ diff -urNp linux-2.6.28.8/arch/x86/lib/usercopy_32.c linux-2.6.28.8/arch/x86/lib
+{
+ int __d0;
+
-+ might_sleep();
++ might_fault();
+ __asm__ __volatile__(
+ " movw %w6,%%es\n"
+ "0: rep; stosl\n"
@@ -11580,7 +12473,7 @@ diff -urNp linux-2.6.28.8/arch/x86/lib/usercopy_32.c linux-2.6.28.8/arch/x86/lib
* clear_user: - Zero a block of memory in user space.
@@ -157,7 +168,7 @@ clear_user(void __user *to, unsigned lon
{
- might_sleep();
+ might_fault();
if (access_ok(VERIFY_WRITE, to, n))
- __do_clear_user(to, n);
+ n = __do_clear_user(to, n);
@@ -11598,7 +12491,7 @@ diff -urNp linux-2.6.28.8/arch/x86/lib/usercopy_32.c linux-2.6.28.8/arch/x86/lib
EXPORT_SYMBOL(__clear_user);
@@ -200,14 +210,17 @@ long strnlen_user(const char __user *s,
- might_sleep();
+ might_fault();
__asm__ __volatile__(
+ " movw %w8,%%es\n"
@@ -11625,97 +12518,16 @@ diff -urNp linux-2.6.28.8/arch/x86/lib/usercopy_32.c linux-2.6.28.8/arch/x86/lib
:"cc");
return res & mask;
}
-@@ -227,10 +240,11 @@ EXPORT_SYMBOL(strnlen_user);
+@@ -227,10 +240,121 @@ EXPORT_SYMBOL(strnlen_user);
#ifdef CONFIG_X86_INTEL_USERCOPY
static unsigned long
-__copy_user_intel(void __user *to, const void *from, unsigned long size)
+__generic_copy_to_user_intel(void __user *to, const void *from, unsigned long size)
- {
- int d0, d1;
- __asm__ __volatile__(
-+ " movw %w6, %%es\n"
- " .align 2,0x90\n"
- "1: movl 32(%4), %%eax\n"
- " cmpl $67, %0\n"
-@@ -239,36 +253,36 @@ __copy_user_intel(void __user *to, const
- " .align 2,0x90\n"
- "3: movl 0(%4), %%eax\n"
- "4: movl 4(%4), %%edx\n"
-- "5: movl %%eax, 0(%3)\n"
-- "6: movl %%edx, 4(%3)\n"
-+ "5: movl %%eax, %%es:0(%3)\n"
-+ "6: movl %%edx, %%es:4(%3)\n"
- "7: movl 8(%4), %%eax\n"
- "8: movl 12(%4),%%edx\n"
-- "9: movl %%eax, 8(%3)\n"
-- "10: movl %%edx, 12(%3)\n"
-+ "9: movl %%eax, %%es:8(%3)\n"
-+ "10: movl %%edx, %%es:12(%3)\n"
- "11: movl 16(%4), %%eax\n"
- "12: movl 20(%4), %%edx\n"
-- "13: movl %%eax, 16(%3)\n"
-- "14: movl %%edx, 20(%3)\n"
-+ "13: movl %%eax, %%es:16(%3)\n"
-+ "14: movl %%edx, %%es:20(%3)\n"
- "15: movl 24(%4), %%eax\n"
- "16: movl 28(%4), %%edx\n"
-- "17: movl %%eax, 24(%3)\n"
-- "18: movl %%edx, 28(%3)\n"
-+ "17: movl %%eax, %%es:24(%3)\n"
-+ "18: movl %%edx, %%es:28(%3)\n"
- "19: movl 32(%4), %%eax\n"
- "20: movl 36(%4), %%edx\n"
-- "21: movl %%eax, 32(%3)\n"
-- "22: movl %%edx, 36(%3)\n"
-+ "21: movl %%eax, %%es:32(%3)\n"
-+ "22: movl %%edx, %%es:36(%3)\n"
- "23: movl 40(%4), %%eax\n"
- "24: movl 44(%4), %%edx\n"
-- "25: movl %%eax, 40(%3)\n"
-- "26: movl %%edx, 44(%3)\n"
-+ "25: movl %%eax, %%es:40(%3)\n"
-+ "26: movl %%edx, %%es:44(%3)\n"
- "27: movl 48(%4), %%eax\n"
- "28: movl 52(%4), %%edx\n"
-- "29: movl %%eax, 48(%3)\n"
-- "30: movl %%edx, 52(%3)\n"
-+ "29: movl %%eax, %%es:48(%3)\n"
-+ "30: movl %%edx, %%es:52(%3)\n"
- "31: movl 56(%4), %%eax\n"
- "32: movl 60(%4), %%edx\n"
-- "33: movl %%eax, 56(%3)\n"
-- "34: movl %%edx, 60(%3)\n"
-+ "33: movl %%eax, %%es:56(%3)\n"
-+ "34: movl %%edx, %%es:60(%3)\n"
- " addl $-64, %0\n"
- " addl $64, %4\n"
- " addl $64, %3\n"
-@@ -282,6 +296,8 @@ __copy_user_intel(void __user *to, const
- "36: movl %%eax, %0\n"
- "37: rep; movsb\n"
- "100:\n"
-+ " pushl %%ss\n"
-+ " popl %%es\n"
- ".section .fixup,\"ax\"\n"
- "101: lea 0(%%eax,%0,4),%0\n"
- " jmp 100b\n"
-@@ -328,7 +344,117 @@ __copy_user_intel(void __user *to, const
- " .long 99b,101b\n"
- ".previous"
- : "=&c"(size), "=&D" (d0), "=&S" (d1)
-- : "1"(to), "2"(from), "0"(size)
-+ : "1"(to), "2"(from), "0"(size), "r"(__USER_DS)
-+ : "eax", "edx", "memory");
-+ return size;
-+}
-+
-+static unsigned long
-+__generic_copy_from_user_intel(void *to, const void __user *from, unsigned long size)
+{
+ int d0, d1;
+ __asm__ __volatile__(
-+ " movw %w6, %%ds\n"
++ " movw %w6, %%es\n"
+ " .align 2,0x90\n"
+ "1: movl 32(%4), %%eax\n"
+ " cmpl $67, %0\n"
@@ -11768,7 +12580,7 @@ diff -urNp linux-2.6.28.8/arch/x86/lib/usercopy_32.c linux-2.6.28.8/arch/x86/lib
+ "37: rep; movsb\n"
+ "100:\n"
+ " pushl %%ss\n"
-+ " popl %%ds\n"
++ " popl %%es\n"
+ ".section .fixup,\"ax\"\n"
+ "101: lea 0(%%eax,%0,4),%0\n"
+ " jmp 100b\n"
@@ -11816,6 +12628,87 @@ diff -urNp linux-2.6.28.8/arch/x86/lib/usercopy_32.c linux-2.6.28.8/arch/x86/lib
+ ".previous"
+ : "=&c"(size), "=&D" (d0), "=&S" (d1)
+ : "1"(to), "2"(from), "0"(size), "r"(__USER_DS)
++ : "eax", "edx", "memory");
++ return size;
++}
++
++static unsigned long
++__generic_copy_from_user_intel(void *to, const void __user *from, unsigned long size)
+ {
+ int d0, d1;
+ __asm__ __volatile__(
++ " movw %w6, %%ds\n"
+ " .align 2,0x90\n"
+ "1: movl 32(%4), %%eax\n"
+ " cmpl $67, %0\n"
+@@ -239,36 +363,36 @@ __copy_user_intel(void __user *to, const
+ " .align 2,0x90\n"
+ "3: movl 0(%4), %%eax\n"
+ "4: movl 4(%4), %%edx\n"
+- "5: movl %%eax, 0(%3)\n"
+- "6: movl %%edx, 4(%3)\n"
++ "5: movl %%eax, %%es:0(%3)\n"
++ "6: movl %%edx, %%es:4(%3)\n"
+ "7: movl 8(%4), %%eax\n"
+ "8: movl 12(%4),%%edx\n"
+- "9: movl %%eax, 8(%3)\n"
+- "10: movl %%edx, 12(%3)\n"
++ "9: movl %%eax, %%es:8(%3)\n"
++ "10: movl %%edx, %%es:12(%3)\n"
+ "11: movl 16(%4), %%eax\n"
+ "12: movl 20(%4), %%edx\n"
+- "13: movl %%eax, 16(%3)\n"
+- "14: movl %%edx, 20(%3)\n"
++ "13: movl %%eax, %%es:16(%3)\n"
++ "14: movl %%edx, %%es:20(%3)\n"
+ "15: movl 24(%4), %%eax\n"
+ "16: movl 28(%4), %%edx\n"
+- "17: movl %%eax, 24(%3)\n"
+- "18: movl %%edx, 28(%3)\n"
++ "17: movl %%eax, %%es:24(%3)\n"
++ "18: movl %%edx, %%es:28(%3)\n"
+ "19: movl 32(%4), %%eax\n"
+ "20: movl 36(%4), %%edx\n"
+- "21: movl %%eax, 32(%3)\n"
+- "22: movl %%edx, 36(%3)\n"
++ "21: movl %%eax, %%es:32(%3)\n"
++ "22: movl %%edx, %%es:36(%3)\n"
+ "23: movl 40(%4), %%eax\n"
+ "24: movl 44(%4), %%edx\n"
+- "25: movl %%eax, 40(%3)\n"
+- "26: movl %%edx, 44(%3)\n"
++ "25: movl %%eax, %%es:40(%3)\n"
++ "26: movl %%edx, %%es:44(%3)\n"
+ "27: movl 48(%4), %%eax\n"
+ "28: movl 52(%4), %%edx\n"
+- "29: movl %%eax, 48(%3)\n"
+- "30: movl %%edx, 52(%3)\n"
++ "29: movl %%eax, %%es:48(%3)\n"
++ "30: movl %%edx, %%es:52(%3)\n"
+ "31: movl 56(%4), %%eax\n"
+ "32: movl 60(%4), %%edx\n"
+- "33: movl %%eax, 56(%3)\n"
+- "34: movl %%edx, 60(%3)\n"
++ "33: movl %%eax, %%es:56(%3)\n"
++ "34: movl %%edx, %%es:60(%3)\n"
+ " addl $-64, %0\n"
+ " addl $64, %4\n"
+ " addl $64, %3\n"
+@@ -282,6 +406,8 @@ __copy_user_intel(void __user *to, const
+ "36: movl %%eax, %0\n"
+ "37: rep; movsb\n"
+ "100:\n"
++ " pushl %%ss\n"
++ " popl %%ds\n"
+ ".section .fixup,\"ax\"\n"
+ "101: lea 0(%%eax,%0,4),%0\n"
+ " jmp 100b\n"
+@@ -328,7 +454,7 @@ __copy_user_intel(void __user *to, const
+ " .long 99b,101b\n"
+ ".previous"
+ : "=&c"(size), "=&D" (d0), "=&S" (d1)
+- : "1"(to), "2"(from), "0"(size)
++ : "1"(to), "2"(from), "0"(size), "r"(__USER_DS)
: "eax", "edx", "memory");
return size;
}
@@ -12327,7 +13220,7 @@ diff -urNp linux-2.6.28.8/arch/x86/lib/usercopy_32.c linux-2.6.28.8/arch/x86/lib
#endif
return n;
}
-@@ -827,9 +1017,9 @@ unsigned long __copy_from_user_ll_nocach
+@@ -827,59 +1017,37 @@ unsigned long __copy_from_user_ll_nocach
if (n > 64 && cpu_has_xmm2)
n = __copy_user_intel_nocache(to, from, n);
else
@@ -12339,20 +13232,29 @@ diff -urNp linux-2.6.28.8/arch/x86/lib/usercopy_32.c linux-2.6.28.8/arch/x86/lib
#endif
return n;
}
-@@ -878,8 +1068,35 @@ copy_from_user(void *to, const void __us
- {
- if (access_ok(VERIFY_READ, from, n))
- n = __copy_from_user(to, from, n);
-- else
-+ else if ((long)n > 0)
- memset(to, 0, n);
- return n;
- }
- EXPORT_SYMBOL(copy_from_user);
-+
+ EXPORT_SYMBOL(__copy_from_user_ll_nocache_nozero);
+
+-/**
+- * copy_to_user: - Copy a block of data into user space.
+- * @to: Destination address, in user space.
+- * @from: Source address, in kernel space.
+- * @n: Number of bytes to copy.
+- *
+- * Context: User context only. This function may sleep.
+- *
+- * Copy data from kernel space to user space.
+- *
+- * Returns number of bytes that could not be copied.
+- * On success, this will be zero.
+- */
+-unsigned long
+-copy_to_user(void __user *to, const void *from, unsigned long n)
+#ifdef CONFIG_PAX_MEMORY_UDEREF
+void __set_fs(mm_segment_t x, int cpu)
-+{
+ {
+- if (access_ok(VERIFY_WRITE, to, n))
+- n = __copy_to_user(to, from, n);
+- return n;
+ unsigned long limit = x.seg;
+ struct desc_struct d;
+
@@ -12361,13 +13263,38 @@ diff -urNp linux-2.6.28.8/arch/x86/lib/usercopy_32.c linux-2.6.28.8/arch/x86/lib
+ limit = (limit - 1UL) >> PAGE_SHIFT;
+ pack_descriptor(&d, 0UL, limit, 0xF3, 0xC);
+ write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_DEFAULT_USER_DS, &d, DESCTYPE_S);
-+}
-+
+ }
+-EXPORT_SYMBOL(copy_to_user);
+
+-/**
+- * copy_from_user: - Copy a block of data from user space.
+- * @to: Destination address, in kernel space.
+- * @from: Source address, in user space.
+- * @n: Number of bytes to copy.
+- *
+- * Context: User context only. This function may sleep.
+- *
+- * Copy data from user space to kernel space.
+- *
+- * Returns number of bytes that could not be copied.
+- * On success, this will be zero.
+- *
+- * If some data could not be copied, this function will pad the copied
+- * data to the requested size using zero bytes.
+- */
+-unsigned long
+-copy_from_user(void *to, const void __user *from, unsigned long n)
+void set_fs(mm_segment_t x)
-+{
+ {
+- if (access_ok(VERIFY_READ, from, n))
+- n = __copy_from_user(to, from, n);
+- else
+- memset(to, 0, n);
+- return n;
+ __set_fs(x, get_cpu());
+ put_cpu_no_resched();
-+}
+ }
+-EXPORT_SYMBOL(copy_from_user);
+#else
+void set_fs(mm_segment_t x)
+{
@@ -12376,9 +13303,9 @@ diff -urNp linux-2.6.28.8/arch/x86/lib/usercopy_32.c linux-2.6.28.8/arch/x86/lib
+#endif
+
+EXPORT_SYMBOL(set_fs);
-diff -urNp linux-2.6.28.8/arch/x86/mach-voyager/voyager_basic.c linux-2.6.28.8/arch/x86/mach-voyager/voyager_basic.c
---- linux-2.6.28.8/arch/x86/mach-voyager/voyager_basic.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/mach-voyager/voyager_basic.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/mach-voyager/voyager_basic.c linux-2.6.29.5/arch/x86/mach-voyager/voyager_basic.c
+--- linux-2.6.29.5/arch/x86/mach-voyager/voyager_basic.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/mach-voyager/voyager_basic.c 2009-06-12 23:57:32.000000000 -0400
@@ -123,7 +123,7 @@ int __init voyager_memory_detect(int reg
__u8 cmos[4];
ClickMap_t *map;
@@ -12397,10 +13324,10 @@ diff -urNp linux-2.6.28.8/arch/x86/mach-voyager/voyager_basic.c linux-2.6.28.8/a
local_flush_tlb();
/* now clear everything out but page 0 */
map = (ClickMap_t *) (map_addr & (~PAGE_MASK));
-diff -urNp linux-2.6.28.8/arch/x86/mach-voyager/voyager_smp.c linux-2.6.28.8/arch/x86/mach-voyager/voyager_smp.c
---- linux-2.6.28.8/arch/x86/mach-voyager/voyager_smp.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/mach-voyager/voyager_smp.c 2009-02-21 09:37:48.000000000 -0500
-@@ -521,6 +521,10 @@ static void __init do_boot_cpu(__u8 cpu)
+diff -urNp linux-2.6.29.5/arch/x86/mach-voyager/voyager_smp.c linux-2.6.29.5/arch/x86/mach-voyager/voyager_smp.c
+--- linux-2.6.29.5/arch/x86/mach-voyager/voyager_smp.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/mach-voyager/voyager_smp.c 2009-06-12 23:57:32.000000000 -0400
+@@ -511,6 +511,10 @@ static void __init do_boot_cpu(__u8 cpu)
__u32 *hijack_vector;
__u32 start_phys_address = setup_trampoline();
@@ -12411,7 +13338,7 @@ diff -urNp linux-2.6.28.8/arch/x86/mach-voyager/voyager_smp.c linux-2.6.28.8/arc
/* There's a clever trick to this: The linux trampoline is
* compiled to begin at absolute location zero, so make the
* address zero but have the data segment selector compensate
-@@ -540,7 +544,17 @@ static void __init do_boot_cpu(__u8 cpu)
+@@ -530,7 +534,17 @@ static void __init do_boot_cpu(__u8 cpu)
init_gdt(cpu);
per_cpu(current_task, cpu) = idle;
@@ -12430,7 +13357,7 @@ diff -urNp linux-2.6.28.8/arch/x86/mach-voyager/voyager_smp.c linux-2.6.28.8/arc
irq_ctx_init(cpu);
/* Note: Don't modify initial ss override */
-@@ -1154,7 +1168,7 @@ void smp_local_timer_interrupt(void)
+@@ -1144,7 +1158,7 @@ void smp_local_timer_interrupt(void)
per_cpu(prof_counter, cpu);
}
@@ -12439,9 +13366,9 @@ diff -urNp linux-2.6.28.8/arch/x86/mach-voyager/voyager_smp.c linux-2.6.28.8/arc
}
if (((1 << cpu) & voyager_extended_vic_processors) == 0)
-diff -urNp linux-2.6.28.8/arch/x86/Makefile linux-2.6.28.8/arch/x86/Makefile
---- linux-2.6.28.8/arch/x86/Makefile 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/Makefile 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/Makefile linux-2.6.29.5/arch/x86/Makefile
+--- linux-2.6.29.5/arch/x86/Makefile 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/Makefile 2009-06-12 23:57:32.000000000 -0400
@@ -232,3 +232,12 @@ endef
CLEAN_FILES += arch/x86/boot/fdimage \
arch/x86/boot/image.iso \
@@ -12455,9 +13382,9 @@ diff -urNp linux-2.6.28.8/arch/x86/Makefile linux-2.6.28.8/arch/x86/Makefile
+
+archprepare:
+ $(if $(LDFLAGS_BUILD_ID),,$(error $(OLD_LD)))
-diff -urNp linux-2.6.28.8/arch/x86/mm/extable.c linux-2.6.28.8/arch/x86/mm/extable.c
---- linux-2.6.28.8/arch/x86/mm/extable.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/mm/extable.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/mm/extable.c linux-2.6.29.5/arch/x86/mm/extable.c
+--- linux-2.6.29.5/arch/x86/mm/extable.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/mm/extable.c 2009-06-12 23:57:32.000000000 -0400
@@ -1,14 +1,62 @@
#include <linux/module.h>
#include <linux/spinlock.h>
@@ -12522,9 +13449,9 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/extable.c linux-2.6.28.8/arch/x86/mm/extab
extern u32 pnp_bios_fault_eip, pnp_bios_fault_esp;
extern u32 pnp_bios_is_utter_crap;
pnp_bios_is_utter_crap = 1;
-diff -urNp linux-2.6.28.8/arch/x86/mm/fault.c linux-2.6.28.8/arch/x86/mm/fault.c
---- linux-2.6.28.8/arch/x86/mm/fault.c 2009-02-07 16:10:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/mm/fault.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/mm/fault.c linux-2.6.29.5/arch/x86/mm/fault.c
+--- linux-2.6.29.5/arch/x86/mm/fault.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/mm/fault.c 2009-06-12 23:57:32.000000000 -0400
@@ -26,6 +26,8 @@
#include <linux/kprobes.h>
#include <linux/uaccess.h>
@@ -12595,9 +13522,9 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/fault.c linux-2.6.28.8/arch/x86/mm/fault.c
if (pte && pte_present(*pte) && !pte_exec(*pte))
printk(KERN_CRIT "kernel tried to execute "
"NX-protected page - exploit attempt? "
-- "(uid: %d)\n", current->uid);
+- "(uid: %d)\n", current_uid());
+ "(uid: %d, task: %s, pid: %d)\n",
-+ current->uid, current->comm, task_pid_nr(current));
++ current_uid(), current->comm, task_pid_nr(current));
+ }
+#endif
+
@@ -12610,14 +13537,14 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/fault.c linux-2.6.28.8/arch/x86/mm/fault.c
+ {
+ if (current->signal->curr_ip)
+ printk(KERN_ERR "PAX: From %u.%u.%u.%u: %s:%d, uid/euid: %u/%u, attempted to modify kernel code\n",
-+ NIPQUAD(current->signal->curr_ip), current->comm, task_pid_nr(current), current->uid, current->euid);
++ NIPQUAD(current->signal->curr_ip), current->comm, task_pid_nr(current), current_uid(), current_euid());
+ else
+ printk(KERN_ERR "PAX: %s:%d, uid/euid: %u/%u, attempted to modify kernel code\n",
-+ current->comm, task_pid_nr(current), current->uid, current->euid);
++ current->comm, task_pid_nr(current), current_uid(), current_euid());
}
#endif
-@@ -585,20 +628,26 @@ void __kprobes do_page_fault(struct pt_r
+@@ -586,7 +629,6 @@ void __kprobes do_page_fault(struct pt_r
struct task_struct *tsk;
struct mm_struct *mm;
struct vm_area_struct *vma;
@@ -12625,7 +13552,8 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/fault.c linux-2.6.28.8/arch/x86/mm/fault.c
int write, si_code;
int fault;
#ifdef CONFIG_X86_64
- unsigned long flags;
+@@ -594,13 +636,20 @@ void __kprobes do_page_fault(struct pt_r
+ int sig;
#endif
+#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_PAGEEXEC)
@@ -12648,7 +13576,7 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/fault.c linux-2.6.28.8/arch/x86/mm/fault.c
si_code = SEGV_MAPERR;
if (unlikely(kmmio_fault(regs, address)))
-@@ -651,7 +700,7 @@ void __kprobes do_page_fault(struct pt_r
+@@ -653,7 +702,7 @@ void __kprobes do_page_fault(struct pt_r
* User-mode registers count as a user access even for any
* potential system fault or CPU buglet.
*/
@@ -12657,16 +13585,16 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/fault.c linux-2.6.28.8/arch/x86/mm/fault.c
local_irq_enable();
error_code |= PF_USER;
} else if (regs->flags & X86_EFLAGS_IF)
-@@ -667,7 +716,7 @@ void __kprobes do_page_fault(struct pt_r
+@@ -669,7 +718,7 @@ void __kprobes do_page_fault(struct pt_r
* atomic region then we must not take the fault.
*/
if (unlikely(in_atomic() || !mm))
- goto bad_area_nosemaphore;
+ goto bad_area_nopax;
- again:
/*
-@@ -689,10 +738,104 @@ again:
+ * When running in the kernel we expect faults to occur only to
+@@ -690,10 +739,104 @@ void __kprobes do_page_fault(struct pt_r
if (!down_read_trylock(&mm->mmap_sem)) {
if ((error_code & PF_USER) == 0 &&
!search_exception_tables(regs->ip))
@@ -12772,7 +13700,7 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/fault.c linux-2.6.28.8/arch/x86/mm/fault.c
vma = find_vma(mm, address);
if (!vma)
goto bad_area;
-@@ -700,16 +843,20 @@ again:
+@@ -701,16 +844,20 @@ void __kprobes do_page_fault(struct pt_r
goto good_area;
if (!(vma->vm_flags & VM_GROWSDOWN))
goto bad_area;
@@ -12803,7 +13731,7 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/fault.c linux-2.6.28.8/arch/x86/mm/fault.c
if (expand_stack(vma, address))
goto bad_area;
/*
-@@ -719,6 +866,8 @@ again:
+@@ -720,6 +867,8 @@ void __kprobes do_page_fault(struct pt_r
good_area:
si_code = SEGV_ACCERR;
write = 0;
@@ -12812,11 +13740,26 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/fault.c linux-2.6.28.8/arch/x86/mm/fault.c
switch (error_code & (PF_PROT|PF_WRITE)) {
default: /* 3: write, present */
/* fall through */
-@@ -773,6 +922,54 @@ bad_area:
+@@ -774,6 +923,69 @@ bad_area:
up_read(&mm->mmap_sem);
bad_area_nosemaphore:
+
++#ifdef CONFIG_X86_64
++ if (mm && (error_code & PF_INSTR)) {
++ if (regs->ip == (unsigned long)vgettimeofday) {
++ regs->ip = (unsigned long)VDSO64_SYMBOL(mm->context.vdso, fallback_gettimeofday);
++ return;
++ } else if (regs->ip == (unsigned long)vtime) {
++ regs->ip = (unsigned long)VDSO64_SYMBOL(mm->context.vdso, fallback_time);
++ return;
++ } else if (regs->ip == (unsigned long)vgetcpu) {
++ regs->ip = (unsigned long)VDSO64_SYMBOL(mm->context.vdso, getcpu);
++ return;
++ }
++ }
++#endif
++
+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
+ if (mm && (error_code & PF_USER)) {
+ unsigned long ip = regs->ip;
@@ -12867,16 +13810,16 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/fault.c linux-2.6.28.8/arch/x86/mm/fault.c
/* User mode accesses just cause a SIGSEGV */
if (error_code & PF_USER) {
/*
-@@ -851,7 +1048,7 @@ no_context:
+@@ -852,7 +1064,7 @@ no_context:
#ifdef CONFIG_X86_32
die("Oops", regs, error_code);
bust_spinlocks(0);
- do_exit(SIGKILL);
+ do_group_exit(SIGKILL);
#else
+ sig = SIGKILL;
if (__die("Oops", regs, error_code))
- regs = NULL;
-@@ -944,3 +1141,174 @@ void vmalloc_sync_all(void)
+@@ -935,3 +1147,174 @@ void vmalloc_sync_all(void)
}
#endif
}
@@ -13051,9 +13994,9 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/fault.c linux-2.6.28.8/arch/x86/mm/fault.c
+ printk("\n");
+}
+#endif
-diff -urNp linux-2.6.28.8/arch/x86/mm/highmem_32.c linux-2.6.28.8/arch/x86/mm/highmem_32.c
---- linux-2.6.28.8/arch/x86/mm/highmem_32.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/mm/highmem_32.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/mm/highmem_32.c linux-2.6.29.5/arch/x86/mm/highmem_32.c
+--- linux-2.6.29.5/arch/x86/mm/highmem_32.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/mm/highmem_32.c 2009-06-12 23:57:32.000000000 -0400
@@ -74,6 +74,10 @@ void *kmap_atomic_prot(struct page *page
enum fixed_addresses idx;
unsigned long vaddr;
@@ -13141,10 +14084,10 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/highmem_32.c linux-2.6.28.8/arch/x86/mm/hi
arch_flush_lazy_mmu_mode();
return (void*) vaddr;
-diff -urNp linux-2.6.28.8/arch/x86/mm/hugetlbpage.c linux-2.6.28.8/arch/x86/mm/hugetlbpage.c
---- linux-2.6.28.8/arch/x86/mm/hugetlbpage.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/mm/hugetlbpage.c 2009-02-21 09:37:48.000000000 -0500
-@@ -263,13 +263,18 @@ static unsigned long hugetlb_get_unmappe
+diff -urNp linux-2.6.29.5/arch/x86/mm/hugetlbpage.c linux-2.6.29.5/arch/x86/mm/hugetlbpage.c
+--- linux-2.6.29.5/arch/x86/mm/hugetlbpage.c 2009-06-12 23:55:00.000000000 -0400
++++ linux-2.6.29.5/arch/x86/mm/hugetlbpage.c 2009-06-12 23:57:32.000000000 -0400
+@@ -267,13 +267,18 @@ static unsigned long hugetlb_get_unmappe
struct hstate *h = hstate_file(file);
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma;
@@ -13167,7 +14110,7 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/hugetlbpage.c linux-2.6.28.8/arch/x86/mm/h
}
full_search:
-@@ -277,13 +282,13 @@ full_search:
+@@ -281,13 +286,13 @@ full_search:
for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
/* At this point: (!vma || addr < vma->vm_end). */
@@ -13184,7 +14127,7 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/hugetlbpage.c linux-2.6.28.8/arch/x86/mm/h
mm->cached_hole_size = 0;
goto full_search;
}
-@@ -306,9 +311,8 @@ static unsigned long hugetlb_get_unmappe
+@@ -310,9 +315,8 @@ static unsigned long hugetlb_get_unmappe
struct hstate *h = hstate_file(file);
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma, *prev_vma;
@@ -13195,7 +14138,7 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/hugetlbpage.c linux-2.6.28.8/arch/x86/mm/h
/* don't allow allocations above current base */
if (mm->free_area_cache > base)
-@@ -318,7 +322,7 @@ static unsigned long hugetlb_get_unmappe
+@@ -322,7 +326,7 @@ static unsigned long hugetlb_get_unmappe
largest_hole = 0;
mm->free_area_cache = base;
}
@@ -13204,7 +14147,7 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/hugetlbpage.c linux-2.6.28.8/arch/x86/mm/h
/* make sure it can fit in the remaining address space */
if (mm->free_area_cache < len)
goto fail;
-@@ -360,22 +364,26 @@ try_again:
+@@ -364,22 +368,26 @@ try_again:
fail:
/*
@@ -13242,7 +14185,7 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/hugetlbpage.c linux-2.6.28.8/arch/x86/mm/h
mm->cached_hole_size = ~0UL;
addr = hugetlb_get_unmapped_area_bottomup(file, addr0,
len, pgoff, flags);
-@@ -383,6 +391,7 @@ fail:
+@@ -387,6 +395,7 @@ fail:
/*
* Restore the topdown base:
*/
@@ -13250,7 +14193,7 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/hugetlbpage.c linux-2.6.28.8/arch/x86/mm/h
mm->free_area_cache = base;
mm->cached_hole_size = ~0UL;
-@@ -396,10 +405,17 @@ hugetlb_get_unmapped_area(struct file *f
+@@ -400,10 +409,17 @@ hugetlb_get_unmapped_area(struct file *f
struct hstate *h = hstate_file(file);
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma;
@@ -13269,7 +14212,7 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/hugetlbpage.c linux-2.6.28.8/arch/x86/mm/h
return -ENOMEM;
if (flags & MAP_FIXED) {
-@@ -411,7 +427,7 @@ hugetlb_get_unmapped_area(struct file *f
+@@ -415,7 +431,7 @@ hugetlb_get_unmapped_area(struct file *f
if (addr) {
addr = ALIGN(addr, huge_page_size(h));
vma = find_vma(mm, addr);
@@ -13278,10 +14221,10 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/hugetlbpage.c linux-2.6.28.8/arch/x86/mm/h
(!vma || addr + len <= vma->vm_start))
return addr;
}
-diff -urNp linux-2.6.28.8/arch/x86/mm/init_32.c linux-2.6.28.8/arch/x86/mm/init_32.c
---- linux-2.6.28.8/arch/x86/mm/init_32.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/mm/init_32.c 2009-02-21 09:37:48.000000000 -0500
-@@ -49,6 +49,7 @@
+diff -urNp linux-2.6.29.5/arch/x86/mm/init_32.c linux-2.6.29.5/arch/x86/mm/init_32.c
+--- linux-2.6.29.5/arch/x86/mm/init_32.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/mm/init_32.c 2009-06-12 23:57:32.000000000 -0400
+@@ -50,6 +50,7 @@
#include <asm/setup.h>
#include <asm/cacheflush.h>
#include <asm/smp.h>
@@ -13289,7 +14232,7 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/init_32.c linux-2.6.28.8/arch/x86/mm/init_
unsigned int __VMALLOC_RESERVE = 128 << 20;
-@@ -82,35 +83,6 @@ static __init void *alloc_low_page(unsig
+@@ -82,36 +83,6 @@ static __init void *alloc_low_page(void)
}
/*
@@ -13303,16 +14246,17 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/init_32.c linux-2.6.28.8/arch/x86/mm/init_
- pmd_t *pmd_table;
-
-#ifdef CONFIG_X86_PAE
-- unsigned long phys;
- if (!(pgd_val(*pgd) & _PAGE_PRESENT)) {
- if (after_init_bootmem)
- pmd_table = (pmd_t *)alloc_bootmem_low_pages(PAGE_SIZE);
- else
-- pmd_table = (pmd_t *)alloc_low_page(&phys);
+- pmd_table = (pmd_t *)alloc_low_page();
- paravirt_alloc_pmd(&init_mm, __pa(pmd_table) >> PAGE_SHIFT);
- set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT));
- pud = pud_offset(pgd, 0);
- BUG_ON(pmd_table != pmd_offset(pud, 0));
+-
+- return pmd_table;
- }
-#endif
- pud = pud_offset(pgd, 0);
@@ -13325,8 +14269,8 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/init_32.c linux-2.6.28.8/arch/x86/mm/init_
* Create a page table and place a pointer to it in a middle page
* directory entry:
*/
-@@ -132,7 +104,11 @@ static pte_t * __init one_page_table_ini
- }
+@@ -131,7 +102,11 @@ static pte_t * __init one_page_table_ini
+ page_table = (pte_t *)alloc_low_page();
paravirt_alloc_pte(&init_mm, __pa(page_table) >> PAGE_SHIFT);
+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
@@ -13337,15 +14281,15 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/init_32.c linux-2.6.28.8/arch/x86/mm/init_
BUG_ON(page_table != pte_offset_kernel(pmd, 0));
}
-@@ -154,6 +130,7 @@ page_table_range_init(unsigned long star
+@@ -194,6 +169,7 @@ page_table_range_init(unsigned long star
int pgd_idx, pmd_idx;
unsigned long vaddr;
pgd_t *pgd;
+ pud_t *pud;
pmd_t *pmd;
+ pte_t *pte = NULL;
- vaddr = start;
-@@ -162,8 +139,13 @@ page_table_range_init(unsigned long star
+@@ -203,8 +179,13 @@ page_table_range_init(unsigned long star
pgd = pgd_base + pgd_idx;
for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_idx++) {
@@ -13360,8 +14304,8 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/init_32.c linux-2.6.28.8/arch/x86/mm/init_
+
for (; (pmd_idx < PTRS_PER_PMD) && (vaddr != end);
pmd++, pmd_idx++) {
- one_page_table_init(pmd);
-@@ -174,11 +156,23 @@ page_table_range_init(unsigned long star
+ pte = page_table_kmap_check(one_page_table_init(pmd),
+@@ -216,11 +197,23 @@ page_table_range_init(unsigned long star
}
}
@@ -13389,7 +14333,7 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/init_32.c linux-2.6.28.8/arch/x86/mm/init_
}
/*
-@@ -191,9 +185,10 @@ static void __init kernel_physical_mappi
+@@ -233,9 +226,10 @@ static void __init kernel_physical_mappi
unsigned long end_pfn,
int use_pse)
{
@@ -13401,7 +14345,7 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/init_32.c linux-2.6.28.8/arch/x86/mm/init_
pmd_t *pmd;
pte_t *pte;
unsigned pages_2m, pages_4k;
-@@ -223,8 +218,13 @@ repeat:
+@@ -265,8 +259,13 @@ repeat:
pfn = start_pfn;
pgd_idx = pgd_index((pfn<<PAGE_SHIFT) + PAGE_OFFSET);
pgd = pgd_base + pgd_idx;
@@ -13417,7 +14361,7 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/init_32.c linux-2.6.28.8/arch/x86/mm/init_
if (pfn >= end_pfn)
continue;
-@@ -236,14 +236,13 @@ repeat:
+@@ -278,14 +277,13 @@ repeat:
#endif
for (; pmd_idx < PTRS_PER_PMD && pfn < end_pfn;
pmd++, pmd_idx++) {
@@ -13433,7 +14377,7 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/init_32.c linux-2.6.28.8/arch/x86/mm/init_
pgprot_t prot = PAGE_KERNEL_LARGE;
/*
* first pass will use the same initial
-@@ -253,11 +252,7 @@ repeat:
+@@ -295,11 +293,7 @@ repeat:
__pgprot(PTE_IDENT_ATTR |
_PAGE_PSE);
@@ -13446,7 +14390,7 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/init_32.c linux-2.6.28.8/arch/x86/mm/init_
prot = PAGE_KERNEL_LARGE_EXEC;
pages_2m++;
-@@ -274,7 +269,7 @@ repeat:
+@@ -316,7 +310,7 @@ repeat:
pte_ofs = pte_index((pfn<<PAGE_SHIFT) + PAGE_OFFSET);
pte += pte_ofs;
for (; pte_ofs < PTRS_PER_PTE && pfn < end_pfn;
@@ -13455,7 +14399,7 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/init_32.c linux-2.6.28.8/arch/x86/mm/init_
pgprot_t prot = PAGE_KERNEL;
/*
* first pass will use the same initial
-@@ -282,7 +277,7 @@ repeat:
+@@ -324,7 +318,7 @@ repeat:
*/
pgprot_t init_prot = __pgprot(PTE_IDENT_ATTR);
@@ -13464,18 +14408,22 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/init_32.c linux-2.6.28.8/arch/x86/mm/init_
prot = PAGE_KERNEL_EXEC;
pages_4k++;
-@@ -327,7 +322,9 @@ repeat:
+@@ -369,7 +363,13 @@ repeat:
*/
int devmem_is_allowed(unsigned long pagenr)
{
- if (pagenr <= 256)
+ if (!pagenr)
+ return 1;
++#ifdef CONFIG_VM86
++ if (pagenr < (ISA_START_ADDRESS >> PAGE_SHIFT))
++ return 1;
++#endif
+ if ((ISA_START_ADDRESS >> PAGE_SHIFT) <= pagenr && pagenr < (ISA_END_ADDRESS >> PAGE_SHIFT))
return 1;
- if (!page_is_ram(pagenr))
- return 1;
-@@ -460,7 +457,7 @@ void __init native_pagetable_setup_start
+ if (iomem_is_exclusive(pagenr << PAGE_SHIFT))
+ return 0;
+@@ -508,7 +508,7 @@ void __init native_pagetable_setup_start
pud = pud_offset(pgd, va);
pmd = pmd_offset(pud, va);
@@ -13484,7 +14432,7 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/init_32.c linux-2.6.28.8/arch/x86/mm/init_
break;
pte = pte_offset_kernel(pmd, va);
-@@ -512,9 +509,7 @@ static void __init early_ioremap_page_ta
+@@ -559,9 +559,7 @@ static void __init early_ioremap_page_ta
static void __init pagetable_init(void)
{
@@ -13495,7 +14443,7 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/init_32.c linux-2.6.28.8/arch/x86/mm/init_
}
#ifdef CONFIG_ACPI_SLEEP
-@@ -522,12 +517,12 @@ static void __init pagetable_init(void)
+@@ -569,12 +567,12 @@ static void __init pagetable_init(void)
* ACPI suspend needs this for resume, because things like the intel-agp
* driver might have split up a kernel 4MB mapping.
*/
@@ -13510,7 +14458,7 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/init_32.c linux-2.6.28.8/arch/x86/mm/init_
}
#else /* !CONFIG_ACPI_SLEEP */
static inline void save_pg_dir(void)
-@@ -557,13 +552,11 @@ void zap_low_mappings(void)
+@@ -604,13 +602,11 @@ void zap_low_mappings(void)
int nx_enabled;
@@ -13525,7 +14473,7 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/init_32.c linux-2.6.28.8/arch/x86/mm/init_
/*
* noexec = on|off
*
-@@ -572,40 +565,33 @@ static int disable_nx __initdata;
+@@ -619,40 +615,33 @@ static int disable_nx __initdata;
* on Enable
* off Disable
*/
@@ -13559,12 +14507,12 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/init_32.c linux-2.6.28.8/arch/x86/mm/init_
static void __init set_nx(void)
{
- unsigned int v[4], l, h;
--
-- if (cpu_has_pae && (cpuid_eax(0x80000000) > 0x80000001)) {
-- cpuid(0x80000001, &v[0], &v[1], &v[2], &v[3]);
+ if (!nx_enabled && cpu_has_nx) {
+ unsigned l, h;
+- if (cpu_has_pae && (cpuid_eax(0x80000000) > 0x80000001)) {
+- cpuid(0x80000001, &v[0], &v[1], &v[2], &v[3]);
+-
- if ((v[3] & (1 << 20)) && !disable_nx) {
- rdmsr(MSR_EFER, l, h);
- l |= EFER_NX;
@@ -13579,7 +14527,7 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/init_32.c linux-2.6.28.8/arch/x86/mm/init_
}
}
#endif
-@@ -988,7 +974,7 @@ void __init mem_init(void)
+@@ -1035,7 +1024,7 @@ void __init mem_init(void)
set_highmem_pages_init();
codesize = (unsigned long) &_etext - (unsigned long) &_text;
@@ -13588,7 +14536,7 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/init_32.c linux-2.6.28.8/arch/x86/mm/init_
initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin;
kclist_add(&kcore_mem, __va(0), max_low_pfn << PAGE_SHIFT);
-@@ -1034,10 +1020,10 @@ void __init mem_init(void)
+@@ -1081,10 +1070,10 @@ void __init mem_init(void)
((unsigned long)&__init_end -
(unsigned long)&__init_begin) >> 10,
@@ -13601,8 +14549,8 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/init_32.c linux-2.6.28.8/arch/x86/mm/init_
+ ktla_ktva((unsigned long)&_text), ktla_ktva((unsigned long)&_etext),
((unsigned long)&_etext - (unsigned long)&_text) >> 10);
- #ifdef CONFIG_HIGHMEM
-@@ -1166,6 +1152,46 @@ void free_init_pages(char *what, unsigne
+ /*
+@@ -1227,6 +1216,46 @@ void free_init_pages(char *what, unsigne
void free_initmem(void)
{
@@ -13649,9 +14597,9 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/init_32.c linux-2.6.28.8/arch/x86/mm/init_
free_init_pages("unused kernel memory",
(unsigned long)(&__init_begin),
(unsigned long)(&__init_end));
-diff -urNp linux-2.6.28.8/arch/x86/mm/init_64.c linux-2.6.28.8/arch/x86/mm/init_64.c
---- linux-2.6.28.8/arch/x86/mm/init_64.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/mm/init_64.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/mm/init_64.c linux-2.6.29.5/arch/x86/mm/init_64.c
+--- linux-2.6.29.5/arch/x86/mm/init_64.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/mm/init_64.c 2009-06-12 23:57:32.000000000 -0400
@@ -175,6 +175,10 @@ set_pte_vaddr_pud(pud_t *pud_page, unsig
pmd_t *pmd;
pte_t *pte;
@@ -13698,7 +14646,7 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/init_64.c linux-2.6.28.8/arch/x86/mm/init_
}
pmd = pmd_offset(pud, phys);
BUG_ON(!pmd_none(*pmd));
-@@ -886,7 +897,9 @@ EXPORT_SYMBOL_GPL(memory_add_physaddr_to
+@@ -888,7 +899,9 @@ EXPORT_SYMBOL_GPL(memory_add_physaddr_to
*/
int devmem_is_allowed(unsigned long pagenr)
{
@@ -13707,9 +14655,9 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/init_64.c linux-2.6.28.8/arch/x86/mm/init_
+ return 1;
+ if ((ISA_START_ADDRESS >> PAGE_SHIFT) <= pagenr && pagenr < (ISA_END_ADDRESS >> PAGE_SHIFT))
return 1;
- if (!page_is_ram(pagenr))
- return 1;
-@@ -977,6 +990,39 @@ void free_init_pages(char *what, unsigne
+ if (iomem_is_exclusive(pagenr << PAGE_SHIFT))
+ return 0;
+@@ -979,6 +992,39 @@ void free_init_pages(char *what, unsigne
void free_initmem(void)
{
@@ -13749,7 +14697,18 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/init_64.c linux-2.6.28.8/arch/x86/mm/init_
free_init_pages("unused kernel memory",
(unsigned long)(&__init_begin),
(unsigned long)(&__init_end));
-@@ -1149,7 +1195,7 @@ int in_gate_area_no_task(unsigned long a
+@@ -1116,8 +1162,8 @@ int kern_addr_valid(unsigned long addr)
+ static struct vm_area_struct gate_vma = {
+ .vm_start = VSYSCALL_START,
+ .vm_end = VSYSCALL_START + (VSYSCALL_MAPPED_PAGES * PAGE_SIZE),
+- .vm_page_prot = PAGE_READONLY_EXEC,
+- .vm_flags = VM_READ | VM_EXEC
++ .vm_page_prot = PAGE_READONLY,
++ .vm_flags = VM_READ
+ };
+
+ struct vm_area_struct *get_gate_vma(struct task_struct *tsk)
+@@ -1151,7 +1197,7 @@ int in_gate_area_no_task(unsigned long a
const char *arch_vma_name(struct vm_area_struct *vma)
{
@@ -13758,9 +14717,21 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/init_64.c linux-2.6.28.8/arch/x86/mm/init_
return "[vdso]";
if (vma == &gate_vma)
return "[vsyscall]";
-diff -urNp linux-2.6.28.8/arch/x86/mm/ioremap.c linux-2.6.28.8/arch/x86/mm/ioremap.c
---- linux-2.6.28.8/arch/x86/mm/ioremap.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/mm/ioremap.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/mm/iomap_32.c linux-2.6.29.5/arch/x86/mm/iomap_32.c
+--- linux-2.6.29.5/arch/x86/mm/iomap_32.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/mm/iomap_32.c 2009-06-12 23:57:32.000000000 -0400
+@@ -24,7 +24,7 @@ int is_io_mapping_possible(resource_size
+ {
+ #ifndef CONFIG_X86_PAE
+ /* There is no way to map greater than 1 << 32 address without PAE */
+- if (base + size > 0x100000000ULL)
++ if ((u64)base + size > 0x100000000ULL)
+ return 0;
+ #endif
+ return 1;
+diff -urNp linux-2.6.29.5/arch/x86/mm/ioremap.c linux-2.6.29.5/arch/x86/mm/ioremap.c
+--- linux-2.6.29.5/arch/x86/mm/ioremap.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/mm/ioremap.c 2009-06-12 23:57:32.000000000 -0400
@@ -114,8 +114,8 @@ int page_is_ram(unsigned long pagenr)
* Second special case: Some BIOSen report the PC BIOS
* area (640->1Mb) as ram even though it is not.
@@ -13772,7 +14743,7 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/ioremap.c linux-2.6.28.8/arch/x86/mm/iorem
return 0;
for (i = 0; i < e820.nr_map; i++) {
-@@ -293,6 +293,8 @@ static void __iomem *__ioremap_caller(re
+@@ -275,6 +275,8 @@ static void __iomem *__ioremap_caller(re
break;
}
@@ -13781,16 +14752,18 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/ioremap.c linux-2.6.28.8/arch/x86/mm/iorem
/*
* Ok, go for it..
*/
-@@ -508,7 +510,7 @@ static int __init early_ioremap_debug_se
+@@ -490,7 +492,9 @@ static int __init early_ioremap_debug_se
early_param("early_ioremap_debug", early_ioremap_debug_setup);
static __initdata int after_paging_init;
-static pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)] __page_aligned_bss;
-+static __initdata pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)] __aligned(PAGE_SIZE);
++#ifdef CONFIG_X86_32
++static __read_only pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)] __aligned(PAGE_SIZE);
++#endif
static inline pmd_t * __init early_ioremap_pmd(unsigned long addr)
{
-@@ -523,7 +525,11 @@ static inline pmd_t * __init early_iorem
+@@ -505,7 +509,11 @@ static inline pmd_t * __init early_iorem
static inline pte_t * __init early_ioremap_pte(unsigned long addr)
{
@@ -13802,20 +14775,24 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/ioremap.c linux-2.6.28.8/arch/x86/mm/iorem
}
void __init early_ioremap_init(void)
-@@ -534,8 +540,10 @@ void __init early_ioremap_init(void)
+@@ -516,8 +524,14 @@ void __init early_ioremap_init(void)
printk(KERN_INFO "early_ioremap_init()\n");
pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN));
+#ifdef CONFIG_X86_32
memset(bm_pte, 0, sizeof(bm_pte));
++#ifdef CONFIG_COMPAT_VDSO
++ pmd_populate(&init_mm, pmd, bm_pte);
++#else
pmd_populate_kernel(&init_mm, pmd, bm_pte);
+#endif
++#endif
/*
* The boot-ioremap range spans multiple pmds, for which
-diff -urNp linux-2.6.28.8/arch/x86/mm/mmap.c linux-2.6.28.8/arch/x86/mm/mmap.c
---- linux-2.6.28.8/arch/x86/mm/mmap.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/mm/mmap.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/mm/mmap.c linux-2.6.29.5/arch/x86/mm/mmap.c
+--- linux-2.6.29.5/arch/x86/mm/mmap.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/mm/mmap.c 2009-06-12 23:57:32.000000000 -0400
@@ -36,7 +36,7 @@
* Leave an at least ~128 MB hole.
*/
@@ -13897,9 +14874,9 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/mmap.c linux-2.6.28.8/arch/x86/mm/mmap.c
mm->get_unmapped_area = arch_get_unmapped_area_topdown;
mm->unmap_area = arch_unmap_area_topdown;
}
-diff -urNp linux-2.6.28.8/arch/x86/mm/numa_32.c linux-2.6.28.8/arch/x86/mm/numa_32.c
---- linux-2.6.28.8/arch/x86/mm/numa_32.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/mm/numa_32.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/mm/numa_32.c linux-2.6.29.5/arch/x86/mm/numa_32.c
+--- linux-2.6.29.5/arch/x86/mm/numa_32.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/mm/numa_32.c 2009-06-12 23:57:32.000000000 -0400
@@ -98,7 +98,6 @@ unsigned long node_memmap_size_bytes(int
}
#endif
@@ -13908,9 +14885,9 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/numa_32.c linux-2.6.28.8/arch/x86/mm/numa_
extern unsigned long highend_pfn, highstart_pfn;
#define LARGE_PAGE_BYTES (PTRS_PER_PTE * PAGE_SIZE)
-diff -urNp linux-2.6.28.8/arch/x86/mm/pageattr.c linux-2.6.28.8/arch/x86/mm/pageattr.c
---- linux-2.6.28.8/arch/x86/mm/pageattr.c 2009-02-20 22:26:38.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/mm/pageattr.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/mm/pageattr.c linux-2.6.29.5/arch/x86/mm/pageattr.c
+--- linux-2.6.29.5/arch/x86/mm/pageattr.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/mm/pageattr.c 2009-06-12 23:57:32.000000000 -0400
@@ -20,6 +20,7 @@
#include <asm/pgalloc.h>
#include <asm/proto.h>
@@ -13919,7 +14896,7 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/pageattr.c linux-2.6.28.8/arch/x86/mm/page
/*
* The current flushing context - we pass it instead of 5 arguments:
-@@ -259,7 +260,7 @@ static inline pgprot_t static_protection
+@@ -259,9 +260,10 @@ static inline pgprot_t static_protection
* Does not cover __inittext since that is gone later on. On
* 64bit we do not enforce !NX on the low mapping
*/
@@ -13927,8 +14904,19 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/pageattr.c linux-2.6.28.8/arch/x86/mm/page
+ if (within(address, ktla_ktva((unsigned long)_text), ktla_ktva((unsigned long)_etext)))
pgprot_val(forbidden) |= _PAGE_NX;
++#ifdef CONFIG_DEBUG_RODATA
/*
-@@ -321,8 +322,20 @@ EXPORT_SYMBOL_GPL(lookup_address);
+ * The .rodata section needs to be read-only. Using the pfn
+ * catches all aliases.
+@@ -269,6 +271,7 @@ static inline pgprot_t static_protection
+ if (within(pfn, __pa((unsigned long)__start_rodata) >> PAGE_SHIFT,
+ __pa((unsigned long)__end_rodata) >> PAGE_SHIFT))
+ pgprot_val(forbidden) |= _PAGE_RW;
++#endif
+
+ prot = __pgprot(pgprot_val(prot) & ~pgprot_val(forbidden));
+
+@@ -321,8 +324,20 @@ EXPORT_SYMBOL_GPL(lookup_address);
*/
static void __set_pmd_pte(pte_t *kpte, unsigned long address, pte_t pte)
{
@@ -13949,9 +14937,9 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/pageattr.c linux-2.6.28.8/arch/x86/mm/page
#ifdef CONFIG_X86_32
if (!SHARED_KERNEL_PMD) {
struct page *page;
-diff -urNp linux-2.6.28.8/arch/x86/mm/pageattr-test.c linux-2.6.28.8/arch/x86/mm/pageattr-test.c
---- linux-2.6.28.8/arch/x86/mm/pageattr-test.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/mm/pageattr-test.c 2009-03-07 10:35:39.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/mm/pageattr-test.c linux-2.6.29.5/arch/x86/mm/pageattr-test.c
+--- linux-2.6.29.5/arch/x86/mm/pageattr-test.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/mm/pageattr-test.c 2009-06-12 23:57:32.000000000 -0400
@@ -36,7 +36,7 @@ enum {
static int pte_testbit(pte_t pte)
@@ -13961,21 +14949,66 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/pageattr-test.c linux-2.6.28.8/arch/x86/mm
}
struct split_state {
-diff -urNp linux-2.6.28.8/arch/x86/mm/pat.c linux-2.6.28.8/arch/x86/mm/pat.c
---- linux-2.6.28.8/arch/x86/mm/pat.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/mm/pat.c 2009-03-07 14:05:58.000000000 -0500
-@@ -491,7 +491,7 @@ pgprot_t phys_mem_access_prot(struct fil
- return vma_prot;
+diff -urNp linux-2.6.29.5/arch/x86/mm/pat.c linux-2.6.29.5/arch/x86/mm/pat.c
+--- linux-2.6.29.5/arch/x86/mm/pat.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/mm/pat.c 2009-06-12 23:57:32.000000000 -0400
+@@ -204,7 +204,7 @@ chk_conflict(struct memtype *new, struct
+
+ conflict:
+ printk(KERN_INFO "%s:%d conflicting memory types "
+- "%Lx-%Lx %s<->%s\n", current->comm, current->pid, new->start,
++ "%Lx-%Lx %s<->%s\n", current->comm, task_pid_nr(current), new->start,
+ new->end, cattr_name(new->type), cattr_name(entry->type));
+ return -EBUSY;
}
+@@ -488,7 +488,7 @@ int free_memtype(u64 start, u64 end)
--#ifdef CONFIG_STRICT_DEVMEM
-+#ifndef CONFIG_STRICT_DEVMEM
- /* This check is done in drivers/char/mem.c in case of STRICT_DEVMEM*/
- static inline int range_is_allowed(unsigned long pfn, unsigned long size)
- {
-diff -urNp linux-2.6.28.8/arch/x86/mm/pgtable_32.c linux-2.6.28.8/arch/x86/mm/pgtable_32.c
---- linux-2.6.28.8/arch/x86/mm/pgtable_32.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/mm/pgtable_32.c 2009-02-21 09:37:48.000000000 -0500
+ if (err) {
+ printk(KERN_INFO "%s:%d freeing invalid memtype %Lx-%Lx\n",
+- current->comm, current->pid, start, end);
++ current->comm, task_pid_nr(current), start, end);
+ }
+
+ dprintk("free_memtype request 0x%Lx-0x%Lx\n", start, end);
+@@ -590,7 +590,7 @@ int phys_mem_access_prot_allowed(struct
+ free_memtype(offset, offset + size);
+ printk(KERN_INFO
+ "%s:%d /dev/mem ioremap_change_attr failed %s for %Lx-%Lx\n",
+- current->comm, current->pid,
++ current->comm, task_pid_nr(current),
+ cattr_name(flags),
+ offset, (unsigned long long)(offset + size));
+ return 0;
+@@ -611,7 +611,7 @@ void map_devmem(unsigned long pfn, unsig
+ if (flags != want_flags) {
+ printk(KERN_INFO
+ "%s:%d /dev/mem expected mapping type %s for %Lx-%Lx, got %s\n",
+- current->comm, current->pid,
++ current->comm, task_pid_nr(current),
+ cattr_name(want_flags),
+ addr, (unsigned long long)(addr + size),
+ cattr_name(flags));
+@@ -656,7 +656,7 @@ static int reserve_pfn_range(u64 paddr,
+ free_memtype(paddr, paddr + size);
+ printk(KERN_ERR "%s:%d map pfn expected mapping type %s"
+ " for %Lx-%Lx, got %s\n",
+- current->comm, current->pid,
++ current->comm, task_pid_nr(current),
+ cattr_name(want_flags),
+ (unsigned long long)paddr,
+ (unsigned long long)(paddr + size),
+@@ -685,7 +685,7 @@ static int reserve_pfn_range(u64 paddr,
+ printk(KERN_ERR
+ "%s:%d reserve_pfn_range ioremap_change_attr failed %s "
+ "for %Lx-%Lx\n",
+- current->comm, current->pid,
++ current->comm, task_pid_nr(current),
+ cattr_name(flags),
+ (unsigned long long)paddr,
+ (unsigned long long)(paddr + size));
+diff -urNp linux-2.6.29.5/arch/x86/mm/pgtable_32.c linux-2.6.29.5/arch/x86/mm/pgtable_32.c
+--- linux-2.6.29.5/arch/x86/mm/pgtable_32.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/mm/pgtable_32.c 2009-06-12 23:57:32.000000000 -0400
@@ -31,6 +31,10 @@ void set_pte_vaddr(unsigned long vaddr,
pmd_t *pmd;
pte_t *pte;
@@ -14008,9 +15041,9 @@ diff -urNp linux-2.6.28.8/arch/x86/mm/pgtable_32.c linux-2.6.28.8/arch/x86/mm/pg
/*
* It's enough to flush this one mapping.
* (PGE mappings get flushed as well)
-diff -urNp linux-2.6.28.8/arch/x86/oprofile/backtrace.c linux-2.6.28.8/arch/x86/oprofile/backtrace.c
---- linux-2.6.28.8/arch/x86/oprofile/backtrace.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/oprofile/backtrace.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/oprofile/backtrace.c linux-2.6.29.5/arch/x86/oprofile/backtrace.c
+--- linux-2.6.29.5/arch/x86/oprofile/backtrace.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/oprofile/backtrace.c 2009-06-12 23:57:32.000000000 -0400
@@ -37,7 +37,7 @@ static void backtrace_address(void *data
unsigned int *depth = data;
@@ -14029,9 +15062,9 @@ diff -urNp linux-2.6.28.8/arch/x86/oprofile/backtrace.c linux-2.6.28.8/arch/x86/
if (depth)
dump_trace(NULL, regs, (unsigned long *)stack, 0,
&backtrace_ops, &depth);
-diff -urNp linux-2.6.28.8/arch/x86/oprofile/op_model_p4.c linux-2.6.28.8/arch/x86/oprofile/op_model_p4.c
---- linux-2.6.28.8/arch/x86/oprofile/op_model_p4.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/oprofile/op_model_p4.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/oprofile/op_model_p4.c linux-2.6.29.5/arch/x86/oprofile/op_model_p4.c
+--- linux-2.6.29.5/arch/x86/oprofile/op_model_p4.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/oprofile/op_model_p4.c 2009-06-12 23:57:32.000000000 -0400
@@ -48,7 +48,7 @@ static inline void setup_num_counters(vo
#endif
}
@@ -14041,10 +15074,10 @@ diff -urNp linux-2.6.28.8/arch/x86/oprofile/op_model_p4.c linux-2.6.28.8/arch/x8
{
#ifdef CONFIG_SMP
return smp_num_siblings == 2 ? 2 : 1;
-diff -urNp linux-2.6.28.8/arch/x86/pci/common.c linux-2.6.28.8/arch/x86/pci/common.c
---- linux-2.6.28.8/arch/x86/pci/common.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/pci/common.c 2009-02-21 09:37:48.000000000 -0500
-@@ -362,7 +362,7 @@ static struct dmi_system_id __devinitdat
+diff -urNp linux-2.6.29.5/arch/x86/pci/common.c linux-2.6.29.5/arch/x86/pci/common.c
+--- linux-2.6.29.5/arch/x86/pci/common.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/pci/common.c 2009-06-12 23:57:32.000000000 -0400
+@@ -367,7 +367,7 @@ static struct dmi_system_id __devinitdat
DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL585 G2"),
},
},
@@ -14053,10 +15086,10 @@ diff -urNp linux-2.6.28.8/arch/x86/pci/common.c linux-2.6.28.8/arch/x86/pci/comm
};
void __init dmi_check_pciprobe(void)
-diff -urNp linux-2.6.28.8/arch/x86/pci/fixup.c linux-2.6.28.8/arch/x86/pci/fixup.c
---- linux-2.6.28.8/arch/x86/pci/fixup.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/pci/fixup.c 2009-02-21 09:37:48.000000000 -0500
-@@ -365,7 +365,7 @@ static struct dmi_system_id __devinitdat
+diff -urNp linux-2.6.29.5/arch/x86/pci/fixup.c linux-2.6.29.5/arch/x86/pci/fixup.c
+--- linux-2.6.29.5/arch/x86/pci/fixup.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/pci/fixup.c 2009-06-12 23:57:32.000000000 -0400
+@@ -364,7 +364,7 @@ static struct dmi_system_id __devinitdat
DMI_MATCH(DMI_PRODUCT_NAME, "MS-6702E"),
},
},
@@ -14065,7 +15098,7 @@ diff -urNp linux-2.6.28.8/arch/x86/pci/fixup.c linux-2.6.28.8/arch/x86/pci/fixup
};
/*
-@@ -436,7 +436,7 @@ static struct dmi_system_id __devinitdat
+@@ -435,7 +435,7 @@ static struct dmi_system_id __devinitdat
DMI_MATCH(DMI_PRODUCT_VERSION, "PSA40U"),
},
},
@@ -14074,10 +15107,10 @@ diff -urNp linux-2.6.28.8/arch/x86/pci/fixup.c linux-2.6.28.8/arch/x86/pci/fixup
};
static void __devinit pci_pre_fixup_toshiba_ohci1394(struct pci_dev *dev)
-diff -urNp linux-2.6.28.8/arch/x86/pci/irq.c linux-2.6.28.8/arch/x86/pci/irq.c
---- linux-2.6.28.8/arch/x86/pci/irq.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/pci/irq.c 2009-02-21 09:37:48.000000000 -0500
-@@ -544,7 +544,7 @@ static __init int intel_router_probe(str
+diff -urNp linux-2.6.29.5/arch/x86/pci/irq.c linux-2.6.29.5/arch/x86/pci/irq.c
+--- linux-2.6.29.5/arch/x86/pci/irq.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/pci/irq.c 2009-06-12 23:57:32.000000000 -0400
+@@ -543,7 +543,7 @@ static __init int intel_router_probe(str
static struct pci_device_id __initdata pirq_440gx[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_0) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_2) },
@@ -14086,7 +15119,7 @@ diff -urNp linux-2.6.28.8/arch/x86/pci/irq.c linux-2.6.28.8/arch/x86/pci/irq.c
};
/* 440GX has a proprietary PIRQ router -- don't use it */
-@@ -1148,7 +1148,7 @@ static struct dmi_system_id __initdata p
+@@ -1145,7 +1145,7 @@ static struct dmi_system_id __initdata p
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
},
},
@@ -14095,10 +15128,10 @@ diff -urNp linux-2.6.28.8/arch/x86/pci/irq.c linux-2.6.28.8/arch/x86/pci/irq.c
};
int __init pcibios_irq_init(void)
-diff -urNp linux-2.6.28.8/arch/x86/pci/pcbios.c linux-2.6.28.8/arch/x86/pci/pcbios.c
---- linux-2.6.28.8/arch/x86/pci/pcbios.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/pci/pcbios.c 2009-02-21 09:37:48.000000000 -0500
-@@ -57,50 +57,120 @@ union bios32 {
+diff -urNp linux-2.6.29.5/arch/x86/pci/pcbios.c linux-2.6.29.5/arch/x86/pci/pcbios.c
+--- linux-2.6.29.5/arch/x86/pci/pcbios.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/pci/pcbios.c 2009-06-12 23:57:32.000000000 -0400
+@@ -56,50 +56,120 @@ union bios32 {
static struct {
unsigned long address;
unsigned short segment;
@@ -14233,7 +15266,7 @@ diff -urNp linux-2.6.28.8/arch/x86/pci/pcbios.c linux-2.6.28.8/arch/x86/pci/pcbi
static int __devinit check_pcibios(void)
{
-@@ -109,11 +179,13 @@ static int __devinit check_pcibios(void)
+@@ -108,11 +178,13 @@ static int __devinit check_pcibios(void)
unsigned long flags, pcibios_entry;
if ((pcibios_entry = bios32_service(PCI_SERVICE))) {
@@ -14250,7 +15283,7 @@ diff -urNp linux-2.6.28.8/arch/x86/pci/pcbios.c linux-2.6.28.8/arch/x86/pci/pcbi
"jc 1f\n\t"
"xor %%ah, %%ah\n"
"1:"
-@@ -122,7 +194,8 @@ static int __devinit check_pcibios(void)
+@@ -121,7 +193,8 @@ static int __devinit check_pcibios(void)
"=b" (ebx),
"=c" (ecx)
: "1" (PCIBIOS_PCI_BIOS_PRESENT),
@@ -14260,7 +15293,7 @@ diff -urNp linux-2.6.28.8/arch/x86/pci/pcbios.c linux-2.6.28.8/arch/x86/pci/pcbi
: "memory");
local_irq_restore(flags);
-@@ -166,7 +239,10 @@ static int pci_bios_read(unsigned int se
+@@ -165,7 +238,10 @@ static int pci_bios_read(unsigned int se
switch (len) {
case 1:
@@ -14272,7 +15305,7 @@ diff -urNp linux-2.6.28.8/arch/x86/pci/pcbios.c linux-2.6.28.8/arch/x86/pci/pcbi
"jc 1f\n\t"
"xor %%ah, %%ah\n"
"1:"
-@@ -175,7 +251,8 @@ static int pci_bios_read(unsigned int se
+@@ -174,7 +250,8 @@ static int pci_bios_read(unsigned int se
: "1" (PCIBIOS_READ_CONFIG_BYTE),
"b" (bx),
"D" ((long)reg),
@@ -14282,7 +15315,7 @@ diff -urNp linux-2.6.28.8/arch/x86/pci/pcbios.c linux-2.6.28.8/arch/x86/pci/pcbi
/*
* Zero-extend the result beyond 8 bits, do not trust the
* BIOS having done it:
-@@ -183,7 +260,10 @@ static int pci_bios_read(unsigned int se
+@@ -182,7 +259,10 @@ static int pci_bios_read(unsigned int se
*value &= 0xff;
break;
case 2:
@@ -14294,7 +15327,7 @@ diff -urNp linux-2.6.28.8/arch/x86/pci/pcbios.c linux-2.6.28.8/arch/x86/pci/pcbi
"jc 1f\n\t"
"xor %%ah, %%ah\n"
"1:"
-@@ -192,7 +272,8 @@ static int pci_bios_read(unsigned int se
+@@ -191,7 +271,8 @@ static int pci_bios_read(unsigned int se
: "1" (PCIBIOS_READ_CONFIG_WORD),
"b" (bx),
"D" ((long)reg),
@@ -14304,7 +15337,7 @@ diff -urNp linux-2.6.28.8/arch/x86/pci/pcbios.c linux-2.6.28.8/arch/x86/pci/pcbi
/*
* Zero-extend the result beyond 16 bits, do not trust the
* BIOS having done it:
-@@ -200,7 +281,10 @@ static int pci_bios_read(unsigned int se
+@@ -199,7 +280,10 @@ static int pci_bios_read(unsigned int se
*value &= 0xffff;
break;
case 4:
@@ -14316,7 +15349,7 @@ diff -urNp linux-2.6.28.8/arch/x86/pci/pcbios.c linux-2.6.28.8/arch/x86/pci/pcbi
"jc 1f\n\t"
"xor %%ah, %%ah\n"
"1:"
-@@ -209,7 +293,8 @@ static int pci_bios_read(unsigned int se
+@@ -208,7 +292,8 @@ static int pci_bios_read(unsigned int se
: "1" (PCIBIOS_READ_CONFIG_DWORD),
"b" (bx),
"D" ((long)reg),
@@ -14326,7 +15359,7 @@ diff -urNp linux-2.6.28.8/arch/x86/pci/pcbios.c linux-2.6.28.8/arch/x86/pci/pcbi
break;
}
-@@ -232,7 +317,10 @@ static int pci_bios_write(unsigned int s
+@@ -231,7 +316,10 @@ static int pci_bios_write(unsigned int s
switch (len) {
case 1:
@@ -14338,7 +15371,7 @@ diff -urNp linux-2.6.28.8/arch/x86/pci/pcbios.c linux-2.6.28.8/arch/x86/pci/pcbi
"jc 1f\n\t"
"xor %%ah, %%ah\n"
"1:"
-@@ -241,10 +329,14 @@ static int pci_bios_write(unsigned int s
+@@ -240,10 +328,14 @@ static int pci_bios_write(unsigned int s
"c" (value),
"b" (bx),
"D" ((long)reg),
@@ -14355,7 +15388,7 @@ diff -urNp linux-2.6.28.8/arch/x86/pci/pcbios.c linux-2.6.28.8/arch/x86/pci/pcbi
"jc 1f\n\t"
"xor %%ah, %%ah\n"
"1:"
-@@ -253,10 +345,14 @@ static int pci_bios_write(unsigned int s
+@@ -252,10 +344,14 @@ static int pci_bios_write(unsigned int s
"c" (value),
"b" (bx),
"D" ((long)reg),
@@ -14372,7 +15405,7 @@ diff -urNp linux-2.6.28.8/arch/x86/pci/pcbios.c linux-2.6.28.8/arch/x86/pci/pcbi
"jc 1f\n\t"
"xor %%ah, %%ah\n"
"1:"
-@@ -265,7 +361,8 @@ static int pci_bios_write(unsigned int s
+@@ -264,7 +360,8 @@ static int pci_bios_write(unsigned int s
"c" (value),
"b" (bx),
"D" ((long)reg),
@@ -14382,7 +15415,7 @@ diff -urNp linux-2.6.28.8/arch/x86/pci/pcbios.c linux-2.6.28.8/arch/x86/pci/pcbi
break;
}
-@@ -369,10 +466,13 @@ struct irq_routing_table * pcibios_get_i
+@@ -368,10 +465,13 @@ struct irq_routing_table * pcibios_get_i
DBG("PCI: Fetching IRQ routing table... ");
__asm__("push %%es\n\t"
@@ -14397,7 +15430,7 @@ diff -urNp linux-2.6.28.8/arch/x86/pci/pcbios.c linux-2.6.28.8/arch/x86/pci/pcbi
"jc 1f\n\t"
"xor %%ah, %%ah\n"
"1:"
-@@ -383,7 +483,8 @@ struct irq_routing_table * pcibios_get_i
+@@ -382,7 +482,8 @@ struct irq_routing_table * pcibios_get_i
"1" (0),
"D" ((long) &opt),
"S" (&pci_indirect),
@@ -14407,7 +15440,7 @@ diff -urNp linux-2.6.28.8/arch/x86/pci/pcbios.c linux-2.6.28.8/arch/x86/pci/pcbi
: "memory");
DBG("OK ret=%d, size=%d, map=%x\n", ret, opt.size, map);
if (ret & 0xff00)
-@@ -407,7 +508,10 @@ int pcibios_set_irq_routing(struct pci_d
+@@ -406,7 +507,10 @@ int pcibios_set_irq_routing(struct pci_d
{
int ret;
@@ -14419,7 +15452,7 @@ diff -urNp linux-2.6.28.8/arch/x86/pci/pcbios.c linux-2.6.28.8/arch/x86/pci/pcbi
"jc 1f\n\t"
"xor %%ah, %%ah\n"
"1:"
-@@ -415,7 +519,8 @@ int pcibios_set_irq_routing(struct pci_d
+@@ -414,7 +518,8 @@ int pcibios_set_irq_routing(struct pci_d
: "0" (PCIBIOS_SET_PCI_HW_INT),
"b" ((dev->bus->number << 8) | dev->devfn),
"c" ((irq << 8) | (pin + 10)),
@@ -14429,9 +15462,9 @@ diff -urNp linux-2.6.28.8/arch/x86/pci/pcbios.c linux-2.6.28.8/arch/x86/pci/pcbi
return !(ret & 0xff00);
}
EXPORT_SYMBOL(pcibios_set_irq_routing);
-diff -urNp linux-2.6.28.8/arch/x86/power/cpu_32.c linux-2.6.28.8/arch/x86/power/cpu_32.c
---- linux-2.6.28.8/arch/x86/power/cpu_32.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/power/cpu_32.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/power/cpu_32.c linux-2.6.29.5/arch/x86/power/cpu_32.c
+--- linux-2.6.29.5/arch/x86/power/cpu_32.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/power/cpu_32.c 2009-06-12 23:57:32.000000000 -0400
@@ -67,7 +67,7 @@ static void do_fpu_end(void)
static void fix_processor_context(void)
{
@@ -14441,9 +15474,9 @@ diff -urNp linux-2.6.28.8/arch/x86/power/cpu_32.c linux-2.6.28.8/arch/x86/power/
set_tss_desc(cpu, t); /*
* This just modifies memory; should not be
-diff -urNp linux-2.6.28.8/arch/x86/power/cpu_64.c linux-2.6.28.8/arch/x86/power/cpu_64.c
---- linux-2.6.28.8/arch/x86/power/cpu_64.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/power/cpu_64.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/power/cpu_64.c linux-2.6.29.5/arch/x86/power/cpu_64.c
+--- linux-2.6.29.5/arch/x86/power/cpu_64.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/power/cpu_64.c 2009-06-12 23:57:32.000000000 -0400
@@ -143,7 +143,11 @@ void restore_processor_state(void)
static void fix_processor_context(void)
{
@@ -14474,9 +15507,117 @@ diff -urNp linux-2.6.28.8/arch/x86/power/cpu_64.c linux-2.6.28.8/arch/x86/power/
syscall_init(); /* This sets MSR_*STAR and related */
load_TR_desc(); /* This does ltr */
load_LDT(&current->active_mm->context); /* This does lldt */
-diff -urNp linux-2.6.28.8/arch/x86/vdso/vdso32-setup.c linux-2.6.28.8/arch/x86/vdso/vdso32-setup.c
---- linux-2.6.28.8/arch/x86/vdso/vdso32-setup.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/vdso/vdso32-setup.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/vdso/Makefile linux-2.6.29.5/arch/x86/vdso/Makefile
+--- linux-2.6.29.5/arch/x86/vdso/Makefile 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/vdso/Makefile 2009-06-12 23:57:32.000000000 -0400
+@@ -122,7 +122,7 @@ quiet_cmd_vdso = VDSO $@
+ $(VDSO_LDFLAGS) $(VDSO_LDFLAGS_$(filter %.lds,$(^F))) \
+ -Wl,-T,$(filter %.lds,$^) $(filter %.o,$^)
+
+-VDSO_LDFLAGS = -fPIC -shared $(call ld-option, -Wl$(comma)--hash-style=sysv)
++VDSO_LDFLAGS = -fPIC -shared --no-undefined $(call ld-option, -Wl$(comma)--hash-style=sysv)
+
+ #
+ # Install the unstripped copy of vdso*.so listed in $(vdso-install-y).
+diff -urNp linux-2.6.29.5/arch/x86/vdso/vclock_gettime.c linux-2.6.29.5/arch/x86/vdso/vclock_gettime.c
+--- linux-2.6.29.5/arch/x86/vdso/vclock_gettime.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/vdso/vclock_gettime.c 2009-06-12 23:57:32.000000000 -0400
+@@ -26,20 +26,43 @@
+
+ #define gtod vdso_vsyscall_gtod_data
+
++notrace noinline long __vdso_fallback_time(long *t)
++{
++ long secs;
++ asm volatile("syscall"
++ : "=a" (secs)
++ : "0" (__NR_time),"D" (t) : "r11", "cx", "memory");
++ return secs;
++}
++
+ notrace static long vdso_fallback_gettime(long clock, struct timespec *ts)
+ {
+ long ret;
+ asm("syscall" : "=a" (ret) :
+- "0" (__NR_clock_gettime),"D" (clock), "S" (ts) : "memory");
++ "0" (__NR_clock_gettime),"D" (clock), "S" (ts) : "r11", "cx", "memory");
+ return ret;
+ }
+
++notrace static inline cycle_t __vdso_vread_hpet(void)
++{
++ return readl((const void __iomem *)fix_to_virt(VSYSCALL_HPET) + 0xf0);
++}
++
++notrace static inline cycle_t __vdso_vread_tsc(void)
++{
++ cycle_t ret = (cycle_t)vget_cycles();
++
++ return ret >= gtod->clock.cycle_last ? ret : gtod->clock.cycle_last;
++}
++
+ notrace static inline long vgetns(void)
+ {
+ long v;
+- cycles_t (*vread)(void);
+- vread = gtod->clock.vread;
+- v = (vread() - gtod->clock.cycle_last) & gtod->clock.mask;
++ if (gtod->clock.name[0] == 't' && gtod->clock.name[1] == 's' && gtod->clock.name[2] == 'c' && !gtod->clock.name[3])
++ v = __vdso_vread_tsc();
++ else
++ v = __vdso_vread_hpet();
++ v = (v - gtod->clock.cycle_last) & gtod->clock.mask;
+ return (v * gtod->clock.mult) >> gtod->clock.shift;
+ }
+
+@@ -88,7 +111,9 @@ notrace static noinline int do_monotonic
+
+ notrace int __vdso_clock_gettime(clockid_t clock, struct timespec *ts)
+ {
+- if (likely(gtod->sysctl_enabled && gtod->clock.vread))
++ if (likely(gtod->sysctl_enabled &&
++ ((gtod->clock.name[0] == 'h' && gtod->clock.name[1] == 'p' && gtod->clock.name[2] == 'e' && gtod->clock.name[3] == 't' && !gtod->clock.name[4]) ||
++ (gtod->clock.name[0] == 't' && gtod->clock.name[1] == 's' && gtod->clock.name[2] == 'c' && !gtod->clock.name[3]))))
+ switch (clock) {
+ case CLOCK_REALTIME:
+ return do_realtime(ts);
+@@ -100,10 +125,20 @@ notrace int __vdso_clock_gettime(clockid
+ int clock_gettime(clockid_t, struct timespec *)
+ __attribute__((weak, alias("__vdso_clock_gettime")));
+
+-notrace int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
++notrace noinline int __vdso_fallback_gettimeofday(struct timeval *tv, struct timezone *tz)
+ {
+ long ret;
+- if (likely(gtod->sysctl_enabled && gtod->clock.vread)) {
++ asm("syscall" : "=a" (ret) :
++ "0" (__NR_gettimeofday), "D" (tv), "S" (tz) : "r11", "cx", "memory");
++ return ret;
++}
++
++notrace int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
++{
++ if (likely(gtod->sysctl_enabled &&
++ ((gtod->clock.name[0] == 'h' && gtod->clock.name[1] == 'p' && gtod->clock.name[2] == 'e' && gtod->clock.name[3] == 't' && !gtod->clock.name[4]) ||
++ (gtod->clock.name[0] == 't' && gtod->clock.name[1] == 's' && gtod->clock.name[2] == 'c' && !gtod->clock.name[3]))))
++ {
+ BUILD_BUG_ON(offsetof(struct timeval, tv_usec) !=
+ offsetof(struct timespec, tv_nsec) ||
+ sizeof(*tv) != sizeof(struct timespec));
+@@ -116,9 +151,7 @@ notrace int __vdso_gettimeofday(struct t
+ }
+ return 0;
+ }
+- asm("syscall" : "=a" (ret) :
+- "0" (__NR_gettimeofday), "D" (tv), "S" (tz) : "memory");
+- return ret;
++ return __vdso_fallback_gettimeofday(tv, tz);
+ }
+ int gettimeofday(struct timeval *, struct timezone *)
+ __attribute__((weak, alias("__vdso_gettimeofday")));
+diff -urNp linux-2.6.29.5/arch/x86/vdso/vdso32-setup.c linux-2.6.29.5/arch/x86/vdso/vdso32-setup.c
+--- linux-2.6.29.5/arch/x86/vdso/vdso32-setup.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/vdso/vdso32-setup.c 2009-06-12 23:57:32.000000000 -0400
@@ -226,7 +226,7 @@ static inline void map_compat_vdso(int m
void enable_sep_cpu(void)
{
@@ -14556,10 +15697,58 @@ diff -urNp linux-2.6.28.8/arch/x86/vdso/vdso32-setup.c linux-2.6.28.8/arch/x86/v
return &gate_vma;
return NULL;
}
-diff -urNp linux-2.6.28.8/arch/x86/vdso/vma.c linux-2.6.28.8/arch/x86/vdso/vma.c
---- linux-2.6.28.8/arch/x86/vdso/vma.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/vdso/vma.c 2009-02-21 09:37:48.000000000 -0500
-@@ -123,7 +123,7 @@ int arch_setup_additional_pages(struct l
+diff -urNp linux-2.6.29.5/arch/x86/vdso/vdso.lds.S linux-2.6.29.5/arch/x86/vdso/vdso.lds.S
+--- linux-2.6.29.5/arch/x86/vdso/vdso.lds.S 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/vdso/vdso.lds.S 2009-06-12 23:57:32.000000000 -0400
+@@ -35,3 +35,9 @@ VDSO64_PRELINK = VDSO_PRELINK;
+ #define VEXTERN(x) VDSO64_ ## x = vdso_ ## x;
+ #include "vextern.h"
+ #undef VEXTERN
++
++#define VEXTERN(x) VDSO64_ ## x = __vdso_ ## x;
++VEXTERN(fallback_gettimeofday)
++VEXTERN(fallback_time)
++VEXTERN(getcpu)
++#undef VEXTERN
+diff -urNp linux-2.6.29.5/arch/x86/vdso/vextern.h linux-2.6.29.5/arch/x86/vdso/vextern.h
+--- linux-2.6.29.5/arch/x86/vdso/vextern.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/vdso/vextern.h 2009-06-12 23:57:32.000000000 -0400
+@@ -11,6 +11,5 @@
+ put into vextern.h and be referenced as a pointer with vdso prefix.
+ The main kernel later fills in the values. */
+
+-VEXTERN(jiffies)
+ VEXTERN(vgetcpu_mode)
+ VEXTERN(vsyscall_gtod_data)
+diff -urNp linux-2.6.29.5/arch/x86/vdso/vma.c linux-2.6.29.5/arch/x86/vdso/vma.c
+--- linux-2.6.29.5/arch/x86/vdso/vma.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/vdso/vma.c 2009-06-12 23:57:32.000000000 -0400
+@@ -8,6 +8,7 @@
+ #include <linux/sched.h>
+ #include <linux/init.h>
+ #include <linux/random.h>
++#include <linux/elf.h>
+ #include <asm/vsyscall.h>
+ #include <asm/vgtod.h>
+ #include <asm/proto.h>
+@@ -56,7 +57,7 @@ static int __init init_vdso_vars(void)
+ if (!vbase)
+ goto oom;
+
+- if (memcmp(vbase, "\177ELF", 4)) {
++ if (memcmp(vbase, ELFMAG, SELFMAG)) {
+ printk("VDSO: I'm broken; not ELF\n");
+ vdso_enabled = 0;
+ }
+@@ -65,6 +66,7 @@ static int __init init_vdso_vars(void)
+ *(typeof(__ ## x) **) var_ref(VDSO64_SYMBOL(vbase, x), #x) = &__ ## x;
+ #include "vextern.h"
+ #undef VEXTERN
++ vunmap(vbase);
+ return 0;
+
+ oom:
+@@ -123,7 +125,7 @@ int arch_setup_additional_pages(struct l
if (ret)
goto up_fail;
@@ -14568,10 +15757,10 @@ diff -urNp linux-2.6.28.8/arch/x86/vdso/vma.c linux-2.6.28.8/arch/x86/vdso/vma.c
up_fail:
up_write(&mm->mmap_sem);
return ret;
-diff -urNp linux-2.6.28.8/arch/x86/xen/enlighten.c linux-2.6.28.8/arch/x86/xen/enlighten.c
---- linux-2.6.28.8/arch/x86/xen/enlighten.c 2009-03-07 10:24:49.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/xen/enlighten.c 2009-03-07 10:29:51.000000000 -0500
-@@ -318,7 +318,7 @@ static void xen_set_ldt(const void *addr
+diff -urNp linux-2.6.29.5/arch/x86/xen/enlighten.c linux-2.6.29.5/arch/x86/xen/enlighten.c
+--- linux-2.6.29.5/arch/x86/xen/enlighten.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/xen/enlighten.c 2009-06-12 23:57:32.000000000 -0400
+@@ -319,7 +319,7 @@ static void xen_set_ldt(const void *addr
static void xen_load_gdt(const struct desc_ptr *dtr)
{
unsigned long *frames;
@@ -14580,7 +15769,7 @@ diff -urNp linux-2.6.28.8/arch/x86/xen/enlighten.c linux-2.6.28.8/arch/x86/xen/e
unsigned int size = dtr->size + 1;
unsigned pages = (size + PAGE_SIZE - 1) / PAGE_SIZE;
int f;
-@@ -333,7 +333,7 @@ static void xen_load_gdt(const struct de
+@@ -334,7 +334,7 @@ static void xen_load_gdt(const struct de
mcs = xen_mc_entry(sizeof(*frames) * pages);
frames = mcs.args;
@@ -14589,7 +15778,7 @@ diff -urNp linux-2.6.28.8/arch/x86/xen/enlighten.c linux-2.6.28.8/arch/x86/xen/e
frames[f] = virt_to_mfn(va);
make_lowmem_page_readonly((void *)va);
}
-@@ -441,7 +441,7 @@ static void xen_write_idt_entry(gate_des
+@@ -442,7 +442,7 @@ static void xen_write_idt_entry(gate_des
preempt_disable();
@@ -14598,7 +15787,7 @@ diff -urNp linux-2.6.28.8/arch/x86/xen/enlighten.c linux-2.6.28.8/arch/x86/xen/e
end = start + __get_cpu_var(idt_desc).size + 1;
xen_mc_flush();
-@@ -1526,6 +1526,8 @@ static __init pgd_t *xen_setup_kernel_pa
+@@ -1528,6 +1528,8 @@ static __init pgd_t *xen_setup_kernel_pa
convert_pfn_mfn(init_level4_pgt);
convert_pfn_mfn(level3_ident_pgt);
convert_pfn_mfn(level3_kernel_pgt);
@@ -14607,7 +15796,7 @@ diff -urNp linux-2.6.28.8/arch/x86/xen/enlighten.c linux-2.6.28.8/arch/x86/xen/e
l3 = m2v(pgd[pgd_index(__START_KERNEL_map)].pgd);
l2 = m2v(l3[pud_index(__START_KERNEL_map)].pud);
-@@ -1544,9 +1546,12 @@ static __init pgd_t *xen_setup_kernel_pa
+@@ -1546,9 +1548,12 @@ static __init pgd_t *xen_setup_kernel_pa
set_page_prot(init_level4_pgt, PAGE_KERNEL_RO);
set_page_prot(level3_ident_pgt, PAGE_KERNEL_RO);
set_page_prot(level3_kernel_pgt, PAGE_KERNEL_RO);
@@ -14620,9 +15809,9 @@ diff -urNp linux-2.6.28.8/arch/x86/xen/enlighten.c linux-2.6.28.8/arch/x86/xen/e
/* Pin down new L4 */
pin_pagetable_pfn(MMUEXT_PIN_L4_TABLE,
-diff -urNp linux-2.6.28.8/arch/x86/xen/smp.c linux-2.6.28.8/arch/x86/xen/smp.c
---- linux-2.6.28.8/arch/x86/xen/smp.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/arch/x86/xen/smp.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/arch/x86/xen/smp.c linux-2.6.29.5/arch/x86/xen/smp.c
+--- linux-2.6.29.5/arch/x86/xen/smp.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/x86/xen/smp.c 2009-06-12 23:57:32.000000000 -0400
@@ -171,11 +171,6 @@ static void __init xen_smp_prepare_boot_
{
BUG_ON(smp_processor_id() != 0);
@@ -14635,7 +15824,7 @@ diff -urNp linux-2.6.28.8/arch/x86/xen/smp.c linux-2.6.28.8/arch/x86/xen/smp.c
xen_setup_vcpu_info_placement();
}
-@@ -231,8 +226,8 @@ cpu_initialize_context(unsigned int cpu,
+@@ -234,8 +229,8 @@ cpu_initialize_context(unsigned int cpu,
gdt = get_cpu_gdt_table(cpu);
ctxt->flags = VGCF_IN_KERNEL;
@@ -14646,24 +15835,34 @@ diff -urNp linux-2.6.28.8/arch/x86/xen/smp.c linux-2.6.28.8/arch/x86/xen/smp.c
ctxt->user_regs.ss = __KERNEL_DS;
#ifdef CONFIG_X86_32
ctxt->user_regs.fs = __KERNEL_PERCPU;
-diff -urNp linux-2.6.28.8/crypto/async_tx/async_tx.c linux-2.6.28.8/crypto/async_tx/async_tx.c
---- linux-2.6.28.8/crypto/async_tx/async_tx.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/crypto/async_tx/async_tx.c 2009-02-21 09:37:48.000000000 -0500
-@@ -358,8 +358,8 @@ async_tx_init(void)
- err:
- printk(KERN_ERR "async_tx: initialization failure\n");
+diff -urNp linux-2.6.29.5/arch/xtensa/include/asm/atomic.h linux-2.6.29.5/arch/xtensa/include/asm/atomic.h
+--- linux-2.6.29.5/arch/xtensa/include/asm/atomic.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/xtensa/include/asm/atomic.h 2009-06-12 23:57:32.000000000 -0400
+@@ -165,6 +165,9 @@ static inline int atomic_sub_return(int
+ * Atomically increments @v by 1.
+ */
+ #define atomic_inc(v) atomic_add(1,(v))
++#define atomic_inc_unchecked(v) atomic_inc(v)
++#define atomic_add_unchecked(i, v) atomic_add((i), (v))
++#define atomic_sub_unchecked(i, v) atomic_sub((i), (v))
-- while (--cap >= 0)
-- free_percpu(channel_table[cap]);
-+ while (cap)
-+ free_percpu(channel_table[--cap]);
+ /**
+ * atomic_inc - increment atomic variable
+diff -urNp linux-2.6.29.5/arch/xtensa/include/asm/kmap_types.h linux-2.6.29.5/arch/xtensa/include/asm/kmap_types.h
+--- linux-2.6.29.5/arch/xtensa/include/asm/kmap_types.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/arch/xtensa/include/asm/kmap_types.h 2009-06-12 23:57:32.000000000 -0400
+@@ -25,6 +25,7 @@ enum km_type {
+ KM_IRQ1,
+ KM_SOFTIRQ0,
+ KM_SOFTIRQ1,
++ KM_CLEARPAGE,
+ KM_TYPE_NR
+ };
- return 1;
- }
-diff -urNp linux-2.6.28.8/crypto/lrw.c linux-2.6.28.8/crypto/lrw.c
---- linux-2.6.28.8/crypto/lrw.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/crypto/lrw.c 2009-02-21 09:37:48.000000000 -0500
-@@ -54,7 +54,7 @@ static int setkey(struct crypto_tfm *par
+diff -urNp linux-2.6.29.5/crypto/lrw.c linux-2.6.29.5/crypto/lrw.c
+--- linux-2.6.29.5/crypto/lrw.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/crypto/lrw.c 2009-06-12 23:57:32.000000000 -0400
+@@ -60,7 +60,7 @@ static int setkey(struct crypto_tfm *par
struct priv *ctx = crypto_tfm_ctx(parent);
struct crypto_cipher *child = ctx->child;
int err, i;
@@ -14672,9 +15871,9 @@ diff -urNp linux-2.6.28.8/crypto/lrw.c linux-2.6.28.8/crypto/lrw.c
int bsize = crypto_cipher_blocksize(child);
crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
-diff -urNp linux-2.6.28.8/Documentation/dontdiff linux-2.6.28.8/Documentation/dontdiff
---- linux-2.6.28.8/Documentation/dontdiff 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/Documentation/dontdiff 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/Documentation/dontdiff linux-2.6.29.5/Documentation/dontdiff
+--- linux-2.6.29.5/Documentation/dontdiff 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/Documentation/dontdiff 2009-06-12 23:57:31.000000000 -0400
@@ -3,6 +3,7 @@
*.bin
*.cpio
@@ -14710,7 +15909,23 @@ diff -urNp linux-2.6.28.8/Documentation/dontdiff linux-2.6.28.8/Documentation/do
classlist.h*
comp*.log
compile.h*
-@@ -188,12 +193,15 @@ version.h*
+@@ -104,6 +109,7 @@ gen_crc32table
+ gen_init_cpio
+ genksyms
+ *_gray256.c
++hash
+ ihex2fw
+ ikconfig.h*
+ initramfs_data.cpio
+@@ -165,6 +171,7 @@ setup
+ setup.bin
+ setup.elf
+ sImage
++slabinfo
+ sm_tbl*
+ split-include
+ syscalltab.h
+@@ -188,12 +195,15 @@ version.h*
vmlinux
vmlinux-*
vmlinux.aout
@@ -14726,9 +15941,9 @@ diff -urNp linux-2.6.28.8/Documentation/dontdiff linux-2.6.28.8/Documentation/do
wakeup.bin
wakeup.elf
wakeup.lds
-diff -urNp linux-2.6.28.8/drivers/acpi/blacklist.c linux-2.6.28.8/drivers/acpi/blacklist.c
---- linux-2.6.28.8/drivers/acpi/blacklist.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/acpi/blacklist.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/acpi/blacklist.c linux-2.6.29.5/drivers/acpi/blacklist.c
+--- linux-2.6.29.5/drivers/acpi/blacklist.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/acpi/blacklist.c 2009-06-12 23:57:32.000000000 -0400
@@ -71,7 +71,7 @@ static struct acpi_blacklist_item acpi_b
{"IBM ", "TP600E ", 0x00000105, ACPI_SIG_DSDT, less_than_or_equal,
"Incorrect _ADR", 1},
@@ -14738,9 +15953,9 @@ diff -urNp linux-2.6.28.8/drivers/acpi/blacklist.c linux-2.6.28.8/drivers/acpi/b
};
#if CONFIG_ACPI_BLACKLIST_YEAR
-diff -urNp linux-2.6.28.8/drivers/acpi/osl.c linux-2.6.28.8/drivers/acpi/osl.c
---- linux-2.6.28.8/drivers/acpi/osl.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/acpi/osl.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/acpi/osl.c linux-2.6.29.5/drivers/acpi/osl.c
+--- linux-2.6.29.5/drivers/acpi/osl.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/acpi/osl.c 2009-06-12 23:57:32.000000000 -0400
@@ -483,6 +483,8 @@ acpi_os_read_memory(acpi_physical_addres
void __iomem *virt_addr;
@@ -14759,9 +15974,9 @@ diff -urNp linux-2.6.28.8/drivers/acpi/osl.c linux-2.6.28.8/drivers/acpi/osl.c
switch (width) {
case 8:
-diff -urNp linux-2.6.28.8/drivers/acpi/processor_core.c linux-2.6.28.8/drivers/acpi/processor_core.c
---- linux-2.6.28.8/drivers/acpi/processor_core.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/acpi/processor_core.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/acpi/processor_core.c linux-2.6.29.5/drivers/acpi/processor_core.c
+--- linux-2.6.29.5/drivers/acpi/processor_core.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/acpi/processor_core.c 2009-06-12 23:57:32.000000000 -0400
@@ -678,7 +678,7 @@ static int __cpuinit acpi_processor_star
return 0;
}
@@ -14771,10 +15986,10 @@ diff -urNp linux-2.6.28.8/drivers/acpi/processor_core.c linux-2.6.28.8/drivers/a
/*
* Buggy BIOS check
-diff -urNp linux-2.6.28.8/drivers/acpi/processor_idle.c linux-2.6.28.8/drivers/acpi/processor_idle.c
---- linux-2.6.28.8/drivers/acpi/processor_idle.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/acpi/processor_idle.c 2009-02-21 09:37:48.000000000 -0500
-@@ -181,7 +181,7 @@ static struct dmi_system_id __cpuinitdat
+diff -urNp linux-2.6.29.5/drivers/acpi/processor_idle.c linux-2.6.29.5/drivers/acpi/processor_idle.c
+--- linux-2.6.29.5/drivers/acpi/processor_idle.c 2009-06-12 23:55:00.000000000 -0400
++++ linux-2.6.29.5/drivers/acpi/processor_idle.c 2009-06-12 23:57:32.000000000 -0400
+@@ -156,7 +156,7 @@ static struct dmi_system_id __cpuinitdat
DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
DMI_MATCH(DMI_BIOS_VERSION,"SHE845M0.86C.0013.D.0302131307")},
(void *)2},
@@ -14783,31 +15998,10 @@ diff -urNp linux-2.6.28.8/drivers/acpi/processor_idle.c linux-2.6.28.8/drivers/a
};
static inline u32 ticks_elapsed(u32 t1, u32 t2)
-diff -urNp linux-2.6.28.8/drivers/acpi/tables/tbfadt.c linux-2.6.28.8/drivers/acpi/tables/tbfadt.c
---- linux-2.6.28.8/drivers/acpi/tables/tbfadt.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/acpi/tables/tbfadt.c 2009-02-21 09:37:48.000000000 -0500
-@@ -48,7 +48,7 @@
- ACPI_MODULE_NAME("tbfadt")
-
- /* Local prototypes */
--static void inline
-+static inline void
- acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
- u8 byte_width, u64 address);
-
-@@ -122,7 +122,7 @@ static struct acpi_fadt_info fadt_info_t
- *
- ******************************************************************************/
-
--static void inline
-+static inline void
- acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
- u8 byte_width, u64 address)
- {
-diff -urNp linux-2.6.28.8/drivers/ata/ahci.c linux-2.6.28.8/drivers/ata/ahci.c
---- linux-2.6.28.8/drivers/ata/ahci.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/ata/ahci.c 2009-02-21 09:37:48.000000000 -0500
-@@ -606,7 +606,7 @@ static const struct pci_device_id ahci_p
+diff -urNp linux-2.6.29.5/drivers/ata/ahci.c linux-2.6.29.5/drivers/ata/ahci.c
+--- linux-2.6.29.5/drivers/ata/ahci.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/ata/ahci.c 2009-06-12 23:57:32.000000000 -0400
+@@ -611,7 +611,7 @@ static const struct pci_device_id ahci_p
{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci },
@@ -14816,10 +16010,10 @@ diff -urNp linux-2.6.28.8/drivers/ata/ahci.c linux-2.6.28.8/drivers/ata/ahci.c
};
-diff -urNp linux-2.6.28.8/drivers/ata/ata_piix.c linux-2.6.28.8/drivers/ata/ata_piix.c
---- linux-2.6.28.8/drivers/ata/ata_piix.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/ata/ata_piix.c 2009-02-21 09:37:48.000000000 -0500
-@@ -289,7 +289,7 @@ static const struct pci_device_id piix_p
+diff -urNp linux-2.6.29.5/drivers/ata/ata_piix.c linux-2.6.29.5/drivers/ata/ata_piix.c
+--- linux-2.6.29.5/drivers/ata/ata_piix.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/ata/ata_piix.c 2009-06-12 23:57:32.000000000 -0400
+@@ -291,7 +291,7 @@ static const struct pci_device_id piix_p
{ 0x8086, 0x3b2d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
/* SATA Controller IDE (PCH) */
{ 0x8086, 0x3b2e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
@@ -14828,7 +16022,7 @@ diff -urNp linux-2.6.28.8/drivers/ata/ata_piix.c linux-2.6.28.8/drivers/ata/ata_
};
static struct pci_driver piix_pci_driver = {
-@@ -593,7 +593,7 @@ static const struct ich_laptop ich_lapto
+@@ -595,7 +595,7 @@ static const struct ich_laptop ich_lapto
{ 0x266F, 0x1025, 0x0066 }, /* ICH6 on ACER Aspire 1694WLMi */
{ 0x2653, 0x1043, 0x82D8 }, /* ICH6M on Asus Eee 701 */
/* end marker */
@@ -14837,7 +16031,7 @@ diff -urNp linux-2.6.28.8/drivers/ata/ata_piix.c linux-2.6.28.8/drivers/ata/ata_
};
/**
-@@ -1052,7 +1052,7 @@ static int piix_broken_suspend(void)
+@@ -1054,7 +1054,7 @@ static int piix_broken_suspend(void)
},
},
@@ -14846,10 +16040,10 @@ diff -urNp linux-2.6.28.8/drivers/ata/ata_piix.c linux-2.6.28.8/drivers/ata/ata_
};
static const char *oemstrs[] = {
"Tecra M3,",
-diff -urNp linux-2.6.28.8/drivers/ata/libata-core.c linux-2.6.28.8/drivers/ata/libata-core.c
---- linux-2.6.28.8/drivers/ata/libata-core.c 2009-03-07 10:24:49.000000000 -0500
-+++ linux-2.6.28.8/drivers/ata/libata-core.c 2009-03-07 10:29:51.000000000 -0500
-@@ -807,7 +807,7 @@ static const struct ata_xfer_ent {
+diff -urNp linux-2.6.29.5/drivers/ata/libata-core.c linux-2.6.29.5/drivers/ata/libata-core.c
+--- linux-2.6.29.5/drivers/ata/libata-core.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/ata/libata-core.c 2009-06-12 23:57:32.000000000 -0400
+@@ -889,7 +889,7 @@ static const struct ata_xfer_ent {
{ ATA_SHIFT_PIO, ATA_NR_PIO_MODES, XFER_PIO_0 },
{ ATA_SHIFT_MWDMA, ATA_NR_MWDMA_MODES, XFER_MW_DMA_0 },
{ ATA_SHIFT_UDMA, ATA_NR_UDMA_MODES, XFER_UDMA_0 },
@@ -14858,17 +16052,17 @@ diff -urNp linux-2.6.28.8/drivers/ata/libata-core.c linux-2.6.28.8/drivers/ata/l
};
/**
-@@ -2983,7 +2983,7 @@ static const struct ata_timing ata_timin
- { XFER_UDMA_5, 0, 0, 0, 0, 0, 0, 0, 20 },
- { XFER_UDMA_6, 0, 0, 0, 0, 0, 0, 0, 15 },
+@@ -3105,7 +3105,7 @@ static const struct ata_timing ata_timin
+ { XFER_UDMA_5, 0, 0, 0, 0, 0, 0, 0, 0, 20 },
+ { XFER_UDMA_6, 0, 0, 0, 0, 0, 0, 0, 0, 15 },
- { 0xFF }
+ { 0xFF, 0, 0, 0, 0, 0, 0, 0, 0 }
};
#define ENOUGH(v, unit) (((v)-1)/(unit)+1)
-@@ -4149,7 +4149,7 @@ static const struct ata_blacklist_entry
- { "MTRON MSP-SATA*", NULL, ATA_HORKAGE_BRIDGE_OK, },
+@@ -4267,7 +4267,7 @@ static const struct ata_blacklist_entry
+ { "WD My Book", NULL, ATA_HORKAGE_1_5_GBPS, },
/* End Marker */
- { }
@@ -14876,9 +16070,905 @@ diff -urNp linux-2.6.28.8/drivers/ata/libata-core.c linux-2.6.28.8/drivers/ata/l
};
static int strn_pattern_cmp(const char *patt, const char *name, int wildchar)
-diff -urNp linux-2.6.28.8/drivers/char/agp/frontend.c linux-2.6.28.8/drivers/char/agp/frontend.c
---- linux-2.6.28.8/drivers/char/agp/frontend.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/char/agp/frontend.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/atm/adummy.c linux-2.6.29.5/drivers/atm/adummy.c
+--- linux-2.6.29.5/drivers/atm/adummy.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/atm/adummy.c 2009-06-12 23:57:32.000000000 -0400
+@@ -77,7 +77,7 @@ adummy_send(struct atm_vcc *vcc, struct
+ vcc->pop(vcc, skb);
+ else
+ dev_kfree_skb_any(skb);
+- atomic_inc(&vcc->stats->tx);
++ atomic_inc_unchecked(&vcc->stats->tx);
+
+ return 0;
+ }
+diff -urNp linux-2.6.29.5/drivers/atm/ambassador.c linux-2.6.29.5/drivers/atm/ambassador.c
+--- linux-2.6.29.5/drivers/atm/ambassador.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/atm/ambassador.c 2009-06-12 23:57:32.000000000 -0400
+@@ -453,7 +453,7 @@ static void tx_complete (amb_dev * dev,
+ PRINTD (DBG_FLOW|DBG_TX, "tx_complete %p %p", dev, tx);
+
+ // VC layer stats
+- atomic_inc(&ATM_SKB(skb)->vcc->stats->tx);
++ atomic_inc_unchecked(&ATM_SKB(skb)->vcc->stats->tx);
+
+ // free the descriptor
+ kfree (tx_descr);
+@@ -494,7 +494,7 @@ static void rx_complete (amb_dev * dev,
+ dump_skb ("<<<", vc, skb);
+
+ // VC layer stats
+- atomic_inc(&atm_vcc->stats->rx);
++ atomic_inc_unchecked(&atm_vcc->stats->rx);
+ __net_timestamp(skb);
+ // end of our responsability
+ atm_vcc->push (atm_vcc, skb);
+@@ -509,7 +509,7 @@ static void rx_complete (amb_dev * dev,
+ } else {
+ PRINTK (KERN_INFO, "dropped over-size frame");
+ // should we count this?
+- atomic_inc(&atm_vcc->stats->rx_drop);
++ atomic_inc_unchecked(&atm_vcc->stats->rx_drop);
+ }
+
+ } else {
+@@ -1349,7 +1349,7 @@ static int amb_send (struct atm_vcc * at
+ }
+
+ if (check_area (skb->data, skb->len)) {
+- atomic_inc(&atm_vcc->stats->tx_err);
++ atomic_inc_unchecked(&atm_vcc->stats->tx_err);
+ return -ENOMEM; // ?
+ }
+
+diff -urNp linux-2.6.29.5/drivers/atm/atmtcp.c linux-2.6.29.5/drivers/atm/atmtcp.c
+--- linux-2.6.29.5/drivers/atm/atmtcp.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/atm/atmtcp.c 2009-06-12 23:57:32.000000000 -0400
+@@ -206,7 +206,7 @@ static int atmtcp_v_send(struct atm_vcc
+ if (vcc->pop) vcc->pop(vcc,skb);
+ else dev_kfree_skb(skb);
+ if (dev_data) return 0;
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+ return -ENOLINK;
+ }
+ size = skb->len+sizeof(struct atmtcp_hdr);
+@@ -214,7 +214,7 @@ static int atmtcp_v_send(struct atm_vcc
+ if (!new_skb) {
+ if (vcc->pop) vcc->pop(vcc,skb);
+ else dev_kfree_skb(skb);
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+ return -ENOBUFS;
+ }
+ hdr = (void *) skb_put(new_skb,sizeof(struct atmtcp_hdr));
+@@ -225,8 +225,8 @@ static int atmtcp_v_send(struct atm_vcc
+ if (vcc->pop) vcc->pop(vcc,skb);
+ else dev_kfree_skb(skb);
+ out_vcc->push(out_vcc,new_skb);
+- atomic_inc(&vcc->stats->tx);
+- atomic_inc(&out_vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->tx);
++ atomic_inc_unchecked(&out_vcc->stats->rx);
+ return 0;
+ }
+
+@@ -300,7 +300,7 @@ static int atmtcp_c_send(struct atm_vcc
+ out_vcc = find_vcc(dev, ntohs(hdr->vpi), ntohs(hdr->vci));
+ read_unlock(&vcc_sklist_lock);
+ if (!out_vcc) {
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+ goto done;
+ }
+ skb_pull(skb,sizeof(struct atmtcp_hdr));
+@@ -312,8 +312,8 @@ static int atmtcp_c_send(struct atm_vcc
+ __net_timestamp(new_skb);
+ skb_copy_from_linear_data(skb, skb_put(new_skb, skb->len), skb->len);
+ out_vcc->push(out_vcc,new_skb);
+- atomic_inc(&vcc->stats->tx);
+- atomic_inc(&out_vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->tx);
++ atomic_inc_unchecked(&out_vcc->stats->rx);
+ done:
+ if (vcc->pop) vcc->pop(vcc,skb);
+ else dev_kfree_skb(skb);
+diff -urNp linux-2.6.29.5/drivers/atm/eni.c linux-2.6.29.5/drivers/atm/eni.c
+--- linux-2.6.29.5/drivers/atm/eni.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/atm/eni.c 2009-06-12 23:57:32.000000000 -0400
+@@ -525,7 +525,7 @@ static int rx_aal0(struct atm_vcc *vcc)
+ DPRINTK(DEV_LABEL "(itf %d): trashing empty cell\n",
+ vcc->dev->number);
+ length = 0;
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ }
+ else {
+ length = ATM_CELL_SIZE-1; /* no HEC */
+@@ -580,7 +580,7 @@ static int rx_aal5(struct atm_vcc *vcc)
+ size);
+ }
+ eff = length = 0;
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ }
+ else {
+ size = (descr & MID_RED_COUNT)*(ATM_CELL_PAYLOAD >> 2);
+@@ -597,7 +597,7 @@ static int rx_aal5(struct atm_vcc *vcc)
+ "(VCI=%d,length=%ld,size=%ld (descr 0x%lx))\n",
+ vcc->dev->number,vcc->vci,length,size << 2,descr);
+ length = eff = 0;
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ }
+ }
+ skb = eff ? atm_alloc_charge(vcc,eff << 2,GFP_ATOMIC) : NULL;
+@@ -770,7 +770,7 @@ rx_dequeued++;
+ vcc->push(vcc,skb);
+ pushed++;
+ }
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+ }
+ wake_up(&eni_dev->rx_wait);
+ }
+@@ -1227,7 +1227,7 @@ static void dequeue_tx(struct atm_dev *d
+ PCI_DMA_TODEVICE);
+ if (vcc->pop) vcc->pop(vcc,skb);
+ else dev_kfree_skb_irq(skb);
+- atomic_inc(&vcc->stats->tx);
++ atomic_inc_unchecked(&vcc->stats->tx);
+ wake_up(&eni_dev->tx_wait);
+ dma_complete++;
+ }
+diff -urNp linux-2.6.29.5/drivers/atm/firestream.c linux-2.6.29.5/drivers/atm/firestream.c
+--- linux-2.6.29.5/drivers/atm/firestream.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/atm/firestream.c 2009-06-12 23:57:32.000000000 -0400
+@@ -748,7 +748,7 @@ static void process_txdone_queue (struct
+ }
+ }
+
+- atomic_inc(&ATM_SKB(skb)->vcc->stats->tx);
++ atomic_inc_unchecked(&ATM_SKB(skb)->vcc->stats->tx);
+
+ fs_dprintk (FS_DEBUG_TXMEM, "i");
+ fs_dprintk (FS_DEBUG_ALLOC, "Free t-skb: %p\n", skb);
+@@ -815,7 +815,7 @@ static void process_incoming (struct fs_
+ #endif
+ skb_put (skb, qe->p1 & 0xffff);
+ ATM_SKB(skb)->vcc = atm_vcc;
+- atomic_inc(&atm_vcc->stats->rx);
++ atomic_inc_unchecked(&atm_vcc->stats->rx);
+ __net_timestamp(skb);
+ fs_dprintk (FS_DEBUG_ALLOC, "Free rec-skb: %p (pushed)\n", skb);
+ atm_vcc->push (atm_vcc, skb);
+@@ -836,12 +836,12 @@ static void process_incoming (struct fs_
+ kfree (pe);
+ }
+ if (atm_vcc)
+- atomic_inc(&atm_vcc->stats->rx_drop);
++ atomic_inc_unchecked(&atm_vcc->stats->rx_drop);
+ break;
+ case 0x1f: /* Reassembly abort: no buffers. */
+ /* Silently increment error counter. */
+ if (atm_vcc)
+- atomic_inc(&atm_vcc->stats->rx_drop);
++ atomic_inc_unchecked(&atm_vcc->stats->rx_drop);
+ break;
+ default: /* Hmm. Haven't written the code to handle the others yet... -- REW */
+ printk (KERN_WARNING "Don't know what to do with RX status %x: %s.\n",
+diff -urNp linux-2.6.29.5/drivers/atm/fore200e.c linux-2.6.29.5/drivers/atm/fore200e.c
+--- linux-2.6.29.5/drivers/atm/fore200e.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/atm/fore200e.c 2009-06-12 23:57:32.000000000 -0400
+@@ -931,9 +931,9 @@ fore200e_tx_irq(struct fore200e* fore200
+ #endif
+ /* check error condition */
+ if (*entry->status & STATUS_ERROR)
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+ else
+- atomic_inc(&vcc->stats->tx);
++ atomic_inc_unchecked(&vcc->stats->tx);
+ }
+ }
+
+@@ -1082,7 +1082,7 @@ fore200e_push_rpd(struct fore200e* fore2
+ if (skb == NULL) {
+ DPRINTK(2, "unable to alloc new skb, rx PDU length = %d\n", pdu_len);
+
+- atomic_inc(&vcc->stats->rx_drop);
++ atomic_inc_unchecked(&vcc->stats->rx_drop);
+ return -ENOMEM;
+ }
+
+@@ -1125,14 +1125,14 @@ fore200e_push_rpd(struct fore200e* fore2
+
+ dev_kfree_skb_any(skb);
+
+- atomic_inc(&vcc->stats->rx_drop);
++ atomic_inc_unchecked(&vcc->stats->rx_drop);
+ return -ENOMEM;
+ }
+
+ ASSERT(atomic_read(&sk_atm(vcc)->sk_wmem_alloc) >= 0);
+
+ vcc->push(vcc, skb);
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+
+ ASSERT(atomic_read(&sk_atm(vcc)->sk_wmem_alloc) >= 0);
+
+@@ -1210,7 +1210,7 @@ fore200e_rx_irq(struct fore200e* fore200
+ DPRINTK(2, "damaged PDU on %d.%d.%d\n",
+ fore200e->atm_dev->number,
+ entry->rpd->atm_header.vpi, entry->rpd->atm_header.vci);
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ }
+ }
+
+@@ -1655,7 +1655,7 @@ fore200e_send(struct atm_vcc *vcc, struc
+ goto retry_here;
+ }
+
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+
+ fore200e->tx_sat++;
+ DPRINTK(2, "tx queue of device %s is saturated, PDU dropped - heartbeat is %08x\n",
+diff -urNp linux-2.6.29.5/drivers/atm/he.c linux-2.6.29.5/drivers/atm/he.c
+--- linux-2.6.29.5/drivers/atm/he.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/atm/he.c 2009-06-12 23:57:32.000000000 -0400
+@@ -1728,7 +1728,7 @@ he_service_rbrq(struct he_dev *he_dev, i
+
+ if (RBRQ_HBUF_ERR(he_dev->rbrq_head)) {
+ hprintk("HBUF_ERR! (cid 0x%x)\n", cid);
+- atomic_inc(&vcc->stats->rx_drop);
++ atomic_inc_unchecked(&vcc->stats->rx_drop);
+ goto return_host_buffers;
+ }
+
+@@ -1761,7 +1761,7 @@ he_service_rbrq(struct he_dev *he_dev, i
+ RBRQ_LEN_ERR(he_dev->rbrq_head)
+ ? "LEN_ERR" : "",
+ vcc->vpi, vcc->vci);
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ goto return_host_buffers;
+ }
+
+@@ -1820,7 +1820,7 @@ he_service_rbrq(struct he_dev *he_dev, i
+ vcc->push(vcc, skb);
+ spin_lock(&he_dev->global_lock);
+
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+
+ return_host_buffers:
+ ++pdus_assembled;
+@@ -2673,7 +2673,7 @@ he_send(struct atm_vcc *vcc, struct sk_b
+ __enqueue_tpd(he_dev, tpd, cid);
+ spin_unlock_irqrestore(&he_dev->global_lock, flags);
+
+- atomic_inc(&vcc->stats->tx);
++ atomic_inc_unchecked(&vcc->stats->tx);
+
+ return 0;
+ }
+diff -urNp linux-2.6.29.5/drivers/atm/horizon.c linux-2.6.29.5/drivers/atm/horizon.c
+--- linux-2.6.29.5/drivers/atm/horizon.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/atm/horizon.c 2009-06-12 23:57:32.000000000 -0400
+@@ -1033,7 +1033,7 @@ static void rx_schedule (hrz_dev * dev,
+ {
+ struct atm_vcc * vcc = ATM_SKB(skb)->vcc;
+ // VC layer stats
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+ __net_timestamp(skb);
+ // end of our responsability
+ vcc->push (vcc, skb);
+@@ -1185,7 +1185,7 @@ static void tx_schedule (hrz_dev * const
+ dev->tx_iovec = NULL;
+
+ // VC layer stats
+- atomic_inc(&ATM_SKB(skb)->vcc->stats->tx);
++ atomic_inc_unchecked(&ATM_SKB(skb)->vcc->stats->tx);
+
+ // free the skb
+ hrz_kfree_skb (skb);
+diff -urNp linux-2.6.29.5/drivers/atm/idt77252.c linux-2.6.29.5/drivers/atm/idt77252.c
+--- linux-2.6.29.5/drivers/atm/idt77252.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/atm/idt77252.c 2009-06-12 23:57:32.000000000 -0400
+@@ -810,7 +810,7 @@ drain_scq(struct idt77252_dev *card, str
+ else
+ dev_kfree_skb(skb);
+
+- atomic_inc(&vcc->stats->tx);
++ atomic_inc_unchecked(&vcc->stats->tx);
+ }
+
+ atomic_dec(&scq->used);
+@@ -1073,13 +1073,13 @@ dequeue_rx(struct idt77252_dev *card, st
+ if ((sb = dev_alloc_skb(64)) == NULL) {
+ printk("%s: Can't allocate buffers for aal0.\n",
+ card->name);
+- atomic_add(i, &vcc->stats->rx_drop);
++ atomic_add_unchecked(i, &vcc->stats->rx_drop);
+ break;
+ }
+ if (!atm_charge(vcc, sb->truesize)) {
+ RXPRINTK("%s: atm_charge() dropped aal0 packets.\n",
+ card->name);
+- atomic_add(i - 1, &vcc->stats->rx_drop);
++ atomic_add_unchecked(i - 1, &vcc->stats->rx_drop);
+ dev_kfree_skb(sb);
+ break;
+ }
+@@ -1096,7 +1096,7 @@ dequeue_rx(struct idt77252_dev *card, st
+ ATM_SKB(sb)->vcc = vcc;
+ __net_timestamp(sb);
+ vcc->push(vcc, sb);
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+
+ cell += ATM_CELL_PAYLOAD;
+ }
+@@ -1133,13 +1133,13 @@ dequeue_rx(struct idt77252_dev *card, st
+ "(CDC: %08x)\n",
+ card->name, len, rpp->len, readl(SAR_REG_CDC));
+ recycle_rx_pool_skb(card, rpp);
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ return;
+ }
+ if (stat & SAR_RSQE_CRC) {
+ RXPRINTK("%s: AAL5 CRC error.\n", card->name);
+ recycle_rx_pool_skb(card, rpp);
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ return;
+ }
+ if (skb_queue_len(&rpp->queue) > 1) {
+@@ -1150,7 +1150,7 @@ dequeue_rx(struct idt77252_dev *card, st
+ RXPRINTK("%s: Can't alloc RX skb.\n",
+ card->name);
+ recycle_rx_pool_skb(card, rpp);
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ return;
+ }
+ if (!atm_charge(vcc, skb->truesize)) {
+@@ -1169,7 +1169,7 @@ dequeue_rx(struct idt77252_dev *card, st
+ __net_timestamp(skb);
+
+ vcc->push(vcc, skb);
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+
+ return;
+ }
+@@ -1191,7 +1191,7 @@ dequeue_rx(struct idt77252_dev *card, st
+ __net_timestamp(skb);
+
+ vcc->push(vcc, skb);
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+
+ if (skb->truesize > SAR_FB_SIZE_3)
+ add_rx_skb(card, 3, SAR_FB_SIZE_3, 1);
+@@ -1303,14 +1303,14 @@ idt77252_rx_raw(struct idt77252_dev *car
+ if (vcc->qos.aal != ATM_AAL0) {
+ RPRINTK("%s: raw cell for non AAL0 vc %u.%u\n",
+ card->name, vpi, vci);
+- atomic_inc(&vcc->stats->rx_drop);
++ atomic_inc_unchecked(&vcc->stats->rx_drop);
+ goto drop;
+ }
+
+ if ((sb = dev_alloc_skb(64)) == NULL) {
+ printk("%s: Can't allocate buffers for AAL0.\n",
+ card->name);
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ goto drop;
+ }
+
+@@ -1329,7 +1329,7 @@ idt77252_rx_raw(struct idt77252_dev *car
+ ATM_SKB(sb)->vcc = vcc;
+ __net_timestamp(sb);
+ vcc->push(vcc, sb);
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+
+ drop:
+ skb_pull(queue, 64);
+@@ -1954,13 +1954,13 @@ idt77252_send_skb(struct atm_vcc *vcc, s
+
+ if (vc == NULL) {
+ printk("%s: NULL connection in send().\n", card->name);
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+ dev_kfree_skb(skb);
+ return -EINVAL;
+ }
+ if (!test_bit(VCF_TX, &vc->flags)) {
+ printk("%s: Trying to transmit on a non-tx VC.\n", card->name);
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+ dev_kfree_skb(skb);
+ return -EINVAL;
+ }
+@@ -1972,14 +1972,14 @@ idt77252_send_skb(struct atm_vcc *vcc, s
+ break;
+ default:
+ printk("%s: Unsupported AAL: %d\n", card->name, vcc->qos.aal);
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+ dev_kfree_skb(skb);
+ return -EINVAL;
+ }
+
+ if (skb_shinfo(skb)->nr_frags != 0) {
+ printk("%s: No scatter-gather yet.\n", card->name);
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+ dev_kfree_skb(skb);
+ return -EINVAL;
+ }
+@@ -1987,7 +1987,7 @@ idt77252_send_skb(struct atm_vcc *vcc, s
+
+ err = queue_skb(card, vc, skb, oam);
+ if (err) {
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+ dev_kfree_skb(skb);
+ return err;
+ }
+@@ -2010,7 +2010,7 @@ idt77252_send_oam(struct atm_vcc *vcc, v
+ skb = dev_alloc_skb(64);
+ if (!skb) {
+ printk("%s: Out of memory in send_oam().\n", card->name);
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+ return -ENOMEM;
+ }
+ atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
+diff -urNp linux-2.6.29.5/drivers/atm/iphase.c linux-2.6.29.5/drivers/atm/iphase.c
+--- linux-2.6.29.5/drivers/atm/iphase.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/atm/iphase.c 2009-06-12 23:57:32.000000000 -0400
+@@ -1125,7 +1125,7 @@ static int rx_pkt(struct atm_dev *dev)
+ status = (u_short) (buf_desc_ptr->desc_mode);
+ if (status & (RX_CER | RX_PTE | RX_OFL))
+ {
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ IF_ERR(printk("IA: bad packet, dropping it");)
+ if (status & RX_CER) {
+ IF_ERR(printk(" cause: packet CRC error\n");)
+@@ -1148,7 +1148,7 @@ static int rx_pkt(struct atm_dev *dev)
+ len = dma_addr - buf_addr;
+ if (len > iadev->rx_buf_sz) {
+ printk("Over %d bytes sdu received, dropped!!!\n", iadev->rx_buf_sz);
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ goto out_free_desc;
+ }
+
+@@ -1298,7 +1298,7 @@ static void rx_dle_intr(struct atm_dev *
+ ia_vcc = INPH_IA_VCC(vcc);
+ if (ia_vcc == NULL)
+ {
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ dev_kfree_skb_any(skb);
+ atm_return(vcc, atm_guess_pdu2truesize(len));
+ goto INCR_DLE;
+@@ -1310,7 +1310,7 @@ static void rx_dle_intr(struct atm_dev *
+ if ((length > iadev->rx_buf_sz) || (length >
+ (skb->len - sizeof(struct cpcs_trailer))))
+ {
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ IF_ERR(printk("rx_dle_intr: Bad AAL5 trailer %d (skb len %d)",
+ length, skb->len);)
+ dev_kfree_skb_any(skb);
+@@ -1326,7 +1326,7 @@ static void rx_dle_intr(struct atm_dev *
+
+ IF_RX(printk("rx_dle_intr: skb push");)
+ vcc->push(vcc,skb);
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+ iadev->rx_pkt_cnt++;
+ }
+ INCR_DLE:
+@@ -2921,7 +2921,7 @@ static int ia_pkt_tx (struct atm_vcc *vc
+ if ((desc == 0) || (desc > iadev->num_tx_desc))
+ {
+ IF_ERR(printk(DEV_LABEL "invalid desc for send: %d\n", desc);)
+- atomic_inc(&vcc->stats->tx);
++ atomic_inc_unchecked(&vcc->stats->tx);
+ if (vcc->pop)
+ vcc->pop(vcc, skb);
+ else
+@@ -3026,7 +3026,7 @@ static int ia_pkt_tx (struct atm_vcc *vc
+ ATM_DESC(skb) = vcc->vci;
+ skb_queue_tail(&iadev->tx_dma_q, skb);
+
+- atomic_inc(&vcc->stats->tx);
++ atomic_inc_unchecked(&vcc->stats->tx);
+ iadev->tx_pkt_cnt++;
+ /* Increment transaction counter */
+ writel(2, iadev->dma+IPHASE5575_TX_COUNTER);
+diff -urNp linux-2.6.29.5/drivers/atm/lanai.c linux-2.6.29.5/drivers/atm/lanai.c
+--- linux-2.6.29.5/drivers/atm/lanai.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/atm/lanai.c 2009-06-12 23:57:32.000000000 -0400
+@@ -1305,7 +1305,7 @@ static void lanai_send_one_aal5(struct l
+ vcc_tx_add_aal5_trailer(lvcc, skb->len, 0, 0);
+ lanai_endtx(lanai, lvcc);
+ lanai_free_skb(lvcc->tx.atmvcc, skb);
+- atomic_inc(&lvcc->tx.atmvcc->stats->tx);
++ atomic_inc_unchecked(&lvcc->tx.atmvcc->stats->tx);
+ }
+
+ /* Try to fill the buffer - don't call unless there is backlog */
+@@ -1428,7 +1428,7 @@ static void vcc_rx_aal5(struct lanai_vcc
+ ATM_SKB(skb)->vcc = lvcc->rx.atmvcc;
+ __net_timestamp(skb);
+ lvcc->rx.atmvcc->push(lvcc->rx.atmvcc, skb);
+- atomic_inc(&lvcc->rx.atmvcc->stats->rx);
++ atomic_inc_unchecked(&lvcc->rx.atmvcc->stats->rx);
+ out:
+ lvcc->rx.buf.ptr = end;
+ cardvcc_write(lvcc, endptr, vcc_rxreadptr);
+@@ -1670,7 +1670,7 @@ static int handle_service(struct lanai_d
+ DPRINTK("(itf %d) got RX service entry 0x%X for non-AAL5 "
+ "vcc %d\n", lanai->number, (unsigned int) s, vci);
+ lanai->stats.service_rxnotaal5++;
+- atomic_inc(&lvcc->rx.atmvcc->stats->rx_err);
++ atomic_inc_unchecked(&lvcc->rx.atmvcc->stats->rx_err);
+ return 0;
+ }
+ if (likely(!(s & (SERVICE_TRASH | SERVICE_STREAM | SERVICE_CRCERR)))) {
+@@ -1682,7 +1682,7 @@ static int handle_service(struct lanai_d
+ int bytes;
+ read_unlock(&vcc_sklist_lock);
+ DPRINTK("got trashed rx pdu on vci %d\n", vci);
+- atomic_inc(&lvcc->rx.atmvcc->stats->rx_err);
++ atomic_inc_unchecked(&lvcc->rx.atmvcc->stats->rx_err);
+ lvcc->stats.x.aal5.service_trash++;
+ bytes = (SERVICE_GET_END(s) * 16) -
+ (((unsigned long) lvcc->rx.buf.ptr) -
+@@ -1694,7 +1694,7 @@ static int handle_service(struct lanai_d
+ }
+ if (s & SERVICE_STREAM) {
+ read_unlock(&vcc_sklist_lock);
+- atomic_inc(&lvcc->rx.atmvcc->stats->rx_err);
++ atomic_inc_unchecked(&lvcc->rx.atmvcc->stats->rx_err);
+ lvcc->stats.x.aal5.service_stream++;
+ printk(KERN_ERR DEV_LABEL "(itf %d): Got AAL5 stream "
+ "PDU on VCI %d!\n", lanai->number, vci);
+@@ -1702,7 +1702,7 @@ static int handle_service(struct lanai_d
+ return 0;
+ }
+ DPRINTK("got rx crc error on vci %d\n", vci);
+- atomic_inc(&lvcc->rx.atmvcc->stats->rx_err);
++ atomic_inc_unchecked(&lvcc->rx.atmvcc->stats->rx_err);
+ lvcc->stats.x.aal5.service_rxcrc++;
+ lvcc->rx.buf.ptr = &lvcc->rx.buf.start[SERVICE_GET_END(s) * 4];
+ cardvcc_write(lvcc, SERVICE_GET_END(s), vcc_rxreadptr);
+diff -urNp linux-2.6.29.5/drivers/atm/nicstar.c linux-2.6.29.5/drivers/atm/nicstar.c
+--- linux-2.6.29.5/drivers/atm/nicstar.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/atm/nicstar.c 2009-06-12 23:57:32.000000000 -0400
+@@ -1723,7 +1723,7 @@ static int ns_send(struct atm_vcc *vcc,
+ if ((vc = (vc_map *) vcc->dev_data) == NULL)
+ {
+ printk("nicstar%d: vcc->dev_data == NULL on ns_send().\n", card->index);
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+ dev_kfree_skb_any(skb);
+ return -EINVAL;
+ }
+@@ -1731,7 +1731,7 @@ static int ns_send(struct atm_vcc *vcc,
+ if (!vc->tx)
+ {
+ printk("nicstar%d: Trying to transmit on a non-tx VC.\n", card->index);
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+ dev_kfree_skb_any(skb);
+ return -EINVAL;
+ }
+@@ -1739,7 +1739,7 @@ static int ns_send(struct atm_vcc *vcc,
+ if (vcc->qos.aal != ATM_AAL5 && vcc->qos.aal != ATM_AAL0)
+ {
+ printk("nicstar%d: Only AAL0 and AAL5 are supported.\n", card->index);
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+ dev_kfree_skb_any(skb);
+ return -EINVAL;
+ }
+@@ -1747,7 +1747,7 @@ static int ns_send(struct atm_vcc *vcc,
+ if (skb_shinfo(skb)->nr_frags != 0)
+ {
+ printk("nicstar%d: No scatter-gather yet.\n", card->index);
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+ dev_kfree_skb_any(skb);
+ return -EINVAL;
+ }
+@@ -1792,11 +1792,11 @@ static int ns_send(struct atm_vcc *vcc,
+
+ if (push_scqe(card, vc, scq, &scqe, skb) != 0)
+ {
+- atomic_inc(&vcc->stats->tx_err);
++ atomic_inc_unchecked(&vcc->stats->tx_err);
+ dev_kfree_skb_any(skb);
+ return -EIO;
+ }
+- atomic_inc(&vcc->stats->tx);
++ atomic_inc_unchecked(&vcc->stats->tx);
+
+ return 0;
+ }
+@@ -2111,14 +2111,14 @@ static void dequeue_rx(ns_dev *card, ns_
+ {
+ printk("nicstar%d: Can't allocate buffers for aal0.\n",
+ card->index);
+- atomic_add(i,&vcc->stats->rx_drop);
++ atomic_add_unchecked(i,&vcc->stats->rx_drop);
+ break;
+ }
+ if (!atm_charge(vcc, sb->truesize))
+ {
+ RXPRINTK("nicstar%d: atm_charge() dropped aal0 packets.\n",
+ card->index);
+- atomic_add(i-1,&vcc->stats->rx_drop); /* already increased by 1 */
++ atomic_add_unchecked(i-1,&vcc->stats->rx_drop); /* already increased by 1 */
+ dev_kfree_skb_any(sb);
+ break;
+ }
+@@ -2133,7 +2133,7 @@ static void dequeue_rx(ns_dev *card, ns_
+ ATM_SKB(sb)->vcc = vcc;
+ __net_timestamp(sb);
+ vcc->push(vcc, sb);
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+ cell += ATM_CELL_PAYLOAD;
+ }
+
+@@ -2152,7 +2152,7 @@ static void dequeue_rx(ns_dev *card, ns_
+ if (iovb == NULL)
+ {
+ printk("nicstar%d: Out of iovec buffers.\n", card->index);
+- atomic_inc(&vcc->stats->rx_drop);
++ atomic_inc_unchecked(&vcc->stats->rx_drop);
+ recycle_rx_buf(card, skb);
+ return;
+ }
+@@ -2182,7 +2182,7 @@ static void dequeue_rx(ns_dev *card, ns_
+ else if (NS_SKB(iovb)->iovcnt >= NS_MAX_IOVECS)
+ {
+ printk("nicstar%d: received too big AAL5 SDU.\n", card->index);
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data, NS_MAX_IOVECS);
+ NS_SKB(iovb)->iovcnt = 0;
+ iovb->len = 0;
+@@ -2202,7 +2202,7 @@ static void dequeue_rx(ns_dev *card, ns_
+ printk("nicstar%d: Expected a small buffer, and this is not one.\n",
+ card->index);
+ which_list(card, skb);
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ recycle_rx_buf(card, skb);
+ vc->rx_iov = NULL;
+ recycle_iov_buf(card, iovb);
+@@ -2216,7 +2216,7 @@ static void dequeue_rx(ns_dev *card, ns_
+ printk("nicstar%d: Expected a large buffer, and this is not one.\n",
+ card->index);
+ which_list(card, skb);
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data,
+ NS_SKB(iovb)->iovcnt);
+ vc->rx_iov = NULL;
+@@ -2240,7 +2240,7 @@ static void dequeue_rx(ns_dev *card, ns_
+ printk(" - PDU size mismatch.\n");
+ else
+ printk(".\n");
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data,
+ NS_SKB(iovb)->iovcnt);
+ vc->rx_iov = NULL;
+@@ -2256,7 +2256,7 @@ static void dequeue_rx(ns_dev *card, ns_
+ if (!atm_charge(vcc, skb->truesize))
+ {
+ push_rxbufs(card, skb);
+- atomic_inc(&vcc->stats->rx_drop);
++ atomic_inc_unchecked(&vcc->stats->rx_drop);
+ }
+ else
+ {
+@@ -2268,7 +2268,7 @@ static void dequeue_rx(ns_dev *card, ns_
+ ATM_SKB(skb)->vcc = vcc;
+ __net_timestamp(skb);
+ vcc->push(vcc, skb);
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+ }
+ }
+ else if (NS_SKB(iovb)->iovcnt == 2) /* One small plus one large buffer */
+@@ -2283,7 +2283,7 @@ static void dequeue_rx(ns_dev *card, ns_
+ if (!atm_charge(vcc, sb->truesize))
+ {
+ push_rxbufs(card, sb);
+- atomic_inc(&vcc->stats->rx_drop);
++ atomic_inc_unchecked(&vcc->stats->rx_drop);
+ }
+ else
+ {
+@@ -2295,7 +2295,7 @@ static void dequeue_rx(ns_dev *card, ns_
+ ATM_SKB(sb)->vcc = vcc;
+ __net_timestamp(sb);
+ vcc->push(vcc, sb);
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+ }
+
+ push_rxbufs(card, skb);
+@@ -2306,7 +2306,7 @@ static void dequeue_rx(ns_dev *card, ns_
+ if (!atm_charge(vcc, skb->truesize))
+ {
+ push_rxbufs(card, skb);
+- atomic_inc(&vcc->stats->rx_drop);
++ atomic_inc_unchecked(&vcc->stats->rx_drop);
+ }
+ else
+ {
+@@ -2320,7 +2320,7 @@ static void dequeue_rx(ns_dev *card, ns_
+ ATM_SKB(skb)->vcc = vcc;
+ __net_timestamp(skb);
+ vcc->push(vcc, skb);
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+ }
+
+ push_rxbufs(card, sb);
+@@ -2342,7 +2342,7 @@ static void dequeue_rx(ns_dev *card, ns_
+ if (hb == NULL)
+ {
+ printk("nicstar%d: Out of huge buffers.\n", card->index);
+- atomic_inc(&vcc->stats->rx_drop);
++ atomic_inc_unchecked(&vcc->stats->rx_drop);
+ recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data,
+ NS_SKB(iovb)->iovcnt);
+ vc->rx_iov = NULL;
+@@ -2393,7 +2393,7 @@ static void dequeue_rx(ns_dev *card, ns_
+ }
+ else
+ dev_kfree_skb_any(hb);
+- atomic_inc(&vcc->stats->rx_drop);
++ atomic_inc_unchecked(&vcc->stats->rx_drop);
+ }
+ else
+ {
+@@ -2427,7 +2427,7 @@ static void dequeue_rx(ns_dev *card, ns_
+ #endif /* NS_USE_DESTRUCTORS */
+ __net_timestamp(hb);
+ vcc->push(vcc, hb);
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+ }
+ }
+
+diff -urNp linux-2.6.29.5/drivers/atm/solos-pci.c linux-2.6.29.5/drivers/atm/solos-pci.c
+--- linux-2.6.29.5/drivers/atm/solos-pci.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/atm/solos-pci.c 2009-06-12 23:57:32.000000000 -0400
+@@ -261,7 +261,7 @@ void solos_bh(unsigned long card_arg)
+ }
+ atm_charge(vcc, skb->truesize);
+ vcc->push(vcc, skb);
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+ break;
+
+ case PKT_COMMAND:
+@@ -487,7 +487,7 @@ static int fpga_tx(struct solos_card *ca
+ vcc = *(void **)skb->cb;
+
+ if (vcc) {
+- atomic_inc(&vcc->stats->tx);
++ atomic_inc_unchecked(&vcc->stats->tx);
+ solos_pop(vcc, skb);
+ } else
+ dev_kfree_skb_irq(skb);
+@@ -517,9 +517,9 @@ static int psend(struct atm_vcc *vcc, st
+ memcpy(skb2->data, skb->data, skb->len);
+ skb_put(skb2, skb->len);
+ vcc->push(vcc, skb2);
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+ }
+- atomic_inc(&vcc->stats->tx);
++ atomic_inc_unchecked(&vcc->stats->tx);
+ solos_pop(vcc, skb);
+ return 0;
+ }
+diff -urNp linux-2.6.29.5/drivers/atm/suni.c linux-2.6.29.5/drivers/atm/suni.c
+--- linux-2.6.29.5/drivers/atm/suni.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/atm/suni.c 2009-06-12 23:57:32.000000000 -0400
+@@ -49,7 +49,7 @@ static DEFINE_SPINLOCK(sunis_lock);
+
+
+ #define ADD_LIMITED(s,v) \
+- atomic_add((v),&stats->s); \
++ atomic_add_unchecked((v),&stats->s); \
+ if (atomic_read(&stats->s) < 0) atomic_set(&stats->s,INT_MAX);
+
+
+diff -urNp linux-2.6.29.5/drivers/atm/uPD98402.c linux-2.6.29.5/drivers/atm/uPD98402.c
+--- linux-2.6.29.5/drivers/atm/uPD98402.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/atm/uPD98402.c 2009-06-12 23:57:32.000000000 -0400
+@@ -41,7 +41,7 @@ static int fetch_stats(struct atm_dev *d
+ struct sonet_stats tmp;
+ int error = 0;
+
+- atomic_add(GET(HECCT),&PRIV(dev)->sonet_stats.uncorr_hcs);
++ atomic_add_unchecked(GET(HECCT),&PRIV(dev)->sonet_stats.uncorr_hcs);
+ sonet_copy_stats(&PRIV(dev)->sonet_stats,&tmp);
+ if (arg) error = copy_to_user(arg,&tmp,sizeof(tmp));
+ if (zero && !error) {
+@@ -160,7 +160,7 @@ static int uPD98402_ioctl(struct atm_dev
+
+
+ #define ADD_LIMITED(s,v) \
+- { atomic_add(GET(v),&PRIV(dev)->sonet_stats.s); \
++ { atomic_add_unchecked(GET(v),&PRIV(dev)->sonet_stats.s); \
+ if (atomic_read(&PRIV(dev)->sonet_stats.s) < 0) \
+ atomic_set(&PRIV(dev)->sonet_stats.s,INT_MAX); }
+
+@@ -193,7 +193,7 @@ static void uPD98402_int(struct atm_dev
+ if (reason & uPD98402_INT_PFM) stat_event(dev);
+ if (reason & uPD98402_INT_PCO) {
+ (void) GET(PCOCR); /* clear interrupt cause */
+- atomic_add(GET(HECCT),
++ atomic_add_unchecked(GET(HECCT),
+ &PRIV(dev)->sonet_stats.uncorr_hcs);
+ }
+ if ((reason & uPD98402_INT_RFO) &&
+diff -urNp linux-2.6.29.5/drivers/atm/zatm.c linux-2.6.29.5/drivers/atm/zatm.c
+--- linux-2.6.29.5/drivers/atm/zatm.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/atm/zatm.c 2009-06-12 23:57:32.000000000 -0400
+@@ -458,7 +458,7 @@ printk("dummy: 0x%08lx, 0x%08lx\n",dummy
+ }
+ if (!size) {
+ dev_kfree_skb_irq(skb);
+- if (vcc) atomic_inc(&vcc->stats->rx_err);
++ if (vcc) atomic_inc_unchecked(&vcc->stats->rx_err);
+ continue;
+ }
+ if (!atm_charge(vcc,skb->truesize)) {
+@@ -468,7 +468,7 @@ printk("dummy: 0x%08lx, 0x%08lx\n",dummy
+ skb->len = size;
+ ATM_SKB(skb)->vcc = vcc;
+ vcc->push(vcc,skb);
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+ }
+ zout(pos & 0xffff,MTA(mbx));
+ #if 0 /* probably a stupid idea */
+@@ -732,7 +732,7 @@ if (*ZATM_PRV_DSC(skb) != (uPD98401_TXPD
+ skb_queue_head(&zatm_vcc->backlog,skb);
+ break;
+ }
+- atomic_inc(&vcc->stats->tx);
++ atomic_inc_unchecked(&vcc->stats->tx);
+ wake_up(&zatm_vcc->tx_wait);
+ }
+
+diff -urNp linux-2.6.29.5/drivers/char/agp/frontend.c linux-2.6.29.5/drivers/char/agp/frontend.c
+--- linux-2.6.29.5/drivers/char/agp/frontend.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/char/agp/frontend.c 2009-06-12 23:57:32.000000000 -0400
@@ -824,7 +824,7 @@ static int agpioc_reserve_wrap(struct ag
if (copy_from_user(&reserve, arg, sizeof(struct agp_region)))
return -EFAULT;
@@ -14888,9 +16978,9 @@ diff -urNp linux-2.6.28.8/drivers/char/agp/frontend.c linux-2.6.28.8/drivers/cha
return -EFAULT;
client = agp_find_client_by_pid(reserve.pid);
-diff -urNp linux-2.6.28.8/drivers/char/agp/intel-agp.c linux-2.6.28.8/drivers/char/agp/intel-agp.c
---- linux-2.6.28.8/drivers/char/agp/intel-agp.c 2009-03-07 10:24:49.000000000 -0500
-+++ linux-2.6.28.8/drivers/char/agp/intel-agp.c 2009-03-07 10:29:51.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/char/agp/intel-agp.c linux-2.6.29.5/drivers/char/agp/intel-agp.c
+--- linux-2.6.29.5/drivers/char/agp/intel-agp.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/char/agp/intel-agp.c 2009-06-12 23:57:32.000000000 -0400
@@ -2369,7 +2369,7 @@ static struct pci_device_id agp_intel_pc
ID(PCI_DEVICE_ID_INTEL_Q45_HB),
ID(PCI_DEVICE_ID_INTEL_G45_HB),
@@ -14900,9 +16990,9 @@ diff -urNp linux-2.6.28.8/drivers/char/agp/intel-agp.c linux-2.6.28.8/drivers/ch
};
MODULE_DEVICE_TABLE(pci, agp_intel_pci_table);
-diff -urNp linux-2.6.28.8/drivers/char/hpet.c linux-2.6.28.8/drivers/char/hpet.c
---- linux-2.6.28.8/drivers/char/hpet.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/char/hpet.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/char/hpet.c linux-2.6.29.5/drivers/char/hpet.c
+--- linux-2.6.29.5/drivers/char/hpet.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/char/hpet.c 2009-06-12 23:57:32.000000000 -0400
@@ -975,7 +975,7 @@ static struct acpi_driver hpet_acpi_driv
},
};
@@ -14912,9 +17002,42 @@ diff -urNp linux-2.6.28.8/drivers/char/hpet.c linux-2.6.28.8/drivers/char/hpet.c
static int __init hpet_init(void)
{
-diff -urNp linux-2.6.28.8/drivers/char/keyboard.c linux-2.6.28.8/drivers/char/keyboard.c
---- linux-2.6.28.8/drivers/char/keyboard.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/char/keyboard.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/char/ipmi/ipmi_msghandler.c linux-2.6.29.5/drivers/char/ipmi/ipmi_msghandler.c
+--- linux-2.6.29.5/drivers/char/ipmi/ipmi_msghandler.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/char/ipmi/ipmi_msghandler.c 2009-06-12 23:57:32.000000000 -0400
+@@ -408,7 +408,7 @@ struct ipmi_smi {
+ struct proc_dir_entry *proc_dir;
+ char proc_dir_name[10];
+
+- atomic_t stats[IPMI_NUM_STATS];
++ atomic_unchecked_t stats[IPMI_NUM_STATS];
+
+ /*
+ * run_to_completion duplicate of smb_info, smi_info
+@@ -441,7 +441,7 @@ static DEFINE_MUTEX(smi_watchers_mutex);
+
+
+ #define ipmi_inc_stat(intf, stat) \
+- atomic_inc(&(intf)->stats[IPMI_STAT_ ## stat])
++ atomic_inc_unchecked(&(intf)->stats[IPMI_STAT_ ## stat])
+ #define ipmi_get_stat(intf, stat) \
+ ((unsigned int) atomic_read(&(intf)->stats[IPMI_STAT_ ## stat]))
+
+diff -urNp linux-2.6.29.5/drivers/char/ipmi/ipmi_si_intf.c linux-2.6.29.5/drivers/char/ipmi/ipmi_si_intf.c
+--- linux-2.6.29.5/drivers/char/ipmi/ipmi_si_intf.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/char/ipmi/ipmi_si_intf.c 2009-06-12 23:57:32.000000000 -0400
+@@ -288,7 +288,7 @@ struct smi_info {
+ };
+
+ #define smi_inc_stat(smi, stat) \
+- atomic_inc(&(smi)->stats[SI_STAT_ ## stat])
++ atomic_inc_unchecked(&(smi)->stats[SI_STAT_ ## stat])
+ #define smi_get_stat(smi, stat) \
+ ((unsigned int) atomic_read(&(smi)->stats[SI_STAT_ ## stat]))
+
+diff -urNp linux-2.6.29.5/drivers/char/keyboard.c linux-2.6.29.5/drivers/char/keyboard.c
+--- linux-2.6.29.5/drivers/char/keyboard.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/char/keyboard.c 2009-06-12 23:57:32.000000000 -0400
@@ -635,6 +635,16 @@ static void k_spec(struct vc_data *vc, u
kbd->kbdmode == VC_MEDIUMRAW) &&
value != KVAL(K_SAK))
@@ -14941,9 +17064,9 @@ diff -urNp linux-2.6.28.8/drivers/char/keyboard.c linux-2.6.28.8/drivers/char/ke
};
MODULE_DEVICE_TABLE(input, kbd_ids);
-diff -urNp linux-2.6.28.8/drivers/char/mem.c linux-2.6.28.8/drivers/char/mem.c
---- linux-2.6.28.8/drivers/char/mem.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/char/mem.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/char/mem.c linux-2.6.29.5/drivers/char/mem.c
+--- linux-2.6.29.5/drivers/char/mem.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/char/mem.c 2009-06-12 23:57:32.000000000 -0400
@@ -18,6 +18,7 @@
#include <linux/raw.h>
#include <linux/tty.h>
@@ -14956,7 +17079,7 @@ diff -urNp linux-2.6.28.8/drivers/char/mem.c linux-2.6.28.8/drivers/char/mem.c
# include <linux/efi.h>
#endif
-+#ifdef CONFIG_GRKERNSEC
++#if defined(CONFIG_GRKERNSEC) && !defined(CONFIG_GRKERNSEC_NO_RBAC)
+extern struct file_operations grsec_fops;
+#endif
+
@@ -14987,7 +17110,7 @@ diff -urNp linux-2.6.28.8/drivers/char/mem.c linux-2.6.28.8/drivers/char/mem.c
vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff,
size,
vma->vm_page_prot);
-@@ -588,6 +603,11 @@ static ssize_t write_kmem(struct file *
+@@ -585,6 +600,11 @@ static ssize_t write_kmem(struct file *
ssize_t written;
char * kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */
@@ -14999,7 +17122,7 @@ diff -urNp linux-2.6.28.8/drivers/char/mem.c linux-2.6.28.8/drivers/char/mem.c
if (p < (unsigned long) high_memory) {
wrote = count;
-@@ -791,6 +811,16 @@ static loff_t memory_lseek(struct file *
+@@ -788,6 +808,16 @@ static loff_t memory_lseek(struct file *
static int open_port(struct inode * inode, struct file * filp)
{
@@ -15016,7 +17139,7 @@ diff -urNp linux-2.6.28.8/drivers/char/mem.c linux-2.6.28.8/drivers/char/mem.c
return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
}
-@@ -798,7 +828,6 @@ static int open_port(struct inode * inod
+@@ -795,7 +825,6 @@ static int open_port(struct inode * inod
#define full_lseek null_lseek
#define write_zero write_null
#define read_full read_zero
@@ -15024,11 +17147,11 @@ diff -urNp linux-2.6.28.8/drivers/char/mem.c linux-2.6.28.8/drivers/char/mem.c
#define open_kmem open_mem
#define open_oldmem open_mem
-@@ -938,6 +967,11 @@ static int memory_open(struct inode * in
+@@ -935,6 +964,11 @@ static int memory_open(struct inode * in
filp->f_op = &oldmem_fops;
break;
#endif
-+#ifdef CONFIG_GRKERNSEC
++#if defined(CONFIG_GRKERNSEC) && !defined(CONFIG_GRKERNSEC_NO_RBAC)
+ case 13:
+ filp->f_op = &grsec_fops;
+ break;
@@ -15036,20 +17159,20 @@ diff -urNp linux-2.6.28.8/drivers/char/mem.c linux-2.6.28.8/drivers/char/mem.c
default:
unlock_kernel();
return -ENXIO;
-@@ -974,6 +1008,9 @@ static const struct {
+@@ -971,6 +1005,9 @@ static const struct {
#ifdef CONFIG_CRASH_DUMP
{12,"oldmem", S_IRUSR | S_IWUSR | S_IRGRP, &oldmem_fops},
#endif
-+#ifdef CONFIG_GRKERNSEC
++#if defined(CONFIG_GRKERNSEC) && !defined(CONFIG_GRKERNSEC_NO_RBAC)
+ {13,"grsec", S_IRUSR | S_IWUGO, &grsec_fops},
+#endif
};
static struct class *mem_class;
-diff -urNp linux-2.6.28.8/drivers/char/nvram.c linux-2.6.28.8/drivers/char/nvram.c
---- linux-2.6.28.8/drivers/char/nvram.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/char/nvram.c 2009-02-21 09:37:48.000000000 -0500
-@@ -433,7 +433,10 @@ static const struct file_operations nvra
+diff -urNp linux-2.6.29.5/drivers/char/nvram.c linux-2.6.29.5/drivers/char/nvram.c
+--- linux-2.6.29.5/drivers/char/nvram.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/char/nvram.c 2009-06-12 23:57:32.000000000 -0400
+@@ -429,7 +429,10 @@ static const struct file_operations nvra
static struct miscdevice nvram_dev = {
NVRAM_MINOR,
"nvram",
@@ -15060,10 +17183,10 @@ diff -urNp linux-2.6.28.8/drivers/char/nvram.c linux-2.6.28.8/drivers/char/nvram
+ NULL
};
- static int __init
-diff -urNp linux-2.6.28.8/drivers/char/random.c linux-2.6.28.8/drivers/char/random.c
---- linux-2.6.28.8/drivers/char/random.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/char/random.c 2009-02-21 09:37:48.000000000 -0500
+ static int __init nvram_init(void)
+diff -urNp linux-2.6.29.5/drivers/char/random.c linux-2.6.29.5/drivers/char/random.c
+--- linux-2.6.29.5/drivers/char/random.c 2009-06-12 23:55:00.000000000 -0400
++++ linux-2.6.29.5/drivers/char/random.c 2009-06-12 23:57:32.000000000 -0400
@@ -249,8 +249,13 @@
/*
* Configuration information
@@ -15096,7 +17219,7 @@ diff -urNp linux-2.6.28.8/drivers/char/random.c linux-2.6.28.8/drivers/char/rand
#if 0
/* x^2048 + x^1638 + x^1231 + x^819 + x^411 + x + 1 -- 115 */
{ 2048, 1638, 1231, 819, 411, 1 },
-@@ -1185,7 +1197,7 @@ EXPORT_SYMBOL(generate_random_uuid);
+@@ -1200,7 +1212,7 @@ EXPORT_SYMBOL(generate_random_uuid);
#include <linux/sysctl.h>
static int min_read_thresh = 8, min_write_thresh;
@@ -15105,21 +17228,132 @@ diff -urNp linux-2.6.28.8/drivers/char/random.c linux-2.6.28.8/drivers/char/rand
static int max_write_thresh = INPUT_POOL_WORDS * 32;
static char sysctl_bootid[16];
-diff -urNp linux-2.6.28.8/drivers/char/tpm/tpm.c linux-2.6.28.8/drivers/char/tpm/tpm.c
---- linux-2.6.28.8/drivers/char/tpm/tpm.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/char/tpm/tpm.c 2009-02-21 09:37:48.000000000 -0500
-@@ -1035,7 +1035,7 @@ ssize_t tpm_write(struct file *file, con
+diff -urNp linux-2.6.29.5/drivers/char/tty_ldisc.c linux-2.6.29.5/drivers/char/tty_ldisc.c
+--- linux-2.6.29.5/drivers/char/tty_ldisc.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/char/tty_ldisc.c 2009-06-12 23:57:32.000000000 -0400
+@@ -74,7 +74,7 @@ int tty_register_ldisc(int disc, struct
+ spin_lock_irqsave(&tty_ldisc_lock, flags);
+ tty_ldiscs[disc] = new_ldisc;
+ new_ldisc->num = disc;
+- new_ldisc->refcount = 0;
++ atomic_set(&new_ldisc->refcount, 0);
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
- mutex_lock(&chip->buffer_mutex);
+ return ret;
+@@ -102,7 +102,7 @@ int tty_unregister_ldisc(int disc)
+ return -EINVAL;
-- if (in_size > TPM_BUFSIZE)
-+ if (in_size > (unsigned int)TPM_BUFSIZE)
- in_size = TPM_BUFSIZE;
+ spin_lock_irqsave(&tty_ldisc_lock, flags);
+- if (tty_ldiscs[disc]->refcount)
++ if (atomic_read(&tty_ldiscs[disc]->refcount))
+ ret = -EBUSY;
+ else
+ tty_ldiscs[disc] = NULL;
+@@ -139,7 +139,7 @@ static int tty_ldisc_try_get(int disc, s
+ err = -EAGAIN;
+ else {
+ /* lock it */
+- ldops->refcount++;
++ atomic_inc(&ldops->refcount);
+ ld->ops = ldops;
+ err = 0;
+ }
+@@ -196,8 +196,8 @@ static void tty_ldisc_put(struct tty_ldi
+
+ spin_lock_irqsave(&tty_ldisc_lock, flags);
+ ld = tty_ldiscs[disc];
+- BUG_ON(ld->refcount == 0);
+- ld->refcount--;
++ BUG_ON(atomic_read(&ld->refcount) == 0);
++ atomic_dec(&ld->refcount);
+ module_put(ld->owner);
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+ }
+@@ -264,7 +264,7 @@ const struct file_operations tty_ldiscs_
+
+ static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld)
+ {
+- ld->refcount = 0;
++ atomic_set(&ld->refcount, 0);
+ tty->ldisc = *ld;
+ }
- if (copy_from_user
-diff -urNp linux-2.6.28.8/drivers/char/vt_ioctl.c linux-2.6.28.8/drivers/char/vt_ioctl.c
---- linux-2.6.28.8/drivers/char/vt_ioctl.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/char/vt_ioctl.c 2009-02-21 09:37:48.000000000 -0500
+@@ -289,7 +289,7 @@ static int tty_ldisc_try(struct tty_stru
+ spin_lock_irqsave(&tty_ldisc_lock, flags);
+ ld = &tty->ldisc;
+ if (test_bit(TTY_LDISC, &tty->flags)) {
+- ld->refcount++;
++ atomic_inc(&ld->refcount);
+ ret = 1;
+ }
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+@@ -316,7 +316,7 @@ struct tty_ldisc *tty_ldisc_ref_wait(str
+ {
+ /* wait_event is a macro */
+ wait_event(tty_ldisc_wait, tty_ldisc_try(tty));
+- WARN_ON(tty->ldisc.refcount == 0);
++ WARN_ON(atomic_read(&tty->ldisc.refcount) == 0);
+ return &tty->ldisc;
+ }
+
+@@ -359,11 +359,9 @@ void tty_ldisc_deref(struct tty_ldisc *l
+ BUG_ON(ld == NULL);
+
+ spin_lock_irqsave(&tty_ldisc_lock, flags);
+- if (ld->refcount == 0)
++ if (!atomic_add_unless(&ld->refcount, -1, 0))
+ printk(KERN_ERR "tty_ldisc_deref: no references.\n");
+- else
+- ld->refcount--;
+- if (ld->refcount == 0)
++ if (atomic_read(&ld->refcount) == 0)
+ wake_up(&tty_ldisc_wait);
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+ }
+@@ -507,8 +505,8 @@ restart:
+ clear_bit(TTY_LDISC, &o_tty->flags);
+
+ spin_lock_irqsave(&tty_ldisc_lock, flags);
+- if (tty->ldisc.refcount || (o_tty && o_tty->ldisc.refcount)) {
+- if (tty->ldisc.refcount) {
++ if (atomic_read(&tty->ldisc.refcount) || (o_tty && atomic_read(&o_tty->ldisc.refcount))) {
++ if (atomic_read(&tty->ldisc.refcount)) {
+ /* Free the new ldisc we grabbed. Must drop the lock
+ first. */
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+@@ -520,14 +518,14 @@ restart:
+ * and retries if we made tty_ldisc_wait() smarter.
+ * That is up for discussion.
+ */
+- if (wait_event_interruptible(tty_ldisc_wait, tty->ldisc.refcount == 0) < 0)
++ if (wait_event_interruptible(tty_ldisc_wait, atomic_read(&tty->ldisc.refcount) == 0) < 0)
+ return -ERESTARTSYS;
+ goto restart;
+ }
+- if (o_tty && o_tty->ldisc.refcount) {
++ if (o_tty && atomic_read(&o_tty->ldisc.refcount)) {
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+ tty_ldisc_put(o_tty->ldisc.ops);
+- if (wait_event_interruptible(tty_ldisc_wait, o_tty->ldisc.refcount == 0) < 0)
++ if (wait_event_interruptible(tty_ldisc_wait, atomic_read(&o_tty->ldisc.refcount) == 0) < 0)
+ return -ERESTARTSYS;
+ goto restart;
+ }
+@@ -670,9 +668,9 @@ void tty_ldisc_release(struct tty_struct
+ * side is zero.
+ */
+ spin_lock_irqsave(&tty_ldisc_lock, flags);
+- while (tty->ldisc.refcount) {
++ while (atomic_read(&tty->ldisc.refcount)) {
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+- wait_event(tty_ldisc_wait, tty->ldisc.refcount == 0);
++ wait_event(tty_ldisc_wait, atomic_read(&tty->ldisc.refcount) == 0);
+ spin_lock_irqsave(&tty_ldisc_lock, flags);
+ }
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+diff -urNp linux-2.6.29.5/drivers/char/vt_ioctl.c linux-2.6.29.5/drivers/char/vt_ioctl.c
+--- linux-2.6.29.5/drivers/char/vt_ioctl.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/char/vt_ioctl.c 2009-06-12 23:57:32.000000000 -0400
@@ -96,6 +96,12 @@ do_kdsk_ioctl(int cmd, struct kbentry __
case KDSKBENT:
if (!perm)
@@ -15147,9 +17381,9 @@ diff -urNp linux-2.6.28.8/drivers/char/vt_ioctl.c linux-2.6.28.8/drivers/char/vt
q = func_table[i];
first_free = funcbufptr + (funcbufsize - funcbufleft);
for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++)
-diff -urNp linux-2.6.28.8/drivers/edac/edac_core.h linux-2.6.28.8/drivers/edac/edac_core.h
---- linux-2.6.28.8/drivers/edac/edac_core.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/edac/edac_core.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/edac/edac_core.h linux-2.6.29.5/drivers/edac/edac_core.h
+--- linux-2.6.29.5/drivers/edac/edac_core.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/edac/edac_core.h 2009-06-12 23:57:32.000000000 -0400
@@ -85,11 +85,11 @@ extern int edac_debug_level;
#else /* !CONFIG_EDAC_DEBUG */
@@ -15167,9 +17401,9 @@ diff -urNp linux-2.6.28.8/drivers/edac/edac_core.h linux-2.6.28.8/drivers/edac/e
#endif /* !CONFIG_EDAC_DEBUG */
-diff -urNp linux-2.6.28.8/drivers/firmware/dmi_scan.c linux-2.6.28.8/drivers/firmware/dmi_scan.c
---- linux-2.6.28.8/drivers/firmware/dmi_scan.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/firmware/dmi_scan.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/firmware/dmi_scan.c linux-2.6.29.5/drivers/firmware/dmi_scan.c
+--- linux-2.6.29.5/drivers/firmware/dmi_scan.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/firmware/dmi_scan.c 2009-06-12 23:57:32.000000000 -0400
@@ -389,11 +389,6 @@ void __init dmi_scan_machine(void)
}
}
@@ -15182,9 +17416,112 @@ diff -urNp linux-2.6.28.8/drivers/firmware/dmi_scan.c linux-2.6.28.8/drivers/fir
p = dmi_ioremap(0xF0000, 0x10000);
if (p == NULL)
goto error;
-diff -urNp linux-2.6.28.8/drivers/hwmon/fscpos.c linux-2.6.28.8/drivers/hwmon/fscpos.c
---- linux-2.6.28.8/drivers/hwmon/fscpos.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/hwmon/fscpos.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/gpu/drm/drm_drv.c linux-2.6.29.5/drivers/gpu/drm/drm_drv.c
+--- linux-2.6.29.5/drivers/gpu/drm/drm_drv.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/gpu/drm/drm_drv.c 2009-06-12 23:57:32.000000000 -0400
+@@ -461,7 +461,7 @@ int drm_ioctl(struct inode *inode, struc
+ char *kdata = NULL;
+
+ atomic_inc(&dev->ioctl_count);
+- atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]);
++ atomic_inc_unchecked(&dev->counts[_DRM_STAT_IOCTLS]);
+ ++file_priv->ioctl_count;
+
+ DRM_DEBUG("pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n",
+diff -urNp linux-2.6.29.5/drivers/gpu/drm/drm_fops.c linux-2.6.29.5/drivers/gpu/drm/drm_fops.c
+--- linux-2.6.29.5/drivers/gpu/drm/drm_fops.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/gpu/drm/drm_fops.c 2009-06-12 23:57:32.000000000 -0400
+@@ -130,9 +130,9 @@ int drm_open(struct inode *inode, struct
+
+ retcode = drm_open_helper(inode, filp, dev);
+ if (!retcode) {
+- atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
++ atomic_inc_unchecked(&dev->counts[_DRM_STAT_OPENS]);
+ spin_lock(&dev->count_lock);
+- if (!dev->open_count++) {
++ if (atomic_inc_return(&dev->open_count) == 1) {
+ spin_unlock(&dev->count_lock);
+ retcode = drm_setup(dev);
+ goto out;
+@@ -436,7 +436,7 @@ int drm_release(struct inode *inode, str
+
+ lock_kernel();
+
+- DRM_DEBUG("open_count = %d\n", dev->open_count);
++ DRM_DEBUG("open_count = %d\n", atomic_read(&dev->open_count));
+
+ if (dev->driver->preclose)
+ dev->driver->preclose(dev, file_priv);
+@@ -448,7 +448,7 @@ int drm_release(struct inode *inode, str
+ DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
+ task_pid_nr(current),
+ (long)old_encode_dev(file_priv->minor->device),
+- dev->open_count);
++ atomic_read(&dev->open_count));
+
+ /* if the master has gone away we can't do anything with the lock */
+ if (file_priv->minor->master)
+@@ -525,9 +525,9 @@ int drm_release(struct inode *inode, str
+ * End inline drm_release
+ */
+
+- atomic_inc(&dev->counts[_DRM_STAT_CLOSES]);
++ atomic_inc_unchecked(&dev->counts[_DRM_STAT_CLOSES]);
+ spin_lock(&dev->count_lock);
+- if (!--dev->open_count) {
++ if (atomic_dec_and_test(&dev->open_count)) {
+ if (atomic_read(&dev->ioctl_count)) {
+ DRM_ERROR("Device busy: %d\n",
+ atomic_read(&dev->ioctl_count));
+diff -urNp linux-2.6.29.5/drivers/gpu/drm/drm_lock.c linux-2.6.29.5/drivers/gpu/drm/drm_lock.c
+--- linux-2.6.29.5/drivers/gpu/drm/drm_lock.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/gpu/drm/drm_lock.c 2009-06-12 23:57:32.000000000 -0400
+@@ -87,7 +87,7 @@ int drm_lock(struct drm_device *dev, voi
+ if (drm_lock_take(&master->lock, lock->context)) {
+ master->lock.file_priv = file_priv;
+ master->lock.lock_time = jiffies;
+- atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
++ atomic_inc_unchecked(&dev->counts[_DRM_STAT_LOCKS]);
+ break; /* Got lock */
+ }
+
+@@ -165,7 +165,7 @@ int drm_unlock(struct drm_device *dev, v
+ return -EINVAL;
+ }
+
+- atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]);
++ atomic_inc_unchecked(&dev->counts[_DRM_STAT_UNLOCKS]);
+
+ /* kernel_context_switch isn't used by any of the x86 drm
+ * modules but is required by the Sparc driver.
+diff -urNp linux-2.6.29.5/drivers/gpu/drm/i810/i810_dma.c linux-2.6.29.5/drivers/gpu/drm/i810/i810_dma.c
+--- linux-2.6.29.5/drivers/gpu/drm/i810/i810_dma.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/gpu/drm/i810/i810_dma.c 2009-06-12 23:57:32.000000000 -0400
+@@ -954,8 +954,8 @@ static int i810_dma_vertex(struct drm_de
+ dma->buflist[vertex->idx],
+ vertex->discard, vertex->used);
+
+- atomic_add(vertex->used, &dev->counts[_DRM_STAT_SECONDARY]);
+- atomic_inc(&dev->counts[_DRM_STAT_DMA]);
++ atomic_add_unchecked(vertex->used, &dev->counts[_DRM_STAT_SECONDARY]);
++ atomic_inc_unchecked(&dev->counts[_DRM_STAT_DMA]);
+ sarea_priv->last_enqueue = dev_priv->counter - 1;
+ sarea_priv->last_dispatch = (int)hw_status[5];
+
+@@ -1117,8 +1117,8 @@ static int i810_dma_mc(struct drm_device
+ i810_dma_dispatch_mc(dev, dma->buflist[mc->idx], mc->used,
+ mc->last_render);
+
+- atomic_add(mc->used, &dev->counts[_DRM_STAT_SECONDARY]);
+- atomic_inc(&dev->counts[_DRM_STAT_DMA]);
++ atomic_add_unchecked(mc->used, &dev->counts[_DRM_STAT_SECONDARY]);
++ atomic_inc_unchecked(&dev->counts[_DRM_STAT_DMA]);
+ sarea_priv->last_enqueue = dev_priv->counter - 1;
+ sarea_priv->last_dispatch = (int)hw_status[5];
+
+diff -urNp linux-2.6.29.5/drivers/hwmon/fscpos.c linux-2.6.29.5/drivers/hwmon/fscpos.c
+--- linux-2.6.29.5/drivers/hwmon/fscpos.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/hwmon/fscpos.c 2009-06-12 23:57:32.000000000 -0400
@@ -240,7 +240,6 @@ static ssize_t set_pwm(struct i2c_client
unsigned long v = simple_strtoul(buf, NULL, 10);
@@ -15193,10 +17530,10 @@ diff -urNp linux-2.6.28.8/drivers/hwmon/fscpos.c linux-2.6.28.8/drivers/hwmon/fs
if (v > 255) v = 255;
mutex_lock(&data->update_lock);
-diff -urNp linux-2.6.28.8/drivers/hwmon/k8temp.c linux-2.6.28.8/drivers/hwmon/k8temp.c
---- linux-2.6.28.8/drivers/hwmon/k8temp.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/hwmon/k8temp.c 2009-02-21 09:37:48.000000000 -0500
-@@ -130,7 +130,7 @@ static DEVICE_ATTR(name, S_IRUGO, show_n
+diff -urNp linux-2.6.29.5/drivers/hwmon/k8temp.c linux-2.6.29.5/drivers/hwmon/k8temp.c
+--- linux-2.6.29.5/drivers/hwmon/k8temp.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/hwmon/k8temp.c 2009-06-12 23:57:32.000000000 -0400
+@@ -138,7 +138,7 @@ static DEVICE_ATTR(name, S_IRUGO, show_n
static struct pci_device_id k8temp_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) },
@@ -15205,10 +17542,10 @@ diff -urNp linux-2.6.28.8/drivers/hwmon/k8temp.c linux-2.6.28.8/drivers/hwmon/k8
};
MODULE_DEVICE_TABLE(pci, k8temp_ids);
-diff -urNp linux-2.6.28.8/drivers/hwmon/sis5595.c linux-2.6.28.8/drivers/hwmon/sis5595.c
---- linux-2.6.28.8/drivers/hwmon/sis5595.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/hwmon/sis5595.c 2009-02-21 09:37:48.000000000 -0500
-@@ -698,7 +698,7 @@ static struct sis5595_data *sis5595_upda
+diff -urNp linux-2.6.29.5/drivers/hwmon/sis5595.c linux-2.6.29.5/drivers/hwmon/sis5595.c
+--- linux-2.6.29.5/drivers/hwmon/sis5595.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/hwmon/sis5595.c 2009-06-12 23:57:32.000000000 -0400
+@@ -699,7 +699,7 @@ static struct sis5595_data *sis5595_upda
static struct pci_device_id sis5595_pci_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) },
@@ -15217,10 +17554,10 @@ diff -urNp linux-2.6.28.8/drivers/hwmon/sis5595.c linux-2.6.28.8/drivers/hwmon/s
};
MODULE_DEVICE_TABLE(pci, sis5595_pci_ids);
-diff -urNp linux-2.6.28.8/drivers/hwmon/via686a.c linux-2.6.28.8/drivers/hwmon/via686a.c
---- linux-2.6.28.8/drivers/hwmon/via686a.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/hwmon/via686a.c 2009-02-21 09:37:48.000000000 -0500
-@@ -768,7 +768,7 @@ static struct via686a_data *via686a_upda
+diff -urNp linux-2.6.29.5/drivers/hwmon/via686a.c linux-2.6.29.5/drivers/hwmon/via686a.c
+--- linux-2.6.29.5/drivers/hwmon/via686a.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/hwmon/via686a.c 2009-06-12 23:57:32.000000000 -0400
+@@ -769,7 +769,7 @@ static struct via686a_data *via686a_upda
static struct pci_device_id via686a_pci_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4) },
@@ -15229,10 +17566,10 @@ diff -urNp linux-2.6.28.8/drivers/hwmon/via686a.c linux-2.6.28.8/drivers/hwmon/v
};
MODULE_DEVICE_TABLE(pci, via686a_pci_ids);
-diff -urNp linux-2.6.28.8/drivers/hwmon/vt8231.c linux-2.6.28.8/drivers/hwmon/vt8231.c
---- linux-2.6.28.8/drivers/hwmon/vt8231.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/hwmon/vt8231.c 2009-02-21 09:37:48.000000000 -0500
-@@ -698,7 +698,7 @@ static struct platform_driver vt8231_dri
+diff -urNp linux-2.6.29.5/drivers/hwmon/vt8231.c linux-2.6.29.5/drivers/hwmon/vt8231.c
+--- linux-2.6.29.5/drivers/hwmon/vt8231.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/hwmon/vt8231.c 2009-06-12 23:57:32.000000000 -0400
+@@ -699,7 +699,7 @@ static struct platform_driver vt8231_dri
static struct pci_device_id vt8231_pci_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4) },
@@ -15241,10 +17578,10 @@ diff -urNp linux-2.6.28.8/drivers/hwmon/vt8231.c linux-2.6.28.8/drivers/hwmon/vt
};
MODULE_DEVICE_TABLE(pci, vt8231_pci_ids);
-diff -urNp linux-2.6.28.8/drivers/hwmon/w83791d.c linux-2.6.28.8/drivers/hwmon/w83791d.c
---- linux-2.6.28.8/drivers/hwmon/w83791d.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/hwmon/w83791d.c 2009-02-21 09:37:48.000000000 -0500
-@@ -327,8 +327,8 @@ static int w83791d_detect(struct i2c_cli
+diff -urNp linux-2.6.29.5/drivers/hwmon/w83791d.c linux-2.6.29.5/drivers/hwmon/w83791d.c
+--- linux-2.6.29.5/drivers/hwmon/w83791d.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/hwmon/w83791d.c 2009-06-12 23:57:32.000000000 -0400
+@@ -330,8 +330,8 @@ static int w83791d_detect(struct i2c_cli
struct i2c_board_info *info);
static int w83791d_remove(struct i2c_client *client);
@@ -15255,10 +17592,10 @@ diff -urNp linux-2.6.28.8/drivers/hwmon/w83791d.c linux-2.6.28.8/drivers/hwmon/w
static struct w83791d_data *w83791d_update_device(struct device *dev);
#ifdef DEBUG
-diff -urNp linux-2.6.28.8/drivers/i2c/busses/i2c-i801.c linux-2.6.28.8/drivers/i2c/busses/i2c-i801.c
---- linux-2.6.28.8/drivers/i2c/busses/i2c-i801.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/i2c/busses/i2c-i801.c 2009-02-21 09:37:48.000000000 -0500
-@@ -578,7 +578,7 @@ static struct pci_device_id i801_ids[] =
+diff -urNp linux-2.6.29.5/drivers/i2c/busses/i2c-i801.c linux-2.6.29.5/drivers/i2c/busses/i2c-i801.c
+--- linux-2.6.29.5/drivers/i2c/busses/i2c-i801.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/i2c/busses/i2c-i801.c 2009-06-12 23:57:32.000000000 -0400
+@@ -577,7 +577,7 @@ static struct pci_device_id i801_ids[] =
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_4) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_5) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PCH_SMBUS) },
@@ -15267,9 +17604,9 @@ diff -urNp linux-2.6.28.8/drivers/i2c/busses/i2c-i801.c linux-2.6.28.8/drivers/i
};
MODULE_DEVICE_TABLE (pci, i801_ids);
-diff -urNp linux-2.6.28.8/drivers/i2c/busses/i2c-piix4.c linux-2.6.28.8/drivers/i2c/busses/i2c-piix4.c
---- linux-2.6.28.8/drivers/i2c/busses/i2c-piix4.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/i2c/busses/i2c-piix4.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/i2c/busses/i2c-piix4.c linux-2.6.29.5/drivers/i2c/busses/i2c-piix4.c
+--- linux-2.6.29.5/drivers/i2c/busses/i2c-piix4.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/i2c/busses/i2c-piix4.c 2009-06-12 23:57:32.000000000 -0400
@@ -123,7 +123,7 @@ static struct dmi_system_id __devinitdat
.ident = "IBM",
.matches = { DMI_MATCH(DMI_SYS_VENDOR, "IBM"), },
@@ -15279,7 +17616,7 @@ diff -urNp linux-2.6.28.8/drivers/i2c/busses/i2c-piix4.c linux-2.6.28.8/drivers/
};
static int __devinit piix4_setup(struct pci_dev *PIIX4_dev,
-@@ -424,7 +424,7 @@ static struct pci_device_id piix4_ids[]
+@@ -423,7 +423,7 @@ static struct pci_device_id piix4_ids[]
PCI_DEVICE_ID_SERVERWORKS_CSB6) },
{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS,
PCI_DEVICE_ID_SERVERWORKS_HT1000SB) },
@@ -15288,10 +17625,10 @@ diff -urNp linux-2.6.28.8/drivers/i2c/busses/i2c-piix4.c linux-2.6.28.8/drivers/
};
MODULE_DEVICE_TABLE (pci, piix4_ids);
-diff -urNp linux-2.6.28.8/drivers/i2c/busses/i2c-sis630.c linux-2.6.28.8/drivers/i2c/busses/i2c-sis630.c
---- linux-2.6.28.8/drivers/i2c/busses/i2c-sis630.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/i2c/busses/i2c-sis630.c 2009-02-21 09:37:48.000000000 -0500
-@@ -472,7 +472,7 @@ static struct i2c_adapter sis630_adapter
+diff -urNp linux-2.6.29.5/drivers/i2c/busses/i2c-sis630.c linux-2.6.29.5/drivers/i2c/busses/i2c-sis630.c
+--- linux-2.6.29.5/drivers/i2c/busses/i2c-sis630.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/i2c/busses/i2c-sis630.c 2009-06-12 23:57:32.000000000 -0400
+@@ -471,7 +471,7 @@ static struct i2c_adapter sis630_adapter
static struct pci_device_id sis630_ids[] __devinitdata = {
{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) },
{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC) },
@@ -15300,10 +17637,10 @@ diff -urNp linux-2.6.28.8/drivers/i2c/busses/i2c-sis630.c linux-2.6.28.8/drivers
};
MODULE_DEVICE_TABLE (pci, sis630_ids);
-diff -urNp linux-2.6.28.8/drivers/i2c/busses/i2c-sis96x.c linux-2.6.28.8/drivers/i2c/busses/i2c-sis96x.c
---- linux-2.6.28.8/drivers/i2c/busses/i2c-sis96x.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/i2c/busses/i2c-sis96x.c 2009-02-21 09:37:48.000000000 -0500
-@@ -248,7 +248,7 @@ static struct i2c_adapter sis96x_adapter
+diff -urNp linux-2.6.29.5/drivers/i2c/busses/i2c-sis96x.c linux-2.6.29.5/drivers/i2c/busses/i2c-sis96x.c
+--- linux-2.6.29.5/drivers/i2c/busses/i2c-sis96x.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/i2c/busses/i2c-sis96x.c 2009-06-12 23:57:32.000000000 -0400
+@@ -247,7 +247,7 @@ static struct i2c_adapter sis96x_adapter
static struct pci_device_id sis96x_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_SMBUS) },
@@ -15312,9 +17649,9 @@ diff -urNp linux-2.6.28.8/drivers/i2c/busses/i2c-sis96x.c linux-2.6.28.8/drivers
};
MODULE_DEVICE_TABLE (pci, sis96x_ids);
-diff -urNp linux-2.6.28.8/drivers/ieee1394/dv1394.c linux-2.6.28.8/drivers/ieee1394/dv1394.c
---- linux-2.6.28.8/drivers/ieee1394/dv1394.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/ieee1394/dv1394.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/ieee1394/dv1394.c linux-2.6.29.5/drivers/ieee1394/dv1394.c
+--- linux-2.6.29.5/drivers/ieee1394/dv1394.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/ieee1394/dv1394.c 2009-06-12 23:57:32.000000000 -0400
@@ -739,7 +739,7 @@ static void frame_prepare(struct video_c
based upon DIF section and sequence
*/
@@ -15324,7 +17661,7 @@ diff -urNp linux-2.6.28.8/drivers/ieee1394/dv1394.c linux-2.6.28.8/drivers/ieee1
frame_put_packet (struct frame *f, struct packet *p)
{
int section_type = p->data[0] >> 5; /* section type is in bits 5 - 7 */
-@@ -2177,7 +2177,7 @@ static struct ieee1394_device_id dv1394_
+@@ -2181,7 +2181,7 @@ static struct ieee1394_device_id dv1394_
.specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff,
.version = AVC_SW_VERSION_ENTRY & 0xffffff
},
@@ -15333,10 +17670,10 @@ diff -urNp linux-2.6.28.8/drivers/ieee1394/dv1394.c linux-2.6.28.8/drivers/ieee1
};
MODULE_DEVICE_TABLE(ieee1394, dv1394_id_table);
-diff -urNp linux-2.6.28.8/drivers/ieee1394/eth1394.c linux-2.6.28.8/drivers/ieee1394/eth1394.c
---- linux-2.6.28.8/drivers/ieee1394/eth1394.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/ieee1394/eth1394.c 2009-02-21 09:37:48.000000000 -0500
-@@ -451,7 +451,7 @@ static struct ieee1394_device_id eth1394
+diff -urNp linux-2.6.29.5/drivers/ieee1394/eth1394.c linux-2.6.29.5/drivers/ieee1394/eth1394.c
+--- linux-2.6.29.5/drivers/ieee1394/eth1394.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/ieee1394/eth1394.c 2009-06-12 23:57:32.000000000 -0400
+@@ -445,7 +445,7 @@ static struct ieee1394_device_id eth1394
.specifier_id = ETHER1394_GASP_SPECIFIER_ID,
.version = ETHER1394_GASP_VERSION,
},
@@ -15345,9 +17682,9 @@ diff -urNp linux-2.6.28.8/drivers/ieee1394/eth1394.c linux-2.6.28.8/drivers/ieee
};
MODULE_DEVICE_TABLE(ieee1394, eth1394_id_table);
-diff -urNp linux-2.6.28.8/drivers/ieee1394/hosts.c linux-2.6.28.8/drivers/ieee1394/hosts.c
---- linux-2.6.28.8/drivers/ieee1394/hosts.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/ieee1394/hosts.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/ieee1394/hosts.c linux-2.6.29.5/drivers/ieee1394/hosts.c
+--- linux-2.6.29.5/drivers/ieee1394/hosts.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/ieee1394/hosts.c 2009-06-12 23:57:32.000000000 -0400
@@ -78,6 +78,7 @@ static int dummy_isoctl(struct hpsb_iso
}
@@ -15356,9 +17693,9 @@ diff -urNp linux-2.6.28.8/drivers/ieee1394/hosts.c linux-2.6.28.8/drivers/ieee13
.transmit_packet = dummy_transmit_packet,
.devctl = dummy_devctl,
.isoctl = dummy_isoctl
-diff -urNp linux-2.6.28.8/drivers/ieee1394/ohci1394.c linux-2.6.28.8/drivers/ieee1394/ohci1394.c
---- linux-2.6.28.8/drivers/ieee1394/ohci1394.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/ieee1394/ohci1394.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/ieee1394/ohci1394.c linux-2.6.29.5/drivers/ieee1394/ohci1394.c
+--- linux-2.6.29.5/drivers/ieee1394/ohci1394.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/ieee1394/ohci1394.c 2009-06-12 23:57:32.000000000 -0400
@@ -147,9 +147,9 @@ printk(level "%s: " fmt "\n" , OHCI1394_
printk(level "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->id , ## args)
@@ -15371,7 +17708,7 @@ diff -urNp linux-2.6.28.8/drivers/ieee1394/ohci1394.c linux-2.6.28.8/drivers/iee
static void dma_trm_tasklet(unsigned long data);
static void dma_trm_reset(struct dma_trm_ctx *d);
-@@ -3437,7 +3437,7 @@ static struct pci_device_id ohci1394_pci
+@@ -3449,7 +3449,7 @@ static struct pci_device_id ohci1394_pci
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
},
@@ -15380,9 +17717,9 @@ diff -urNp linux-2.6.28.8/drivers/ieee1394/ohci1394.c linux-2.6.28.8/drivers/iee
};
MODULE_DEVICE_TABLE(pci, ohci1394_pci_tbl);
-diff -urNp linux-2.6.28.8/drivers/ieee1394/raw1394.c linux-2.6.28.8/drivers/ieee1394/raw1394.c
---- linux-2.6.28.8/drivers/ieee1394/raw1394.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/ieee1394/raw1394.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/ieee1394/raw1394.c linux-2.6.29.5/drivers/ieee1394/raw1394.c
+--- linux-2.6.29.5/drivers/ieee1394/raw1394.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/ieee1394/raw1394.c 2009-06-12 23:57:32.000000000 -0400
@@ -2995,7 +2995,7 @@ static struct ieee1394_device_id raw1394
.match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
.specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
@@ -15392,9 +17729,9 @@ diff -urNp linux-2.6.28.8/drivers/ieee1394/raw1394.c linux-2.6.28.8/drivers/ieee
};
MODULE_DEVICE_TABLE(ieee1394, raw1394_id_table);
-diff -urNp linux-2.6.28.8/drivers/ieee1394/sbp2.c linux-2.6.28.8/drivers/ieee1394/sbp2.c
---- linux-2.6.28.8/drivers/ieee1394/sbp2.c 2009-02-07 16:10:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/ieee1394/sbp2.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/ieee1394/sbp2.c linux-2.6.29.5/drivers/ieee1394/sbp2.c
+--- linux-2.6.29.5/drivers/ieee1394/sbp2.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/ieee1394/sbp2.c 2009-06-12 23:57:32.000000000 -0400
@@ -290,7 +290,7 @@ static struct ieee1394_device_id sbp2_id
.match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
.specifier_id = SBP2_UNIT_SPEC_ID_ENTRY & 0xffffff,
@@ -15404,7 +17741,7 @@ diff -urNp linux-2.6.28.8/drivers/ieee1394/sbp2.c linux-2.6.28.8/drivers/ieee139
};
MODULE_DEVICE_TABLE(ieee1394, sbp2_id_table);
-@@ -2110,7 +2110,7 @@ MODULE_DESCRIPTION("IEEE-1394 SBP-2 prot
+@@ -2112,7 +2112,7 @@ MODULE_DESCRIPTION("IEEE-1394 SBP-2 prot
MODULE_SUPPORTED_DEVICE(SBP2_DEVICE_NAME);
MODULE_LICENSE("GPL");
@@ -15413,9 +17750,9 @@ diff -urNp linux-2.6.28.8/drivers/ieee1394/sbp2.c linux-2.6.28.8/drivers/ieee139
{
int ret;
-diff -urNp linux-2.6.28.8/drivers/ieee1394/video1394.c linux-2.6.28.8/drivers/ieee1394/video1394.c
---- linux-2.6.28.8/drivers/ieee1394/video1394.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/ieee1394/video1394.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/ieee1394/video1394.c linux-2.6.29.5/drivers/ieee1394/video1394.c
+--- linux-2.6.29.5/drivers/ieee1394/video1394.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/ieee1394/video1394.c 2009-06-12 23:57:32.000000000 -0400
@@ -1310,7 +1310,7 @@ static struct ieee1394_device_id video13
.specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
.version = (CAMERA_SW_VERSION_ENTRY + 2) & 0xffffff
@@ -15425,10 +17762,10 @@ diff -urNp linux-2.6.28.8/drivers/ieee1394/video1394.c linux-2.6.28.8/drivers/ie
};
MODULE_DEVICE_TABLE(ieee1394, video1394_id_table);
-diff -urNp linux-2.6.28.8/drivers/input/keyboard/atkbd.c linux-2.6.28.8/drivers/input/keyboard/atkbd.c
---- linux-2.6.28.8/drivers/input/keyboard/atkbd.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/input/keyboard/atkbd.c 2009-02-21 09:37:48.000000000 -0500
-@@ -1164,7 +1164,7 @@ static struct serio_device_id atkbd_seri
+diff -urNp linux-2.6.29.5/drivers/input/keyboard/atkbd.c linux-2.6.29.5/drivers/input/keyboard/atkbd.c
+--- linux-2.6.29.5/drivers/input/keyboard/atkbd.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/input/keyboard/atkbd.c 2009-06-12 23:57:32.000000000 -0400
+@@ -1181,7 +1181,7 @@ static struct serio_device_id atkbd_seri
.id = SERIO_ANY,
.extra = SERIO_ANY,
},
@@ -15437,9 +17774,9 @@ diff -urNp linux-2.6.28.8/drivers/input/keyboard/atkbd.c linux-2.6.28.8/drivers/
};
MODULE_DEVICE_TABLE(serio, atkbd_serio_ids);
-diff -urNp linux-2.6.28.8/drivers/input/mouse/lifebook.c linux-2.6.28.8/drivers/input/mouse/lifebook.c
---- linux-2.6.28.8/drivers/input/mouse/lifebook.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/input/mouse/lifebook.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/input/mouse/lifebook.c linux-2.6.29.5/drivers/input/mouse/lifebook.c
+--- linux-2.6.29.5/drivers/input/mouse/lifebook.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/input/mouse/lifebook.c 2009-06-12 23:57:32.000000000 -0400
@@ -110,7 +110,7 @@ static const struct dmi_system_id lifebo
DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B142"),
},
@@ -15449,9 +17786,9 @@ diff -urNp linux-2.6.28.8/drivers/input/mouse/lifebook.c linux-2.6.28.8/drivers/
};
static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse)
-diff -urNp linux-2.6.28.8/drivers/input/mouse/psmouse-base.c linux-2.6.28.8/drivers/input/mouse/psmouse-base.c
---- linux-2.6.28.8/drivers/input/mouse/psmouse-base.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/input/mouse/psmouse-base.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/input/mouse/psmouse-base.c linux-2.6.29.5/drivers/input/mouse/psmouse-base.c
+--- linux-2.6.29.5/drivers/input/mouse/psmouse-base.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/input/mouse/psmouse-base.c 2009-06-12 23:57:32.000000000 -0400
@@ -1378,7 +1378,7 @@ static struct serio_device_id psmouse_se
.id = SERIO_ANY,
.extra = SERIO_ANY,
@@ -15461,10 +17798,10 @@ diff -urNp linux-2.6.28.8/drivers/input/mouse/psmouse-base.c linux-2.6.28.8/driv
};
MODULE_DEVICE_TABLE(serio, psmouse_serio_ids);
-diff -urNp linux-2.6.28.8/drivers/input/mouse/synaptics.c linux-2.6.28.8/drivers/input/mouse/synaptics.c
---- linux-2.6.28.8/drivers/input/mouse/synaptics.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/input/mouse/synaptics.c 2009-02-21 09:37:48.000000000 -0500
-@@ -417,7 +417,7 @@ static void synaptics_process_packet(str
+diff -urNp linux-2.6.29.5/drivers/input/mouse/synaptics.c linux-2.6.29.5/drivers/input/mouse/synaptics.c
+--- linux-2.6.29.5/drivers/input/mouse/synaptics.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/input/mouse/synaptics.c 2009-06-12 23:57:32.000000000 -0400
+@@ -412,7 +412,7 @@ static void synaptics_process_packet(str
break;
case 2:
if (SYN_MODEL_PEN(priv->model_id))
@@ -15473,7 +17810,7 @@ diff -urNp linux-2.6.28.8/drivers/input/mouse/synaptics.c linux-2.6.28.8/drivers
break;
case 4 ... 15:
if (SYN_CAP_PALMDETECT(priv->capabilities))
-@@ -624,7 +624,7 @@ static const struct dmi_system_id toshib
+@@ -625,7 +625,7 @@ static const struct dmi_system_id toshib
DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE M300"),
},
},
@@ -15482,10 +17819,10 @@ diff -urNp linux-2.6.28.8/drivers/input/mouse/synaptics.c linux-2.6.28.8/drivers
};
#endif
-diff -urNp linux-2.6.28.8/drivers/input/mousedev.c linux-2.6.28.8/drivers/input/mousedev.c
---- linux-2.6.28.8/drivers/input/mousedev.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/input/mousedev.c 2009-02-21 09:37:48.000000000 -0500
-@@ -1063,7 +1063,7 @@ static struct input_handler mousedev_han
+diff -urNp linux-2.6.29.5/drivers/input/mousedev.c linux-2.6.29.5/drivers/input/mousedev.c
+--- linux-2.6.29.5/drivers/input/mousedev.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/input/mousedev.c 2009-06-12 23:57:32.000000000 -0400
+@@ -1062,7 +1062,7 @@ static struct input_handler mousedev_han
#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
static struct miscdevice psaux_mouse = {
@@ -15494,11 +17831,11 @@ diff -urNp linux-2.6.28.8/drivers/input/mousedev.c linux-2.6.28.8/drivers/input/
};
static int psaux_registered;
#endif
-diff -urNp linux-2.6.28.8/drivers/input/serio/i8042-x86ia64io.h linux-2.6.28.8/drivers/input/serio/i8042-x86ia64io.h
---- linux-2.6.28.8/drivers/input/serio/i8042-x86ia64io.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/input/serio/i8042-x86ia64io.h 2009-02-21 09:37:48.000000000 -0500
-@@ -143,7 +143,7 @@ static struct dmi_system_id __initdata i
- DMI_MATCH(DMI_PRODUCT_VERSION, "M606"),
+diff -urNp linux-2.6.29.5/drivers/input/serio/i8042-x86ia64io.h linux-2.6.29.5/drivers/input/serio/i8042-x86ia64io.h
+--- linux-2.6.29.5/drivers/input/serio/i8042-x86ia64io.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/input/serio/i8042-x86ia64io.h 2009-06-12 23:57:32.000000000 -0400
+@@ -151,7 +151,7 @@ static struct dmi_system_id __initdata i
+ DMI_MATCH(DMI_PRODUCT_VERSION, "01"),
},
},
- { }
@@ -15506,8 +17843,8 @@ diff -urNp linux-2.6.28.8/drivers/input/serio/i8042-x86ia64io.h linux-2.6.28.8/d
};
/*
-@@ -351,7 +351,7 @@ static struct dmi_system_id __initdata i
- DMI_MATCH(DMI_PRODUCT_NAME, "HEL80I"),
+@@ -366,7 +366,7 @@ static struct dmi_system_id __initdata i
+ DMI_MATCH(DMI_PRODUCT_NAME, "Vostro1510"),
},
},
- { }
@@ -15515,7 +17852,7 @@ diff -urNp linux-2.6.28.8/drivers/input/serio/i8042-x86ia64io.h linux-2.6.28.8/d
};
#ifdef CONFIG_PNP
-@@ -363,7 +363,7 @@ static struct dmi_system_id __initdata i
+@@ -378,7 +378,7 @@ static struct dmi_system_id __initdata i
DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
},
},
@@ -15524,7 +17861,7 @@ diff -urNp linux-2.6.28.8/drivers/input/serio/i8042-x86ia64io.h linux-2.6.28.8/d
};
#endif
-@@ -430,7 +430,7 @@ static struct dmi_system_id __initdata i
+@@ -445,7 +445,7 @@ static struct dmi_system_id __initdata i
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 4280"),
},
},
@@ -15533,9 +17870,9 @@ diff -urNp linux-2.6.28.8/drivers/input/serio/i8042-x86ia64io.h linux-2.6.28.8/d
};
#endif /* CONFIG_X86 */
-diff -urNp linux-2.6.28.8/drivers/input/serio/serio_raw.c linux-2.6.28.8/drivers/input/serio/serio_raw.c
---- linux-2.6.28.8/drivers/input/serio/serio_raw.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/input/serio/serio_raw.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/input/serio/serio_raw.c linux-2.6.29.5/drivers/input/serio/serio_raw.c
+--- linux-2.6.29.5/drivers/input/serio/serio_raw.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/input/serio/serio_raw.c 2009-06-12 23:57:32.000000000 -0400
@@ -378,7 +378,7 @@ static struct serio_device_id serio_raw_
.id = SERIO_ANY,
.extra = SERIO_ANY,
@@ -15545,9 +17882,9 @@ diff -urNp linux-2.6.28.8/drivers/input/serio/serio_raw.c linux-2.6.28.8/drivers
};
MODULE_DEVICE_TABLE(serio, serio_raw_serio_ids);
-diff -urNp linux-2.6.28.8/drivers/lguest/core.c linux-2.6.28.8/drivers/lguest/core.c
---- linux-2.6.28.8/drivers/lguest/core.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/lguest/core.c 2009-03-07 10:28:24.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/lguest/core.c linux-2.6.29.5/drivers/lguest/core.c
+--- linux-2.6.29.5/drivers/lguest/core.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/lguest/core.c 2009-06-12 23:57:32.000000000 -0400
@@ -80,9 +80,17 @@ static __init int map_switcher(void)
* (SWITCHER_ADDR). We might not get it in theory, but in practice
* it's worked so far. The end address needs +1 because __get_vm_area
@@ -15566,9 +17903,9 @@ diff -urNp linux-2.6.28.8/drivers/lguest/core.c linux-2.6.28.8/drivers/lguest/co
if (!switcher_vma) {
err = -ENOMEM;
printk("lguest: could not map switcher pages high\n");
-diff -urNp linux-2.6.28.8/drivers/md/bitmap.c linux-2.6.28.8/drivers/md/bitmap.c
---- linux-2.6.28.8/drivers/md/bitmap.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/md/bitmap.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/md/bitmap.c linux-2.6.29.5/drivers/md/bitmap.c
+--- linux-2.6.29.5/drivers/md/bitmap.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/md/bitmap.c 2009-06-12 23:57:32.000000000 -0400
@@ -57,7 +57,7 @@
# if DEBUG > 0
# define PRINTK(x...) printk(KERN_DEBUG x)
@@ -15578,9 +17915,21 @@ diff -urNp linux-2.6.28.8/drivers/md/bitmap.c linux-2.6.28.8/drivers/md/bitmap.c
# endif
#endif
-diff -urNp linux-2.6.28.8/drivers/mtd/devices/doc2000.c linux-2.6.28.8/drivers/mtd/devices/doc2000.c
---- linux-2.6.28.8/drivers/mtd/devices/doc2000.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/mtd/devices/doc2000.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/md/md.c linux-2.6.29.5/drivers/md/md.c
+--- linux-2.6.29.5/drivers/md/md.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/md/md.c 2009-06-12 23:57:32.000000000 -0400
+@@ -5637,7 +5637,7 @@ static int md_seq_show(struct seq_file *
+ chunk_kb ? "KB" : "B");
+ if (bitmap->file) {
+ seq_printf(seq, ", file: ");
+- seq_path(seq, &bitmap->file->f_path, " \t\n");
++ seq_path(seq, &bitmap->file->f_path, " \t\n\\");
+ }
+
+ seq_printf(seq, "\n");
+diff -urNp linux-2.6.29.5/drivers/mtd/devices/doc2000.c linux-2.6.29.5/drivers/mtd/devices/doc2000.c
+--- linux-2.6.29.5/drivers/mtd/devices/doc2000.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/mtd/devices/doc2000.c 2009-06-12 23:57:32.000000000 -0400
@@ -777,7 +777,7 @@ static int doc_write(struct mtd_info *mt
/* The ECC will not be calculated correctly if less than 512 is written */
@@ -15590,9 +17939,9 @@ diff -urNp linux-2.6.28.8/drivers/mtd/devices/doc2000.c linux-2.6.28.8/drivers/m
printk(KERN_WARNING
"ECC needs a full sector write (adr: %lx size %lx)\n",
(long) to, (long) len);
-diff -urNp linux-2.6.28.8/drivers/mtd/devices/doc2001.c linux-2.6.28.8/drivers/mtd/devices/doc2001.c
---- linux-2.6.28.8/drivers/mtd/devices/doc2001.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/mtd/devices/doc2001.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/mtd/devices/doc2001.c linux-2.6.29.5/drivers/mtd/devices/doc2001.c
+--- linux-2.6.29.5/drivers/mtd/devices/doc2001.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/mtd/devices/doc2001.c 2009-06-12 23:57:32.000000000 -0400
@@ -396,6 +396,8 @@ static int doc_read (struct mtd_info *mt
/* Don't allow read past end of device */
if (from >= this->totlen)
@@ -15602,22 +17951,10 @@ diff -urNp linux-2.6.28.8/drivers/mtd/devices/doc2001.c linux-2.6.28.8/drivers/m
/* Don't allow a single read to cross a 512-byte block boundary */
if (from + len > ((from | 0x1ff) + 1))
-diff -urNp linux-2.6.28.8/drivers/mtd/devices/slram.c linux-2.6.28.8/drivers/mtd/devices/slram.c
---- linux-2.6.28.8/drivers/mtd/devices/slram.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/mtd/devices/slram.c 2009-02-21 09:37:48.000000000 -0500
-@@ -273,7 +273,7 @@ static int parse_cmdline(char *devname,
- }
- T("slram: devname=%s, devstart=0x%lx, devlength=0x%lx\n",
- devname, devstart, devlength);
-- if ((devstart < 0) || (devlength < 0) || (devlength % SLRAM_BLK_SZ != 0)) {
-+ if (devlength % SLRAM_BLK_SZ != 0) {
- E("slram: Illegal start / length parameter.\n");
- return(-EINVAL);
- }
-diff -urNp linux-2.6.28.8/drivers/mtd/ubi/build.c linux-2.6.28.8/drivers/mtd/ubi/build.c
---- linux-2.6.28.8/drivers/mtd/ubi/build.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/mtd/ubi/build.c 2009-02-21 09:37:48.000000000 -0500
-@@ -1104,7 +1104,7 @@ static int __init bytes_str_to_int(const
+diff -urNp linux-2.6.29.5/drivers/mtd/ubi/build.c linux-2.6.29.5/drivers/mtd/ubi/build.c
+--- linux-2.6.29.5/drivers/mtd/ubi/build.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/mtd/ubi/build.c 2009-06-12 23:57:32.000000000 -0400
+@@ -1112,7 +1112,7 @@ static int __init bytes_str_to_int(const
unsigned long result;
result = simple_strtoul(str, &endp, 0);
@@ -15626,82 +17963,9 @@ diff -urNp linux-2.6.28.8/drivers/mtd/ubi/build.c linux-2.6.28.8/drivers/mtd/ubi
printk(KERN_ERR "UBI error: incorrect bytes count: \"%s\"\n",
str);
return -EINVAL;
-diff -urNp linux-2.6.28.8/drivers/net/eepro100.c linux-2.6.28.8/drivers/net/eepro100.c
---- linux-2.6.28.8/drivers/net/eepro100.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/net/eepro100.c 2009-02-21 09:37:48.000000000 -0500
-@@ -47,7 +47,7 @@ static int rxdmacount /* = 0 */;
- # define rx_align(skb) skb_reserve((skb), 2)
- # define RxFD_ALIGNMENT __attribute__ ((aligned (2), packed))
- #else
--# define rx_align(skb)
-+# define rx_align(skb) do {} while (0)
- # define RxFD_ALIGNMENT
- #endif
-
-@@ -2334,33 +2334,33 @@ static void __devexit eepro100_remove_on
- }
-
- static struct pci_device_id eepro100_pci_tbl[] = {
-- { PCI_VENDOR_ID_INTEL, 0x1229, PCI_ANY_ID, PCI_ANY_ID, },
-- { PCI_VENDOR_ID_INTEL, 0x1209, PCI_ANY_ID, PCI_ANY_ID, },
-- { PCI_VENDOR_ID_INTEL, 0x1029, PCI_ANY_ID, PCI_ANY_ID, },
-- { PCI_VENDOR_ID_INTEL, 0x1030, PCI_ANY_ID, PCI_ANY_ID, },
-- { PCI_VENDOR_ID_INTEL, 0x1031, PCI_ANY_ID, PCI_ANY_ID, },
-- { PCI_VENDOR_ID_INTEL, 0x1032, PCI_ANY_ID, PCI_ANY_ID, },
-- { PCI_VENDOR_ID_INTEL, 0x1033, PCI_ANY_ID, PCI_ANY_ID, },
-- { PCI_VENDOR_ID_INTEL, 0x1034, PCI_ANY_ID, PCI_ANY_ID, },
-- { PCI_VENDOR_ID_INTEL, 0x1035, PCI_ANY_ID, PCI_ANY_ID, },
-- { PCI_VENDOR_ID_INTEL, 0x1036, PCI_ANY_ID, PCI_ANY_ID, },
-- { PCI_VENDOR_ID_INTEL, 0x1037, PCI_ANY_ID, PCI_ANY_ID, },
-- { PCI_VENDOR_ID_INTEL, 0x1038, PCI_ANY_ID, PCI_ANY_ID, },
-- { PCI_VENDOR_ID_INTEL, 0x1039, PCI_ANY_ID, PCI_ANY_ID, },
-- { PCI_VENDOR_ID_INTEL, 0x103A, PCI_ANY_ID, PCI_ANY_ID, },
-- { PCI_VENDOR_ID_INTEL, 0x103B, PCI_ANY_ID, PCI_ANY_ID, },
-- { PCI_VENDOR_ID_INTEL, 0x103C, PCI_ANY_ID, PCI_ANY_ID, },
-- { PCI_VENDOR_ID_INTEL, 0x103D, PCI_ANY_ID, PCI_ANY_ID, },
-- { PCI_VENDOR_ID_INTEL, 0x103E, PCI_ANY_ID, PCI_ANY_ID, },
-- { PCI_VENDOR_ID_INTEL, 0x1050, PCI_ANY_ID, PCI_ANY_ID, },
-- { PCI_VENDOR_ID_INTEL, 0x1059, PCI_ANY_ID, PCI_ANY_ID, },
-- { PCI_VENDOR_ID_INTEL, 0x1227, PCI_ANY_ID, PCI_ANY_ID, },
-- { PCI_VENDOR_ID_INTEL, 0x2449, PCI_ANY_ID, PCI_ANY_ID, },
-- { PCI_VENDOR_ID_INTEL, 0x2459, PCI_ANY_ID, PCI_ANY_ID, },
-- { PCI_VENDOR_ID_INTEL, 0x245D, PCI_ANY_ID, PCI_ANY_ID, },
-- { PCI_VENDOR_ID_INTEL, 0x5200, PCI_ANY_ID, PCI_ANY_ID, },
-- { PCI_VENDOR_ID_INTEL, 0x5201, PCI_ANY_ID, PCI_ANY_ID, },
-- { 0,}
-+ { PCI_VENDOR_ID_INTEL, 0x1229, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-+ { PCI_VENDOR_ID_INTEL, 0x1209, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-+ { PCI_VENDOR_ID_INTEL, 0x1029, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-+ { PCI_VENDOR_ID_INTEL, 0x1030, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-+ { PCI_VENDOR_ID_INTEL, 0x1031, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-+ { PCI_VENDOR_ID_INTEL, 0x1032, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-+ { PCI_VENDOR_ID_INTEL, 0x1033, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-+ { PCI_VENDOR_ID_INTEL, 0x1034, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-+ { PCI_VENDOR_ID_INTEL, 0x1035, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-+ { PCI_VENDOR_ID_INTEL, 0x1036, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-+ { PCI_VENDOR_ID_INTEL, 0x1037, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-+ { PCI_VENDOR_ID_INTEL, 0x1038, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-+ { PCI_VENDOR_ID_INTEL, 0x1039, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-+ { PCI_VENDOR_ID_INTEL, 0x103A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-+ { PCI_VENDOR_ID_INTEL, 0x103B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-+ { PCI_VENDOR_ID_INTEL, 0x103C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-+ { PCI_VENDOR_ID_INTEL, 0x103D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-+ { PCI_VENDOR_ID_INTEL, 0x103E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-+ { PCI_VENDOR_ID_INTEL, 0x1050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-+ { PCI_VENDOR_ID_INTEL, 0x1059, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-+ { PCI_VENDOR_ID_INTEL, 0x1227, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-+ { PCI_VENDOR_ID_INTEL, 0x2449, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-+ { PCI_VENDOR_ID_INTEL, 0x2459, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-+ { PCI_VENDOR_ID_INTEL, 0x245D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-+ { PCI_VENDOR_ID_INTEL, 0x5200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-+ { PCI_VENDOR_ID_INTEL, 0x5201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-+ { 0, 0, 0, 0, 0, 0, 0 }
- };
- MODULE_DEVICE_TABLE(pci, eepro100_pci_tbl);
-
-diff -urNp linux-2.6.28.8/drivers/net/irda/vlsi_ir.c linux-2.6.28.8/drivers/net/irda/vlsi_ir.c
---- linux-2.6.28.8/drivers/net/irda/vlsi_ir.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/net/irda/vlsi_ir.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/net/irda/vlsi_ir.c linux-2.6.29.5/drivers/net/irda/vlsi_ir.c
+--- linux-2.6.29.5/drivers/net/irda/vlsi_ir.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/net/irda/vlsi_ir.c 2009-06-12 23:57:32.000000000 -0400
@@ -906,13 +906,12 @@ static int vlsi_hard_start_xmit(struct s
/* no race - tx-ring already empty */
vlsi_set_baud(idev, iobase);
@@ -15718,9 +17982,9 @@ diff -urNp linux-2.6.28.8/drivers/net/irda/vlsi_ir.c linux-2.6.28.8/drivers/net/
spin_unlock_irqrestore(&idev->lock, flags);
dev_kfree_skb_any(skb);
return 0;
-diff -urNp linux-2.6.28.8/drivers/net/pcnet32.c linux-2.6.28.8/drivers/net/pcnet32.c
---- linux-2.6.28.8/drivers/net/pcnet32.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/net/pcnet32.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/net/pcnet32.c linux-2.6.29.5/drivers/net/pcnet32.c
+--- linux-2.6.29.5/drivers/net/pcnet32.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/net/pcnet32.c 2009-06-12 23:57:32.000000000 -0400
@@ -78,7 +78,7 @@ static int cards_found;
/*
* VLB I/O addresses
@@ -15730,10 +17994,10 @@ diff -urNp linux-2.6.28.8/drivers/net/pcnet32.c linux-2.6.28.8/drivers/net/pcnet
{ 0x300, 0x320, 0x340, 0x360, 0 };
static int pcnet32_debug = 0;
-diff -urNp linux-2.6.28.8/drivers/net/tg3.h linux-2.6.28.8/drivers/net/tg3.h
---- linux-2.6.28.8/drivers/net/tg3.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/net/tg3.h 2009-02-21 09:37:48.000000000 -0500
-@@ -102,6 +102,7 @@
+diff -urNp linux-2.6.29.5/drivers/net/tg3.h linux-2.6.29.5/drivers/net/tg3.h
+--- linux-2.6.29.5/drivers/net/tg3.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/net/tg3.h 2009-06-12 23:57:32.000000000 -0400
+@@ -89,6 +89,7 @@
#define CHIPREV_ID_5750_A0 0x4000
#define CHIPREV_ID_5750_A1 0x4001
#define CHIPREV_ID_5750_A3 0x4003
@@ -15741,21 +18005,89 @@ diff -urNp linux-2.6.28.8/drivers/net/tg3.h linux-2.6.28.8/drivers/net/tg3.h
#define CHIPREV_ID_5750_C2 0x4202
#define CHIPREV_ID_5752_A0_HW 0x5000
#define CHIPREV_ID_5752_A0 0x6000
-diff -urNp linux-2.6.28.8/drivers/net/wireless/iwlwifi/iwl3945-base.c linux-2.6.28.8/drivers/net/wireless/iwlwifi/iwl3945-base.c
---- linux-2.6.28.8/drivers/net/wireless/iwlwifi/iwl3945-base.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/net/wireless/iwlwifi/iwl3945-base.c 2009-02-21 09:37:48.000000000 -0500
-@@ -785,7 +785,7 @@ static int iwl3945_send_cmd_sync(struct
- IWL_ERROR("Error: Response NULL in '%s'\n",
- get_cmd_string(cmd->id));
- ret = -EIO;
-- goto out;
-+ goto cancel;
+diff -urNp linux-2.6.29.5/drivers/oprofile/buffer_sync.c linux-2.6.29.5/drivers/oprofile/buffer_sync.c
+--- linux-2.6.29.5/drivers/oprofile/buffer_sync.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/oprofile/buffer_sync.c 2009-06-12 23:57:32.000000000 -0400
+@@ -335,7 +335,7 @@ static void add_data(struct op_entry *en
+ if (cookie == NO_COOKIE)
+ offset = pc;
+ if (cookie == INVALID_COOKIE) {
+- atomic_inc(&oprofile_stats.sample_lost_no_mapping);
++ atomic_inc_unchecked(&oprofile_stats.sample_lost_no_mapping);
+ offset = pc;
+ }
+ if (cookie != last_cookie) {
+@@ -379,14 +379,14 @@ add_sample(struct mm_struct *mm, struct
+ /* add userspace sample */
+
+ if (!mm) {
+- atomic_inc(&oprofile_stats.sample_lost_no_mm);
++ atomic_inc_unchecked(&oprofile_stats.sample_lost_no_mm);
+ return 0;
}
- ret = 0;
-diff -urNp linux-2.6.28.8/drivers/pci/hotplug/cpqphp_nvram.c linux-2.6.28.8/drivers/pci/hotplug/cpqphp_nvram.c
---- linux-2.6.28.8/drivers/pci/hotplug/cpqphp_nvram.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/pci/hotplug/cpqphp_nvram.c 2009-02-21 09:37:48.000000000 -0500
+ cookie = lookup_dcookie(mm, s->eip, &offset);
+
+ if (cookie == INVALID_COOKIE) {
+- atomic_inc(&oprofile_stats.sample_lost_no_mapping);
++ atomic_inc_unchecked(&oprofile_stats.sample_lost_no_mapping);
+ return 0;
+ }
+
+@@ -555,7 +555,7 @@ void sync_buffer(int cpu)
+ /* ignore backtraces if failed to add a sample */
+ if (state == sb_bt_start) {
+ state = sb_bt_ignore;
+- atomic_inc(&oprofile_stats.bt_lost_no_mapping);
++ atomic_inc_unchecked(&oprofile_stats.bt_lost_no_mapping);
+ }
+ }
+ release_mm(mm);
+diff -urNp linux-2.6.29.5/drivers/oprofile/event_buffer.c linux-2.6.29.5/drivers/oprofile/event_buffer.c
+--- linux-2.6.29.5/drivers/oprofile/event_buffer.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/oprofile/event_buffer.c 2009-06-12 23:57:32.000000000 -0400
+@@ -42,7 +42,7 @@ static atomic_t buffer_ready = ATOMIC_IN
+ void add_event_entry(unsigned long value)
+ {
+ if (buffer_pos == buffer_size) {
+- atomic_inc(&oprofile_stats.event_lost_overflow);
++ atomic_inc_unchecked(&oprofile_stats.event_lost_overflow);
+ return;
+ }
+
+diff -urNp linux-2.6.29.5/drivers/oprofile/oprofilefs.c linux-2.6.29.5/drivers/oprofile/oprofilefs.c
+--- linux-2.6.29.5/drivers/oprofile/oprofilefs.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/oprofile/oprofilefs.c 2009-06-12 23:57:32.000000000 -0400
+@@ -187,7 +187,7 @@ static const struct file_operations atom
+
+
+ int oprofilefs_create_ro_atomic(struct super_block *sb, struct dentry *root,
+- char const *name, atomic_t *val)
++ char const *name, atomic_unchecked_t *val)
+ {
+ struct dentry *d = __oprofilefs_create_file(sb, root, name,
+ &atomic_ro_fops, 0444);
+diff -urNp linux-2.6.29.5/drivers/oprofile/oprofile_stats.h linux-2.6.29.5/drivers/oprofile/oprofile_stats.h
+--- linux-2.6.29.5/drivers/oprofile/oprofile_stats.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/oprofile/oprofile_stats.h 2009-06-12 23:57:32.000000000 -0400
+@@ -13,10 +13,10 @@
+ #include <asm/atomic.h>
+
+ struct oprofile_stat_struct {
+- atomic_t sample_lost_no_mm;
+- atomic_t sample_lost_no_mapping;
+- atomic_t bt_lost_no_mapping;
+- atomic_t event_lost_overflow;
++ atomic_unchecked_t sample_lost_no_mm;
++ atomic_unchecked_t sample_lost_no_mapping;
++ atomic_unchecked_t bt_lost_no_mapping;
++ atomic_unchecked_t event_lost_overflow;
+ };
+
+ extern struct oprofile_stat_struct oprofile_stats;
+diff -urNp linux-2.6.29.5/drivers/pci/hotplug/cpqphp_nvram.c linux-2.6.29.5/drivers/pci/hotplug/cpqphp_nvram.c
+--- linux-2.6.29.5/drivers/pci/hotplug/cpqphp_nvram.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/pci/hotplug/cpqphp_nvram.c 2009-06-12 23:57:32.000000000 -0400
@@ -425,9 +425,13 @@ static u32 store_HRT (void __iomem *rom_
void compaq_nvram_init (void __iomem *rom_start)
@@ -15770,9 +18102,9 @@ diff -urNp linux-2.6.28.8/drivers/pci/hotplug/cpqphp_nvram.c linux-2.6.28.8/driv
dbg("int15 entry = %p\n", compaq_int15_entry_point);
/* initialize our int15 lock */
-diff -urNp linux-2.6.28.8/drivers/pci/pcie/aer/aerdrv.c linux-2.6.28.8/drivers/pci/pcie/aer/aerdrv.c
---- linux-2.6.28.8/drivers/pci/pcie/aer/aerdrv.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/pci/pcie/aer/aerdrv.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/pci/pcie/aer/aerdrv.c linux-2.6.29.5/drivers/pci/pcie/aer/aerdrv.c
+--- linux-2.6.29.5/drivers/pci/pcie/aer/aerdrv.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/pci/pcie/aer/aerdrv.c 2009-06-12 23:57:32.000000000 -0400
@@ -59,7 +59,7 @@ static struct pcie_port_service_id aer_i
.port_type = PCIE_RC_PORT,
.service_type = PCIE_PORT_SERVICE_AER,
@@ -15782,10 +18114,10 @@ diff -urNp linux-2.6.28.8/drivers/pci/pcie/aer/aerdrv.c linux-2.6.28.8/drivers/p
};
static struct pci_error_handlers aer_error_handlers = {
-diff -urNp linux-2.6.28.8/drivers/pci/pcie/aer/aerdrv_core.c linux-2.6.28.8/drivers/pci/pcie/aer/aerdrv_core.c
---- linux-2.6.28.8/drivers/pci/pcie/aer/aerdrv_core.c 2009-03-07 10:24:49.000000000 -0500
-+++ linux-2.6.28.8/drivers/pci/pcie/aer/aerdrv_core.c 2009-03-07 10:29:51.000000000 -0500
-@@ -667,7 +667,7 @@ static void aer_isr_one_error(struct pci
+diff -urNp linux-2.6.29.5/drivers/pci/pcie/aer/aerdrv_core.c linux-2.6.29.5/drivers/pci/pcie/aer/aerdrv_core.c
+--- linux-2.6.29.5/drivers/pci/pcie/aer/aerdrv_core.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/pci/pcie/aer/aerdrv_core.c 2009-06-12 23:57:32.000000000 -0400
+@@ -670,7 +670,7 @@ static void aer_isr_one_error(struct pci
struct aer_err_source *e_src)
{
struct device *s_device;
@@ -15794,10 +18126,10 @@ diff -urNp linux-2.6.28.8/drivers/pci/pcie/aer/aerdrv_core.c linux-2.6.28.8/driv
int i;
u16 id;
-diff -urNp linux-2.6.28.8/drivers/pci/pcie/portdrv_pci.c linux-2.6.28.8/drivers/pci/pcie/portdrv_pci.c
---- linux-2.6.28.8/drivers/pci/pcie/portdrv_pci.c 2009-03-07 10:24:49.000000000 -0500
-+++ linux-2.6.28.8/drivers/pci/pcie/portdrv_pci.c 2009-03-07 10:29:51.000000000 -0500
-@@ -263,7 +263,7 @@ static void pcie_portdrv_err_resume(stru
+diff -urNp linux-2.6.29.5/drivers/pci/pcie/portdrv_pci.c linux-2.6.29.5/drivers/pci/pcie/portdrv_pci.c
+--- linux-2.6.29.5/drivers/pci/pcie/portdrv_pci.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/pci/pcie/portdrv_pci.c 2009-06-12 23:57:32.000000000 -0400
+@@ -260,7 +260,7 @@ static void pcie_portdrv_err_resume(stru
static const struct pci_device_id port_pci_ids[] = { {
/* handle any PCI-Express port */
PCI_DEVICE_CLASS(((PCI_CLASS_BRIDGE_PCI << 8) | 0x00), ~0),
@@ -15806,10 +18138,10 @@ diff -urNp linux-2.6.28.8/drivers/pci/pcie/portdrv_pci.c linux-2.6.28.8/drivers/
};
MODULE_DEVICE_TABLE(pci, port_pci_ids);
-diff -urNp linux-2.6.28.8/drivers/pci/proc.c linux-2.6.28.8/drivers/pci/proc.c
---- linux-2.6.28.8/drivers/pci/proc.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/pci/proc.c 2009-02-21 09:37:48.000000000 -0500
-@@ -470,7 +470,16 @@ static const struct file_operations proc
+diff -urNp linux-2.6.29.5/drivers/pci/proc.c linux-2.6.29.5/drivers/pci/proc.c
+--- linux-2.6.29.5/drivers/pci/proc.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/pci/proc.c 2009-06-12 23:57:32.000000000 -0400
+@@ -480,7 +480,16 @@ static const struct file_operations proc
static int __init pci_proc_init(void)
{
struct pci_dev *dev = NULL;
@@ -15826,9 +18158,9 @@ diff -urNp linux-2.6.28.8/drivers/pci/proc.c linux-2.6.28.8/drivers/pci/proc.c
proc_create("devices", 0, proc_bus_pci_dir,
&proc_bus_pci_dev_operations);
proc_initialized = 1;
-diff -urNp linux-2.6.28.8/drivers/pcmcia/ti113x.h linux-2.6.28.8/drivers/pcmcia/ti113x.h
---- linux-2.6.28.8/drivers/pcmcia/ti113x.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/pcmcia/ti113x.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/pcmcia/ti113x.h linux-2.6.29.5/drivers/pcmcia/ti113x.h
+--- linux-2.6.29.5/drivers/pcmcia/ti113x.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/pcmcia/ti113x.h 2009-06-12 23:57:32.000000000 -0400
@@ -903,7 +903,7 @@ static struct pci_device_id ene_tune_tbl
DEVID(PCI_VENDOR_ID_MOTOROLA, 0x3410, 0xECC0, PCI_ANY_ID,
ENE_TEST_C9_TLTENABLE | ENE_TEST_C9_PFENABLE, ENE_TEST_C9_TLTENABLE),
@@ -15838,9 +18170,9 @@ diff -urNp linux-2.6.28.8/drivers/pcmcia/ti113x.h linux-2.6.28.8/drivers/pcmcia/
};
static void ene_tune_bridge(struct pcmcia_socket *sock, struct pci_bus *bus)
-diff -urNp linux-2.6.28.8/drivers/pcmcia/yenta_socket.c linux-2.6.28.8/drivers/pcmcia/yenta_socket.c
---- linux-2.6.28.8/drivers/pcmcia/yenta_socket.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/pcmcia/yenta_socket.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/pcmcia/yenta_socket.c linux-2.6.29.5/drivers/pcmcia/yenta_socket.c
+--- linux-2.6.29.5/drivers/pcmcia/yenta_socket.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/pcmcia/yenta_socket.c 2009-06-12 23:57:32.000000000 -0400
@@ -1366,7 +1366,7 @@ static struct pci_device_id yenta_table
/* match any cardbus bridge */
@@ -15850,9 +18182,9 @@ diff -urNp linux-2.6.28.8/drivers/pcmcia/yenta_socket.c linux-2.6.28.8/drivers/p
};
MODULE_DEVICE_TABLE(pci, yenta_table);
-diff -urNp linux-2.6.28.8/drivers/pnp/pnpbios/bioscalls.c linux-2.6.28.8/drivers/pnp/pnpbios/bioscalls.c
---- linux-2.6.28.8/drivers/pnp/pnpbios/bioscalls.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/pnp/pnpbios/bioscalls.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/pnp/pnpbios/bioscalls.c linux-2.6.29.5/drivers/pnp/pnpbios/bioscalls.c
+--- linux-2.6.29.5/drivers/pnp/pnpbios/bioscalls.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/pnp/pnpbios/bioscalls.c 2009-06-12 23:57:32.000000000 -0400
@@ -60,7 +60,7 @@ set_base(gdt[(selname) >> 3], (u32)(addr
set_limit(gdt[(selname) >> 3], size); \
} while(0)
@@ -15945,9 +18277,9 @@ diff -urNp linux-2.6.28.8/drivers/pnp/pnpbios/bioscalls.c linux-2.6.28.8/drivers
+#endif
+
}
-diff -urNp linux-2.6.28.8/drivers/pnp/quirks.c linux-2.6.28.8/drivers/pnp/quirks.c
---- linux-2.6.28.8/drivers/pnp/quirks.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/pnp/quirks.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/pnp/quirks.c linux-2.6.29.5/drivers/pnp/quirks.c
+--- linux-2.6.29.5/drivers/pnp/quirks.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/pnp/quirks.c 2009-06-12 23:57:32.000000000 -0400
@@ -327,7 +327,7 @@ static struct pnp_fixup pnp_fixups[] = {
/* PnP resources that might overlap PCI BARs */
{"PNP0c01", quirk_system_pci_resources},
@@ -15957,9 +18289,9 @@ diff -urNp linux-2.6.28.8/drivers/pnp/quirks.c linux-2.6.28.8/drivers/pnp/quirks
};
void pnp_fixup_device(struct pnp_dev *dev)
-diff -urNp linux-2.6.28.8/drivers/pnp/resource.c linux-2.6.28.8/drivers/pnp/resource.c
---- linux-2.6.28.8/drivers/pnp/resource.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/pnp/resource.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/pnp/resource.c linux-2.6.29.5/drivers/pnp/resource.c
+--- linux-2.6.29.5/drivers/pnp/resource.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/pnp/resource.c 2009-06-12 23:57:32.000000000 -0400
@@ -355,7 +355,7 @@ int pnp_check_irq(struct pnp_dev *dev, s
return 1;
@@ -15978,9 +18310,129 @@ diff -urNp linux-2.6.28.8/drivers/pnp/resource.c linux-2.6.28.8/drivers/pnp/reso
return 0;
/* check if the resource is reserved */
-diff -urNp linux-2.6.28.8/drivers/scsi/scsi_logging.h linux-2.6.28.8/drivers/scsi/scsi_logging.h
---- linux-2.6.28.8/drivers/scsi/scsi_logging.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/scsi/scsi_logging.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/scsi/libfc/fc_exch.c linux-2.6.29.5/drivers/scsi/libfc/fc_exch.c
+--- linux-2.6.29.5/drivers/scsi/libfc/fc_exch.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/scsi/libfc/fc_exch.c 2009-06-12 23:57:32.000000000 -0400
+@@ -84,12 +84,12 @@ struct fc_exch_mgr {
+ * all together if not used XXX
+ */
+ struct {
+- atomic_t no_free_exch;
+- atomic_t no_free_exch_xid;
+- atomic_t xid_not_found;
+- atomic_t xid_busy;
+- atomic_t seq_not_found;
+- atomic_t non_bls_resp;
++ atomic_unchecked_t no_free_exch;
++ atomic_unchecked_t no_free_exch_xid;
++ atomic_unchecked_t xid_not_found;
++ atomic_unchecked_t xid_busy;
++ atomic_unchecked_t seq_not_found;
++ atomic_unchecked_t non_bls_resp;
+ } stats;
+ struct fc_exch **exches; /* for exch pointers indexed by xid */
+ };
+@@ -534,7 +534,7 @@ struct fc_exch *fc_exch_alloc(struct fc_
+ /* allocate memory for exchange */
+ ep = mempool_alloc(mp->ep_pool, GFP_ATOMIC);
+ if (!ep) {
+- atomic_inc(&mp->stats.no_free_exch);
++ atomic_inc_unchecked(&mp->stats.no_free_exch);
+ goto out;
+ }
+ memset(ep, 0, sizeof(*ep));
+@@ -579,7 +579,7 @@ out:
+ return ep;
+ err:
+ spin_unlock_bh(&mp->em_lock);
+- atomic_inc(&mp->stats.no_free_exch_xid);
++ atomic_inc_unchecked(&mp->stats.no_free_exch_xid);
+ mempool_free(ep, mp->ep_pool);
+ return NULL;
+ }
+@@ -682,7 +682,7 @@ static enum fc_pf_rjt_reason fc_seq_look
+ xid = ntohs(fh->fh_ox_id); /* we originated exch */
+ ep = fc_exch_find(mp, xid);
+ if (!ep) {
+- atomic_inc(&mp->stats.xid_not_found);
++ atomic_inc_unchecked(&mp->stats.xid_not_found);
+ reject = FC_RJT_OX_ID;
+ goto out;
+ }
+@@ -712,7 +712,7 @@ static enum fc_pf_rjt_reason fc_seq_look
+ ep = fc_exch_find(mp, xid);
+ if ((f_ctl & FC_FC_FIRST_SEQ) && fc_sof_is_init(fr_sof(fp))) {
+ if (ep) {
+- atomic_inc(&mp->stats.xid_busy);
++ atomic_inc_unchecked(&mp->stats.xid_busy);
+ reject = FC_RJT_RX_ID;
+ goto rel;
+ }
+@@ -723,7 +723,7 @@ static enum fc_pf_rjt_reason fc_seq_look
+ }
+ xid = ep->xid; /* get our XID */
+ } else if (!ep) {
+- atomic_inc(&mp->stats.xid_not_found);
++ atomic_inc_unchecked(&mp->stats.xid_not_found);
+ reject = FC_RJT_RX_ID; /* XID not found */
+ goto out;
+ }
+@@ -744,7 +744,7 @@ static enum fc_pf_rjt_reason fc_seq_look
+ } else {
+ sp = &ep->seq;
+ if (sp->id != fh->fh_seq_id) {
+- atomic_inc(&mp->stats.seq_not_found);
++ atomic_inc_unchecked(&mp->stats.seq_not_found);
+ reject = FC_RJT_SEQ_ID; /* sequence/exch should exist */
+ goto rel;
+ }
+@@ -1156,18 +1156,18 @@ static void fc_exch_recv_seq_resp(struct
+
+ ep = fc_exch_find(mp, ntohs(fh->fh_ox_id));
+ if (!ep) {
+- atomic_inc(&mp->stats.xid_not_found);
++ atomic_inc_unchecked(&mp->stats.xid_not_found);
+ goto out;
+ }
+ if (ep->rxid == FC_XID_UNKNOWN)
+ ep->rxid = ntohs(fh->fh_rx_id);
+ if (ep->sid != 0 && ep->sid != ntoh24(fh->fh_d_id)) {
+- atomic_inc(&mp->stats.xid_not_found);
++ atomic_inc_unchecked(&mp->stats.xid_not_found);
+ goto rel;
+ }
+ if (ep->did != ntoh24(fh->fh_s_id) &&
+ ep->did != FC_FID_FLOGI) {
+- atomic_inc(&mp->stats.xid_not_found);
++ atomic_inc_unchecked(&mp->stats.xid_not_found);
+ goto rel;
+ }
+ sof = fr_sof(fp);
+@@ -1178,7 +1178,7 @@ static void fc_exch_recv_seq_resp(struct
+ } else {
+ sp = &ep->seq;
+ if (sp->id != fh->fh_seq_id) {
+- atomic_inc(&mp->stats.seq_not_found);
++ atomic_inc_unchecked(&mp->stats.seq_not_found);
+ goto rel;
+ }
+ }
+@@ -1237,10 +1237,10 @@ static void fc_exch_recv_resp(struct fc_
+
+ sp = fc_seq_lookup_orig(mp, fp); /* doesn't hold sequence */
+ if (!sp) {
+- atomic_inc(&mp->stats.xid_not_found);
++ atomic_inc_unchecked(&mp->stats.xid_not_found);
+ FC_DEBUG_EXCH("seq lookup failed\n");
+ } else {
+- atomic_inc(&mp->stats.non_bls_resp);
++ atomic_inc_unchecked(&mp->stats.non_bls_resp);
+ FC_DEBUG_EXCH("non-BLS response to sequence");
+ }
+ fc_frame_free(fp);
+diff -urNp linux-2.6.29.5/drivers/scsi/scsi_logging.h linux-2.6.29.5/drivers/scsi/scsi_logging.h
+--- linux-2.6.29.5/drivers/scsi/scsi_logging.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/scsi/scsi_logging.h 2009-06-12 23:57:32.000000000 -0400
@@ -51,7 +51,7 @@ do { \
} while (0); \
} while (0)
@@ -15990,10 +18442,10 @@ diff -urNp linux-2.6.28.8/drivers/scsi/scsi_logging.h linux-2.6.28.8/drivers/scs
#endif /* CONFIG_SCSI_LOGGING */
/*
-diff -urNp linux-2.6.28.8/drivers/serial/8250_pci.c linux-2.6.28.8/drivers/serial/8250_pci.c
---- linux-2.6.28.8/drivers/serial/8250_pci.c 2009-03-07 10:24:49.000000000 -0500
-+++ linux-2.6.28.8/drivers/serial/8250_pci.c 2009-03-07 10:29:51.000000000 -0500
-@@ -3138,7 +3138,7 @@ static struct pci_device_id serial_pci_t
+diff -urNp linux-2.6.29.5/drivers/serial/8250_pci.c linux-2.6.29.5/drivers/serial/8250_pci.c
+--- linux-2.6.29.5/drivers/serial/8250_pci.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/serial/8250_pci.c 2009-06-12 23:57:32.000000000 -0400
+@@ -3162,7 +3162,7 @@ static struct pci_device_id serial_pci_t
PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_COMMUNICATION_MULTISERIAL << 8,
0xffff00, pbn_default },
@@ -16002,10 +18454,75 @@ diff -urNp linux-2.6.28.8/drivers/serial/8250_pci.c linux-2.6.28.8/drivers/seria
};
static struct pci_driver serial_pci_driver = {
-diff -urNp linux-2.6.28.8/drivers/usb/class/cdc-acm.c linux-2.6.28.8/drivers/usb/class/cdc-acm.c
---- linux-2.6.28.8/drivers/usb/class/cdc-acm.c 2009-03-07 10:24:49.000000000 -0500
-+++ linux-2.6.28.8/drivers/usb/class/cdc-acm.c 2009-03-07 10:29:51.000000000 -0500
-@@ -1388,7 +1388,7 @@ static struct usb_device_id acm_ids[] =
+diff -urNp linux-2.6.29.5/drivers/usb/atm/usbatm.c linux-2.6.29.5/drivers/usb/atm/usbatm.c
+--- linux-2.6.29.5/drivers/usb/atm/usbatm.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/usb/atm/usbatm.c 2009-06-12 23:57:32.000000000 -0400
+@@ -333,7 +333,7 @@ static void usbatm_extract_one_cell(stru
+ if (printk_ratelimit())
+ atm_warn(instance, "%s: OAM not supported (vpi %d, vci %d)!\n",
+ __func__, vpi, vci);
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ return;
+ }
+
+@@ -361,7 +361,7 @@ static void usbatm_extract_one_cell(stru
+ if (length > ATM_MAX_AAL5_PDU) {
+ atm_rldbg(instance, "%s: bogus length %u (vcc: 0x%p)!\n",
+ __func__, length, vcc);
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ goto out;
+ }
+
+@@ -370,14 +370,14 @@ static void usbatm_extract_one_cell(stru
+ if (sarb->len < pdu_length) {
+ atm_rldbg(instance, "%s: bogus pdu_length %u (sarb->len: %u, vcc: 0x%p)!\n",
+ __func__, pdu_length, sarb->len, vcc);
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ goto out;
+ }
+
+ if (crc32_be(~0, skb_tail_pointer(sarb) - pdu_length, pdu_length) != 0xc704dd7b) {
+ atm_rldbg(instance, "%s: packet failed crc check (vcc: 0x%p)!\n",
+ __func__, vcc);
+- atomic_inc(&vcc->stats->rx_err);
++ atomic_inc_unchecked(&vcc->stats->rx_err);
+ goto out;
+ }
+
+@@ -387,7 +387,7 @@ static void usbatm_extract_one_cell(stru
+ if (printk_ratelimit())
+ atm_err(instance, "%s: no memory for skb (length: %u)!\n",
+ __func__, length);
+- atomic_inc(&vcc->stats->rx_drop);
++ atomic_inc_unchecked(&vcc->stats->rx_drop);
+ goto out;
+ }
+
+@@ -412,7 +412,7 @@ static void usbatm_extract_one_cell(stru
+
+ vcc->push(vcc, skb);
+
+- atomic_inc(&vcc->stats->rx);
++ atomic_inc_unchecked(&vcc->stats->rx);
+ out:
+ skb_trim(sarb, 0);
+ }
+@@ -616,7 +616,7 @@ static void usbatm_tx_process(unsigned l
+ struct atm_vcc *vcc = UDSL_SKB(skb)->atm.vcc;
+
+ usbatm_pop(vcc, skb);
+- atomic_inc(&vcc->stats->tx);
++ atomic_inc_unchecked(&vcc->stats->tx);
+
+ skb = skb_dequeue(&instance->sndqueue);
+ }
+diff -urNp linux-2.6.29.5/drivers/usb/class/cdc-acm.c linux-2.6.29.5/drivers/usb/class/cdc-acm.c
+--- linux-2.6.29.5/drivers/usb/class/cdc-acm.c 2009-06-12 23:55:00.000000000 -0400
++++ linux-2.6.29.5/drivers/usb/class/cdc-acm.c 2009-06-12 23:57:32.000000000 -0400
+@@ -1397,7 +1397,7 @@ static struct usb_device_id acm_ids[] =
USB_CDC_ACM_PROTO_AT_CDMA) },
/* NOTE: COMM/ACM/0xff is likely MSFT RNDIS ... NOT a modem!! */
@@ -16014,19 +18531,19 @@ diff -urNp linux-2.6.28.8/drivers/usb/class/cdc-acm.c linux-2.6.28.8/drivers/usb
};
MODULE_DEVICE_TABLE (usb, acm_ids);
-diff -urNp linux-2.6.28.8/drivers/usb/class/usblp.c linux-2.6.28.8/drivers/usb/class/usblp.c
---- linux-2.6.28.8/drivers/usb/class/usblp.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/usb/class/usblp.c 2009-02-21 09:37:48.000000000 -0500
-@@ -227,7 +227,7 @@ static const struct quirk_printer_struct
- { 0x0409, 0xf1be, USBLP_QUIRK_BIDIR }, /* NEC Picty800 (HP OEM) */
+diff -urNp linux-2.6.29.5/drivers/usb/class/usblp.c linux-2.6.29.5/drivers/usb/class/usblp.c
+--- linux-2.6.29.5/drivers/usb/class/usblp.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/usb/class/usblp.c 2009-06-12 23:57:32.000000000 -0400
+@@ -228,7 +228,7 @@ static const struct quirk_printer_struct
{ 0x0482, 0x0010, USBLP_QUIRK_BIDIR }, /* Kyocera Mita FS 820, by zut <kernel@zut.de> */
+ { 0x04f9, 0x000d, USBLP_QUIRK_BIDIR }, /* Brother Industries, Ltd HL-1440 Laser Printer */
{ 0x04b8, 0x0202, USBLP_QUIRK_BAD_CLASS }, /* Seiko Epson Receipt Printer M129C */
- { 0, 0 }
+ { 0, 0, 0 }
};
static int usblp_wwait(struct usblp *usblp, int nonblock);
-@@ -1402,7 +1402,7 @@ static struct usb_device_id usblp_ids []
+@@ -1403,7 +1403,7 @@ static struct usb_device_id usblp_ids []
{ USB_INTERFACE_INFO(7, 1, 2) },
{ USB_INTERFACE_INFO(7, 1, 3) },
{ USB_DEVICE(0x04b8, 0x0202) }, /* Seiko Epson Receipt Printer M129C */
@@ -16035,10 +18552,10 @@ diff -urNp linux-2.6.28.8/drivers/usb/class/usblp.c linux-2.6.28.8/drivers/usb/c
};
MODULE_DEVICE_TABLE (usb, usblp_ids);
-diff -urNp linux-2.6.28.8/drivers/usb/core/hub.c linux-2.6.28.8/drivers/usb/core/hub.c
---- linux-2.6.28.8/drivers/usb/core/hub.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/usb/core/hub.c 2009-02-21 09:37:48.000000000 -0500
-@@ -3194,7 +3194,7 @@ static struct usb_device_id hub_id_table
+diff -urNp linux-2.6.29.5/drivers/usb/core/hub.c linux-2.6.29.5/drivers/usb/core/hub.c
+--- linux-2.6.29.5/drivers/usb/core/hub.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/usb/core/hub.c 2009-06-12 23:57:32.000000000 -0400
+@@ -3193,7 +3193,7 @@ static struct usb_device_id hub_id_table
.bDeviceClass = USB_CLASS_HUB},
{ .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
.bInterfaceClass = USB_CLASS_HUB},
@@ -16047,10 +18564,23 @@ diff -urNp linux-2.6.28.8/drivers/usb/core/hub.c linux-2.6.28.8/drivers/usb/core
};
MODULE_DEVICE_TABLE (usb, hub_id_table);
-diff -urNp linux-2.6.28.8/drivers/usb/host/ehci-pci.c linux-2.6.28.8/drivers/usb/host/ehci-pci.c
---- linux-2.6.28.8/drivers/usb/host/ehci-pci.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/usb/host/ehci-pci.c 2009-02-21 09:37:48.000000000 -0500
-@@ -414,7 +414,7 @@ static const struct pci_device_id pci_id
+diff -urNp linux-2.6.29.5/drivers/usb/core/message.c linux-2.6.29.5/drivers/usb/core/message.c
+--- linux-2.6.29.5/drivers/usb/core/message.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/usb/core/message.c 2009-06-12 23:57:32.000000000 -0400
+@@ -866,7 +866,8 @@ char *usb_cache_string(struct usb_device
+ if (buf) {
+ len = usb_string(udev, index, buf, 256);
+ if (len > 0) {
+- smallbuf = kmalloc(++len, GFP_KERNEL);
++ ++len;
++ smallbuf = kmalloc(len, GFP_KERNEL);
+ if (!smallbuf)
+ return buf;
+ memcpy(smallbuf, buf, len);
+diff -urNp linux-2.6.29.5/drivers/usb/host/ehci-pci.c linux-2.6.29.5/drivers/usb/host/ehci-pci.c
+--- linux-2.6.29.5/drivers/usb/host/ehci-pci.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/usb/host/ehci-pci.c 2009-06-12 23:57:32.000000000 -0400
+@@ -418,7 +418,7 @@ static const struct pci_device_id pci_id
PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_EHCI, ~0),
.driver_data = (unsigned long) &ehci_pci_hc_driver,
},
@@ -16059,9 +18589,9 @@ diff -urNp linux-2.6.28.8/drivers/usb/host/ehci-pci.c linux-2.6.28.8/drivers/usb
};
MODULE_DEVICE_TABLE(pci, pci_ids);
-diff -urNp linux-2.6.28.8/drivers/usb/host/uhci-hcd.c linux-2.6.28.8/drivers/usb/host/uhci-hcd.c
---- linux-2.6.28.8/drivers/usb/host/uhci-hcd.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/usb/host/uhci-hcd.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/usb/host/uhci-hcd.c linux-2.6.29.5/drivers/usb/host/uhci-hcd.c
+--- linux-2.6.29.5/drivers/usb/host/uhci-hcd.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/usb/host/uhci-hcd.c 2009-06-12 23:57:32.000000000 -0400
@@ -927,7 +927,7 @@ static const struct pci_device_id uhci_p
/* handle any USB UHCI controller */
PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_UHCI, ~0),
@@ -16071,9 +18601,9 @@ diff -urNp linux-2.6.28.8/drivers/usb/host/uhci-hcd.c linux-2.6.28.8/drivers/usb
};
MODULE_DEVICE_TABLE(pci, uhci_pci_ids);
-diff -urNp linux-2.6.28.8/drivers/usb/storage/debug.h linux-2.6.28.8/drivers/usb/storage/debug.h
---- linux-2.6.28.8/drivers/usb/storage/debug.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/usb/storage/debug.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/usb/storage/debug.h linux-2.6.29.5/drivers/usb/storage/debug.h
+--- linux-2.6.29.5/drivers/usb/storage/debug.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/usb/storage/debug.h 2009-06-12 23:57:32.000000000 -0400
@@ -54,9 +54,9 @@ void usb_stor_show_sense( unsigned char
#define US_DEBUGPX(x...) printk( x )
#define US_DEBUG(x) x
@@ -16087,10 +18617,10 @@ diff -urNp linux-2.6.28.8/drivers/usb/storage/debug.h linux-2.6.28.8/drivers/usb
#endif
#endif
-diff -urNp linux-2.6.28.8/drivers/usb/storage/usb.c linux-2.6.28.8/drivers/usb/storage/usb.c
---- linux-2.6.28.8/drivers/usb/storage/usb.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/usb/storage/usb.c 2009-02-21 09:37:48.000000000 -0500
-@@ -139,7 +139,7 @@ static struct usb_device_id storage_usb_
+diff -urNp linux-2.6.29.5/drivers/usb/storage/usb.c linux-2.6.29.5/drivers/usb/storage/usb.c
+--- linux-2.6.29.5/drivers/usb/storage/usb.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/usb/storage/usb.c 2009-06-12 23:57:32.000000000 -0400
+@@ -141,7 +141,7 @@ static struct usb_device_id storage_usb_
#undef COMPLIANT_DEV
#undef USUAL_DEV
/* Terminating entry */
@@ -16099,7 +18629,7 @@ diff -urNp linux-2.6.28.8/drivers/usb/storage/usb.c linux-2.6.28.8/drivers/usb/s
};
MODULE_DEVICE_TABLE (usb, storage_usb_ids);
-@@ -182,7 +182,7 @@ static struct us_unusual_dev us_unusual_
+@@ -184,7 +184,7 @@ static struct us_unusual_dev us_unusual_
# undef USUAL_DEV
/* Terminating entry */
@@ -16108,10 +18638,10 @@ diff -urNp linux-2.6.28.8/drivers/usb/storage/usb.c linux-2.6.28.8/drivers/usb/s
};
-diff -urNp linux-2.6.28.8/drivers/uwb/wlp/messages.c linux-2.6.28.8/drivers/uwb/wlp/messages.c
---- linux-2.6.28.8/drivers/uwb/wlp/messages.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/uwb/wlp/messages.c 2009-02-21 09:37:48.000000000 -0500
-@@ -988,7 +988,7 @@ int wlp_parse_f0(struct wlp *wlp, struct
+diff -urNp linux-2.6.29.5/drivers/uwb/wlp/messages.c linux-2.6.29.5/drivers/uwb/wlp/messages.c
+--- linux-2.6.29.5/drivers/uwb/wlp/messages.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/uwb/wlp/messages.c 2009-06-12 23:57:32.000000000 -0400
+@@ -903,7 +903,7 @@ int wlp_parse_f0(struct wlp *wlp, struct
size_t len = skb->len;
size_t used;
ssize_t result;
@@ -16120,22 +18650,9 @@ diff -urNp linux-2.6.28.8/drivers/uwb/wlp/messages.c linux-2.6.28.8/drivers/uwb/
enum wlp_assc_error assc_err;
char enonce_buf[WLP_WSS_NONCE_STRSIZE];
char rnonce_buf[WLP_WSS_NONCE_STRSIZE];
-diff -urNp linux-2.6.28.8/drivers/video/fbcmap.c linux-2.6.28.8/drivers/video/fbcmap.c
---- linux-2.6.28.8/drivers/video/fbcmap.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/video/fbcmap.c 2009-02-21 09:37:48.000000000 -0500
-@@ -250,8 +250,7 @@ int fb_set_user_cmap(struct fb_cmap_user
- int rc, size = cmap->len * sizeof(u16);
- struct fb_cmap umap;
-
-- if (cmap->start < 0 || (!info->fbops->fb_setcolreg &&
-- !info->fbops->fb_setcmap))
-+ if (!info->fbops->fb_setcolreg && !info->fbops->fb_setcmap)
- return -EINVAL;
-
- memset(&umap, 0, sizeof(struct fb_cmap));
-diff -urNp linux-2.6.28.8/drivers/video/fbmem.c linux-2.6.28.8/drivers/video/fbmem.c
---- linux-2.6.28.8/drivers/video/fbmem.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/video/fbmem.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/video/fbmem.c linux-2.6.29.5/drivers/video/fbmem.c
+--- linux-2.6.29.5/drivers/video/fbmem.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/video/fbmem.c 2009-06-12 23:57:32.000000000 -0400
@@ -393,7 +393,7 @@ static void fb_do_show_logo(struct fb_in
image->dx += image->width + 8;
}
@@ -16154,18 +18671,18 @@ diff -urNp linux-2.6.28.8/drivers/video/fbmem.c linux-2.6.28.8/drivers/video/fbm
info->fbops->fb_imageblit(info, image);
image->dy -= image->height + 8;
}
-@@ -1090,7 +1090,7 @@ static long do_fb_ioctl(struct fb_info *
- ret = -EINVAL;
- break;
- }
-- if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX) {
-+ if (con2fb.framebuffer >= FB_MAX) {
- ret = -EINVAL;
- break;
- }
-diff -urNp linux-2.6.28.8/drivers/video/fbmon.c linux-2.6.28.8/drivers/video/fbmon.c
---- linux-2.6.28.8/drivers/video/fbmon.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/video/fbmon.c 2009-02-21 09:37:48.000000000 -0500
+@@ -1098,7 +1098,7 @@ static long do_fb_ioctl(struct fb_info *
+ return -EFAULT;
+ if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
+ return -EINVAL;
+- if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX)
++ if (con2fb.framebuffer >= FB_MAX)
+ return -EINVAL;
+ if (!registered_fb[con2fb.framebuffer])
+ request_module("fb%d", con2fb.framebuffer);
+diff -urNp linux-2.6.29.5/drivers/video/fbmon.c linux-2.6.29.5/drivers/video/fbmon.c
+--- linux-2.6.29.5/drivers/video/fbmon.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/video/fbmon.c 2009-06-12 23:57:32.000000000 -0400
@@ -45,7 +45,7 @@
#ifdef DEBUG
#define DPRINTK(fmt, args...) printk(fmt,## args)
@@ -16175,9 +18692,9 @@ diff -urNp linux-2.6.28.8/drivers/video/fbmon.c linux-2.6.28.8/drivers/video/fbm
#endif
#define FBMON_FIX_HEADER 1
-diff -urNp linux-2.6.28.8/drivers/video/i810/i810_accel.c linux-2.6.28.8/drivers/video/i810/i810_accel.c
---- linux-2.6.28.8/drivers/video/i810/i810_accel.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/video/i810/i810_accel.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/video/i810/i810_accel.c linux-2.6.29.5/drivers/video/i810/i810_accel.c
+--- linux-2.6.29.5/drivers/video/i810/i810_accel.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/video/i810/i810_accel.c 2009-06-12 23:57:32.000000000 -0400
@@ -73,6 +73,7 @@ static inline int wait_for_space(struct
}
}
@@ -16186,9 +18703,9 @@ diff -urNp linux-2.6.28.8/drivers/video/i810/i810_accel.c linux-2.6.28.8/drivers
i810_report_error(mmio);
par->dev_flags |= LOCKUP;
info->pixmap.scan_align = 1;
-diff -urNp linux-2.6.28.8/drivers/video/i810/i810_main.c linux-2.6.28.8/drivers/video/i810/i810_main.c
---- linux-2.6.28.8/drivers/video/i810/i810_main.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/video/i810/i810_main.c 2009-03-07 14:10:58.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/video/i810/i810_main.c linux-2.6.29.5/drivers/video/i810/i810_main.c
+--- linux-2.6.29.5/drivers/video/i810/i810_main.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/video/i810/i810_main.c 2009-06-12 23:57:32.000000000 -0400
@@ -120,7 +120,7 @@ static struct pci_device_id i810fb_pci_t
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_CGC,
@@ -16198,9 +18715,9 @@ diff -urNp linux-2.6.28.8/drivers/video/i810/i810_main.c linux-2.6.28.8/drivers/
};
static struct pci_driver i810fb_driver = {
-diff -urNp linux-2.6.28.8/drivers/video/modedb.c linux-2.6.28.8/drivers/video/modedb.c
---- linux-2.6.28.8/drivers/video/modedb.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/video/modedb.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/video/modedb.c linux-2.6.29.5/drivers/video/modedb.c
+--- linux-2.6.29.5/drivers/video/modedb.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/video/modedb.c 2009-06-12 23:57:32.000000000 -0400
@@ -38,232 +38,232 @@ static const struct fb_videomode modedb[
{
/* 640x400 @ 70 Hz, 31.5 kHz hsync */
@@ -16491,9 +19008,9 @@ diff -urNp linux-2.6.28.8/drivers/video/modedb.c linux-2.6.28.8/drivers/video/mo
},
};
-diff -urNp linux-2.6.28.8/drivers/video/uvesafb.c linux-2.6.28.8/drivers/video/uvesafb.c
---- linux-2.6.28.8/drivers/video/uvesafb.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/video/uvesafb.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/video/uvesafb.c linux-2.6.29.5/drivers/video/uvesafb.c
+--- linux-2.6.29.5/drivers/video/uvesafb.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/video/uvesafb.c 2009-06-12 23:57:32.000000000 -0400
@@ -18,6 +18,7 @@
#include <linux/fb.h>
#include <linux/io.h>
@@ -16571,9 +19088,9 @@ diff -urNp linux-2.6.28.8/drivers/video/uvesafb.c linux-2.6.28.8/drivers/video/u
}
framebuffer_release(info);
-diff -urNp linux-2.6.28.8/drivers/video/vesafb.c linux-2.6.28.8/drivers/video/vesafb.c
---- linux-2.6.28.8/drivers/video/vesafb.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/drivers/video/vesafb.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/drivers/video/vesafb.c linux-2.6.29.5/drivers/video/vesafb.c
+--- linux-2.6.29.5/drivers/video/vesafb.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/drivers/video/vesafb.c 2009-06-12 23:57:32.000000000 -0400
@@ -9,6 +9,7 @@
*/
@@ -16681,9 +19198,9 @@ diff -urNp linux-2.6.28.8/drivers/video/vesafb.c linux-2.6.28.8/drivers/video/ve
if (info->screen_base)
iounmap(info->screen_base);
framebuffer_release(info);
-diff -urNp linux-2.6.28.8/fs/9p/vfs_inode.c linux-2.6.28.8/fs/9p/vfs_inode.c
---- linux-2.6.28.8/fs/9p/vfs_inode.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/9p/vfs_inode.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/9p/vfs_inode.c linux-2.6.29.5/fs/9p/vfs_inode.c
+--- linux-2.6.29.5/fs/9p/vfs_inode.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/9p/vfs_inode.c 2009-06-12 23:57:32.000000000 -0400
@@ -1021,7 +1021,7 @@ static void *v9fs_vfs_follow_link(struct
static void
v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
@@ -16693,9 +19210,9 @@ diff -urNp linux-2.6.28.8/fs/9p/vfs_inode.c linux-2.6.28.8/fs/9p/vfs_inode.c
P9_DPRINTK(P9_DEBUG_VFS, " %s %s\n", dentry->d_name.name,
IS_ERR(s) ? "<error>" : s);
-diff -urNp linux-2.6.28.8/fs/aio.c linux-2.6.28.8/fs/aio.c
---- linux-2.6.28.8/fs/aio.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/aio.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/aio.c linux-2.6.29.5/fs/aio.c
+--- linux-2.6.29.5/fs/aio.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/aio.c 2009-06-12 23:57:32.000000000 -0400
@@ -114,7 +114,7 @@ static int aio_setup_ring(struct kioctx
size += sizeof(struct io_event) * nr_events;
nr_pages = (size + PAGE_SIZE-1) >> PAGE_SHIFT;
@@ -16705,9 +19222,22 @@ diff -urNp linux-2.6.28.8/fs/aio.c linux-2.6.28.8/fs/aio.c
return -EINVAL;
nr_events = (PAGE_SIZE * nr_pages - sizeof(struct aio_ring)) / sizeof(struct io_event);
-diff -urNp linux-2.6.28.8/fs/autofs4/symlink.c linux-2.6.28.8/fs/autofs4/symlink.c
---- linux-2.6.28.8/fs/autofs4/symlink.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/autofs4/symlink.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/autofs/root.c linux-2.6.29.5/fs/autofs/root.c
+--- linux-2.6.29.5/fs/autofs/root.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/autofs/root.c 2009-06-12 23:57:32.000000000 -0400
+@@ -299,7 +299,8 @@ static int autofs_root_symlink(struct in
+ set_bit(n,sbi->symlink_bitmap);
+ sl = &sbi->symlink[n];
+ sl->len = strlen(symname);
+- sl->data = kmalloc(slsize = sl->len+1, GFP_KERNEL);
++ slsize = sl->len + 1;
++ sl->data = kmalloc(slsize, GFP_KERNEL);
+ if (!sl->data) {
+ clear_bit(n,sbi->symlink_bitmap);
+ unlock_kernel();
+diff -urNp linux-2.6.29.5/fs/autofs4/symlink.c linux-2.6.29.5/fs/autofs4/symlink.c
+--- linux-2.6.29.5/fs/autofs4/symlink.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/autofs4/symlink.c 2009-06-12 23:57:32.000000000 -0400
@@ -15,7 +15,7 @@
static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
{
@@ -16717,10 +19247,10 @@ diff -urNp linux-2.6.28.8/fs/autofs4/symlink.c linux-2.6.28.8/fs/autofs4/symlink
return NULL;
}
-diff -urNp linux-2.6.28.8/fs/befs/linuxvfs.c linux-2.6.28.8/fs/befs/linuxvfs.c
---- linux-2.6.28.8/fs/befs/linuxvfs.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/befs/linuxvfs.c 2009-02-21 09:37:48.000000000 -0500
-@@ -490,7 +490,7 @@ static void befs_put_link(struct dentry
+diff -urNp linux-2.6.29.5/fs/befs/linuxvfs.c linux-2.6.29.5/fs/befs/linuxvfs.c
+--- linux-2.6.29.5/fs/befs/linuxvfs.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/befs/linuxvfs.c 2009-06-12 23:57:32.000000000 -0400
+@@ -493,7 +493,7 @@ static void befs_put_link(struct dentry
{
befs_inode_info *befs_ino = BEFS_I(dentry->d_inode);
if (befs_ino->i_flags & BEFS_LONG_SYMLINK) {
@@ -16729,9 +19259,9 @@ diff -urNp linux-2.6.28.8/fs/befs/linuxvfs.c linux-2.6.28.8/fs/befs/linuxvfs.c
if (!IS_ERR(link))
kfree(link);
}
-diff -urNp linux-2.6.28.8/fs/binfmt_aout.c linux-2.6.28.8/fs/binfmt_aout.c
---- linux-2.6.28.8/fs/binfmt_aout.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/binfmt_aout.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/binfmt_aout.c linux-2.6.29.5/fs/binfmt_aout.c
+--- linux-2.6.29.5/fs/binfmt_aout.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/binfmt_aout.c 2009-06-12 23:57:32.000000000 -0400
@@ -16,6 +16,7 @@
#include <linux/string.h>
#include <linux/fs.h>
@@ -16740,30 +19270,20 @@ diff -urNp linux-2.6.28.8/fs/binfmt_aout.c linux-2.6.28.8/fs/binfmt_aout.c
#include <linux/stat.h>
#include <linux/fcntl.h>
#include <linux/ptrace.h>
-@@ -124,18 +125,22 @@ static int aout_core_dump(long signr, st
+@@ -113,10 +114,12 @@ static int aout_core_dump(long signr, st
+
/* If the size of the dump file exceeds the rlimit, then see what would happen
if we wrote the stack, but not the data area. */
- #ifdef __sparc__
-+ gr_learn_resource(current, RLIMIT_CORE, dump.u_dsize + dump.u_ssize, 1);
- if ((dump.u_dsize + dump.u_ssize) > limit)
- dump.u_dsize = 0;
- #else
+ gr_learn_resource(current, RLIMIT_CORE, (dump.u_dsize + dump.u_ssize+1) * PAGE_SIZE, 1);
if ((dump.u_dsize + dump.u_ssize+1) * PAGE_SIZE > limit)
dump.u_dsize = 0;
- #endif
/* Make sure we have enough room to write the stack and data areas. */
- #ifdef __sparc__
-+ gr_learn_resource(current, RLIMIT_CORE, dump.u_ssize, 1);
- if (dump.u_ssize > limit)
- dump.u_ssize = 0;
- #else
+ gr_learn_resource(current, RLIMIT_CORE, (dump.u_ssize + 1) * PAGE_SIZE, 1);
if ((dump.u_ssize + 1) * PAGE_SIZE > limit)
dump.u_ssize = 0;
- #endif
-@@ -291,6 +296,8 @@ static int load_aout_binary(struct linux
+
+@@ -249,6 +252,8 @@ static int load_aout_binary(struct linux
rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
if (rlim >= RLIM_INFINITY)
rlim = ~0;
@@ -16772,11 +19292,10 @@ diff -urNp linux-2.6.28.8/fs/binfmt_aout.c linux-2.6.28.8/fs/binfmt_aout.c
if (ex.a_data + ex.a_bss > rlim)
return -ENOMEM;
-@@ -322,6 +329,28 @@ static int load_aout_binary(struct linux
-
- compute_creds(bprm);
+@@ -276,6 +281,27 @@ static int load_aout_binary(struct linux
+ install_exec_creds(bprm);
current->flags &= ~PF_FORKNOEXEC;
-+
+
+#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
+ current->mm->pax_flags = 0UL;
+#endif
@@ -16798,10 +19317,10 @@ diff -urNp linux-2.6.28.8/fs/binfmt_aout.c linux-2.6.28.8/fs/binfmt_aout.c
+ }
+#endif
+
- #ifdef __sparc__
- if (N_MAGIC(ex) == NMAGIC) {
- loff_t pos = fd_offset;
-@@ -413,7 +442,7 @@ static int load_aout_binary(struct linux
+ if (N_MAGIC(ex) == OMAGIC) {
+ unsigned long text_addr, map_size;
+ loff_t pos;
+@@ -348,7 +374,7 @@ static int load_aout_binary(struct linux
down_write(&current->mm->mmap_sem);
error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
@@ -16810,9 +19329,9 @@ diff -urNp linux-2.6.28.8/fs/binfmt_aout.c linux-2.6.28.8/fs/binfmt_aout.c
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
fd_offset + ex.a_text);
up_write(&current->mm->mmap_sem);
-diff -urNp linux-2.6.28.8/fs/binfmt_elf.c linux-2.6.28.8/fs/binfmt_elf.c
---- linux-2.6.28.8/fs/binfmt_elf.c 2009-02-07 16:10:45.000000000 -0500
-+++ linux-2.6.28.8/fs/binfmt_elf.c 2009-03-07 04:29:14.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/binfmt_elf.c linux-2.6.29.5/fs/binfmt_elf.c
+--- linux-2.6.29.5/fs/binfmt_elf.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/binfmt_elf.c 2009-06-12 23:57:32.000000000 -0400
@@ -42,6 +42,10 @@
#include <asm/param.h>
#include <asm/page.h>
@@ -16865,7 +19384,27 @@ diff -urNp linux-2.6.28.8/fs/binfmt_elf.c linux-2.6.28.8/fs/binfmt_elf.c
return 0;
}
-@@ -380,10 +395,10 @@ static unsigned long load_elf_interp(str
+@@ -155,7 +170,7 @@ create_elf_tables(struct linux_binprm *b
+ elf_addr_t __user *u_rand_bytes;
+ const char *k_platform = ELF_PLATFORM;
+ const char *k_base_platform = ELF_BASE_PLATFORM;
+- unsigned char k_rand_bytes[16];
++ u32 k_rand_bytes[4];
+ int items;
+ elf_addr_t *elf_info;
+ int ei_index = 0;
+@@ -202,6 +217,10 @@ create_elf_tables(struct linux_binprm *b
+ * Generate 16 random bytes for userspace PRNG seeding.
+ */
+ get_random_bytes(k_rand_bytes, sizeof(k_rand_bytes));
++ srandom32(k_rand_bytes[0] ^ random32());
++ srandom32(k_rand_bytes[1] ^ random32());
++ srandom32(k_rand_bytes[2] ^ random32());
++ srandom32(k_rand_bytes[3] ^ random32());
+ u_rand_bytes = (elf_addr_t __user *)
+ STACK_ALLOC(p, sizeof(k_rand_bytes));
+ if (__copy_to_user(u_rand_bytes, k_rand_bytes, sizeof(k_rand_bytes)))
+@@ -392,10 +411,10 @@ static unsigned long load_elf_interp(str
{
struct elf_phdr *elf_phdata;
struct elf_phdr *eppnt;
@@ -16878,7 +19417,7 @@ diff -urNp linux-2.6.28.8/fs/binfmt_elf.c linux-2.6.28.8/fs/binfmt_elf.c
unsigned long total_size;
int retval, i, size;
-@@ -429,6 +444,11 @@ static unsigned long load_elf_interp(str
+@@ -441,6 +460,11 @@ static unsigned long load_elf_interp(str
goto out_close;
}
@@ -16890,7 +19429,7 @@ diff -urNp linux-2.6.28.8/fs/binfmt_elf.c linux-2.6.28.8/fs/binfmt_elf.c
eppnt = elf_phdata;
for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) {
if (eppnt->p_type == PT_LOAD) {
-@@ -472,8 +492,8 @@ static unsigned long load_elf_interp(str
+@@ -484,8 +508,8 @@ static unsigned long load_elf_interp(str
k = load_addr + eppnt->p_vaddr;
if (BAD_ADDR(k) ||
eppnt->p_filesz > eppnt->p_memsz ||
@@ -16901,7 +19440,7 @@ diff -urNp linux-2.6.28.8/fs/binfmt_elf.c linux-2.6.28.8/fs/binfmt_elf.c
error = -ENOMEM;
goto out_close;
}
-@@ -527,6 +547,177 @@ out:
+@@ -539,6 +563,177 @@ out:
return error;
}
@@ -17079,7 +19618,7 @@ diff -urNp linux-2.6.28.8/fs/binfmt_elf.c linux-2.6.28.8/fs/binfmt_elf.c
/*
* These are the functions used to load ELF style executables and shared
* libraries. There is no binary dependent code anywhere else.
-@@ -543,6 +734,11 @@ static unsigned long randomize_stack_top
+@@ -555,6 +750,11 @@ static unsigned long randomize_stack_top
{
unsigned int random_variable = 0;
@@ -17091,7 +19630,7 @@ diff -urNp linux-2.6.28.8/fs/binfmt_elf.c linux-2.6.28.8/fs/binfmt_elf.c
if ((current->flags & PF_RANDOMIZE) &&
!(current->personality & ADDR_NO_RANDOMIZE)) {
random_variable = get_random_int() & STACK_RND_MASK;
-@@ -561,7 +757,7 @@ static int load_elf_binary(struct linux_
+@@ -573,7 +773,7 @@ static int load_elf_binary(struct linux_
unsigned long load_addr = 0, load_bias = 0;
int load_addr_set = 0;
char * elf_interpreter = NULL;
@@ -17100,7 +19639,7 @@ diff -urNp linux-2.6.28.8/fs/binfmt_elf.c linux-2.6.28.8/fs/binfmt_elf.c
struct elf_phdr *elf_ppnt, *elf_phdata;
unsigned long elf_bss, elf_brk;
int elf_exec_fileno;
-@@ -572,11 +768,11 @@ static int load_elf_binary(struct linux_
+@@ -584,11 +784,11 @@ static int load_elf_binary(struct linux_
unsigned long start_code, end_code, start_data, end_data;
unsigned long reloc_func_desc = 0;
int executable_stack = EXSTACK_DEFAULT;
@@ -17113,7 +19652,7 @@ diff -urNp linux-2.6.28.8/fs/binfmt_elf.c linux-2.6.28.8/fs/binfmt_elf.c
loc = kmalloc(sizeof(*loc), GFP_KERNEL);
if (!loc) {
-@@ -744,11 +940,80 @@ static int load_elf_binary(struct linux_
+@@ -756,11 +956,80 @@ static int load_elf_binary(struct linux_
/* OK, This is the point of no return */
current->flags &= ~PF_FORKNOEXEC;
@@ -17195,7 +19734,7 @@ diff -urNp linux-2.6.28.8/fs/binfmt_elf.c linux-2.6.28.8/fs/binfmt_elf.c
if (elf_read_implies_exec(loc->elf_ex, executable_stack))
current->personality |= READ_IMPLIES_EXEC;
-@@ -829,6 +1094,20 @@ static int load_elf_binary(struct linux_
+@@ -841,6 +1110,20 @@ static int load_elf_binary(struct linux_
#else
load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);
#endif
@@ -17216,7 +19755,7 @@ diff -urNp linux-2.6.28.8/fs/binfmt_elf.c linux-2.6.28.8/fs/binfmt_elf.c
}
error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt,
-@@ -861,9 +1140,9 @@ static int load_elf_binary(struct linux_
+@@ -873,9 +1156,9 @@ static int load_elf_binary(struct linux_
* allowed task size. Note that p_filesz must always be
* <= p_memsz so it is only necessary to check p_memsz.
*/
@@ -17229,7 +19768,7 @@ diff -urNp linux-2.6.28.8/fs/binfmt_elf.c linux-2.6.28.8/fs/binfmt_elf.c
/* set_brk can never work. Avoid overflows. */
send_sig(SIGKILL, current, 0);
retval = -EINVAL;
-@@ -891,6 +1170,11 @@ static int load_elf_binary(struct linux_
+@@ -903,6 +1186,11 @@ static int load_elf_binary(struct linux_
start_data += load_bias;
end_data += load_bias;
@@ -17241,7 +19780,7 @@ diff -urNp linux-2.6.28.8/fs/binfmt_elf.c linux-2.6.28.8/fs/binfmt_elf.c
/* Calling set_brk effectively mmaps the pages that we need
* for the bss and break sections. We must do this before
* mapping in the interpreter, to make sure it doesn't wind
-@@ -902,9 +1186,11 @@ static int load_elf_binary(struct linux_
+@@ -914,9 +1202,11 @@ static int load_elf_binary(struct linux_
goto out_free_dentry;
}
if (likely(elf_bss != elf_brk) && unlikely(padzero(elf_bss))) {
@@ -17256,7 +19795,7 @@ diff -urNp linux-2.6.28.8/fs/binfmt_elf.c linux-2.6.28.8/fs/binfmt_elf.c
}
if (elf_interpreter) {
-@@ -1141,8 +1427,10 @@ static int dump_seek(struct file *file,
+@@ -1153,8 +1443,10 @@ static int dump_seek(struct file *file,
unsigned long n = off;
if (n > PAGE_SIZE)
n = PAGE_SIZE;
@@ -17268,7 +19807,7 @@ diff -urNp linux-2.6.28.8/fs/binfmt_elf.c linux-2.6.28.8/fs/binfmt_elf.c
off -= n;
}
free_page((unsigned long)buf);
-@@ -1154,7 +1442,7 @@ static int dump_seek(struct file *file,
+@@ -1166,7 +1458,7 @@ static int dump_seek(struct file *file,
* Decide what to dump of a segment, part, all or none.
*/
static unsigned long vma_dump_size(struct vm_area_struct *vma,
@@ -17277,7 +19816,7 @@ diff -urNp linux-2.6.28.8/fs/binfmt_elf.c linux-2.6.28.8/fs/binfmt_elf.c
{
#define FILTER(type) (mm_flags & (1UL << MMF_DUMP_##type))
-@@ -1188,7 +1476,7 @@ static unsigned long vma_dump_size(struc
+@@ -1200,7 +1492,7 @@ static unsigned long vma_dump_size(struc
if (vma->vm_file == NULL)
return 0;
@@ -17286,7 +19825,7 @@ diff -urNp linux-2.6.28.8/fs/binfmt_elf.c linux-2.6.28.8/fs/binfmt_elf.c
goto whole;
/*
-@@ -1284,8 +1572,11 @@ static int writenote(struct memelfnote *
+@@ -1296,8 +1588,11 @@ static int writenote(struct memelfnote *
#undef DUMP_WRITE
#define DUMP_WRITE(addr, nr) \
@@ -17299,7 +19838,7 @@ diff -urNp linux-2.6.28.8/fs/binfmt_elf.c linux-2.6.28.8/fs/binfmt_elf.c
#define DUMP_SEEK(off) \
if (!dump_seek(file, (off))) \
goto end_coredump;
-@@ -1986,7 +2277,7 @@ static int elf_core_dump(long signr, str
+@@ -2002,7 +2297,7 @@ static int elf_core_dump(long signr, str
phdr.p_offset = offset;
phdr.p_vaddr = vma->vm_start;
phdr.p_paddr = 0;
@@ -17308,7 +19847,7 @@ diff -urNp linux-2.6.28.8/fs/binfmt_elf.c linux-2.6.28.8/fs/binfmt_elf.c
phdr.p_memsz = vma->vm_end - vma->vm_start;
offset += phdr.p_filesz;
phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0;
-@@ -2018,7 +2309,7 @@ static int elf_core_dump(long signr, str
+@@ -2034,7 +2329,7 @@ static int elf_core_dump(long signr, str
unsigned long addr;
unsigned long end;
@@ -17317,7 +19856,7 @@ diff -urNp linux-2.6.28.8/fs/binfmt_elf.c linux-2.6.28.8/fs/binfmt_elf.c
for (addr = vma->vm_start; addr < end; addr += PAGE_SIZE) {
struct page *page;
-@@ -2038,6 +2329,7 @@ static int elf_core_dump(long signr, str
+@@ -2054,6 +2349,7 @@ static int elf_core_dump(long signr, str
flush_cache_page(tmp_vma, addr,
page_to_pfn(page));
kaddr = kmap(page);
@@ -17325,7 +19864,7 @@ diff -urNp linux-2.6.28.8/fs/binfmt_elf.c linux-2.6.28.8/fs/binfmt_elf.c
if ((size += PAGE_SIZE) > limit ||
!dump_write(file, kaddr,
PAGE_SIZE)) {
-@@ -2068,6 +2360,99 @@ out:
+@@ -2084,6 +2380,99 @@ out:
#endif /* USE_ELF_CORE_DUMP */
@@ -17425,10 +19964,10 @@ diff -urNp linux-2.6.28.8/fs/binfmt_elf.c linux-2.6.28.8/fs/binfmt_elf.c
static int __init init_elf_binfmt(void)
{
return register_binfmt(&elf_format);
-diff -urNp linux-2.6.28.8/fs/binfmt_flat.c linux-2.6.28.8/fs/binfmt_flat.c
---- linux-2.6.28.8/fs/binfmt_flat.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/binfmt_flat.c 2009-02-21 09:37:48.000000000 -0500
-@@ -561,7 +561,9 @@ static int load_flat_file(struct linux_b
+diff -urNp linux-2.6.29.5/fs/binfmt_flat.c linux-2.6.29.5/fs/binfmt_flat.c
+--- linux-2.6.29.5/fs/binfmt_flat.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/binfmt_flat.c 2009-06-12 23:57:32.000000000 -0400
+@@ -554,7 +554,9 @@ static int load_flat_file(struct linux_b
realdatastart = (unsigned long) -ENOMEM;
printk("Unable to allocate RAM for process data, errno %d\n",
(int)-realdatastart);
@@ -17438,7 +19977,7 @@ diff -urNp linux-2.6.28.8/fs/binfmt_flat.c linux-2.6.28.8/fs/binfmt_flat.c
ret = realdatastart;
goto err;
}
-@@ -583,8 +585,10 @@ static int load_flat_file(struct linux_b
+@@ -576,8 +578,10 @@ static int load_flat_file(struct linux_b
}
if (result >= (unsigned long)-4096) {
printk("Unable to read data+bss, errno %d\n", (int)-result);
@@ -17449,7 +19988,7 @@ diff -urNp linux-2.6.28.8/fs/binfmt_flat.c linux-2.6.28.8/fs/binfmt_flat.c
ret = result;
goto err;
}
-@@ -657,8 +661,10 @@ static int load_flat_file(struct linux_b
+@@ -643,8 +647,10 @@ static int load_flat_file(struct linux_b
}
if (result >= (unsigned long)-4096) {
printk("Unable to read code+data+bss, errno %d\n",(int)-result);
@@ -17460,10 +19999,10 @@ diff -urNp linux-2.6.28.8/fs/binfmt_flat.c linux-2.6.28.8/fs/binfmt_flat.c
ret = result;
goto err;
}
-diff -urNp linux-2.6.28.8/fs/binfmt_misc.c linux-2.6.28.8/fs/binfmt_misc.c
---- linux-2.6.28.8/fs/binfmt_misc.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/binfmt_misc.c 2009-02-21 09:37:48.000000000 -0500
-@@ -696,7 +696,7 @@ static int bm_fill_super(struct super_bl
+diff -urNp linux-2.6.29.5/fs/binfmt_misc.c linux-2.6.29.5/fs/binfmt_misc.c
+--- linux-2.6.29.5/fs/binfmt_misc.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/binfmt_misc.c 2009-06-12 23:57:32.000000000 -0400
+@@ -693,7 +693,7 @@ static int bm_fill_super(struct super_bl
static struct tree_descr bm_files[] = {
[2] = {"status", &bm_status_operations, S_IWUSR|S_IRUGO},
[3] = {"register", &bm_register_operations, S_IWUSR},
@@ -17472,10 +20011,10 @@ diff -urNp linux-2.6.28.8/fs/binfmt_misc.c linux-2.6.28.8/fs/binfmt_misc.c
};
int err = simple_fill_super(sb, 0x42494e4d, bm_files);
if (!err)
-diff -urNp linux-2.6.28.8/fs/bio.c linux-2.6.28.8/fs/bio.c
---- linux-2.6.28.8/fs/bio.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/bio.c 2009-02-21 09:37:48.000000000 -0500
-@@ -554,7 +554,7 @@ static int __bio_copy_iov(struct bio *bi
+diff -urNp linux-2.6.29.5/fs/bio.c linux-2.6.29.5/fs/bio.c
+--- linux-2.6.29.5/fs/bio.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/bio.c 2009-06-12 23:57:32.000000000 -0400
+@@ -710,7 +710,7 @@ static int __bio_copy_iov(struct bio *bi
while (bv_len && iov_idx < iov_count) {
unsigned int bytes;
@@ -17484,9 +20023,9 @@ diff -urNp linux-2.6.28.8/fs/bio.c linux-2.6.28.8/fs/bio.c
bytes = min_t(unsigned int,
iov[iov_idx].iov_len - iov_off, bv_len);
-diff -urNp linux-2.6.28.8/fs/buffer.c linux-2.6.28.8/fs/buffer.c
---- linux-2.6.28.8/fs/buffer.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/buffer.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/buffer.c linux-2.6.29.5/fs/buffer.c
+--- linux-2.6.29.5/fs/buffer.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/buffer.c 2009-06-12 23:57:32.000000000 -0400
@@ -25,6 +25,7 @@
#include <linux/percpu.h>
#include <linux/slab.h>
@@ -17495,7 +20034,7 @@ diff -urNp linux-2.6.28.8/fs/buffer.c linux-2.6.28.8/fs/buffer.c
#include <linux/blkdev.h>
#include <linux/file.h>
#include <linux/quotaops.h>
-@@ -2249,6 +2250,7 @@ int generic_cont_expand_simple(struct in
+@@ -2312,6 +2313,7 @@ int generic_cont_expand_simple(struct in
err = -EFBIG;
limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
@@ -17503,9 +20042,9 @@ diff -urNp linux-2.6.28.8/fs/buffer.c linux-2.6.28.8/fs/buffer.c
if (limit != RLIM_INFINITY && size > (loff_t)limit) {
send_sig(SIGXFSZ, current, 0);
goto out;
-diff -urNp linux-2.6.28.8/fs/cifs/cifs_uniupr.h linux-2.6.28.8/fs/cifs/cifs_uniupr.h
---- linux-2.6.28.8/fs/cifs/cifs_uniupr.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/cifs/cifs_uniupr.h 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/cifs/cifs_uniupr.h linux-2.6.29.5/fs/cifs/cifs_uniupr.h
+--- linux-2.6.29.5/fs/cifs/cifs_uniupr.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/cifs/cifs_uniupr.h 2009-06-12 23:57:32.000000000 -0400
@@ -132,7 +132,7 @@ const struct UniCaseRange CifsUniUpperRa
{0x0490, 0x04cc, UniCaseRangeU0490},
{0x1e00, 0x1ffc, UniCaseRangeU1e00},
@@ -17515,9 +20054,9 @@ diff -urNp linux-2.6.28.8/fs/cifs/cifs_uniupr.h linux-2.6.28.8/fs/cifs/cifs_uniu
};
#endif
-diff -urNp linux-2.6.28.8/fs/cifs/link.c linux-2.6.28.8/fs/cifs/link.c
---- linux-2.6.28.8/fs/cifs/link.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/cifs/link.c 2009-02-21 09:37:48.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/cifs/link.c linux-2.6.29.5/fs/cifs/link.c
+--- linux-2.6.29.5/fs/cifs/link.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/cifs/link.c 2009-06-12 23:57:32.000000000 -0400
@@ -318,7 +318,7 @@ cifs_readlink(struct dentry *direntry, c
void cifs_put_link(struct dentry *direntry, struct nameidata *nd, void *cookie)
@@ -17527,10 +20066,10 @@ diff -urNp linux-2.6.28.8/fs/cifs/link.c linux-2.6.28.8/fs/cifs/link.c
if (!IS_ERR(p))
kfree(p);
}
-diff -urNp linux-2.6.28.8/fs/compat.c linux-2.6.28.8/fs/compat.c
---- linux-2.6.28.8/fs/compat.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/compat.c 2009-02-21 09:37:48.000000000 -0500
-@@ -1331,14 +1331,12 @@ static int compat_copy_strings(int argc,
+diff -urNp linux-2.6.29.5/fs/compat.c linux-2.6.29.5/fs/compat.c
+--- linux-2.6.29.5/fs/compat.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/compat.c 2009-06-12 23:57:32.000000000 -0400
+@@ -1338,14 +1338,12 @@ static int compat_copy_strings(int argc,
if (!kmapped_page || kpos != (pos & PAGE_MASK)) {
struct page *page;
@@ -17545,7 +20084,7 @@ diff -urNp linux-2.6.28.8/fs/compat.c linux-2.6.28.8/fs/compat.c
ret = get_user_pages(current, bprm->mm, pos,
1, 1, 1, &page, NULL);
if (ret <= 0) {
-@@ -1384,6 +1382,11 @@ int compat_do_execve(char * filename,
+@@ -1391,6 +1389,11 @@ int compat_do_execve(char * filename,
compat_uptr_t __user *envp,
struct pt_regs * regs)
{
@@ -17556,12 +20095,12 @@ diff -urNp linux-2.6.28.8/fs/compat.c linux-2.6.28.8/fs/compat.c
+#endif
struct linux_binprm *bprm;
struct file *file;
- int retval;
-@@ -1404,6 +1407,14 @@ int compat_do_execve(char * filename,
+ struct files_struct *displaced;
+@@ -1431,6 +1434,14 @@ int compat_do_execve(char * filename,
bprm->filename = filename;
bprm->interp = filename;
-+ gr_learn_resource(current, RLIMIT_NPROC, atomic_read(&current->user->processes), 1);
++ gr_learn_resource(current, RLIMIT_NPROC, atomic_read(&current->cred->user->processes), 1);
+ retval = -EAGAIN;
+ if (gr_handle_nproc())
+ goto out_file;
@@ -17572,7 +20111,7 @@ diff -urNp linux-2.6.28.8/fs/compat.c linux-2.6.28.8/fs/compat.c
retval = bprm_mm_init(bprm);
if (retval)
goto out_file;
-@@ -1437,8 +1448,36 @@ int compat_do_execve(char * filename,
+@@ -1460,9 +1471,40 @@ int compat_do_execve(char * filename,
if (retval < 0)
goto out;
@@ -17598,21 +20137,27 @@ diff -urNp linux-2.6.28.8/fs/compat.c linux-2.6.28.8/fs/compat.c
+ current->exec_file = file;
+#endif
+
-+ gr_set_proc_label(file->f_dentry, file->f_vfsmnt);
++ retval = gr_set_proc_label(file->f_dentry, file->f_vfsmnt,
++ bprm->unsafe & LSM_UNSAFE_SHARE);
++ if (retval < 0)
++ goto out_fail;
+
retval = search_binary_handler(bprm, regs);
- if (retval >= 0) {
+ if (retval < 0)
+- goto out;
++ goto out_fail;
+#ifdef CONFIG_GRKERNSEC
-+ if (old_exec_file)
-+ fput(old_exec_file);
++ if (old_exec_file)
++ fput(old_exec_file);
+#endif
- /* execve success */
- security_bprm_free(bprm);
- acct_update_integrals(current);
-@@ -1446,6 +1485,13 @@ int compat_do_execve(char * filename,
- return retval;
- }
+ /* execve succeeded */
+ current->fs->in_exec = 0;
+@@ -1473,6 +1515,14 @@ int compat_do_execve(char * filename,
+ put_files_struct(displaced);
+ return retval;
+
++out_fail:
+#ifdef CONFIG_GRKERNSEC
+ current->acl = old_acl;
+ memcpy(current->signal->rlim, old_rlim, sizeof(old_rlim));
@@ -17621,11 +20166,11 @@ diff -urNp linux-2.6.28.8/fs/compat.c linux-2.6.28.8/fs/compat.c
+#endif
+
out:
- if (bprm->security)
- security_bprm_free(bprm);
-diff -urNp linux-2.6.28.8/fs/compat_ioctl.c linux-2.6.28.8/fs/compat_ioctl.c
---- linux-2.6.28.8/fs/compat_ioctl.c 2009-03-07 10:24:49.000000000 -0500
-+++ linux-2.6.28.8/fs/compat_ioctl.c 2009-03-07 10:29:51.000000000 -0500
+ if (bprm->mm)
+ mmput(bprm->mm);
+diff -urNp linux-2.6.29.5/fs/compat_ioctl.c linux-2.6.29.5/fs/compat_ioctl.c
+--- linux-2.6.29.5/fs/compat_ioctl.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/compat_ioctl.c 2009-06-12 23:57:32.000000000 -0400
@@ -1832,15 +1832,15 @@ struct ioctl_trans {
};
@@ -17645,10 +20190,10 @@ diff -urNp linux-2.6.28.8/fs/compat_ioctl.c linux-2.6.28.8/fs/compat_ioctl.c
/* ioctl should not be warned about even if it's not implemented.
Valid reasons to use this:
-diff -urNp linux-2.6.28.8/fs/debugfs/inode.c linux-2.6.28.8/fs/debugfs/inode.c
---- linux-2.6.28.8/fs/debugfs/inode.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/debugfs/inode.c 2009-02-21 09:37:48.000000000 -0500
-@@ -120,7 +120,7 @@ static inline int debugfs_positive(struc
+diff -urNp linux-2.6.29.5/fs/debugfs/inode.c linux-2.6.29.5/fs/debugfs/inode.c
+--- linux-2.6.29.5/fs/debugfs/inode.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/debugfs/inode.c 2009-06-12 23:57:32.000000000 -0400
+@@ -117,7 +117,7 @@ static inline int debugfs_positive(struc
static int debug_fill_super(struct super_block *sb, void *data, int silent)
{
@@ -17657,14 +20202,15 @@ diff -urNp linux-2.6.28.8/fs/debugfs/inode.c linux-2.6.28.8/fs/debugfs/inode.c
return simple_fill_super(sb, DEBUGFS_MAGIC, debug_files);
}
-diff -urNp linux-2.6.28.8/fs/exec.c linux-2.6.28.8/fs/exec.c
---- linux-2.6.28.8/fs/exec.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/exec.c 2009-02-21 09:37:48.000000000 -0500
-@@ -51,6 +51,12 @@
- #include <linux/audit.h>
+diff -urNp linux-2.6.29.5/fs/exec.c linux-2.6.29.5/fs/exec.c
+--- linux-2.6.29.5/fs/exec.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/exec.c 2009-06-12 23:57:32.000000000 -0400
+@@ -52,12 +52,24 @@
#include <linux/tracehook.h>
#include <linux/kmod.h>
+ #include <linux/fsnotify.h>
+#include <linux/random.h>
++#include <linux/seq_file.h>
+
+#ifdef CONFIG_PAX_REFCOUNT
+#include <linux/kallsyms.h>
@@ -17673,9 +20219,8 @@ diff -urNp linux-2.6.28.8/fs/exec.c linux-2.6.28.8/fs/exec.c
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
-@@ -61,6 +67,11 @@
- #include <linux/a.out.h>
- #endif
+ #include <asm/tlb.h>
+ #include "internal.h"
+#ifdef CONFIG_PAX_HOOK_ACL_FLAGS
+void (*pax_set_initial_flags_func)(struct linux_binprm *bprm);
@@ -17685,7 +20230,7 @@ diff -urNp linux-2.6.28.8/fs/exec.c linux-2.6.28.8/fs/exec.c
int core_uses_pid;
char core_pattern[CORENAME_MAX_SIZE] = "core";
int suid_dumpable = 0;
-@@ -169,18 +180,10 @@ static struct page *get_arg_page(struct
+@@ -169,18 +181,10 @@ static struct page *get_arg_page(struct
int write)
{
struct page *page;
@@ -17707,9 +20252,9 @@ diff -urNp linux-2.6.28.8/fs/exec.c linux-2.6.28.8/fs/exec.c
return NULL;
if (write) {
-@@ -253,6 +256,11 @@ static int __bprm_mm_init(struct linux_b
+@@ -252,6 +256,11 @@ static int __bprm_mm_init(struct linux_b
+ vma->vm_end = STACK_TOP_MAX;
vma->vm_start = vma->vm_end - PAGE_SIZE;
-
vma->vm_flags = VM_STACK_FLAGS;
+
+#ifdef CONFIG_PAX_SEGMEXEC
@@ -17718,20 +20263,21 @@ diff -urNp linux-2.6.28.8/fs/exec.c linux-2.6.28.8/fs/exec.c
+
vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
err = insert_vm_struct(mm, vma);
- if (err) {
-@@ -265,6 +273,11 @@ static int __bprm_mm_init(struct linux_b
-
+ if (err)
+@@ -260,6 +269,12 @@ static int __bprm_mm_init(struct linux_b
+ mm->stack_vm = mm->total_vm = 1;
+ up_write(&mm->mmap_sem);
bprm->p = vma->vm_end - sizeof(void *);
-
++
+#ifdef CONFIG_PAX_RANDUSTACK
+ if (randomize_va_space)
+ bprm->p ^= (pax_get_random_long() & ~15) & ~PAGE_MASK;
+#endif
+
return 0;
-
err:
-@@ -528,6 +541,10 @@ static int shift_arg_pages(struct vm_are
+ up_write(&mm->mmap_sem);
+@@ -520,6 +535,10 @@ static int shift_arg_pages(struct vm_are
if (vma != find_vma(mm, new_start))
return -EFAULT;
@@ -17742,7 +20288,7 @@ diff -urNp linux-2.6.28.8/fs/exec.c linux-2.6.28.8/fs/exec.c
/*
* cover the whole range: [new_start, old_end)
*/
-@@ -616,6 +633,14 @@ int setup_arg_pages(struct linux_binprm
+@@ -608,6 +627,14 @@ int setup_arg_pages(struct linux_binprm
bprm->exec -= stack_shift;
down_write(&mm->mmap_sem);
@@ -17757,7 +20303,7 @@ diff -urNp linux-2.6.28.8/fs/exec.c linux-2.6.28.8/fs/exec.c
vm_flags = VM_STACK_FLAGS;
/*
-@@ -629,21 +654,24 @@ int setup_arg_pages(struct linux_binprm
+@@ -621,21 +648,24 @@ int setup_arg_pages(struct linux_binprm
vm_flags &= ~VM_EXEC;
vm_flags |= mm->def_flags;
@@ -17791,7 +20337,7 @@ diff -urNp linux-2.6.28.8/fs/exec.c linux-2.6.28.8/fs/exec.c
#ifdef CONFIG_STACK_GROWSUP
stack_base = vma->vm_end + EXTRA_STACK_VM_PAGES * PAGE_SIZE;
#else
-@@ -655,7 +683,7 @@ int setup_arg_pages(struct linux_binprm
+@@ -647,7 +677,7 @@ int setup_arg_pages(struct linux_binprm
out_unlock:
up_write(&mm->mmap_sem);
@@ -17800,7 +20346,16 @@ diff -urNp linux-2.6.28.8/fs/exec.c linux-2.6.28.8/fs/exec.c
}
EXPORT_SYMBOL(setup_arg_pages);
-@@ -1281,6 +1309,11 @@ int do_execve(char * filename,
+@@ -1066,7 +1096,7 @@ int check_unsafe_exec(struct linux_binpr
+ }
+ rcu_read_unlock();
+
+- if (p->fs->users > n_fs) {
++ if (atomic_read(&p->fs->users) > n_fs) {
+ bprm->unsafe |= LSM_UNSAFE_SHARE;
+ } else {
+ res = -EAGAIN;
+@@ -1270,6 +1300,11 @@ int do_execve(char * filename,
char __user *__user *envp,
struct pt_regs * regs)
{
@@ -17812,28 +20367,26 @@ diff -urNp linux-2.6.28.8/fs/exec.c linux-2.6.28.8/fs/exec.c
struct linux_binprm *bprm;
struct file *file;
struct files_struct *displaced;
-@@ -1300,6 +1333,20 @@ int do_execve(char * filename,
- if (IS_ERR(file))
- goto out_kfree;
+@@ -1310,6 +1345,18 @@ int do_execve(char * filename,
+ bprm->filename = filename;
+ bprm->interp = filename;
-+ gr_learn_resource(current, RLIMIT_NPROC, atomic_read(&current->user->processes), 1);
++ gr_learn_resource(current, RLIMIT_NPROC, atomic_read(&current->cred->user->processes), 1);
+
+ if (gr_handle_nproc()) {
-+ allow_write_access(file);
-+ fput(file);
-+ return -EAGAIN;
++ retval = -EAGAIN;
++ goto out_file;
+ }
+
+ if (!gr_acl_handle_execve(file->f_dentry, file->f_vfsmnt)) {
-+ allow_write_access(file);
-+ fput(file);
-+ return -EACCES;
++ retval = -EACCES;
++ goto out_file;
+ }
+
- sched_exec();
-
- bprm->file = file;
-@@ -1339,9 +1386,39 @@ int do_execve(char * filename,
+ retval = bprm_mm_init(bprm);
+ if (retval)
+ goto out_file;
+@@ -1339,10 +1386,41 @@ int do_execve(char * filename,
if (retval < 0)
goto out;
@@ -17859,23 +20412,26 @@ diff -urNp linux-2.6.28.8/fs/exec.c linux-2.6.28.8/fs/exec.c
+ current->exec_file = file;
+#endif
+
-+ retval = gr_set_proc_label(file->f_dentry, file->f_vfsmnt);
++ retval = gr_set_proc_label(file->f_dentry, file->f_vfsmnt,
++ bprm->unsafe & LSM_UNSAFE_SHARE);
+ if (retval < 0)
+ goto out_fail;
+
current->flags &= ~PF_KTHREAD;
retval = search_binary_handler(bprm,regs);
- if (retval >= 0) {
+ if (retval < 0)
+- goto out;
++ goto out_fail;
+#ifdef CONFIG_GRKERNSEC
-+ if (old_exec_file)
-+ fput(old_exec_file);
++ if (old_exec_file)
++ fput(old_exec_file);
+#endif
- /* execve success */
- security_bprm_free(bprm);
- acct_update_integrals(current);
-@@ -1351,6 +1428,14 @@ int do_execve(char * filename,
- return retval;
- }
+
+ /* execve succeeded */
+ current->fs->in_exec = 0;
+@@ -1353,6 +1431,14 @@ int do_execve(char * filename,
+ put_files_struct(displaced);
+ return retval;
+out_fail:
+#ifdef CONFIG_GRKERNSEC
@@ -17886,9 +20442,9 @@ diff -urNp linux-2.6.28.8/fs/exec.c linux-2.6.28.8/fs/exec.c
+#endif
+
out:
- if (bprm->security)
- security_bprm_free(bprm);
-@@ -1513,6 +1598,129 @@ out:
+ if (bprm->mm)
+ mmput (bprm->mm);
+@@ -1520,6 +1606,164 @@ out:
return ispipe;
}
@@ -17972,6 +20528,14 @@ diff -urNp linux-2.6.28.8/fs/exec.c linux-2.6.28.8/fs/exec.c
+ path_exec = d_path(&vma_exec->vm_file->f_path, buffer_exec, PAGE_SIZE);
+ if (IS_ERR(path_exec))
+ path_exec = "<path too long>";
++ else {
++ path_exec = mangle_path(buffer_exec, path_exec, "\t\n\\");
++ if (path_exec) {
++ *path_exec = 0;
++ path_exec = buffer_exec;
++ } else
++ path_exec = "<path too long>";
++ }
+ }
+ if (vma_fault) {
+ start = vma_fault->vm_start;
@@ -17981,6 +20545,14 @@ diff -urNp linux-2.6.28.8/fs/exec.c linux-2.6.28.8/fs/exec.c
+ path_fault = d_path(&vma_fault->vm_file->f_path, buffer_fault, PAGE_SIZE);
+ if (IS_ERR(path_fault))
+ path_fault = "<path too long>";
++ else {
++ path_fault = mangle_path(buffer_fault, path_fault, "\t\n\\");
++ if (path_fault) {
++ *path_fault = 0;
++ path_fault = buffer_fault;
++ } else
++ path_fault = "<path too long>";
++ }
+ } else
+ path_fault = "<anonymous mapping>";
+ }
@@ -17992,7 +20564,7 @@ diff -urNp linux-2.6.28.8/fs/exec.c linux-2.6.28.8/fs/exec.c
+ printk(KERN_ERR "PAX: execution attempt in: %s, %08lx-%08lx %08lx\n", path_fault, start, end, offset);
+ printk(KERN_ERR "PAX: terminating task: %s(%s):%d, uid/euid: %u/%u, "
+ "PC: %p, SP: %p\n", path_exec, tsk->comm, task_pid_nr(tsk),
-+ tsk->uid, tsk->euid, pc, sp);
++ task_uid(tsk), task_euid(tsk), pc, sp);
+ free_page((unsigned long)buffer_exec);
+ free_page((unsigned long)buffer_fault);
+ pax_report_insns(pc, sp);
@@ -18005,20 +20577,39 @@ diff -urNp linux-2.6.28.8/fs/exec.c linux-2.6.28.8/fs/exec.c
+{
+ if (current->signal->curr_ip)
+ printk(KERN_ERR "PAX: From %u.%u.%u.%u: refcount overflow detected in: %s:%d, uid/euid: %u/%u\n",
-+ NIPQUAD(current->signal->curr_ip), current->comm, task_pid_nr(current), current->uid, current->euid);
++ NIPQUAD(current->signal->curr_ip), current->comm, task_pid_nr(current), current_uid(), current_euid());
+ else
+ printk(KERN_ERR "PAX: refcount overflow detected in: %s:%d, uid/euid: %u/%u\n",
-+ current->comm, task_pid_nr(current), current->uid, current->euid);
++ current->comm, task_pid_nr(current), current_uid(), current_euid());
+ print_symbol(KERN_ERR "PAX: refcount overflow occured at: %s\n", instruction_pointer(regs));
+ show_registers(regs);
+ force_sig_specific(SIGKILL, current);
+}
+#endif
+
++#ifdef CONFIG_PAX_USERCOPY
++void pax_report_leak_to_user(const void *ptr, unsigned long len)
++{
++ if (current->signal->curr_ip)
++ printk(KERN_ERR "PAX: From %u.%u.%u.%u: kernel memory leak attempt detected from %p (%lu bytes)\n", NIPQUAD(current->signal->curr_ip), ptr, len);
++ else
++ printk(KERN_ERR "PAX: kernel memory leak attempt detected from %p (%lu bytes)\n", ptr, len);
++ dump_stack();
++ do_group_exit(SIGKILL);
++}
++
++void pax_report_overflow_from_user(const void *ptr, unsigned long len)
++{
++ printk(KERN_ERR "PAX: kernel memory overflow attempt detected to %p (%lu bytes)\n", ptr, len);
++ dump_stack();
++ do_group_exit(SIGKILL);
++}
++#endif
++
static int zap_process(struct task_struct *start)
{
struct task_struct *t;
-@@ -1759,6 +1967,10 @@ int do_coredump(long signr, int exit_cod
+@@ -1779,6 +2023,10 @@ void do_coredump(long signr, int exit_co
*/
clear_thread_flag(TIF_SIGPENDING);
@@ -18029,57 +20620,45 @@ diff -urNp linux-2.6.28.8/fs/exec.c linux-2.6.28.8/fs/exec.c
/*
* lock_kernel() because format_corename() is controlled by sysctl, which
* uses lock_kernel()
-@@ -1779,6 +1991,8 @@ int do_coredump(long signr, int exit_cod
-
- if (ispipe) {
- helper_argv = argv_split(GFP_KERNEL, corename+1, &helper_argc);
-+ if (!helper_argv)
-+ goto fail_unlock;
- /* Terminate the string before the first option */
- delimit = strchr(corename, ' ');
- if (delimit)
-diff -urNp linux-2.6.28.8/fs/ext2/balloc.c linux-2.6.28.8/fs/ext2/balloc.c
---- linux-2.6.28.8/fs/ext2/balloc.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/ext2/balloc.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/ext2/balloc.c linux-2.6.29.5/fs/ext2/balloc.c
+--- linux-2.6.29.5/fs/ext2/balloc.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/ext2/balloc.c 2009-06-12 23:57:32.000000000 -0400
@@ -1192,7 +1192,7 @@ static int ext2_has_free_blocks(struct e
free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
root_blocks = le32_to_cpu(sbi->s_es->s_r_blocks_count);
- if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) &&
+ if (free_blocks < root_blocks + 1 && !capable_nolog(CAP_SYS_RESOURCE) &&
- sbi->s_resuid != current->fsuid &&
+ sbi->s_resuid != current_fsuid() &&
(sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) {
return 0;
-diff -urNp linux-2.6.28.8/fs/ext3/balloc.c linux-2.6.28.8/fs/ext3/balloc.c
---- linux-2.6.28.8/fs/ext3/balloc.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/ext3/balloc.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/ext3/balloc.c linux-2.6.29.5/fs/ext3/balloc.c
+--- linux-2.6.29.5/fs/ext3/balloc.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/ext3/balloc.c 2009-06-12 23:57:32.000000000 -0400
@@ -1421,7 +1421,7 @@ static int ext3_has_free_blocks(struct e
free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
root_blocks = le32_to_cpu(sbi->s_es->s_r_blocks_count);
- if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) &&
+ if (free_blocks < root_blocks + 1 && !capable_nolog(CAP_SYS_RESOURCE) &&
- sbi->s_resuid != current->fsuid &&
+ sbi->s_resuid != current_fsuid() &&
(sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) {
return 0;
-diff -urNp linux-2.6.28.8/fs/ext3/namei.c linux-2.6.28.8/fs/ext3/namei.c
---- linux-2.6.28.8/fs/ext3/namei.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/ext3/namei.c 2009-02-21 09:37:49.000000000 -0500
-@@ -1156,9 +1156,9 @@ static struct ext3_dir_entry_2 *do_split
- u32 hash2;
- struct dx_map_entry *map;
+diff -urNp linux-2.6.29.5/fs/ext3/namei.c linux-2.6.29.5/fs/ext3/namei.c
+--- linux-2.6.29.5/fs/ext3/namei.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/ext3/namei.c 2009-06-12 23:57:32.000000000 -0400
+@@ -1159,7 +1159,7 @@ static struct ext3_dir_entry_2 *do_split
char *data1 = (*bh)->b_data, *data2;
-- unsigned split, move, size, i;
-+ unsigned split, move, size;
+ unsigned split, move, size;
struct ext3_dir_entry_2 *de = NULL, *de2;
-- int err = 0;
+- int err = 0, i;
+ int i, err = 0;
bh2 = ext3_append (handle, dir, &newblock, &err);
if (!(bh2)) {
-diff -urNp linux-2.6.28.8/fs/ext3/xattr.c linux-2.6.28.8/fs/ext3/xattr.c
---- linux-2.6.28.8/fs/ext3/xattr.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/ext3/xattr.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/ext3/xattr.c linux-2.6.29.5/fs/ext3/xattr.c
+--- linux-2.6.29.5/fs/ext3/xattr.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/ext3/xattr.c 2009-06-12 23:57:32.000000000 -0400
@@ -89,8 +89,8 @@
printk("\n"); \
} while (0)
@@ -18091,37 +20670,34 @@ diff -urNp linux-2.6.28.8/fs/ext3/xattr.c linux-2.6.28.8/fs/ext3/xattr.c
#endif
static void ext3_xattr_cache_insert(struct buffer_head *);
-diff -urNp linux-2.6.28.8/fs/ext4/balloc.c linux-2.6.28.8/fs/ext4/balloc.c
---- linux-2.6.28.8/fs/ext4/balloc.c 2009-02-20 22:26:39.000000000 -0500
-+++ linux-2.6.28.8/fs/ext4/balloc.c 2009-02-21 09:37:49.000000000 -0500
-@@ -576,7 +576,7 @@ int ext4_has_free_blocks(struct ext4_sb_
+diff -urNp linux-2.6.29.5/fs/ext4/balloc.c linux-2.6.29.5/fs/ext4/balloc.c
+--- linux-2.6.29.5/fs/ext4/balloc.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/ext4/balloc.c 2009-06-12 23:57:32.000000000 -0400
+@@ -577,7 +577,7 @@ int ext4_has_free_blocks(struct ext4_sb_
/* Hm, nope. Are (enough) root reserved blocks available? */
- if (sbi->s_resuid == current->fsuid ||
+ if (sbi->s_resuid == current_fsuid() ||
((sbi->s_resgid != 0) && in_group_p(sbi->s_resgid)) ||
- capable(CAP_SYS_RESOURCE)) {
+ capable_nolog(CAP_SYS_RESOURCE)) {
if (free_blocks >= (nblocks + dirty_blocks))
return 1;
}
-diff -urNp linux-2.6.28.8/fs/ext4/namei.c linux-2.6.28.8/fs/ext4/namei.c
---- linux-2.6.28.8/fs/ext4/namei.c 2009-02-20 22:26:39.000000000 -0500
-+++ linux-2.6.28.8/fs/ext4/namei.c 2009-02-21 09:37:49.000000000 -0500
-@@ -1171,9 +1171,9 @@ static struct ext4_dir_entry_2 *do_split
- u32 hash2;
- struct dx_map_entry *map;
+diff -urNp linux-2.6.29.5/fs/ext4/namei.c linux-2.6.29.5/fs/ext4/namei.c
+--- linux-2.6.29.5/fs/ext4/namei.c 2009-06-12 23:55:00.000000000 -0400
++++ linux-2.6.29.5/fs/ext4/namei.c 2009-06-12 23:57:32.000000000 -0400
+@@ -1177,7 +1177,7 @@ static struct ext4_dir_entry_2 *do_split
char *data1 = (*bh)->b_data, *data2;
-- unsigned split, move, size, i;
-+ unsigned split, move, size;
+ unsigned split, move, size;
struct ext4_dir_entry_2 *de = NULL, *de2;
-- int err = 0;
+- int err = 0, i;
+ int i, err = 0;
bh2 = ext4_append (handle, dir, &newblock, &err);
if (!(bh2)) {
-diff -urNp linux-2.6.28.8/fs/fcntl.c linux-2.6.28.8/fs/fcntl.c
---- linux-2.6.28.8/fs/fcntl.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/fcntl.c 2009-02-21 09:37:49.000000000 -0500
-@@ -266,6 +266,7 @@ static long do_fcntl(int fd, unsigned in
+diff -urNp linux-2.6.29.5/fs/fcntl.c linux-2.6.29.5/fs/fcntl.c
+--- linux-2.6.29.5/fs/fcntl.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/fcntl.c 2009-06-12 23:57:32.000000000 -0400
+@@ -269,6 +269,7 @@ static long do_fcntl(int fd, unsigned in
switch (cmd) {
case F_DUPFD:
case F_DUPFD_CLOEXEC:
@@ -18129,19 +20705,19 @@ diff -urNp linux-2.6.28.8/fs/fcntl.c linux-2.6.28.8/fs/fcntl.c
if (arg >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
break;
err = alloc_fd(arg, cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0);
-@@ -411,7 +412,8 @@ static inline int sigio_perm(struct task
- return (((fown->euid == 0) ||
- (fown->euid == p->suid) || (fown->euid == p->uid) ||
- (fown->uid == p->suid) || (fown->uid == p->uid)) &&
-- !security_file_send_sigiotask(p, fown, sig));
-+ !security_file_send_sigiotask(p, fown, sig) &&
-+ !gr_check_protected_task(p) && !gr_pid_is_chrooted(p));
- }
-
- static void send_sigio_to_task(struct task_struct *p,
-diff -urNp linux-2.6.28.8/fs/file.c linux-2.6.28.8/fs/file.c
---- linux-2.6.28.8/fs/file.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/file.c 2009-02-21 09:37:49.000000000 -0500
+@@ -419,7 +420,8 @@ static inline int sigio_perm(struct task
+ ret = ((fown->euid == 0 ||
+ fown->euid == cred->suid || fown->euid == cred->uid ||
+ fown->uid == cred->suid || fown->uid == cred->uid) &&
+- !security_file_send_sigiotask(p, fown, sig));
++ !security_file_send_sigiotask(p, fown, sig) &&
++ !gr_check_protected_task(p) && !gr_pid_is_chrooted(p));
+ rcu_read_unlock();
+ return ret;
+ }
+diff -urNp linux-2.6.29.5/fs/file.c linux-2.6.29.5/fs/file.c
+--- linux-2.6.29.5/fs/file.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/file.c 2009-06-12 23:57:32.000000000 -0400
@@ -13,6 +13,7 @@
#include <linux/slab.h>
#include <linux/vmalloc.h>
@@ -18159,10 +20735,64 @@ diff -urNp linux-2.6.28.8/fs/file.c linux-2.6.28.8/fs/file.c
if (nr >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
return -EMFILE;
-diff -urNp linux-2.6.28.8/fs/fuse/control.c linux-2.6.28.8/fs/fuse/control.c
---- linux-2.6.28.8/fs/fuse/control.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/fuse/control.c 2009-02-21 09:37:49.000000000 -0500
-@@ -159,7 +159,7 @@ void fuse_ctl_remove_conn(struct fuse_co
+diff -urNp linux-2.6.29.5/fs/fs_struct.c linux-2.6.29.5/fs/fs_struct.c
+--- linux-2.6.29.5/fs/fs_struct.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/fs_struct.c 2009-06-12 23:57:32.000000000 -0400
+@@ -88,7 +88,7 @@ void exit_fs(struct task_struct *tsk)
+ task_lock(tsk);
+ write_lock(&fs->lock);
+ tsk->fs = NULL;
+- kill = !--fs->users;
++ kill = !atomic_dec_return(&fs->users);
+ write_unlock(&fs->lock);
+ task_unlock(tsk);
+ if (kill)
+@@ -101,7 +101,7 @@ struct fs_struct *copy_fs_struct(struct
+ struct fs_struct *fs = kmem_cache_alloc(fs_cachep, GFP_KERNEL);
+ /* We don't need to lock fs - think why ;-) */
+ if (fs) {
+- fs->users = 1;
++ atomic_set(&fs->users, 1);
+ fs->in_exec = 0;
+ rwlock_init(&fs->lock);
+ fs->umask = old->umask;
+@@ -126,7 +126,7 @@ int unshare_fs_struct(void)
+
+ task_lock(current);
+ write_lock(&fs->lock);
+- kill = !--fs->users;
++ kill = !atomic_dec_return(&fs->users);
+ current->fs = new_fs;
+ write_unlock(&fs->lock);
+ task_unlock(current);
+@@ -140,7 +140,7 @@ EXPORT_SYMBOL_GPL(unshare_fs_struct);
+
+ /* to be mentioned only in INIT_TASK */
+ struct fs_struct init_fs = {
+- .users = 1,
++ .users = ATOMIC_INIT(1),
+ .lock = __RW_LOCK_UNLOCKED(init_fs.lock),
+ .umask = 0022,
+ };
+@@ -155,12 +155,12 @@ void daemonize_fs_struct(void)
+ task_lock(current);
+
+ write_lock(&init_fs.lock);
+- init_fs.users++;
++ atomic_inc(&init_fs.users);
+ write_unlock(&init_fs.lock);
+
+ write_lock(&fs->lock);
+ current->fs = &init_fs;
+- kill = !--fs->users;
++ kill = !atomic_dec_return(&fs->users);
+ write_unlock(&fs->lock);
+
+ task_unlock(current);
+diff -urNp linux-2.6.29.5/fs/fuse/control.c linux-2.6.29.5/fs/fuse/control.c
+--- linux-2.6.29.5/fs/fuse/control.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/fuse/control.c 2009-06-12 23:57:32.000000000 -0400
+@@ -161,7 +161,7 @@ void fuse_ctl_remove_conn(struct fuse_co
static int fuse_ctl_fill_super(struct super_block *sb, void *data, int silent)
{
@@ -18171,10 +20801,10 @@ diff -urNp linux-2.6.28.8/fs/fuse/control.c linux-2.6.28.8/fs/fuse/control.c
struct fuse_conn *fc;
int err;
-diff -urNp linux-2.6.28.8/fs/fuse/dir.c linux-2.6.28.8/fs/fuse/dir.c
---- linux-2.6.28.8/fs/fuse/dir.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/fuse/dir.c 2009-02-21 09:37:49.000000000 -0500
-@@ -1072,7 +1072,7 @@ static char *read_link(struct dentry *de
+diff -urNp linux-2.6.29.5/fs/fuse/dir.c linux-2.6.29.5/fs/fuse/dir.c
+--- linux-2.6.29.5/fs/fuse/dir.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/fuse/dir.c 2009-06-12 23:57:32.000000000 -0400
+@@ -1081,7 +1081,7 @@ static char *read_link(struct dentry *de
return link;
}
@@ -18183,9 +20813,9 @@ diff -urNp linux-2.6.28.8/fs/fuse/dir.c linux-2.6.28.8/fs/fuse/dir.c
{
if (!IS_ERR(link))
free_page((unsigned long) link);
-diff -urNp linux-2.6.28.8/fs/hfs/inode.c linux-2.6.28.8/fs/hfs/inode.c
---- linux-2.6.28.8/fs/hfs/inode.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/hfs/inode.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/hfs/inode.c linux-2.6.29.5/fs/hfs/inode.c
+--- linux-2.6.29.5/fs/hfs/inode.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/hfs/inode.c 2009-06-12 23:57:32.000000000 -0400
@@ -419,7 +419,7 @@ int hfs_write_inode(struct inode *inode,
if (S_ISDIR(main_inode->i_mode)) {
@@ -18204,9 +20834,9 @@ diff -urNp linux-2.6.28.8/fs/hfs/inode.c linux-2.6.28.8/fs/hfs/inode.c
hfs_bnode_read(fd.bnode, &rec, fd.entryoffset,
sizeof(struct hfs_cat_file));
if (rec.type != HFS_CDR_FIL ||
-diff -urNp linux-2.6.28.8/fs/hfsplus/inode.c linux-2.6.28.8/fs/hfsplus/inode.c
---- linux-2.6.28.8/fs/hfsplus/inode.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/hfsplus/inode.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/hfsplus/inode.c linux-2.6.29.5/fs/hfsplus/inode.c
+--- linux-2.6.29.5/fs/hfsplus/inode.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/hfsplus/inode.c 2009-06-12 23:57:32.000000000 -0400
@@ -406,7 +406,7 @@ int hfsplus_cat_read_inode(struct inode
struct hfsplus_cat_folder *folder = &entry.folder;
@@ -18243,9 +20873,9 @@ diff -urNp linux-2.6.28.8/fs/hfsplus/inode.c linux-2.6.28.8/fs/hfsplus/inode.c
hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
sizeof(struct hfsplus_cat_file));
hfsplus_inode_write_fork(inode, &file->data_fork);
-diff -urNp linux-2.6.28.8/fs/jffs2/debug.h linux-2.6.28.8/fs/jffs2/debug.h
---- linux-2.6.28.8/fs/jffs2/debug.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/jffs2/debug.h 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/jffs2/debug.h linux-2.6.29.5/fs/jffs2/debug.h
+--- linux-2.6.29.5/fs/jffs2/debug.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/jffs2/debug.h 2009-06-12 23:57:32.000000000 -0400
@@ -52,13 +52,13 @@
#if CONFIG_JFFS2_FS_DEBUG > 0
#define D1(x) x
@@ -18347,10 +20977,10 @@ diff -urNp linux-2.6.28.8/fs/jffs2/debug.h linux-2.6.28.8/fs/jffs2/debug.h
#endif
/* "Sanity" checks */
-diff -urNp linux-2.6.28.8/fs/jffs2/erase.c linux-2.6.28.8/fs/jffs2/erase.c
---- linux-2.6.28.8/fs/jffs2/erase.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/jffs2/erase.c 2009-02-21 09:37:49.000000000 -0500
-@@ -431,7 +431,8 @@ static void jffs2_mark_erased_block(stru
+diff -urNp linux-2.6.29.5/fs/jffs2/erase.c linux-2.6.29.5/fs/jffs2/erase.c
+--- linux-2.6.29.5/fs/jffs2/erase.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/jffs2/erase.c 2009-06-12 23:57:32.000000000 -0400
+@@ -432,7 +432,8 @@ static void jffs2_mark_erased_block(stru
struct jffs2_unknown_node marker = {
.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK),
.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER),
@@ -18360,9 +20990,9 @@ diff -urNp linux-2.6.28.8/fs/jffs2/erase.c linux-2.6.28.8/fs/jffs2/erase.c
};
jffs2_prealloc_raw_node_refs(c, jeb, 1);
-diff -urNp linux-2.6.28.8/fs/jffs2/summary.h linux-2.6.28.8/fs/jffs2/summary.h
---- linux-2.6.28.8/fs/jffs2/summary.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/jffs2/summary.h 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/jffs2/summary.h linux-2.6.29.5/fs/jffs2/summary.h
+--- linux-2.6.29.5/fs/jffs2/summary.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/jffs2/summary.h 2009-06-12 23:57:32.000000000 -0400
@@ -194,18 +194,18 @@ int jffs2_sum_scan_sumnode(struct jffs2_
#define jffs2_sum_active() (0)
@@ -18391,9 +21021,9 @@ diff -urNp linux-2.6.28.8/fs/jffs2/summary.h linux-2.6.28.8/fs/jffs2/summary.h
#define jffs2_sum_scan_sumnode(a,b,c,d,e) (0)
#endif /* CONFIG_JFFS2_SUMMARY */
-diff -urNp linux-2.6.28.8/fs/jffs2/wbuf.c linux-2.6.28.8/fs/jffs2/wbuf.c
---- linux-2.6.28.8/fs/jffs2/wbuf.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/jffs2/wbuf.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/jffs2/wbuf.c linux-2.6.29.5/fs/jffs2/wbuf.c
+--- linux-2.6.29.5/fs/jffs2/wbuf.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/jffs2/wbuf.c 2009-06-12 23:57:32.000000000 -0400
@@ -1012,7 +1012,8 @@ static const struct jffs2_unknown_node o
{
.magic = constant_cpu_to_je16(JFFS2_MAGIC_BITMASK),
@@ -18404,9 +21034,9 @@ diff -urNp linux-2.6.28.8/fs/jffs2/wbuf.c linux-2.6.28.8/fs/jffs2/wbuf.c
};
/*
-diff -urNp linux-2.6.28.8/fs/locks.c linux-2.6.28.8/fs/locks.c
---- linux-2.6.28.8/fs/locks.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/locks.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/locks.c linux-2.6.29.5/fs/locks.c
+--- linux-2.6.29.5/fs/locks.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/locks.c 2009-06-12 23:57:32.000000000 -0400
@@ -2006,16 +2006,16 @@ void locks_remove_flock(struct file *fil
return;
@@ -18428,10 +21058,10 @@ diff -urNp linux-2.6.28.8/fs/locks.c linux-2.6.28.8/fs/locks.c
}
lock_kernel();
-diff -urNp linux-2.6.28.8/fs/namei.c linux-2.6.28.8/fs/namei.c
---- linux-2.6.28.8/fs/namei.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/namei.c 2009-03-07 04:29:14.000000000 -0500
-@@ -633,7 +633,7 @@ static __always_inline int __do_follow_l
+diff -urNp linux-2.6.29.5/fs/namei.c linux-2.6.29.5/fs/namei.c
+--- linux-2.6.29.5/fs/namei.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/namei.c 2009-06-12 23:57:32.000000000 -0400
+@@ -622,7 +622,7 @@ static __always_inline int __do_follow_l
cookie = dentry->d_inode->i_op->follow_link(dentry, nd);
error = PTR_ERR(cookie);
if (!IS_ERR(cookie)) {
@@ -18440,7 +21070,7 @@ diff -urNp linux-2.6.28.8/fs/namei.c linux-2.6.28.8/fs/namei.c
error = 0;
if (s)
error = __vfs_follow_link(nd, s);
-@@ -664,6 +664,13 @@ static inline int do_follow_link(struct
+@@ -653,6 +653,13 @@ static inline int do_follow_link(struct
err = security_inode_follow_link(path->dentry, nd);
if (err)
goto loop;
@@ -18454,7 +21084,7 @@ diff -urNp linux-2.6.28.8/fs/namei.c linux-2.6.28.8/fs/namei.c
current->link_count++;
current->total_link_count++;
nd->depth++;
-@@ -1012,11 +1019,18 @@ return_reval:
+@@ -996,11 +1003,18 @@ return_reval:
break;
}
return_base:
@@ -18473,25 +21103,27 @@ diff -urNp linux-2.6.28.8/fs/namei.c linux-2.6.28.8/fs/namei.c
path_put(&nd->path);
return_err:
return err;
-@@ -1582,9 +1596,17 @@ static int __open_namei_create(struct na
+@@ -1571,12 +1585,19 @@ static int __open_namei_create(struct na
int error;
struct dentry *dir = nd->path.dentry;
+ if (!gr_acl_handle_creat(path->dentry, nd->path.dentry, nd->path.mnt, flag, mode)) {
+ error = -EACCES;
-+ goto out_unlock_dput;
++ goto out_unlock;
+ }
+
if (!IS_POSIXACL(dir->d_inode))
mode &= ~current->fs->umask;
+ error = security_path_mknod(&nd->path, path->dentry, mode, 0);
+ if (error)
+ goto out_unlock;
error = vfs_create(dir->d_inode, path->dentry, mode, nd);
+ if (!error)
+ gr_handle_create(path->dentry, nd->path.mnt);
-+out_unlock_dput:
+ out_unlock:
mutex_unlock(&dir->d_inode->i_mutex);
dput(nd->path.dentry);
- nd->path.dentry = path->dentry;
-@@ -1665,6 +1687,17 @@ struct file *do_filp_open(int dfd, const
+@@ -1658,6 +1679,17 @@ struct file *do_filp_open(int dfd, const
&nd, flag);
if (error)
return ERR_PTR(error);
@@ -18509,7 +21141,7 @@ diff -urNp linux-2.6.28.8/fs/namei.c linux-2.6.28.8/fs/namei.c
goto ok;
}
-@@ -1737,6 +1770,20 @@ do_last:
+@@ -1730,6 +1762,20 @@ do_last:
/*
* It already exists.
*/
@@ -18530,7 +21162,7 @@ diff -urNp linux-2.6.28.8/fs/namei.c linux-2.6.28.8/fs/namei.c
mutex_unlock(&dir->d_inode->i_mutex);
audit_inode(pathname, path.dentry);
-@@ -1822,6 +1869,13 @@ do_link:
+@@ -1815,6 +1861,13 @@ do_link:
error = security_inode_follow_link(path.dentry, &nd);
if (error)
goto exit_dput;
@@ -18544,7 +21176,7 @@ diff -urNp linux-2.6.28.8/fs/namei.c linux-2.6.28.8/fs/namei.c
error = __do_follow_link(&path, &nd);
if (error) {
/* Does someone understand code flow here? Or it is only
-@@ -1994,6 +2048,17 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const
+@@ -1987,6 +2040,17 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const
error = may_mknod(mode);
if (error)
goto out_dput;
@@ -18562,9 +21194,9 @@ diff -urNp linux-2.6.28.8/fs/namei.c linux-2.6.28.8/fs/namei.c
error = mnt_want_write(nd.path.mnt);
if (error)
goto out_dput;
-@@ -2010,6 +2075,9 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const
- break;
+@@ -2007,6 +2071,9 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const
}
+ out_drop_write:
mnt_drop_write(nd.path.mnt);
+
+ if (!error)
@@ -18572,7 +21204,7 @@ diff -urNp linux-2.6.28.8/fs/namei.c linux-2.6.28.8/fs/namei.c
out_dput:
dput(dentry);
out_unlock:
-@@ -2063,6 +2131,11 @@ SYSCALL_DEFINE3(mkdirat, int, dfd, const
+@@ -2060,6 +2127,11 @@ SYSCALL_DEFINE3(mkdirat, int, dfd, const
if (IS_ERR(dentry))
goto out_unlock;
@@ -18584,9 +21216,9 @@ diff -urNp linux-2.6.28.8/fs/namei.c linux-2.6.28.8/fs/namei.c
if (!IS_POSIXACL(nd.path.dentry->d_inode))
mode &= ~current->fs->umask;
error = mnt_want_write(nd.path.mnt);
-@@ -2070,6 +2143,10 @@ SYSCALL_DEFINE3(mkdirat, int, dfd, const
- goto out_dput;
+@@ -2071,6 +2143,10 @@ SYSCALL_DEFINE3(mkdirat, int, dfd, const
error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode);
+ out_drop_write:
mnt_drop_write(nd.path.mnt);
+
+ if (!error)
@@ -18595,7 +21227,7 @@ diff -urNp linux-2.6.28.8/fs/namei.c linux-2.6.28.8/fs/namei.c
out_dput:
dput(dentry);
out_unlock:
-@@ -2151,6 +2228,8 @@ static long do_rmdir(int dfd, const char
+@@ -2152,6 +2228,8 @@ static long do_rmdir(int dfd, const char
char * name;
struct dentry *dentry;
struct nameidata nd;
@@ -18604,7 +21236,7 @@ diff -urNp linux-2.6.28.8/fs/namei.c linux-2.6.28.8/fs/namei.c
error = user_path_parent(dfd, pathname, &nd, &name);
if (error)
-@@ -2175,11 +2254,26 @@ static long do_rmdir(int dfd, const char
+@@ -2176,6 +2254,19 @@ static long do_rmdir(int dfd, const char
error = PTR_ERR(dentry);
if (IS_ERR(dentry))
goto exit2;
@@ -18624,14 +21256,16 @@ diff -urNp linux-2.6.28.8/fs/namei.c linux-2.6.28.8/fs/namei.c
error = mnt_want_write(nd.path.mnt);
if (error)
goto exit3;
+@@ -2183,6 +2274,8 @@ static long do_rmdir(int dfd, const char
+ if (error)
+ goto exit4;
error = vfs_rmdir(nd.path.dentry->d_inode, dentry);
- mnt_drop_write(nd.path.mnt);
+ if (!error && (saved_dev || saved_ino))
+ gr_handle_delete(saved_ino, saved_dev);
+ exit4:
+ mnt_drop_write(nd.path.mnt);
exit3:
- dput(dentry);
- exit2:
-@@ -2239,6 +2333,8 @@ static long do_unlinkat(int dfd, const c
+@@ -2244,6 +2337,8 @@ static long do_unlinkat(int dfd, const c
struct dentry *dentry;
struct nameidata nd;
struct inode *inode = NULL;
@@ -18640,7 +21274,7 @@ diff -urNp linux-2.6.28.8/fs/namei.c linux-2.6.28.8/fs/namei.c
error = user_path_parent(dfd, pathname, &nd, &name);
if (error)
-@@ -2258,12 +2354,25 @@ static long do_unlinkat(int dfd, const c
+@@ -2263,8 +2358,19 @@ static long do_unlinkat(int dfd, const c
if (nd.last.name[nd.last.len])
goto slashes;
inode = dentry->d_inode;
@@ -18661,13 +21295,16 @@ diff -urNp linux-2.6.28.8/fs/namei.c linux-2.6.28.8/fs/namei.c
error = mnt_want_write(nd.path.mnt);
if (error)
goto exit2;
+@@ -2272,6 +2378,8 @@ static long do_unlinkat(int dfd, const c
+ if (error)
+ goto exit3;
error = vfs_unlink(nd.path.dentry->d_inode, dentry);
+ if (!error && (saved_ino || saved_dev))
+ gr_handle_delete(saved_ino, saved_dev);
+ exit3:
mnt_drop_write(nd.path.mnt);
exit2:
- dput(dentry);
-@@ -2341,10 +2450,17 @@ SYSCALL_DEFINE3(symlinkat, const char __
+@@ -2350,6 +2458,11 @@ SYSCALL_DEFINE3(symlinkat, const char __
if (IS_ERR(dentry))
goto out_unlock;
@@ -18679,13 +21316,16 @@ diff -urNp linux-2.6.28.8/fs/namei.c linux-2.6.28.8/fs/namei.c
error = mnt_want_write(nd.path.mnt);
if (error)
goto out_dput;
+@@ -2357,6 +2470,8 @@ SYSCALL_DEFINE3(symlinkat, const char __
+ if (error)
+ goto out_drop_write;
error = vfs_symlink(nd.path.dentry->d_inode, dentry, from);
+ if (!error)
+ gr_handle_create(dentry, nd.path.mnt);
+ out_drop_write:
mnt_drop_write(nd.path.mnt);
out_dput:
- dput(dentry);
-@@ -2437,10 +2553,26 @@ SYSCALL_DEFINE5(linkat, int, olddfd, con
+@@ -2450,6 +2565,20 @@ SYSCALL_DEFINE5(linkat, int, olddfd, con
error = PTR_ERR(new_dentry);
if (IS_ERR(new_dentry))
goto out_unlock;
@@ -18706,13 +21346,16 @@ diff -urNp linux-2.6.28.8/fs/namei.c linux-2.6.28.8/fs/namei.c
error = mnt_want_write(nd.path.mnt);
if (error)
goto out_dput;
+@@ -2457,6 +2586,8 @@ SYSCALL_DEFINE5(linkat, int, olddfd, con
+ if (error)
+ goto out_drop_write;
error = vfs_link(old_path.dentry, nd.path.dentry->d_inode, new_dentry);
+ if (!error)
+ gr_handle_create(new_dentry, nd.path.mnt);
+ out_drop_write:
mnt_drop_write(nd.path.mnt);
out_dput:
- dput(new_dentry);
-@@ -2673,11 +2805,21 @@ SYSCALL_DEFINE4(renameat, int, olddfd, c
+@@ -2690,6 +2821,12 @@ SYSCALL_DEFINE4(renameat, int, olddfd, c
if (new_dentry == trap)
goto exit5;
@@ -18725,19 +21368,20 @@ diff -urNp linux-2.6.28.8/fs/namei.c linux-2.6.28.8/fs/namei.c
error = mnt_want_write(oldnd.path.mnt);
if (error)
goto exit5;
+@@ -2699,6 +2836,9 @@ SYSCALL_DEFINE4(renameat, int, olddfd, c
+ goto exit6;
error = vfs_rename(old_dir->d_inode, old_dentry,
new_dir->d_inode, new_dentry);
+ if (!error)
+ gr_handle_rename(old_dir->d_inode, new_dir->d_inode, old_dentry,
+ new_dentry, oldnd.path.mnt, new_dentry->d_inode ? 1 : 0);
-+
+ exit6:
mnt_drop_write(oldnd.path.mnt);
exit5:
- dput(new_dentry);
-diff -urNp linux-2.6.28.8/fs/namespace.c linux-2.6.28.8/fs/namespace.c
---- linux-2.6.28.8/fs/namespace.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/namespace.c 2009-02-21 09:37:49.000000000 -0500
-@@ -1094,6 +1094,8 @@ static int do_umount(struct vfsmount *mn
+diff -urNp linux-2.6.29.5/fs/namespace.c linux-2.6.29.5/fs/namespace.c
+--- linux-2.6.29.5/fs/namespace.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/namespace.c 2009-06-12 23:57:32.000000000 -0400
+@@ -1096,6 +1096,8 @@ static int do_umount(struct vfsmount *mn
lock_kernel();
retval = do_remount_sb(sb, MS_RDONLY, NULL, 0);
unlock_kernel();
@@ -18746,7 +21390,7 @@ diff -urNp linux-2.6.28.8/fs/namespace.c linux-2.6.28.8/fs/namespace.c
}
up_write(&sb->s_umount);
return retval;
-@@ -1117,6 +1119,9 @@ static int do_umount(struct vfsmount *mn
+@@ -1119,6 +1121,9 @@ static int do_umount(struct vfsmount *mn
security_sb_umount_busy(mnt);
up_write(&namespace_sem);
release_mounts(&umount_list);
@@ -18756,7 +21400,7 @@ diff -urNp linux-2.6.28.8/fs/namespace.c linux-2.6.28.8/fs/namespace.c
return retval;
}
-@@ -1946,6 +1951,11 @@ long do_mount(char *dev_name, char *dir_
+@@ -1948,6 +1953,11 @@ long do_mount(char *dev_name, char *dir_
if (retval)
goto dput_out;
@@ -18768,7 +21412,7 @@ diff -urNp linux-2.6.28.8/fs/namespace.c linux-2.6.28.8/fs/namespace.c
if (flags & MS_REMOUNT)
retval = do_remount(&path, flags & ~MS_REMOUNT, mnt_flags,
data_page);
-@@ -1960,6 +1970,9 @@ long do_mount(char *dev_name, char *dir_
+@@ -1962,6 +1972,9 @@ long do_mount(char *dev_name, char *dir_
dev_name, data_page);
dput_out:
path_put(&path);
@@ -18778,7 +21422,7 @@ diff -urNp linux-2.6.28.8/fs/namespace.c linux-2.6.28.8/fs/namespace.c
return retval;
}
-@@ -2071,6 +2084,9 @@ SYSCALL_DEFINE5(mount, char __user *, de
+@@ -2073,6 +2086,9 @@ SYSCALL_DEFINE5(mount, char __user *, de
if (retval < 0)
goto out3;
@@ -18788,10 +21432,10 @@ diff -urNp linux-2.6.28.8/fs/namespace.c linux-2.6.28.8/fs/namespace.c
lock_kernel();
retval = do_mount((char *)dev_page, dir_page, (char *)type_page,
flags, (void *)data_page);
-diff -urNp linux-2.6.28.8/fs/nfs/nfs4proc.c linux-2.6.28.8/fs/nfs/nfs4proc.c
---- linux-2.6.28.8/fs/nfs/nfs4proc.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/nfs/nfs4proc.c 2009-02-21 09:37:49.000000000 -0500
-@@ -653,7 +653,7 @@ static int _nfs4_do_open_reclaim(struct
+diff -urNp linux-2.6.29.5/fs/nfs/nfs4proc.c linux-2.6.29.5/fs/nfs/nfs4proc.c
+--- linux-2.6.29.5/fs/nfs/nfs4proc.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/nfs/nfs4proc.c 2009-06-12 23:57:32.000000000 -0400
+@@ -763,7 +763,7 @@ static int _nfs4_do_open_reclaim(struct
static int nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state *state)
{
struct nfs_server *server = NFS_SERVER(state->inode);
@@ -18800,7 +21444,7 @@ diff -urNp linux-2.6.28.8/fs/nfs/nfs4proc.c linux-2.6.28.8/fs/nfs/nfs4proc.c
int err;
do {
err = _nfs4_do_open_reclaim(ctx, state);
-@@ -695,7 +695,7 @@ static int _nfs4_open_delegation_recall(
+@@ -805,7 +805,7 @@ static int _nfs4_open_delegation_recall(
int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid)
{
@@ -18809,7 +21453,7 @@ diff -urNp linux-2.6.28.8/fs/nfs/nfs4proc.c linux-2.6.28.8/fs/nfs/nfs4proc.c
struct nfs_server *server = NFS_SERVER(state->inode);
int err;
do {
-@@ -988,7 +988,7 @@ static int _nfs4_open_expired(struct nfs
+@@ -1099,7 +1099,7 @@ static int _nfs4_open_expired(struct nfs
static inline int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state)
{
struct nfs_server *server = NFS_SERVER(state->inode);
@@ -18818,16 +21462,16 @@ diff -urNp linux-2.6.28.8/fs/nfs/nfs4proc.c linux-2.6.28.8/fs/nfs/nfs4proc.c
int err;
do {
-@@ -1090,7 +1090,7 @@ out_err:
+@@ -1197,7 +1197,7 @@ out_err:
- static struct nfs4_state *nfs4_do_open(struct inode *dir, struct path *path, int flags, struct iattr *sattr, struct rpc_cred *cred)
+ static struct nfs4_state *nfs4_do_open(struct inode *dir, struct path *path, fmode_t fmode, int flags, struct iattr *sattr, struct rpc_cred *cred)
{
- struct nfs4_exception exception = { };
+ struct nfs4_exception exception = {0, 0};
struct nfs4_state *res;
int status;
-@@ -1181,7 +1181,7 @@ static int nfs4_do_setattr(struct inode
+@@ -1288,7 +1288,7 @@ static int nfs4_do_setattr(struct inode
struct nfs4_state *state)
{
struct nfs_server *server = NFS_SERVER(inode);
@@ -18836,7 +21480,7 @@ diff -urNp linux-2.6.28.8/fs/nfs/nfs4proc.c linux-2.6.28.8/fs/nfs/nfs4proc.c
int err;
do {
err = nfs4_handle_exception(server,
-@@ -1494,7 +1494,7 @@ static int _nfs4_server_capabilities(str
+@@ -1607,7 +1607,7 @@ static int _nfs4_server_capabilities(str
int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
{
@@ -18845,7 +21489,7 @@ diff -urNp linux-2.6.28.8/fs/nfs/nfs4proc.c linux-2.6.28.8/fs/nfs/nfs4proc.c
int err;
do {
err = nfs4_handle_exception(server,
-@@ -1527,7 +1527,7 @@ static int _nfs4_lookup_root(struct nfs_
+@@ -1640,7 +1640,7 @@ static int _nfs4_lookup_root(struct nfs_
static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_fsinfo *info)
{
@@ -18854,7 +21498,7 @@ diff -urNp linux-2.6.28.8/fs/nfs/nfs4proc.c linux-2.6.28.8/fs/nfs/nfs4proc.c
int err;
do {
err = nfs4_handle_exception(server,
-@@ -1616,7 +1616,7 @@ static int _nfs4_proc_getattr(struct nfs
+@@ -1729,7 +1729,7 @@ static int _nfs4_proc_getattr(struct nfs
static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
{
@@ -18863,7 +21507,7 @@ diff -urNp linux-2.6.28.8/fs/nfs/nfs4proc.c linux-2.6.28.8/fs/nfs/nfs4proc.c
int err;
do {
err = nfs4_handle_exception(server,
-@@ -1704,7 +1704,7 @@ static int nfs4_proc_lookupfh(struct nfs
+@@ -1817,7 +1817,7 @@ static int nfs4_proc_lookupfh(struct nfs
struct qstr *name, struct nfs_fh *fhandle,
struct nfs_fattr *fattr)
{
@@ -18872,7 +21516,7 @@ diff -urNp linux-2.6.28.8/fs/nfs/nfs4proc.c linux-2.6.28.8/fs/nfs/nfs4proc.c
int err;
do {
err = _nfs4_proc_lookupfh(server, dirfh, name, fhandle, fattr);
-@@ -1733,7 +1733,7 @@ static int _nfs4_proc_lookup(struct inod
+@@ -1846,7 +1846,7 @@ static int _nfs4_proc_lookup(struct inod
static int nfs4_proc_lookup(struct inode *dir, struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
{
@@ -18881,7 +21525,7 @@ diff -urNp linux-2.6.28.8/fs/nfs/nfs4proc.c linux-2.6.28.8/fs/nfs/nfs4proc.c
int err;
do {
err = nfs4_handle_exception(NFS_SERVER(dir),
-@@ -1797,7 +1797,7 @@ static int _nfs4_proc_access(struct inod
+@@ -1910,7 +1910,7 @@ static int _nfs4_proc_access(struct inod
static int nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry)
{
@@ -18890,7 +21534,7 @@ diff -urNp linux-2.6.28.8/fs/nfs/nfs4proc.c linux-2.6.28.8/fs/nfs/nfs4proc.c
int err;
do {
err = nfs4_handle_exception(NFS_SERVER(inode),
-@@ -1852,7 +1852,7 @@ static int _nfs4_proc_readlink(struct in
+@@ -1965,7 +1965,7 @@ static int _nfs4_proc_readlink(struct in
static int nfs4_proc_readlink(struct inode *inode, struct page *page,
unsigned int pgbase, unsigned int pglen)
{
@@ -18899,7 +21543,7 @@ diff -urNp linux-2.6.28.8/fs/nfs/nfs4proc.c linux-2.6.28.8/fs/nfs/nfs4proc.c
int err;
do {
err = nfs4_handle_exception(NFS_SERVER(inode),
-@@ -1949,7 +1949,7 @@ static int _nfs4_proc_remove(struct inod
+@@ -2063,7 +2063,7 @@ static int _nfs4_proc_remove(struct inod
static int nfs4_proc_remove(struct inode *dir, struct qstr *name)
{
@@ -18908,7 +21552,7 @@ diff -urNp linux-2.6.28.8/fs/nfs/nfs4proc.c linux-2.6.28.8/fs/nfs/nfs4proc.c
int err;
do {
err = nfs4_handle_exception(NFS_SERVER(dir),
-@@ -2021,7 +2021,7 @@ static int _nfs4_proc_rename(struct inod
+@@ -2135,7 +2135,7 @@ static int _nfs4_proc_rename(struct inod
static int nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
struct inode *new_dir, struct qstr *new_name)
{
@@ -18917,7 +21561,7 @@ diff -urNp linux-2.6.28.8/fs/nfs/nfs4proc.c linux-2.6.28.8/fs/nfs/nfs4proc.c
int err;
do {
err = nfs4_handle_exception(NFS_SERVER(old_dir),
-@@ -2068,7 +2068,7 @@ static int _nfs4_proc_link(struct inode
+@@ -2182,7 +2182,7 @@ static int _nfs4_proc_link(struct inode
static int nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
{
@@ -18926,7 +21570,7 @@ diff -urNp linux-2.6.28.8/fs/nfs/nfs4proc.c linux-2.6.28.8/fs/nfs/nfs4proc.c
int err;
do {
err = nfs4_handle_exception(NFS_SERVER(inode),
-@@ -2159,7 +2159,7 @@ out:
+@@ -2273,7 +2273,7 @@ out:
static int nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
struct page *page, unsigned int len, struct iattr *sattr)
{
@@ -18935,7 +21579,7 @@ diff -urNp linux-2.6.28.8/fs/nfs/nfs4proc.c linux-2.6.28.8/fs/nfs/nfs4proc.c
int err;
do {
err = nfs4_handle_exception(NFS_SERVER(dir),
-@@ -2190,7 +2190,7 @@ out:
+@@ -2304,7 +2304,7 @@ out:
static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
struct iattr *sattr)
{
@@ -18944,7 +21588,7 @@ diff -urNp linux-2.6.28.8/fs/nfs/nfs4proc.c linux-2.6.28.8/fs/nfs/nfs4proc.c
int err;
do {
err = nfs4_handle_exception(NFS_SERVER(dir),
-@@ -2239,7 +2239,7 @@ static int _nfs4_proc_readdir(struct den
+@@ -2353,7 +2353,7 @@ static int _nfs4_proc_readdir(struct den
static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
u64 cookie, struct page *page, unsigned int count, int plus)
{
@@ -18953,7 +21597,7 @@ diff -urNp linux-2.6.28.8/fs/nfs/nfs4proc.c linux-2.6.28.8/fs/nfs/nfs4proc.c
int err;
do {
err = nfs4_handle_exception(NFS_SERVER(dentry->d_inode),
-@@ -2287,7 +2287,7 @@ out:
+@@ -2401,7 +2401,7 @@ out:
static int nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
struct iattr *sattr, dev_t rdev)
{
@@ -18962,7 +21606,7 @@ diff -urNp linux-2.6.28.8/fs/nfs/nfs4proc.c linux-2.6.28.8/fs/nfs/nfs4proc.c
int err;
do {
err = nfs4_handle_exception(NFS_SERVER(dir),
-@@ -2316,7 +2316,7 @@ static int _nfs4_proc_statfs(struct nfs_
+@@ -2430,7 +2430,7 @@ static int _nfs4_proc_statfs(struct nfs_
static int nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsstat *fsstat)
{
@@ -18971,7 +21615,7 @@ diff -urNp linux-2.6.28.8/fs/nfs/nfs4proc.c linux-2.6.28.8/fs/nfs/nfs4proc.c
int err;
do {
err = nfs4_handle_exception(server,
-@@ -2344,7 +2344,7 @@ static int _nfs4_do_fsinfo(struct nfs_se
+@@ -2458,7 +2458,7 @@ static int _nfs4_do_fsinfo(struct nfs_se
static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo)
{
@@ -18980,7 +21624,7 @@ diff -urNp linux-2.6.28.8/fs/nfs/nfs4proc.c linux-2.6.28.8/fs/nfs/nfs4proc.c
int err;
do {
-@@ -2387,7 +2387,7 @@ static int _nfs4_proc_pathconf(struct nf
+@@ -2501,7 +2501,7 @@ static int _nfs4_proc_pathconf(struct nf
static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_pathconf *pathconf)
{
@@ -18989,7 +21633,7 @@ diff -urNp linux-2.6.28.8/fs/nfs/nfs4proc.c linux-2.6.28.8/fs/nfs/nfs4proc.c
int err;
do {
-@@ -2674,7 +2674,7 @@ out_free:
+@@ -2788,7 +2788,7 @@ out_free:
static ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen)
{
@@ -18998,7 +21642,7 @@ diff -urNp linux-2.6.28.8/fs/nfs/nfs4proc.c linux-2.6.28.8/fs/nfs/nfs4proc.c
ssize_t ret;
do {
ret = __nfs4_get_acl_uncached(inode, buf, buflen);
-@@ -2731,7 +2731,7 @@ static int __nfs4_proc_set_acl(struct in
+@@ -2845,7 +2845,7 @@ static int __nfs4_proc_set_acl(struct in
static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen)
{
@@ -19007,7 +21651,7 @@ diff -urNp linux-2.6.28.8/fs/nfs/nfs4proc.c linux-2.6.28.8/fs/nfs/nfs4proc.c
int err;
do {
err = nfs4_handle_exception(NFS_SERVER(inode),
-@@ -3022,7 +3022,7 @@ out:
+@@ -3068,7 +3068,7 @@ out:
int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid, int issync)
{
struct nfs_server *server = NFS_SERVER(inode);
@@ -19016,7 +21660,7 @@ diff -urNp linux-2.6.28.8/fs/nfs/nfs4proc.c linux-2.6.28.8/fs/nfs/nfs4proc.c
int err;
do {
err = _nfs4_proc_delegreturn(inode, cred, stateid, issync);
-@@ -3097,7 +3097,7 @@ out:
+@@ -3141,7 +3141,7 @@ out:
static int nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock *request)
{
@@ -19025,7 +21669,7 @@ diff -urNp linux-2.6.28.8/fs/nfs/nfs4proc.c linux-2.6.28.8/fs/nfs/nfs4proc.c
int err;
do {
-@@ -3447,7 +3447,7 @@ static int _nfs4_do_setlk(struct nfs4_st
+@@ -3498,7 +3498,7 @@ static int _nfs4_do_setlk(struct nfs4_st
static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request)
{
struct nfs_server *server = NFS_SERVER(state->inode);
@@ -19034,7 +21678,7 @@ diff -urNp linux-2.6.28.8/fs/nfs/nfs4proc.c linux-2.6.28.8/fs/nfs/nfs4proc.c
int err;
do {
-@@ -3465,7 +3465,7 @@ static int nfs4_lock_reclaim(struct nfs4
+@@ -3516,7 +3516,7 @@ static int nfs4_lock_reclaim(struct nfs4
static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request)
{
struct nfs_server *server = NFS_SERVER(state->inode);
@@ -19043,7 +21687,7 @@ diff -urNp linux-2.6.28.8/fs/nfs/nfs4proc.c linux-2.6.28.8/fs/nfs/nfs4proc.c
int err;
err = nfs4_set_lock_state(state, request);
-@@ -3526,7 +3526,7 @@ out:
+@@ -3571,7 +3571,7 @@ out:
static int nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
{
@@ -19052,7 +21696,7 @@ diff -urNp linux-2.6.28.8/fs/nfs/nfs4proc.c linux-2.6.28.8/fs/nfs/nfs4proc.c
int err;
do {
-@@ -3576,7 +3576,7 @@ nfs4_proc_lock(struct file *filp, int cm
+@@ -3621,7 +3621,7 @@ nfs4_proc_lock(struct file *filp, int cm
int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl)
{
struct nfs_server *server = NFS_SERVER(state->inode);
@@ -19061,9 +21705,9 @@ diff -urNp linux-2.6.28.8/fs/nfs/nfs4proc.c linux-2.6.28.8/fs/nfs/nfs4proc.c
int err;
err = nfs4_set_lock_state(state, fl);
-diff -urNp linux-2.6.28.8/fs/nfsd/export.c linux-2.6.28.8/fs/nfsd/export.c
---- linux-2.6.28.8/fs/nfsd/export.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/nfsd/export.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/nfsd/export.c linux-2.6.29.5/fs/nfsd/export.c
+--- linux-2.6.29.5/fs/nfsd/export.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/nfsd/export.c 2009-06-12 23:57:32.000000000 -0400
@@ -472,7 +472,7 @@ static int secinfo_parse(char **mesg, ch
* probably discover the problem when someone fails to
* authenticate.
@@ -19073,9 +21717,9 @@ diff -urNp linux-2.6.28.8/fs/nfsd/export.c linux-2.6.28.8/fs/nfsd/export.c
return -EINVAL;
err = get_int(mesg, &f->flags);
if (err)
-diff -urNp linux-2.6.28.8/fs/nls/nls_base.c linux-2.6.28.8/fs/nls/nls_base.c
---- linux-2.6.28.8/fs/nls/nls_base.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/nls/nls_base.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/nls/nls_base.c linux-2.6.29.5/fs/nls/nls_base.c
+--- linux-2.6.29.5/fs/nls/nls_base.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/nls/nls_base.c 2009-06-12 23:57:32.000000000 -0400
@@ -40,7 +40,7 @@ static const struct utf8_table utf8_tabl
{0xF8, 0xF0, 3*6, 0x1FFFFF, 0x10000, /* 4 byte sequence */},
{0xFC, 0xF8, 4*6, 0x3FFFFFF, 0x200000, /* 5 byte sequence */},
@@ -19085,9 +21729,9 @@ diff -urNp linux-2.6.28.8/fs/nls/nls_base.c linux-2.6.28.8/fs/nls/nls_base.c
};
int
-diff -urNp linux-2.6.28.8/fs/ntfs/file.c linux-2.6.28.8/fs/ntfs/file.c
---- linux-2.6.28.8/fs/ntfs/file.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/ntfs/file.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/ntfs/file.c linux-2.6.29.5/fs/ntfs/file.c
+--- linux-2.6.29.5/fs/ntfs/file.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/ntfs/file.c 2009-06-12 23:57:32.000000000 -0400
@@ -2291,6 +2291,6 @@ const struct inode_operations ntfs_file_
#endif /* NTFS_RW */
};
@@ -19097,9 +21741,89 @@ diff -urNp linux-2.6.28.8/fs/ntfs/file.c linux-2.6.28.8/fs/ntfs/file.c
-const struct inode_operations ntfs_empty_inode_ops = {};
+const struct inode_operations ntfs_empty_inode_ops;
-diff -urNp linux-2.6.28.8/fs/open.c linux-2.6.28.8/fs/open.c
---- linux-2.6.28.8/fs/open.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/open.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/ocfs2/localalloc.c linux-2.6.29.5/fs/ocfs2/localalloc.c
+--- linux-2.6.29.5/fs/ocfs2/localalloc.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/ocfs2/localalloc.c 2009-06-12 23:57:32.000000000 -0400
+@@ -1272,7 +1272,7 @@ static int ocfs2_local_alloc_slide_windo
+ goto bail;
+ }
+
+- atomic_inc(&osb->alloc_stats.moves);
++ atomic_inc_unchecked(&osb->alloc_stats.moves);
+
+ status = 0;
+ bail:
+diff -urNp linux-2.6.29.5/fs/ocfs2/ocfs2.h linux-2.6.29.5/fs/ocfs2/ocfs2.h
+--- linux-2.6.29.5/fs/ocfs2/ocfs2.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/ocfs2/ocfs2.h 2009-06-12 23:57:32.000000000 -0400
+@@ -168,11 +168,11 @@ enum ocfs2_vol_state
+
+ struct ocfs2_alloc_stats
+ {
+- atomic_t moves;
+- atomic_t local_data;
+- atomic_t bitmap_data;
+- atomic_t bg_allocs;
+- atomic_t bg_extends;
++ atomic_unchecked_t moves;
++ atomic_unchecked_t local_data;
++ atomic_unchecked_t bitmap_data;
++ atomic_unchecked_t bg_allocs;
++ atomic_unchecked_t bg_extends;
+ };
+
+ enum ocfs2_local_alloc_state
+diff -urNp linux-2.6.29.5/fs/ocfs2/suballoc.c linux-2.6.29.5/fs/ocfs2/suballoc.c
+--- linux-2.6.29.5/fs/ocfs2/suballoc.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/ocfs2/suballoc.c 2009-06-12 23:57:32.000000000 -0400
+@@ -602,7 +602,7 @@ static int ocfs2_reserve_suballoc_bits(s
+ mlog_errno(status);
+ goto bail;
+ }
+- atomic_inc(&osb->alloc_stats.bg_extends);
++ atomic_inc_unchecked(&osb->alloc_stats.bg_extends);
+
+ /* You should never ask for this much metadata */
+ BUG_ON(bits_wanted >
+@@ -1608,7 +1608,7 @@ int ocfs2_claim_metadata(struct ocfs2_su
+ mlog_errno(status);
+ goto bail;
+ }
+- atomic_inc(&osb->alloc_stats.bg_allocs);
++ atomic_inc_unchecked(&osb->alloc_stats.bg_allocs);
+
+ *blkno_start = bg_blkno + (u64) *suballoc_bit_start;
+ ac->ac_bits_given += (*num_bits);
+@@ -1647,7 +1647,7 @@ int ocfs2_claim_new_inode(struct ocfs2_s
+ mlog_errno(status);
+ goto bail;
+ }
+- atomic_inc(&osb->alloc_stats.bg_allocs);
++ atomic_inc_unchecked(&osb->alloc_stats.bg_allocs);
+
+ BUG_ON(num_bits != 1);
+
+@@ -1748,7 +1748,7 @@ int __ocfs2_claim_clusters(struct ocfs2_
+ cluster_start,
+ num_clusters);
+ if (!status)
+- atomic_inc(&osb->alloc_stats.local_data);
++ atomic_inc_unchecked(&osb->alloc_stats.local_data);
+ } else {
+ if (min_clusters > (osb->bitmap_cpg - 1)) {
+ /* The only paths asking for contiguousness
+@@ -1776,7 +1776,7 @@ int __ocfs2_claim_clusters(struct ocfs2_
+ ocfs2_desc_bitmap_to_cluster_off(ac->ac_inode,
+ bg_blkno,
+ bg_bit_off);
+- atomic_inc(&osb->alloc_stats.bitmap_data);
++ atomic_inc_unchecked(&osb->alloc_stats.bitmap_data);
+ }
+ }
+ if (status < 0) {
+diff -urNp linux-2.6.29.5/fs/open.c linux-2.6.29.5/fs/open.c
+--- linux-2.6.29.5/fs/open.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/open.c 2009-06-12 23:57:32.000000000 -0400
@@ -205,6 +205,9 @@ int do_truncate(struct dentry *dentry, l
if (length < 0)
return -EINVAL;
@@ -19110,7 +21834,7 @@ diff -urNp linux-2.6.28.8/fs/open.c linux-2.6.28.8/fs/open.c
newattrs.ia_size = length;
newattrs.ia_valid = ATTR_SIZE | time_attrs;
if (filp) {
-@@ -510,6 +513,9 @@ SYSCALL_DEFINE3(faccessat, int, dfd, con
+@@ -509,6 +512,9 @@ SYSCALL_DEFINE3(faccessat, int, dfd, con
if (__mnt_is_readonly(path.mnt))
res = -EROFS;
@@ -19120,7 +21844,7 @@ diff -urNp linux-2.6.28.8/fs/open.c linux-2.6.28.8/fs/open.c
out_path_release:
path_put(&path);
out:
-@@ -540,6 +546,8 @@ SYSCALL_DEFINE1(chdir, const char __user
+@@ -535,6 +541,8 @@ SYSCALL_DEFINE1(chdir, const char __user
if (error)
goto dput_and_out;
@@ -19129,7 +21853,7 @@ diff -urNp linux-2.6.28.8/fs/open.c linux-2.6.28.8/fs/open.c
set_fs_pwd(current->fs, &path);
dput_and_out:
-@@ -566,6 +574,13 @@ SYSCALL_DEFINE1(fchdir, unsigned int, fd
+@@ -561,6 +569,13 @@ SYSCALL_DEFINE1(fchdir, unsigned int, fd
goto out_putf;
error = inode_permission(inode, MAY_EXEC | MAY_ACCESS);
@@ -19143,22 +21867,26 @@ diff -urNp linux-2.6.28.8/fs/open.c linux-2.6.28.8/fs/open.c
if (!error)
set_fs_pwd(current->fs, &file->f_path);
out_putf:
-@@ -591,7 +606,14 @@ SYSCALL_DEFINE1(chroot, const char __use
+@@ -586,7 +601,18 @@ SYSCALL_DEFINE1(chroot, const char __use
if (!capable(CAP_SYS_CHROOT))
goto dput_and_out;
+ if (gr_handle_chroot_chroot(path.dentry, path.mnt))
+ goto dput_and_out;
+
++ if (gr_handle_chroot_caps(&path)) {
++ error = -ENOMEM;
++ goto dput_and_out;
++ }
++
set_fs_root(current->fs, &path);
+
-+ gr_handle_chroot_caps(current);
+ gr_handle_chroot_chdir(&path);
+
error = 0;
dput_and_out:
path_put(&path);
-@@ -619,13 +641,28 @@ SYSCALL_DEFINE2(fchmod, unsigned int, fd
+@@ -614,13 +640,28 @@ SYSCALL_DEFINE2(fchmod, unsigned int, fd
err = mnt_want_write(file->f_path.mnt);
if (err)
goto out_putf;
@@ -19187,7 +21915,7 @@ diff -urNp linux-2.6.28.8/fs/open.c linux-2.6.28.8/fs/open.c
mnt_drop_write(file->f_path.mnt);
out_putf:
fput(file);
-@@ -648,13 +685,28 @@ SYSCALL_DEFINE3(fchmodat, int, dfd, cons
+@@ -643,13 +684,28 @@ SYSCALL_DEFINE3(fchmodat, int, dfd, cons
error = mnt_want_write(path.mnt);
if (error)
goto dput_and_out;
@@ -19216,7 +21944,7 @@ diff -urNp linux-2.6.28.8/fs/open.c linux-2.6.28.8/fs/open.c
mnt_drop_write(path.mnt);
dput_and_out:
path_put(&path);
-@@ -667,12 +719,15 @@ SYSCALL_DEFINE2(chmod, const char __user
+@@ -662,12 +718,15 @@ SYSCALL_DEFINE2(chmod, const char __user
return sys_fchmodat(AT_FDCWD, filename, mode);
}
@@ -19233,7 +21961,7 @@ diff -urNp linux-2.6.28.8/fs/open.c linux-2.6.28.8/fs/open.c
newattrs.ia_valid = ATTR_CTIME;
if (user != (uid_t) -1) {
newattrs.ia_valid |= ATTR_UID;
-@@ -703,7 +758,7 @@ SYSCALL_DEFINE3(chown, const char __user
+@@ -698,7 +757,7 @@ SYSCALL_DEFINE3(chown, const char __user
error = mnt_want_write(path.mnt);
if (error)
goto out_release;
@@ -19242,7 +21970,7 @@ diff -urNp linux-2.6.28.8/fs/open.c linux-2.6.28.8/fs/open.c
mnt_drop_write(path.mnt);
out_release:
path_put(&path);
-@@ -728,7 +783,7 @@ SYSCALL_DEFINE5(fchownat, int, dfd, cons
+@@ -723,7 +782,7 @@ SYSCALL_DEFINE5(fchownat, int, dfd, cons
error = mnt_want_write(path.mnt);
if (error)
goto out_release;
@@ -19251,7 +21979,7 @@ diff -urNp linux-2.6.28.8/fs/open.c linux-2.6.28.8/fs/open.c
mnt_drop_write(path.mnt);
out_release:
path_put(&path);
-@@ -747,7 +802,7 @@ SYSCALL_DEFINE3(lchown, const char __use
+@@ -742,7 +801,7 @@ SYSCALL_DEFINE3(lchown, const char __use
error = mnt_want_write(path.mnt);
if (error)
goto out_release;
@@ -19260,7 +21988,7 @@ diff -urNp linux-2.6.28.8/fs/open.c linux-2.6.28.8/fs/open.c
mnt_drop_write(path.mnt);
out_release:
path_put(&path);
-@@ -770,7 +825,7 @@ SYSCALL_DEFINE3(fchown, unsigned int, fd
+@@ -765,7 +824,7 @@ SYSCALL_DEFINE3(fchown, unsigned int, fd
goto out_fput;
dentry = file->f_path.dentry;
audit_inode(NULL, dentry);
@@ -19269,9 +21997,9 @@ diff -urNp linux-2.6.28.8/fs/open.c linux-2.6.28.8/fs/open.c
mnt_drop_write(file->f_path.mnt);
out_fput:
fput(file);
-diff -urNp linux-2.6.28.8/fs/pipe.c linux-2.6.28.8/fs/pipe.c
---- linux-2.6.28.8/fs/pipe.c 2009-03-07 10:24:49.000000000 -0500
-+++ linux-2.6.28.8/fs/pipe.c 2009-03-07 14:13:22.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/pipe.c linux-2.6.29.5/fs/pipe.c
+--- linux-2.6.29.5/fs/pipe.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/pipe.c 2009-06-12 23:57:32.000000000 -0400
@@ -848,7 +848,7 @@ void free_pipe_info(struct inode *inode)
inode->i_pipe = NULL;
}
@@ -19281,10 +22009,10 @@ diff -urNp linux-2.6.28.8/fs/pipe.c linux-2.6.28.8/fs/pipe.c
static int pipefs_delete_dentry(struct dentry *dentry)
{
/*
-diff -urNp linux-2.6.28.8/fs/proc/array.c linux-2.6.28.8/fs/proc/array.c
---- linux-2.6.28.8/fs/proc/array.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/proc/array.c 2009-02-21 09:37:49.000000000 -0500
-@@ -308,6 +308,21 @@ static inline void task_context_switch_c
+diff -urNp linux-2.6.29.5/fs/proc/array.c linux-2.6.29.5/fs/proc/array.c
+--- linux-2.6.29.5/fs/proc/array.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/proc/array.c 2009-06-12 23:57:32.000000000 -0400
+@@ -321,6 +321,21 @@ static inline void task_context_switch_c
p->nivcsw);
}
@@ -19306,7 +22034,7 @@ diff -urNp linux-2.6.28.8/fs/proc/array.c linux-2.6.28.8/fs/proc/array.c
int proc_pid_status(struct seq_file *m, struct pid_namespace *ns,
struct pid *pid, struct task_struct *task)
{
-@@ -327,9 +342,20 @@ int proc_pid_status(struct seq_file *m,
+@@ -340,9 +355,20 @@ int proc_pid_status(struct seq_file *m,
task_show_regs(m, task);
#endif
task_context_switch_counts(m, task);
@@ -19327,7 +22055,7 @@ diff -urNp linux-2.6.28.8/fs/proc/array.c linux-2.6.28.8/fs/proc/array.c
static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
struct pid *pid, struct task_struct *task, int whole)
{
-@@ -422,6 +448,19 @@ static int do_task_stat(struct seq_file
+@@ -439,6 +465,19 @@ static int do_task_stat(struct seq_file
gtime = task_gtime(task);
}
@@ -19347,23 +22075,23 @@ diff -urNp linux-2.6.28.8/fs/proc/array.c linux-2.6.28.8/fs/proc/array.c
/* scale priority and nice values from timeslices to -20..20 */
/* to make it look like a "normal" Unix priority/nice value */
priority = task_prio(task);
-@@ -462,9 +501,15 @@ static int do_task_stat(struct seq_file
+@@ -479,9 +518,15 @@ static int do_task_stat(struct seq_file
vsize,
mm ? get_mm_rss(mm) : 0,
rsslim,
+#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
+ PAX_RAND_FLAGS(mm) ? 1 : (mm ? mm->start_code : 0),
+ PAX_RAND_FLAGS(mm) ? 1 : (mm ? mm->end_code : 0),
-+ PAX_RAND_FLAGS(mm) ? 0 : (mm ? mm->start_stack : 0),
++ PAX_RAND_FLAGS(mm) ? 0 : ((permitted && mm) ? mm->start_stack : 0),
+#else
mm ? mm->start_code : 0,
mm ? mm->end_code : 0,
- mm ? mm->start_stack : 0,
+ (permitted && mm) ? mm->start_stack : 0,
+#endif
esp,
eip,
/* The signal information here is obsolete.
-@@ -517,3 +562,10 @@ int proc_pid_statm(struct seq_file *m, s
+@@ -534,3 +579,10 @@ int proc_pid_statm(struct seq_file *m, s
return 0;
}
@@ -19374,10 +22102,10 @@ diff -urNp linux-2.6.28.8/fs/proc/array.c linux-2.6.28.8/fs/proc/array.c
+ return sprintf(buffer, "%u.%u.%u.%u\n", NIPQUAD(task->signal->curr_ip));
+}
+#endif
-diff -urNp linux-2.6.28.8/fs/proc/base.c linux-2.6.28.8/fs/proc/base.c
---- linux-2.6.28.8/fs/proc/base.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/proc/base.c 2009-03-07 05:50:38.000000000 -0500
-@@ -225,6 +225,9 @@ static int check_mem_permission(struct t
+diff -urNp linux-2.6.29.5/fs/proc/base.c linux-2.6.29.5/fs/proc/base.c
+--- linux-2.6.29.5/fs/proc/base.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/proc/base.c 2009-06-12 23:57:32.000000000 -0400
+@@ -212,6 +212,9 @@ static int check_mem_permission(struct t
if (task == current)
return 0;
@@ -19387,40 +22115,53 @@ diff -urNp linux-2.6.28.8/fs/proc/base.c linux-2.6.28.8/fs/proc/base.c
/*
* If current is actively ptrace'ing, and would also be
* permitted to freshly attach with ptrace now, permit it.
-@@ -302,15 +305,29 @@ out:
+@@ -262,6 +265,9 @@ static int proc_pid_cmdline(struct task_
+ if (!mm->arg_end)
+ goto out_mm; /* Shh! No looking before we're done */
+
++ if (gr_acl_handle_procpidmem(task))
++ goto out_mm;
++
+ len = mm->arg_end - mm->arg_start;
+
+ if (len > PAGE_SIZE)
+@@ -289,12 +295,26 @@ out:
return res;
}
--static int proc_pid_auxv(struct task_struct *task, char *buffer)
+#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
+#define PAX_RAND_FLAGS(_mm) (_mm != NULL && _mm != current->mm && \
+ (_mm->pax_flags & MF_PAX_RANDMMAP || \
+ _mm->pax_flags & MF_PAX_SEGMEXEC))
+#endif
+
-+static
-+int proc_pid_auxv(struct task_struct *task, char *buffer)
+ static int proc_pid_auxv(struct task_struct *task, char *buffer)
{
int res = 0;
struct mm_struct *mm = get_task_mm(task);
if (mm) {
unsigned int nwords = 0;
-- do
+
+#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
+ if (PAX_RAND_FLAGS(mm)) {
+ mmput(mm);
+ return res;
+ }
-+#endif
-+ do {
++#endif
++
+ do {
nwords += 2;
-- while (mm->saved_auxv[nwords - 2] != 0); /* AT_NULL */
-+ } while (mm->saved_auxv[nwords - 2] != 0); /* AT_NULL */
- res = nwords * sizeof(mm->saved_auxv[0]);
- if (res > PAGE_SIZE)
- res = PAGE_SIZE;
-@@ -502,7 +519,7 @@ static int proc_pid_limits(struct task_s
+ } while (mm->saved_auxv[nwords - 2] != 0); /* AT_NULL */
+@@ -330,7 +350,7 @@ static int proc_pid_wchan(struct task_st
+ }
+ #endif /* CONFIG_KALLSYMS */
+
+-#ifdef CONFIG_STACKTRACE
++#if defined(CONFIG_STACKTRACE) && !defined(CONFIG_GRKERNSEC_HIDESYM)
+
+ #define MAX_STACK_TRACE_DEPTH 64
+
+@@ -523,7 +543,7 @@ static int proc_pid_limits(struct task_s
return count;
}
@@ -19429,49 +22170,57 @@ diff -urNp linux-2.6.28.8/fs/proc/base.c linux-2.6.28.8/fs/proc/base.c
static int proc_pid_syscall(struct task_struct *task, char *buffer)
{
long nr;
-@@ -1429,7 +1446,11 @@ static struct inode *proc_pid_make_inode
- inode->i_gid = 0;
- if (task_dumpable(task)) {
- inode->i_uid = task->euid;
+@@ -937,6 +957,9 @@ static ssize_t environ_read(struct file
+ if (!task)
+ goto out_no_task;
+
++ if (gr_acl_handle_procpidmem(task))
++ goto out;
++
+ if (!ptrace_may_access(task, PTRACE_MODE_READ))
+ goto out;
+
+@@ -1440,7 +1463,11 @@ static struct inode *proc_pid_make_inode
+ rcu_read_lock();
+ cred = __task_cred(task);
+ inode->i_uid = cred->euid;
+#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP
+ inode->i_gid = CONFIG_GRKERNSEC_PROC_GID;
+#else
- inode->i_gid = task->egid;
+ inode->i_gid = cred->egid;
+#endif
+ rcu_read_unlock();
}
security_task_to_inode(task, inode);
-
-@@ -1445,17 +1466,45 @@ static int pid_getattr(struct vfsmount *
- {
+@@ -1458,6 +1485,9 @@ static int pid_getattr(struct vfsmount *
struct inode *inode = dentry->d_inode;
struct task_struct *task;
+ const struct cred *cred;
+#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
-+ struct task_struct *tmp = current;
++ const struct cred *tmpcred = current_cred();
+#endif
-+
+
generic_fillattr(inode, stat);
- rcu_read_lock();
+@@ -1465,12 +1495,34 @@ static int pid_getattr(struct vfsmount *
stat->uid = 0;
stat->gid = 0;
task = pid_task(proc_pid(inode), PIDTYPE_PID);
-- if (task) {
+
+ if (task && (gr_pid_is_chrooted(task) || gr_check_hidden_task(task))) {
+ rcu_read_unlock();
+ return -ENOENT;
+ }
+
-+
-+ if (task
+ if (task) {
++ cred = __task_cred(task);
+#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
-+ && (!tmp->uid || (tmp->uid == task->uid)
++ if (!tmpcred->uid || (tmpcred->uid == cred->uid)
+#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP
-+ || in_group_p(CONFIG_GRKERNSEC_PROC_GID)
++ || in_group_p(CONFIG_GRKERNSEC_PROC_GID)
+#endif
-+ )
++ )
+#endif
-+ ) {
if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) ||
+#ifdef CONFIG_GRKERNSEC_PROC_USER
+ (inode->i_mode == (S_IFDIR|S_IRUSR|S_IXUSR)) ||
@@ -19479,20 +22228,18 @@ diff -urNp linux-2.6.28.8/fs/proc/base.c linux-2.6.28.8/fs/proc/base.c
+ (inode->i_mode == (S_IFDIR|S_IRUSR|S_IRGRP|S_IXUSR|S_IXGRP)) ||
+#endif
task_dumpable(task)) {
- stat->uid = task->euid;
+- cred = __task_cred(task);
+ stat->uid = cred->euid;
+#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP
+ stat->gid = CONFIG_GRKERNSEC_PROC_GID;
+#else
- stat->gid = task->egid;
+ stat->gid = cred->egid;
+#endif
}
}
rcu_read_unlock();
-@@ -1483,11 +1532,21 @@ static int pid_revalidate(struct dentry
- {
- struct inode *inode = dentry->d_inode;
- struct task_struct *task = get_proc_task(inode);
-+
+@@ -1502,11 +1554,20 @@ static int pid_revalidate(struct dentry
+
if (task) {
if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) ||
+#ifdef CONFIG_GRKERNSEC_PROC_USER
@@ -19501,16 +22248,28 @@ diff -urNp linux-2.6.28.8/fs/proc/base.c linux-2.6.28.8/fs/proc/base.c
+ (inode->i_mode == (S_IFDIR|S_IRUSR|S_IRGRP|S_IXUSR|S_IXGRP)) ||
+#endif
task_dumpable(task)) {
- inode->i_uid = task->euid;
+ rcu_read_lock();
+ cred = __task_cred(task);
+ inode->i_uid = cred->euid;
+#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP
+ inode->i_gid = CONFIG_GRKERNSEC_PROC_GID;
+#else
- inode->i_gid = task->egid;
+ inode->i_gid = cred->egid;
+#endif
+ rcu_read_unlock();
} else {
inode->i_uid = 0;
- inode->i_gid = 0;
-@@ -1855,12 +1914,22 @@ static const struct file_operations proc
+@@ -1627,7 +1688,8 @@ static int proc_fd_info(struct inode *in
+ int fd = proc_fd(inode);
+
+ if (task) {
+- files = get_files_struct(task);
++ if (!gr_acl_handle_procpidmem(task))
++ files = get_files_struct(task);
+ put_task_struct(task);
+ }
+ if (files) {
+@@ -1879,12 +1941,22 @@ static const struct file_operations proc
static int proc_fd_permission(struct inode *inode, int mask)
{
int rv;
@@ -19535,7 +22294,7 @@ diff -urNp linux-2.6.28.8/fs/proc/base.c linux-2.6.28.8/fs/proc/base.c
return rv;
}
-@@ -1971,6 +2040,9 @@ static struct dentry *proc_pident_lookup
+@@ -1993,6 +2065,9 @@ static struct dentry *proc_pident_lookup
if (!task)
goto out_no_task;
@@ -19545,7 +22304,7 @@ diff -urNp linux-2.6.28.8/fs/proc/base.c linux-2.6.28.8/fs/proc/base.c
/*
* Yes, it does not scale. And it should not. Don't add
* new entries into /proc/<tgid>/ without very good reasons.
-@@ -2015,6 +2087,9 @@ static int proc_pident_readdir(struct fi
+@@ -2037,6 +2112,9 @@ static int proc_pident_readdir(struct fi
if (!task)
goto out_no_task;
@@ -19555,7 +22314,7 @@ diff -urNp linux-2.6.28.8/fs/proc/base.c linux-2.6.28.8/fs/proc/base.c
ret = 0;
i = filp->f_pos;
switch (i) {
-@@ -2377,6 +2452,9 @@ static struct dentry *proc_base_lookup(s
+@@ -2397,6 +2475,9 @@ static struct dentry *proc_base_lookup(s
if (p > last)
goto out;
@@ -19565,26 +22324,35 @@ diff -urNp linux-2.6.28.8/fs/proc/base.c linux-2.6.28.8/fs/proc/base.c
error = proc_base_instantiate(dir, dentry, task, p);
out:
-@@ -2463,7 +2541,7 @@ static const struct pid_entry tgid_base_
+@@ -2483,7 +2564,7 @@ static const struct pid_entry tgid_base_
#ifdef CONFIG_SCHED_DEBUG
- REG("sched", S_IRUGO|S_IWUSR, pid_sched),
+ REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations),
#endif
-#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
+#if defined(CONFIG_HAVE_ARCH_TRACEHOOK) && !defined(CONFIG_GRKERNSEC_PROC_MEMMAP)
- INF("syscall", S_IRUSR, pid_syscall),
+ INF("syscall", S_IRUSR, proc_pid_syscall),
#endif
- INF("cmdline", S_IRUGO, pid_cmdline),
-@@ -2518,6 +2596,9 @@ static const struct pid_entry tgid_base_
+ INF("cmdline", S_IRUGO, proc_pid_cmdline),
+@@ -2511,7 +2592,7 @@ static const struct pid_entry tgid_base_
+ #ifdef CONFIG_KALLSYMS
+ INF("wchan", S_IRUGO, proc_pid_wchan),
+ #endif
+-#ifdef CONFIG_STACKTRACE
++#if defined(CONFIG_STACKTRACE) && !defined(CONFIG_GRKERNSEC_HIDESYM)
+ ONE("stack", S_IRUSR, proc_pid_stack),
+ #endif
+ #ifdef CONFIG_SCHEDSTATS
+@@ -2541,6 +2622,9 @@ static const struct pid_entry tgid_base_
#ifdef CONFIG_TASK_IO_ACCOUNTING
- INF("io", S_IRUGO, tgid_io_accounting),
+ INF("io", S_IRUGO, proc_tgid_io_accounting),
#endif
+#ifdef CONFIG_GRKERNSEC_PROC_IPADDR
-+ INF("ipaddr", S_IRUSR, pid_ipaddr),
++ INF("ipaddr", S_IRUSR, proc_pid_ipaddr),
+#endif
};
static int proc_tgid_base_readdir(struct file * filp,
-@@ -2647,7 +2728,14 @@ static struct dentry *proc_pid_instantia
+@@ -2670,7 +2754,14 @@ static struct dentry *proc_pid_instantia
if (!inode)
goto out;
@@ -19599,7 +22367,7 @@ diff -urNp linux-2.6.28.8/fs/proc/base.c linux-2.6.28.8/fs/proc/base.c
inode->i_op = &proc_tgid_base_inode_operations;
inode->i_fop = &proc_tgid_base_operations;
inode->i_flags|=S_IMMUTABLE;
-@@ -2689,7 +2777,11 @@ struct dentry *proc_pid_lookup(struct in
+@@ -2712,7 +2803,11 @@ struct dentry *proc_pid_lookup(struct in
if (!task)
goto out;
@@ -19611,23 +22379,27 @@ diff -urNp linux-2.6.28.8/fs/proc/base.c linux-2.6.28.8/fs/proc/base.c
put_task_struct(task);
out:
return result;
-@@ -2754,6 +2846,9 @@ int proc_pid_readdir(struct file * filp,
+@@ -2777,6 +2872,10 @@ int proc_pid_readdir(struct file * filp,
{
unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY;
struct task_struct *reaper = get_proc_task(filp->f_path.dentry->d_inode);
+#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
-+ struct task_struct *tmp = current;
++ const struct cred *tmpcred = current_cred();
++ const struct cred *itercred;
+#endif
struct tgid_iter iter;
struct pid_namespace *ns;
-@@ -2772,6 +2867,17 @@ int proc_pid_readdir(struct file * filp,
+@@ -2795,6 +2894,20 @@ int proc_pid_readdir(struct file * filp,
for (iter = next_tgid(ns, iter);
iter.task;
iter.tgid += 1, iter = next_tgid(ns, iter)) {
++#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
++ itercred = __task_cred(iter.task);
++#endif
+ if (gr_pid_is_chrooted(iter.task) || gr_check_hidden_task(iter.task)
+#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
-+ || (tmp->uid && (iter.task->uid != tmp->uid)
++ || (tmpcred->uid && (itercred->uid != tmpcred->uid)
+#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP
+ && !in_group_p(CONFIG_GRKERNSEC_PROC_GID)
+#endif
@@ -19639,18 +22411,27 @@ diff -urNp linux-2.6.28.8/fs/proc/base.c linux-2.6.28.8/fs/proc/base.c
filp->f_pos = iter.tgid + TGID_OFFSET;
if (proc_pid_fill_cache(filp, dirent, filldir, iter) < 0) {
put_task_struct(iter.task);
-@@ -2799,7 +2905,7 @@ static const struct pid_entry tid_base_s
+@@ -2822,7 +2935,7 @@ static const struct pid_entry tid_base_s
#ifdef CONFIG_SCHED_DEBUG
- REG("sched", S_IRUGO|S_IWUSR, pid_sched),
+ REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations),
#endif
-#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
+#if defined(CONFIG_HAVE_ARCH_TRACEHOOK) && !defined(CONFIG_GRKERNSEC_PROC_MEMMAP)
- INF("syscall", S_IRUSR, pid_syscall),
+ INF("syscall", S_IRUSR, proc_pid_syscall),
#endif
- INF("cmdline", S_IRUGO, pid_cmdline),
-diff -urNp linux-2.6.28.8/fs/proc/cmdline.c linux-2.6.28.8/fs/proc/cmdline.c
---- linux-2.6.28.8/fs/proc/cmdline.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/proc/cmdline.c 2009-02-21 09:37:49.000000000 -0500
+ INF("cmdline", S_IRUGO, proc_pid_cmdline),
+@@ -2849,7 +2962,7 @@ static const struct pid_entry tid_base_s
+ #ifdef CONFIG_KALLSYMS
+ INF("wchan", S_IRUGO, proc_pid_wchan),
+ #endif
+-#ifdef CONFIG_STACKTRACE
++#if defined(CONFIG_STACKTRACE) && !defined(CONFIG_GRKERNSEC_HIDESYM)
+ ONE("stack", S_IRUSR, proc_pid_stack),
+ #endif
+ #ifdef CONFIG_SCHEDSTATS
+diff -urNp linux-2.6.29.5/fs/proc/cmdline.c linux-2.6.29.5/fs/proc/cmdline.c
+--- linux-2.6.29.5/fs/proc/cmdline.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/proc/cmdline.c 2009-06-12 23:57:32.000000000 -0400
@@ -23,7 +23,11 @@ static const struct file_operations cmdl
static int __init proc_cmdline_init(void)
@@ -19663,9 +22444,9 @@ diff -urNp linux-2.6.28.8/fs/proc/cmdline.c linux-2.6.28.8/fs/proc/cmdline.c
return 0;
}
module_init(proc_cmdline_init);
-diff -urNp linux-2.6.28.8/fs/proc/devices.c linux-2.6.28.8/fs/proc/devices.c
---- linux-2.6.28.8/fs/proc/devices.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/proc/devices.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/proc/devices.c linux-2.6.29.5/fs/proc/devices.c
+--- linux-2.6.29.5/fs/proc/devices.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/proc/devices.c 2009-06-12 23:57:32.000000000 -0400
@@ -64,7 +64,11 @@ static const struct file_operations proc
static int __init proc_devices_init(void)
@@ -19678,10 +22459,10 @@ diff -urNp linux-2.6.28.8/fs/proc/devices.c linux-2.6.28.8/fs/proc/devices.c
return 0;
}
module_init(proc_devices_init);
-diff -urNp linux-2.6.28.8/fs/proc/inode.c linux-2.6.28.8/fs/proc/inode.c
---- linux-2.6.28.8/fs/proc/inode.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/proc/inode.c 2009-02-21 09:37:49.000000000 -0500
-@@ -466,7 +466,11 @@ struct inode *proc_get_inode(struct supe
+diff -urNp linux-2.6.29.5/fs/proc/inode.c linux-2.6.29.5/fs/proc/inode.c
+--- linux-2.6.29.5/fs/proc/inode.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/proc/inode.c 2009-06-12 23:57:32.000000000 -0400
+@@ -463,7 +463,11 @@ struct inode *proc_get_inode(struct supe
if (de->mode) {
inode->i_mode = de->mode;
inode->i_uid = de->uid;
@@ -19693,10 +22474,10 @@ diff -urNp linux-2.6.28.8/fs/proc/inode.c linux-2.6.28.8/fs/proc/inode.c
}
if (de->size)
inode->i_size = de->size;
-diff -urNp linux-2.6.28.8/fs/proc/internal.h linux-2.6.28.8/fs/proc/internal.h
---- linux-2.6.28.8/fs/proc/internal.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/proc/internal.h 2009-02-21 09:37:49.000000000 -0500
-@@ -53,6 +53,9 @@ extern int proc_pid_status(struct seq_fi
+diff -urNp linux-2.6.29.5/fs/proc/internal.h linux-2.6.29.5/fs/proc/internal.h
+--- linux-2.6.29.5/fs/proc/internal.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/proc/internal.h 2009-06-12 23:57:32.000000000 -0400
+@@ -51,6 +51,9 @@ extern int proc_pid_status(struct seq_fi
struct pid *pid, struct task_struct *task);
extern int proc_pid_statm(struct seq_file *m, struct pid_namespace *ns,
struct pid *pid, struct task_struct *task);
@@ -19706,9 +22487,9 @@ diff -urNp linux-2.6.28.8/fs/proc/internal.h linux-2.6.28.8/fs/proc/internal.h
extern loff_t mem_lseek(struct file *file, loff_t offset, int orig);
extern const struct file_operations proc_maps_operations;
-diff -urNp linux-2.6.28.8/fs/proc/Kconfig linux-2.6.28.8/fs/proc/Kconfig
---- linux-2.6.28.8/fs/proc/Kconfig 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/proc/Kconfig 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/proc/Kconfig linux-2.6.29.5/fs/proc/Kconfig
+--- linux-2.6.29.5/fs/proc/Kconfig 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/proc/Kconfig 2009-06-12 23:57:32.000000000 -0400
@@ -30,12 +30,12 @@ config PROC_FS
config PROC_KCORE
@@ -19736,9 +22517,9 @@ diff -urNp linux-2.6.28.8/fs/proc/Kconfig linux-2.6.28.8/fs/proc/Kconfig
bool "Enable /proc page monitoring" if EMBEDDED
help
Various /proc files exist to monitor process memory utilization:
-diff -urNp linux-2.6.28.8/fs/proc/kcore.c linux-2.6.28.8/fs/proc/kcore.c
---- linux-2.6.28.8/fs/proc/kcore.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/proc/kcore.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/proc/kcore.c linux-2.6.29.5/fs/proc/kcore.c
+--- linux-2.6.29.5/fs/proc/kcore.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/proc/kcore.c 2009-06-12 23:57:32.000000000 -0400
@@ -404,10 +404,12 @@ read_kcore(struct file *file, char __use
static int __init proc_kcore_init(void)
@@ -19752,27 +22533,42 @@ diff -urNp linux-2.6.28.8/fs/proc/kcore.c linux-2.6.28.8/fs/proc/kcore.c
return 0;
}
module_init(proc_kcore_init);
-diff -urNp linux-2.6.28.8/fs/proc/proc_net.c linux-2.6.28.8/fs/proc/proc_net.c
---- linux-2.6.28.8/fs/proc/proc_net.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/proc/proc_net.c 2009-02-21 09:37:49.000000000 -0500
-@@ -106,6 +106,14 @@ static struct net *get_proc_task_net(str
+diff -urNp linux-2.6.29.5/fs/proc/nommu.c linux-2.6.29.5/fs/proc/nommu.c
+--- linux-2.6.29.5/fs/proc/nommu.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/proc/nommu.c 2009-06-12 23:57:32.000000000 -0400
+@@ -67,7 +67,7 @@ static int nommu_region_show(struct seq_
+ if (len < 1)
+ len = 1;
+ seq_printf(m, "%*c", len, ' ');
+- seq_path(m, &file->f_path, "");
++ seq_path(m, &file->f_path, "\n\\");
+ }
+
+ seq_putc(m, '\n');
+diff -urNp linux-2.6.29.5/fs/proc/proc_net.c linux-2.6.29.5/fs/proc/proc_net.c
+--- linux-2.6.29.5/fs/proc/proc_net.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/proc/proc_net.c 2009-06-12 23:57:32.000000000 -0400
+@@ -104,6 +104,17 @@ static struct net *get_proc_task_net(str
+ struct task_struct *task;
struct nsproxy *ns;
struct net *net = NULL;
-
++#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
++ const struct cred *cred = current_cred();
++#endif
++
+#ifdef CONFIG_GRKERNSEC_PROC_USER
-+ if (current->fsuid)
++ if (cred->fsuid)
+ return net;
+#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
-+ if (current->fsuid && !in_group_p(CONFIG_GRKERNSEC_PROC_GID))
++ if (cred->fsuid && !in_group_p(CONFIG_GRKERNSEC_PROC_GID))
+ return net;
+#endif
-+
+
rcu_read_lock();
task = pid_task(proc_pid(dir), PIDTYPE_PID);
- if (task != NULL) {
-diff -urNp linux-2.6.28.8/fs/proc/proc_sysctl.c linux-2.6.28.8/fs/proc/proc_sysctl.c
---- linux-2.6.28.8/fs/proc/proc_sysctl.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/proc/proc_sysctl.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/proc/proc_sysctl.c linux-2.6.29.5/fs/proc/proc_sysctl.c
+--- linux-2.6.29.5/fs/proc/proc_sysctl.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/proc/proc_sysctl.c 2009-06-12 23:57:32.000000000 -0400
@@ -7,6 +7,8 @@
#include <linux/security.h>
#include "internal.h"
@@ -19782,7 +22578,7 @@ diff -urNp linux-2.6.28.8/fs/proc/proc_sysctl.c linux-2.6.28.8/fs/proc/proc_sysc
static struct dentry_operations proc_sys_dentry_operations;
static const struct file_operations proc_sys_file_operations;
static const struct inode_operations proc_sys_inode_operations;
-@@ -110,6 +112,9 @@ static struct dentry *proc_sys_lookup(st
+@@ -109,6 +111,9 @@ static struct dentry *proc_sys_lookup(st
if (!p)
goto out;
@@ -19792,7 +22588,7 @@ diff -urNp linux-2.6.28.8/fs/proc/proc_sysctl.c linux-2.6.28.8/fs/proc/proc_sysc
err = ERR_PTR(-ENOMEM);
inode = proc_sys_make_inode(dir->i_sb, h ? h : head, p);
if (h)
-@@ -229,6 +234,9 @@ static int scan(struct ctl_table_header
+@@ -228,6 +233,9 @@ static int scan(struct ctl_table_header
if (*pos < file->f_pos)
continue;
@@ -19802,7 +22598,7 @@ diff -urNp linux-2.6.28.8/fs/proc/proc_sysctl.c linux-2.6.28.8/fs/proc/proc_sysc
res = proc_sys_fill_cache(file, dirent, filldir, head, table);
if (res)
return res;
-@@ -345,6 +353,9 @@ static int proc_sys_getattr(struct vfsmo
+@@ -344,6 +352,9 @@ static int proc_sys_getattr(struct vfsmo
if (IS_ERR(head))
return PTR_ERR(head);
@@ -19812,10 +22608,10 @@ diff -urNp linux-2.6.28.8/fs/proc/proc_sysctl.c linux-2.6.28.8/fs/proc/proc_sysc
generic_fillattr(inode, stat);
if (table)
stat->mode = (stat->mode & S_IFMT) | table->mode;
-diff -urNp linux-2.6.28.8/fs/proc/root.c linux-2.6.28.8/fs/proc/root.c
---- linux-2.6.28.8/fs/proc/root.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/proc/root.c 2009-02-21 09:37:49.000000000 -0500
-@@ -135,7 +135,15 @@ void __init proc_root_init(void)
+diff -urNp linux-2.6.29.5/fs/proc/root.c linux-2.6.29.5/fs/proc/root.c
+--- linux-2.6.29.5/fs/proc/root.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/proc/root.c 2009-06-12 23:57:32.000000000 -0400
+@@ -134,7 +134,15 @@ void __init proc_root_init(void)
#ifdef CONFIG_PROC_DEVICETREE
proc_device_tree_init();
#endif
@@ -19831,9 +22627,9 @@ diff -urNp linux-2.6.28.8/fs/proc/root.c linux-2.6.28.8/fs/proc/root.c
proc_sys_init();
}
-diff -urNp linux-2.6.28.8/fs/proc/task_mmu.c linux-2.6.28.8/fs/proc/task_mmu.c
---- linux-2.6.28.8/fs/proc/task_mmu.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/proc/task_mmu.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/proc/task_mmu.c linux-2.6.29.5/fs/proc/task_mmu.c
+--- linux-2.6.29.5/fs/proc/task_mmu.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/proc/task_mmu.c 2009-06-12 23:57:32.000000000 -0400
@@ -46,15 +46,26 @@ void task_mem(struct seq_file *m, struct
"VmStk:\t%8lu kB\n"
"VmExe:\t%8lu kB\n"
@@ -19900,7 +22696,13 @@ diff -urNp linux-2.6.28.8/fs/proc/task_mmu.c linux-2.6.28.8/fs/proc/task_mmu.c
MAJOR(dev), MINOR(dev), ino, &len);
/*
-@@ -234,11 +260,11 @@ static void show_map_vma(struct seq_file
+@@ -229,16 +255,16 @@ static void show_map_vma(struct seq_file
+ */
+ if (file) {
+ pad_len_spaces(m, len);
+- seq_path(m, &file->f_path, "\n");
++ seq_path(m, &file->f_path, "\n\\");
+ } else {
const char *name = arch_vma_name(vma);
if (!name) {
if (mm) {
@@ -19936,10 +22738,10 @@ diff -urNp linux-2.6.28.8/fs/proc/task_mmu.c linux-2.6.28.8/fs/proc/task_mmu.c
show_map_vma(m, vma);
-@@ -397,7 +430,11 @@ static int show_smap(struct seq_file *m,
- "Private_Dirty: %8lu kB\n"
- "Referenced: %8lu kB\n"
- "Swap: %8lu kB\n",
+@@ -399,7 +432,11 @@ static int show_smap(struct seq_file *m,
+ "Swap: %8lu kB\n"
+ "KernelPageSize: %8lu kB\n"
+ "MMUPageSize: %8lu kB\n",
+#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
+ PAX_RAND_FLAGS(vma->vm_mm) ? 0UL : (vma->vm_end - vma->vm_start) >> 10,
+#else
@@ -19948,9 +22750,30 @@ diff -urNp linux-2.6.28.8/fs/proc/task_mmu.c linux-2.6.28.8/fs/proc/task_mmu.c
mss.resident >> 10,
(unsigned long)(mss.pss >> (10 + PSS_SHIFT)),
mss.shared_clean >> 10,
-diff -urNp linux-2.6.28.8/fs/readdir.c linux-2.6.28.8/fs/readdir.c
---- linux-2.6.28.8/fs/readdir.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/readdir.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/proc/task_nommu.c linux-2.6.29.5/fs/proc/task_nommu.c
+--- linux-2.6.29.5/fs/proc/task_nommu.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/proc/task_nommu.c 2009-06-12 23:57:32.000000000 -0400
+@@ -49,7 +49,7 @@ void task_mem(struct seq_file *m, struct
+ else
+ bytes += kobjsize(mm);
+
+- if (current->fs && current->fs->users > 1)
++ if (current->fs && atomic_read(&current->fs->users) > 1)
+ sbytes += kobjsize(current->fs);
+ else
+ bytes += kobjsize(current->fs);
+@@ -151,7 +151,7 @@ static int nommu_vma_show(struct seq_fil
+ if (len < 1)
+ len = 1;
+ seq_printf(m, "%*c", len, ' ');
+- seq_path(m, &file->f_path, "");
++ seq_path(m, &file->f_path, "\n\\");
+ }
+
+ seq_putc(m, '\n');
+diff -urNp linux-2.6.29.5/fs/readdir.c linux-2.6.29.5/fs/readdir.c
+--- linux-2.6.29.5/fs/readdir.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/readdir.c 2009-06-12 23:57:32.000000000 -0400
@@ -16,6 +16,7 @@
#include <linux/security.h>
#include <linux/syscalls.h>
@@ -20040,9 +22863,21 @@ diff -urNp linux-2.6.28.8/fs/readdir.c linux-2.6.28.8/fs/readdir.c
buf.count = count;
buf.error = 0;
-diff -urNp linux-2.6.28.8/fs/select.c linux-2.6.28.8/fs/select.c
---- linux-2.6.28.8/fs/select.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/select.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/reiserfs/do_balan.c linux-2.6.29.5/fs/reiserfs/do_balan.c
+--- linux-2.6.29.5/fs/reiserfs/do_balan.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/reiserfs/do_balan.c 2009-06-12 23:57:32.000000000 -0400
+@@ -2114,7 +2114,7 @@ void do_balance(struct tree_balance *tb,
+ return;
+ }
+
+- atomic_inc(&(fs_generation(tb->tb_sb)));
++ atomic_inc_unchecked(&(fs_generation(tb->tb_sb)));
+ do_balance_starts(tb);
+
+ /* balance leaf returns 0 except if combining L R and S into
+diff -urNp linux-2.6.29.5/fs/select.c linux-2.6.29.5/fs/select.c
+--- linux-2.6.29.5/fs/select.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/select.c 2009-06-12 23:57:32.000000000 -0400
@@ -19,6 +19,7 @@
#include <linux/module.h>
#include <linux/slab.h>
@@ -20051,7 +22886,7 @@ diff -urNp linux-2.6.28.8/fs/select.c linux-2.6.28.8/fs/select.c
#include <linux/personality.h> /* for STICKY_TIMEOUTS */
#include <linux/file.h>
#include <linux/fdtable.h>
-@@ -733,6 +734,7 @@ int do_sys_poll(struct pollfd __user *uf
+@@ -781,6 +782,7 @@ int do_sys_poll(struct pollfd __user *uf
struct poll_list *walk = head;
unsigned long todo = nfds;
@@ -20059,9 +22894,52 @@ diff -urNp linux-2.6.28.8/fs/select.c linux-2.6.28.8/fs/select.c
if (nfds > current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
return -EINVAL;
-diff -urNp linux-2.6.28.8/fs/smbfs/symlink.c linux-2.6.28.8/fs/smbfs/symlink.c
---- linux-2.6.28.8/fs/smbfs/symlink.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/smbfs/symlink.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/seq_file.c linux-2.6.29.5/fs/seq_file.c
+--- linux-2.6.29.5/fs/seq_file.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/seq_file.c 2009-06-12 23:57:32.000000000 -0400
+@@ -76,7 +76,8 @@ static int traverse(struct seq_file *m,
+ return 0;
+ }
+ if (!m->buf) {
+- m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL);
++ m->size = PAGE_SIZE;
++ m->buf = kmalloc(m->size, GFP_KERNEL);
+ if (!m->buf)
+ return -ENOMEM;
+ }
+@@ -116,7 +117,8 @@ static int traverse(struct seq_file *m,
+ Eoverflow:
+ m->op->stop(m, p);
+ kfree(m->buf);
+- m->buf = kmalloc(m->size <<= 1, GFP_KERNEL);
++ m->size <<= 1;
++ m->buf = kmalloc(m->size, GFP_KERNEL);
+ return !m->buf ? -ENOMEM : -EAGAIN;
+ }
+
+@@ -169,7 +171,8 @@ ssize_t seq_read(struct file *file, char
+ m->version = file->f_version;
+ /* grab buffer if we didn't have one */
+ if (!m->buf) {
+- m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL);
++ m->size = PAGE_SIZE;
++ m->buf = kmalloc(m->size, GFP_KERNEL);
+ if (!m->buf)
+ goto Enomem;
+ }
+@@ -210,7 +213,8 @@ ssize_t seq_read(struct file *file, char
+ goto Fill;
+ m->op->stop(m, p);
+ kfree(m->buf);
+- m->buf = kmalloc(m->size <<= 1, GFP_KERNEL);
++ m->size <<= 1;
++ m->buf = kmalloc(m->size, GFP_KERNEL);
+ if (!m->buf)
+ goto Enomem;
+ m->count = 0;
+diff -urNp linux-2.6.29.5/fs/smbfs/symlink.c linux-2.6.29.5/fs/smbfs/symlink.c
+--- linux-2.6.29.5/fs/smbfs/symlink.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/smbfs/symlink.c 2009-06-12 23:57:32.000000000 -0400
@@ -55,7 +55,7 @@ static void *smb_follow_link(struct dent
static void smb_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
@@ -20071,9 +22949,9 @@ diff -urNp linux-2.6.28.8/fs/smbfs/symlink.c linux-2.6.28.8/fs/smbfs/symlink.c
if (!IS_ERR(s))
__putname(s);
}
-diff -urNp linux-2.6.28.8/fs/sysfs/symlink.c linux-2.6.28.8/fs/sysfs/symlink.c
---- linux-2.6.28.8/fs/sysfs/symlink.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/sysfs/symlink.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/sysfs/symlink.c linux-2.6.29.5/fs/sysfs/symlink.c
+--- linux-2.6.29.5/fs/sysfs/symlink.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/sysfs/symlink.c 2009-06-12 23:57:32.000000000 -0400
@@ -200,7 +200,7 @@ static void *sysfs_follow_link(struct de
static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
@@ -20083,9 +22961,9 @@ diff -urNp linux-2.6.28.8/fs/sysfs/symlink.c linux-2.6.28.8/fs/sysfs/symlink.c
if (!IS_ERR(page))
free_page((unsigned long)page);
}
-diff -urNp linux-2.6.28.8/fs/udf/balloc.c linux-2.6.28.8/fs/udf/balloc.c
---- linux-2.6.28.8/fs/udf/balloc.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/udf/balloc.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/udf/balloc.c linux-2.6.29.5/fs/udf/balloc.c
+--- linux-2.6.29.5/fs/udf/balloc.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/udf/balloc.c 2009-06-12 23:57:32.000000000 -0400
@@ -169,9 +169,7 @@ static void udf_bitmap_free_blocks(struc
unsigned long overflow;
@@ -20145,9 +23023,9 @@ diff -urNp linux-2.6.28.8/fs/udf/balloc.c linux-2.6.28.8/fs/udf/balloc.c
goal = 0;
/* We search for the closest matching block to goal. If we find
-diff -urNp linux-2.6.28.8/fs/ufs/inode.c linux-2.6.28.8/fs/ufs/inode.c
---- linux-2.6.28.8/fs/ufs/inode.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/ufs/inode.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/ufs/inode.c linux-2.6.29.5/fs/ufs/inode.c
+--- linux-2.6.29.5/fs/ufs/inode.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/ufs/inode.c 2009-06-12 23:57:32.000000000 -0400
@@ -56,9 +56,7 @@ static int ufs_block_to_path(struct inod
@@ -20179,9 +23057,9 @@ diff -urNp linux-2.6.28.8/fs/ufs/inode.c linux-2.6.28.8/fs/ufs/inode.c
abort_too_big:
ufs_warning(sb, "ufs_get_block", "block > big");
goto abort;
-diff -urNp linux-2.6.28.8/fs/utimes.c linux-2.6.28.8/fs/utimes.c
---- linux-2.6.28.8/fs/utimes.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/utimes.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/utimes.c linux-2.6.29.5/fs/utimes.c
+--- linux-2.6.29.5/fs/utimes.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/utimes.c 2009-06-12 23:57:32.000000000 -0400
@@ -1,6 +1,7 @@
#include <linux/compiler.h>
#include <linux/file.h>
@@ -20203,10 +23081,10 @@ diff -urNp linux-2.6.28.8/fs/utimes.c linux-2.6.28.8/fs/utimes.c
mutex_lock(&inode->i_mutex);
error = notify_change(path->dentry, &newattrs);
mutex_unlock(&inode->i_mutex);
-diff -urNp linux-2.6.28.8/fs/xfs/linux-2.6/xfs_iops.c linux-2.6.28.8/fs/xfs/linux-2.6/xfs_iops.c
---- linux-2.6.28.8/fs/xfs/linux-2.6/xfs_iops.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/xfs/linux-2.6/xfs_iops.c 2009-02-21 09:37:49.000000000 -0500
-@@ -500,7 +500,7 @@ xfs_vn_put_link(
+diff -urNp linux-2.6.29.5/fs/xfs/linux-2.6/xfs_iops.c linux-2.6.29.5/fs/xfs/linux-2.6/xfs_iops.c
+--- linux-2.6.29.5/fs/xfs/linux-2.6/xfs_iops.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/xfs/linux-2.6/xfs_iops.c 2009-06-12 23:57:32.000000000 -0400
+@@ -494,7 +494,7 @@ xfs_vn_put_link(
struct nameidata *nd,
void *p)
{
@@ -20215,9 +23093,9 @@ diff -urNp linux-2.6.28.8/fs/xfs/linux-2.6/xfs_iops.c linux-2.6.28.8/fs/xfs/linu
if (!IS_ERR(s))
kfree(s);
-diff -urNp linux-2.6.28.8/fs/xfs/xfs_bmap.c linux-2.6.28.8/fs/xfs/xfs_bmap.c
---- linux-2.6.28.8/fs/xfs/xfs_bmap.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/fs/xfs/xfs_bmap.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/fs/xfs/xfs_bmap.c linux-2.6.29.5/fs/xfs/xfs_bmap.c
+--- linux-2.6.29.5/fs/xfs/xfs_bmap.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/fs/xfs/xfs_bmap.c 2009-06-12 23:57:32.000000000 -0400
@@ -360,7 +360,7 @@ xfs_bmap_validate_ret(
int nmap,
int ret_nmap);
@@ -20227,10 +23105,10 @@ diff -urNp linux-2.6.28.8/fs/xfs/xfs_bmap.c linux-2.6.28.8/fs/xfs/xfs_bmap.c
#endif /* DEBUG */
#if defined(XFS_RW_TRACE)
-diff -urNp linux-2.6.28.8/grsecurity/gracl_alloc.c linux-2.6.28.8/grsecurity/gracl_alloc.c
---- linux-2.6.28.8/grsecurity/gracl_alloc.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/grsecurity/gracl_alloc.c 2009-02-21 09:37:49.000000000 -0500
-@@ -0,0 +1,91 @@
+diff -urNp linux-2.6.29.5/grsecurity/gracl_alloc.c linux-2.6.29.5/grsecurity/gracl_alloc.c
+--- linux-2.6.29.5/grsecurity/gracl_alloc.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/grsecurity/gracl_alloc.c 2009-06-12 23:57:32.000000000 -0400
+@@ -0,0 +1,105 @@
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
@@ -20255,35 +23133,49 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl_alloc.c linux-2.6.28.8/grsecurity/gra
+ return 1;
+}
+
-+static __inline__ void
++static __inline__ int
+alloc_push(void *buf)
+{
+ if (alloc_stack_next >= alloc_stack_size)
-+ BUG();
++ return 1;
+
+ alloc_stack[alloc_stack_next - 1] = buf;
+
+ alloc_stack_next++;
+
-+ return;
++ return 0;
+}
+
+void *
+acl_alloc(unsigned long len)
+{
-+ void *ret;
++ void *ret = NULL;
+
-+ if (len > PAGE_SIZE)
-+ BUG();
++ if (!len || len > PAGE_SIZE)
++ goto out;
+
+ ret = kmalloc(len, GFP_KERNEL);
+
-+ if (ret)
-+ alloc_push(ret);
++ if (ret) {
++ if (alloc_push(ret)) {
++ kfree(ret);
++ ret = NULL;
++ }
++ }
+
++out:
+ return ret;
+}
+
++void *
++acl_alloc_num(unsigned long num, unsigned long len)
++{
++ if (!len || (num > (PAGE_SIZE / len)))
++ return NULL;
++
++ return acl_alloc(num * len);
++}
++
+void
+acl_free_all(void)
+{
@@ -20322,10 +23214,10 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl_alloc.c linux-2.6.28.8/grsecurity/gra
+ else
+ return 1;
+}
-diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
---- linux-2.6.28.8/grsecurity/gracl.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/grsecurity/gracl.c 2009-02-21 09:37:49.000000000 -0500
-@@ -0,0 +1,3722 @@
+diff -urNp linux-2.6.29.5/grsecurity/gracl.c linux-2.6.29.5/grsecurity/gracl.c
+--- linux-2.6.29.5/grsecurity/gracl.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/grsecurity/gracl.c 2009-06-12 23:57:32.000000000 -0400
+@@ -0,0 +1,3811 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
@@ -20781,6 +23673,26 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
+ return NULL;
+}
+
++struct acl_subject_label *
++lookup_acl_subj_label_deleted(const ino_t ino, const dev_t dev,
++ const struct acl_role_label *role)
++{
++ unsigned int index = fhash(ino, dev, role->subj_hash_size);
++ struct acl_subject_label *match;
++
++ match = role->subj_hash[index];
++
++ while (match && (match->inode != ino || match->device != dev ||
++ !(match->mode & GR_DELETED))) {
++ match = match->next;
++ }
++
++ if (match && (match->mode & GR_DELETED))
++ return match;
++ else
++ return NULL;
++}
++
+static struct acl_object_label *
+lookup_acl_obj_label(const ino_t ino, const dev_t dev,
+ const struct acl_subject_label *subj)
@@ -21033,8 +23945,7 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
+ unsigned int table_sizes[] = {
+ 7, 13, 31, 61, 127, 251, 509, 1021, 2039, 4093, 8191, 16381,
+ 32749, 65521, 131071, 262139, 524287, 1048573, 2097143,
-+ 4194301, 8388593, 16777213, 33554393, 67108859, 134217689,
-+ 268435399, 536870909, 1073741789, 2147483647
++ 4194301, 8388593, 16777213, 33554393, 67108859
+ };
+ void *newtable = NULL;
+ unsigned int pwr = 0;
@@ -21043,7 +23954,7 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
+ table_sizes[pwr] <= *len)
+ pwr++;
+
-+ if (table_sizes[pwr] <= *len)
++ if (table_sizes[pwr] <= *len || (table_sizes[pwr] > ULONG_MAX / elementsize))
+ return newtable;
+
+ if ((table_sizes[pwr] * elementsize) <= PAGE_SIZE)
@@ -21526,7 +24437,7 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
+ if (s_tmp->user_trans_num) {
+ uid_t *uidlist;
+
-+ uidlist = (uid_t *)acl_alloc(s_tmp->user_trans_num * sizeof(uid_t));
++ uidlist = (uid_t *)acl_alloc_num(s_tmp->user_trans_num, sizeof(uid_t));
+ if (uidlist == NULL)
+ return ERR_PTR(-ENOMEM);
+ if (copy_from_user(uidlist, s_tmp->user_transitions, s_tmp->user_trans_num * sizeof(uid_t)))
@@ -21538,7 +24449,7 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
+ if (s_tmp->group_trans_num) {
+ gid_t *gidlist;
+
-+ gidlist = (gid_t *)acl_alloc(s_tmp->group_trans_num * sizeof(gid_t));
++ gidlist = (gid_t *)acl_alloc_num(s_tmp->group_trans_num, sizeof(gid_t));
+ if (gidlist == NULL)
+ return ERR_PTR(-ENOMEM);
+ if (copy_from_user(gidlist, s_tmp->group_transitions, s_tmp->group_trans_num * sizeof(gid_t)))
@@ -21586,9 +24497,8 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
+ }
+
+ i_tmp =
-+ (struct acl_ip_label **) acl_alloc(s_tmp->ip_num *
-+ sizeof (struct
-+ acl_ip_label *));
++ (struct acl_ip_label **) acl_alloc_num(s_tmp->ip_num,
++ sizeof (struct acl_ip_label *));
+
+ if (!i_tmp)
+ return ERR_PTR(-ENOMEM);
@@ -21690,7 +24600,7 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
+ /* copy special role authentication info from userspace */
+
+ num_sprole_pws = arg->num_sprole_pws;
-+ acl_special_roles = (struct sprole_pw **) acl_alloc(num_sprole_pws * sizeof(struct sprole_pw *));
++ acl_special_roles = (struct sprole_pw **) acl_alloc_num(num_sprole_pws, sizeof(struct sprole_pw *));
+
+ if (!acl_special_roles) {
+ err = -ENOMEM;
@@ -21809,7 +24719,7 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
+
+ /* copy domain info */
+ if (r_tmp->domain_children != NULL) {
-+ domainlist = acl_alloc(r_tmp->domain_child_num * sizeof(uid_t));
++ domainlist = acl_alloc_num(r_tmp->domain_child_num, sizeof(uid_t));
+ if (domainlist == NULL) {
+ err = -ENOMEM;
+ goto cleanup;
@@ -22029,7 +24939,7 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
+static struct acl_object_label *
+__full_lookup(const struct dentry *orig_dentry, const struct vfsmount *orig_mnt,
+ const ino_t curr_ino, const dev_t curr_dev,
-+ const struct acl_subject_label *subj, char **path)
++ const struct acl_subject_label *subj, char **path, const int checkglob)
+{
+ struct acl_subject_label *tmpsubj;
+ struct acl_object_label *retval;
@@ -22040,7 +24950,7 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
+ do {
+ retval = lookup_acl_obj_label(curr_ino, curr_dev, tmpsubj);
+ if (retval) {
-+ if (retval->globbed) {
++ if (checkglob && retval->globbed) {
+ retval2 = chk_glob_label(retval->globbed, (struct dentry *)orig_dentry,
+ (struct vfsmount *)orig_mnt, path);
+ if (retval2)
@@ -22057,16 +24967,16 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
+static __inline__ struct acl_object_label *
+full_lookup(const struct dentry *orig_dentry, const struct vfsmount *orig_mnt,
+ const struct dentry *curr_dentry,
-+ const struct acl_subject_label *subj, char **path)
++ const struct acl_subject_label *subj, char **path, const int checkglob)
+{
+ return __full_lookup(orig_dentry, orig_mnt,
+ curr_dentry->d_inode->i_ino,
-+ curr_dentry->d_inode->i_sb->s_dev, subj, path);
++ curr_dentry->d_inode->i_sb->s_dev, subj, path, checkglob);
+}
+
+static struct acl_object_label *
+__chk_obj_label(const struct dentry *l_dentry, const struct vfsmount *l_mnt,
-+ const struct acl_subject_label *subj, char *path)
++ const struct acl_subject_label *subj, char *path, const int checkglob)
+{
+ struct dentry *dentry = (struct dentry *) l_dentry;
+ struct vfsmount *mnt = (struct vfsmount *) l_mnt;
@@ -22089,7 +24999,7 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
+ if (mnt->mnt_parent == mnt)
+ break;
+
-+ retval = full_lookup(l_dentry, l_mnt, dentry, subj, &path);
++ retval = full_lookup(l_dentry, l_mnt, dentry, subj, &path, checkglob);
+ if (retval != NULL)
+ goto out;
+
@@ -22098,17 +25008,17 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
+ continue;
+ }
+
-+ retval = full_lookup(l_dentry, l_mnt, dentry, subj, &path);
++ retval = full_lookup(l_dentry, l_mnt, dentry, subj, &path, checkglob);
+ if (retval != NULL)
+ goto out;
+
+ dentry = dentry->d_parent;
+ }
+
-+ retval = full_lookup(l_dentry, l_mnt, dentry, subj, &path);
++ retval = full_lookup(l_dentry, l_mnt, dentry, subj, &path, checkglob);
+
+ if (retval == NULL)
-+ retval = full_lookup(l_dentry, l_mnt, real_root, subj, &path);
++ retval = full_lookup(l_dentry, l_mnt, real_root, subj, &path, checkglob);
+out:
+ spin_unlock(&dcache_lock);
+ return retval;
@@ -22119,14 +25029,22 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
+ const struct acl_subject_label *subj)
+{
+ char *path = NULL;
-+ return __chk_obj_label(l_dentry, l_mnt, subj, path);
++ return __chk_obj_label(l_dentry, l_mnt, subj, path, 1);
++}
++
++static __inline__ struct acl_object_label *
++chk_obj_label_noglob(const struct dentry *l_dentry, const struct vfsmount *l_mnt,
++ const struct acl_subject_label *subj)
++{
++ char *path = NULL;
++ return __chk_obj_label(l_dentry, l_mnt, subj, path, 0);
+}
+
+static __inline__ struct acl_object_label *
+chk_obj_create_label(const struct dentry *l_dentry, const struct vfsmount *l_mnt,
+ const struct acl_subject_label *subj, char *path)
+{
-+ return __chk_obj_label(l_dentry, l_mnt, subj, path);
++ return __chk_obj_label(l_dentry, l_mnt, subj, path, 1);
+}
+
+static struct acl_subject_label *
@@ -22187,33 +25105,42 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
+}
+
+static void
-+gr_log_learn(const struct task_struct *task, const struct dentry *dentry, const struct vfsmount *mnt, const __u32 mode)
++gr_log_learn(const struct dentry *dentry, const struct vfsmount *mnt, const __u32 mode)
+{
++ struct task_struct *task = current;
++ const struct cred *cred = current_cred();
++
+ security_learn(GR_LEARN_AUDIT_MSG, task->role->rolename, task->role->roletype,
-+ task->uid, task->gid, task->exec_file ? gr_to_filename1(task->exec_file->f_path.dentry,
++ cred->uid, cred->gid, task->exec_file ? gr_to_filename1(task->exec_file->f_path.dentry,
+ task->exec_file->f_path.mnt) : task->acl->filename, task->acl->filename,
-+ 1, 1, gr_to_filename(dentry, mnt), (unsigned long) mode, NIPQUAD(task->signal->curr_ip));
++ 1UL, 1UL, gr_to_filename(dentry, mnt), (unsigned long) mode, NIPQUAD(task->signal->curr_ip));
+
+ return;
+}
+
+static void
-+gr_log_learn_sysctl(const struct task_struct *task, const char *path, const __u32 mode)
++gr_log_learn_sysctl(const char *path, const __u32 mode)
+{
++ struct task_struct *task = current;
++ const struct cred *cred = current_cred();
++
+ security_learn(GR_LEARN_AUDIT_MSG, task->role->rolename, task->role->roletype,
-+ task->uid, task->gid, task->exec_file ? gr_to_filename1(task->exec_file->f_path.dentry,
++ cred->uid, cred->gid, task->exec_file ? gr_to_filename1(task->exec_file->f_path.dentry,
+ task->exec_file->f_path.mnt) : task->acl->filename, task->acl->filename,
-+ 1, 1, path, (unsigned long) mode, NIPQUAD(task->signal->curr_ip));
++ 1UL, 1UL, path, (unsigned long) mode, NIPQUAD(task->signal->curr_ip));
+
+ return;
+}
+
+static void
-+gr_log_learn_id_change(const struct task_struct *task, const char type, const unsigned int real,
++gr_log_learn_id_change(const char type, const unsigned int real,
+ const unsigned int effective, const unsigned int fs)
+{
++ struct task_struct *task = current;
++ const struct cred *cred = current_cred();
++
+ security_learn(GR_ID_LEARN_MSG, task->role->rolename, task->role->roletype,
-+ task->uid, task->gid, task->exec_file ? gr_to_filename1(task->exec_file->f_path.dentry,
++ cred->uid, cred->gid, task->exec_file ? gr_to_filename1(task->exec_file->f_path.dentry,
+ task->exec_file->f_path.mnt) : task->acl->filename, task->acl->filename,
+ type, real, effective, fs, NIPQUAD(task->signal->curr_ip));
+
@@ -22269,7 +25196,7 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
+ needmode |= GR_SETID;
+
+ if (current->acl->mode & (GR_LEARN | GR_INHERITLEARN)) {
-+ gr_log_learn(current, old_dentry, old_mnt, needmode);
++ gr_log_learn(old_dentry, old_mnt, needmode);
+ return (GR_CREATE | GR_LINK);
+ } else if (newmode & GR_SUPPRESS)
+ return GR_SUPPRESS;
@@ -22306,7 +25233,7 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
+ new_mode |= GR_INHERIT;
+
+ if (!(mode & GR_NOLEARN))
-+ gr_log_learn(current, dentry, mnt, new_mode);
++ gr_log_learn(dentry, mnt, new_mode);
+ }
+
+ return retval;
@@ -22346,7 +25273,7 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
+
+ new_mode &= ~(GR_AUDITS | GR_SUPPRESS);
+
-+ gr_log_learn(current, new_dentry, mnt, new_mode);
++ gr_log_learn(new_dentry, mnt, new_mode);
+
+ preempt_enable();
+ return new_mode;
@@ -22367,7 +25294,7 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
+
+ new_mode &= ~(GR_AUDITS | GR_SUPPRESS);
+
-+ gr_log_learn(current, new_dentry, mnt, new_mode);
++ gr_log_learn(new_dentry, mnt, new_mode);
+ preempt_enable();
+ return new_mode;
+ }
@@ -22431,7 +25358,7 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
+ if (proc->mode & (GR_LEARN | GR_INHERITLEARN))
+ return;
+
-+ for (i = 0; i < (GR_NLIMITS - 1); i++) {
++ for (i = 0; i < RLIM_NLIMITS; i++) {
+ if (!(proc->resmask & (1 << i)))
+ continue;
+
@@ -22457,7 +25384,7 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
+ return 0;
+
+ if (current->acl->mode & (GR_LEARN | GR_INHERITLEARN))
-+ gr_log_learn_id_change(current, 'u', real, effective, fs);
++ gr_log_learn_id_change('u', real, effective, fs);
+
+ num = current->acl->user_trans_num;
+ uidlist = current->acl->user_transitions;
@@ -22523,7 +25450,7 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
+ return 0;
+
+ if (current->acl->mode & (GR_LEARN | GR_INHERITLEARN))
-+ gr_log_learn_id_change(current, 'g', real, effective, fs);
++ gr_log_learn_id_change('g', real, effective, fs);
+
+ num = current->acl->group_trans_num;
+ gidlist = current->acl->group_transitions;
@@ -22633,7 +25560,8 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
+}
+
+int
-+gr_set_proc_label(const struct dentry *dentry, const struct vfsmount *mnt)
++gr_set_proc_label(const struct dentry *dentry, const struct vfsmount *mnt,
++ const int unsafe_share)
+{
+ struct task_struct *task = current;
+ struct acl_subject_label *newacl;
@@ -22650,10 +25578,8 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
+ GR_POVERRIDE) && (task->acl != newacl) &&
+ !(task->role->roletype & GR_ROLE_GOD) &&
+ !gr_search_file(dentry, GR_PTRACERD, mnt) &&
-+ !(task->acl->mode & (GR_LEARN | GR_INHERITLEARN))) ||
-+ (atomic_read(&task->fs->count) > 1 ||
-+ atomic_read(&task->files->count) > 1 ||
-+ atomic_read(&task->sighand->count) > 1)) {
++ !(task->acl->mode & (GR_LEARN | GR_INHERITLEARN)))
++ || unsafe_share) {
+ task_unlock(task);
+ gr_log_fs_generic(GR_DONT_AUDIT, GR_PTRACE_EXEC_ACL_MSG, dentry, mnt);
+ return -EACCES;
@@ -23199,7 +26125,7 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
+
+ if (gr_usermode->mode != GR_SPROLE && gr_usermode->mode != GR_STATUS &&
+ gr_usermode->mode != GR_UNSPROLE && gr_usermode->mode != GR_SPROLEPAM &&
-+ current->uid) {
++ current_uid()) {
+ error = -EPERM;
+ goto out;
+ }
@@ -23390,6 +26316,10 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
+ struct file *filp;
+ struct acl_role_label *role = current->role;
+ __u16 acl_role_id = current->acl_role_id;
++ const struct cred *cred;
++ char *tmpname;
++ struct name_entry *nmatch;
++ struct acl_subject_label *tmpsubj;
+
+ read_lock(&tasklist_lock);
+ read_lock(&grsec_exec_file_lock);
@@ -23406,11 +26336,37 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
+ task->acl_sp_role = 0;
+
+ if ((filp = task->exec_file)) {
-+ task->role = lookup_acl_role_label(task, task->uid, task->gid);
-+
-+ task->acl =
-+ chk_subj_label(filp->f_path.dentry, filp->f_path.mnt,
-+ task->role);
++ cred = __task_cred(task);
++ task->role = lookup_acl_role_label(task, cred->uid, cred->gid);
++
++ /* the following is to apply the correct subject
++ on binaries running when the RBAC system
++ is enabled, when the binaries have been
++ replaced or deleted since their execution
++ -----
++ when the RBAC system starts, the inode/dev
++ from exec_file will be one the RBAC system
++ is unaware of. It only knows the inode/dev
++ of the present file on disk, or the absence
++ of it.
++ */
++ preempt_disable();
++ tmpname = gr_to_filename_rbac(filp->f_path.dentry, filp->f_path.mnt);
++
++ nmatch = lookup_name_entry(tmpname);
++ preempt_enable();
++ tmpsubj = NULL;
++ if (nmatch) {
++ if (nmatch->deleted)
++ tmpsubj = lookup_acl_subj_label_deleted(nmatch->inode, nmatch->device, task->role);
++ else
++ tmpsubj = lookup_acl_subj_label(nmatch->inode, nmatch->device, task->role);
++ if (tmpsubj != NULL)
++ task->acl = tmpsubj;
++ }
++ if (tmpsubj == NULL)
++ task->acl = chk_subj_label(filp->f_path.dentry, filp->f_path.mnt,
++ task->role);
+ if (task->acl) {
+ struct acl_subject_label *curr;
+ curr = task->acl;
@@ -23455,6 +26411,7 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
+ const int res, const unsigned long wanted, const int gt)
+{
+ struct acl_subject_label *acl;
++ const struct cred *cred;
+
+ if (unlikely((gr_status & GR_READY) &&
+ task->acl && (task->acl->mode & (GR_LEARN | GR_INHERITLEARN))))
@@ -23465,7 +26422,7 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
+#endif
+ skip_reslog:
+
-+ if (unlikely(!(gr_status & GR_READY) || !wanted))
++ if (unlikely(!(gr_status & GR_READY) || !wanted || res >= GR_NLIMITS))
+ return;
+
+ acl = task->acl;
@@ -23512,6 +26469,21 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
+ case RLIMIT_LOCKS:
+ res_add += GR_RLIM_LOCKS_BUMP;
+ break;
++ case RLIMIT_SIGPENDING:
++ res_add += GR_RLIM_SIGPENDING_BUMP;
++ break;
++ case RLIMIT_MSGQUEUE:
++ res_add += GR_RLIM_MSGQUEUE_BUMP;
++ break;
++ case RLIMIT_NICE:
++ res_add += GR_RLIM_NICE_BUMP;
++ break;
++ case RLIMIT_RTPRIO:
++ res_add += GR_RLIM_RTPRIO_BUMP;
++ break;
++ case RLIMIT_RTTIME:
++ res_add += GR_RLIM_RTTIME_BUMP;
++ break;
+ }
+
+ acl->res[res].rlim_cur = res_add;
@@ -23519,16 +26491,19 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
+ if (wanted > acl->res[res].rlim_max)
+ acl->res[res].rlim_max = res_add;
+
++ /* only log the subject filename, since resource logging is supported for
++ single-subject learning only */
++ cred = __task_cred(task);
+ security_learn(GR_LEARN_AUDIT_MSG, task->role->rolename,
-+ task->role->roletype, acl->filename,
-+ acl->res[res].rlim_cur, acl->res[res].rlim_max,
-+ "", (unsigned long) res);
++ task->role->roletype, cred->uid, cred->gid, acl->filename,
++ acl->filename, acl->res[res].rlim_cur, acl->res[res].rlim_max,
++ "", (unsigned long) res, NIPQUAD(task->signal->curr_ip));
+ }
+
+ return;
+}
+
-+#ifdef CONFIG_PAX_HAVE_ACL_FLAGS
++#if defined(CONFIG_PAX_HAVE_ACL_FLAGS) && (defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR))
+void
+pax_set_initial_flags(struct linux_binprm *bprm)
+{
@@ -23710,7 +26685,7 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
+ new_mode &= ~(GR_AUDITS | GR_SUPPRESS);
+
+ err = 0;
-+ gr_log_learn_sysctl(current, path, new_mode);
++ gr_log_learn_sysctl(path, new_mode);
+ } else if (!(err & GR_FIND) && !(err & GR_SUPPRESS) && op != 0) {
+ gr_log_hidden_sysctl(GR_DONT_AUDIT, GR_HIDDEN_ACL_MSG, path);
+ err = -ENOENT;
@@ -24005,7 +26980,13 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
+ return (obj->mode & GR_FIND) ? 1 : 0;
+ } while ((subj = subj->parent_subject));
+
-+ obj = chk_obj_label(dentry, mnt, task->acl);
++ /* this is purely an optimization since we're looking for an object
++ for the directory we're doing a readdir on
++ if it's possible for any globbed object to match the entry we're
++ filling into the directory, then the object we find here will be
++ an anchor point with attached globbed objects
++ */
++ obj = chk_obj_label_noglob(dentry, mnt, task->acl);
+ if (obj->globbed == NULL)
+ return (obj->mode & GR_FIND) ? 1 : 0;
+
@@ -24048,10 +27029,10 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c
+EXPORT_SYMBOL(gr_check_group_change);
+#endif
+
-diff -urNp linux-2.6.28.8/grsecurity/gracl_cap.c linux-2.6.28.8/grsecurity/gracl_cap.c
---- linux-2.6.28.8/grsecurity/gracl_cap.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/grsecurity/gracl_cap.c 2009-02-21 09:37:49.000000000 -0500
-@@ -0,0 +1,129 @@
+diff -urNp linux-2.6.29.5/grsecurity/gracl_cap.c linux-2.6.29.5/grsecurity/gracl_cap.c
+--- linux-2.6.29.5/grsecurity/gracl_cap.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/grsecurity/gracl_cap.c 2009-06-12 23:57:32.000000000 -0400
+@@ -0,0 +1,131 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
@@ -24096,12 +27077,14 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl_cap.c linux-2.6.28.8/grsecurity/gracl
+ "CAP_MAC_ADMIN"
+};
+
-+EXPORT_SYMBOL(gr_task_is_capable);
++EXPORT_SYMBOL(gr_is_capable);
+EXPORT_SYMBOL(gr_is_capable_nolog);
+
+int
-+gr_task_is_capable(struct task_struct *task, const int cap)
++gr_is_capable(const int cap)
+{
++ struct task_struct *task = current;
++ const struct cred *cred = current_cred();
+ struct acl_subject_label *curracl;
+ kernel_cap_t cap_drop = __cap_empty_set, cap_mask = __cap_empty_set;
+
@@ -24132,10 +27115,10 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl_cap.c linux-2.6.28.8/grsecurity/gracl
+ curracl = task->acl;
+
+ if ((curracl->mode & (GR_LEARN | GR_INHERITLEARN))
-+ && cap_raised(task->cap_effective, cap)) {
++ && cap_raised(cred->cap_effective, cap)) {
+ security_learn(GR_LEARN_AUDIT_MSG, task->role->rolename,
-+ task->role->roletype, task->uid,
-+ task->gid, task->exec_file ?
++ task->role->roletype, cred->uid,
++ cred->gid, task->exec_file ?
+ gr_to_filename(task->exec_file->f_path.dentry,
+ task->exec_file->f_path.mnt) : curracl->filename,
+ curracl->filename, 0UL,
@@ -24143,7 +27126,7 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl_cap.c linux-2.6.28.8/grsecurity/gracl
+ return 1;
+ }
+
-+ if ((cap >= 0) && (cap < (sizeof(captab_log)/sizeof(captab_log[0]))) && cap_raised(task->cap_effective, cap))
++ if ((cap >= 0) && (cap < (sizeof(captab_log)/sizeof(captab_log[0]))) && cap_raised(cred->cap_effective, cap))
+ gr_log_cap(GR_DONT_AUDIT, GR_CAP_ACL_MSG, task, captab_log[cap]);
+ return 0;
+}
@@ -24181,9 +27164,9 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl_cap.c linux-2.6.28.8/grsecurity/gracl
+ return 0;
+}
+
-diff -urNp linux-2.6.28.8/grsecurity/gracl_fs.c linux-2.6.28.8/grsecurity/gracl_fs.c
---- linux-2.6.28.8/grsecurity/gracl_fs.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/grsecurity/gracl_fs.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/grsecurity/gracl_fs.c linux-2.6.29.5/grsecurity/gracl_fs.c
+--- linux-2.6.29.5/grsecurity/gracl_fs.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/grsecurity/gracl_fs.c 2009-06-12 23:57:32.000000000 -0400
@@ -0,0 +1,423 @@
+#include <linux/kernel.h>
+#include <linux/sched.h>
@@ -24608,10 +27591,10 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl_fs.c linux-2.6.28.8/grsecurity/gracl_
+
+ return 0;
+}
-diff -urNp linux-2.6.28.8/grsecurity/gracl_ip.c linux-2.6.28.8/grsecurity/gracl_ip.c
---- linux-2.6.28.8/grsecurity/gracl_ip.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/grsecurity/gracl_ip.c 2009-02-21 09:37:49.000000000 -0500
-@@ -0,0 +1,338 @@
+diff -urNp linux-2.6.29.5/grsecurity/gracl_ip.c linux-2.6.29.5/grsecurity/gracl_ip.c
+--- linux-2.6.29.5/grsecurity/gracl_ip.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/grsecurity/gracl_ip.c 2009-06-12 23:57:32.000000000 -0400
+@@ -0,0 +1,340 @@
+#include <linux/kernel.h>
+#include <asm/uaccess.h>
+#include <asm/errno.h>
@@ -24694,6 +27677,7 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl_ip.c linux-2.6.28.8/grsecurity/gracl_
+gr_search_socket(const int domain, const int type, const int protocol)
+{
+ struct acl_subject_label *curr;
++ const struct cred *cred = current_cred();
+
+ if (unlikely(!gr_acl_is_enabled()))
+ goto exit;
@@ -24718,8 +27702,8 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl_ip.c linux-2.6.28.8/grsecurity/gracl_
+ if (type == SOCK_RAW || type == SOCK_PACKET) {
+ __u32 fakeip = 0;
+ security_learn(GR_IP_LEARN_MSG, current->role->rolename,
-+ current->role->roletype, current->uid,
-+ current->gid, current->exec_file ?
++ current->role->roletype, cred->uid,
++ cred->gid, current->exec_file ?
+ gr_to_filename(current->exec_file->f_path.dentry,
+ current->exec_file->f_path.mnt) :
+ curr->filename, curr->filename,
@@ -24729,8 +27713,8 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl_ip.c linux-2.6.28.8/grsecurity/gracl_
+ } else if ((type == SOCK_DGRAM) && (protocol == IPPROTO_IP)) {
+ __u32 fakeip = 0;
+ security_learn(GR_IP_LEARN_MSG, current->role->rolename,
-+ current->role->roletype, current->uid,
-+ current->gid, current->exec_file ?
++ current->role->roletype, cred->uid,
++ cred->gid, current->exec_file ?
+ gr_to_filename(current->exec_file->f_path.dentry,
+ current->exec_file->f_path.mnt) :
+ curr->filename, curr->filename,
@@ -24785,6 +27769,7 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl_ip.c linux-2.6.28.8/grsecurity/gracl_
+ __u32 our_netmask;
+ char *p;
+ __u16 ip_port = 0;
++ const struct cred *cred = current_cred();
+
+ if (unlikely(!gr_acl_is_enabled() || sk->sk_family != PF_INET))
+ return 0;
@@ -24820,8 +27805,8 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl_ip.c linux-2.6.28.8/grsecurity/gracl_
+
+ if (curr->mode & (GR_LEARN | GR_INHERITLEARN)) {
+ security_learn(GR_IP_LEARN_MSG, current->role->rolename,
-+ current->role->roletype, current->uid,
-+ current->gid, current->exec_file ?
++ current->role->roletype, cred->uid,
++ cred->gid, current->exec_file ?
+ gr_to_filename(current->exec_file->f_path.dentry,
+ current->exec_file->f_path.mnt) :
+ curr->filename, curr->filename,
@@ -24950,9 +27935,9 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl_ip.c linux-2.6.28.8/grsecurity/gracl_
+
+ return gr_search_connectbind(GR_CONNECT | GR_CONNECTOVERRIDE, sk, &sin, SOCK_DGRAM);
+}
-diff -urNp linux-2.6.28.8/grsecurity/gracl_learn.c linux-2.6.28.8/grsecurity/gracl_learn.c
---- linux-2.6.28.8/grsecurity/gracl_learn.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/grsecurity/gracl_learn.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/grsecurity/gracl_learn.c linux-2.6.29.5/grsecurity/gracl_learn.c
+--- linux-2.6.29.5/grsecurity/gracl_learn.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/grsecurity/gracl_learn.c 2009-06-12 23:57:32.000000000 -0400
@@ -0,0 +1,211 @@
+#include <linux/kernel.h>
+#include <linux/mm.h>
@@ -25165,10 +28150,10 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl_learn.c linux-2.6.28.8/grsecurity/gra
+ .release = close_learn,
+ .poll = poll_learn,
+};
-diff -urNp linux-2.6.28.8/grsecurity/gracl_res.c linux-2.6.28.8/grsecurity/gracl_res.c
---- linux-2.6.28.8/grsecurity/gracl_res.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/grsecurity/gracl_res.c 2009-02-21 09:37:49.000000000 -0500
-@@ -0,0 +1,45 @@
+diff -urNp linux-2.6.29.5/grsecurity/gracl_res.c linux-2.6.29.5/grsecurity/gracl_res.c
+--- linux-2.6.29.5/grsecurity/gracl_res.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/grsecurity/gracl_res.c 2009-06-12 23:57:32.000000000 -0400
+@@ -0,0 +1,58 @@
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/gracl.h>
@@ -25186,24 +28171,37 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl_res.c linux-2.6.28.8/grsecurity/gracl
+ [RLIMIT_MEMLOCK] = "RLIMIT_MEMLOCK",
+ [RLIMIT_AS] = "RLIMIT_AS",
+ [RLIMIT_LOCKS] = "RLIMIT_LOCKS",
-+ [RLIMIT_LOCKS + 1] = "RLIMIT_CRASH"
++ [RLIMIT_SIGPENDING] = "RLIMIT_SIGPENDING",
++ [RLIMIT_MSGQUEUE] = "RLIMIT_MSGQUEUE",
++ [RLIMIT_NICE] = "RLIMIT_NICE",
++ [RLIMIT_RTPRIO] = "RLIMIT_RTPRIO",
++ [RLIMIT_RTTIME] = "RLIMIT_RTTIME",
++ [GR_CRASH_RES] = "RLIMIT_CRASH"
+};
+
+void
+gr_log_resource(const struct task_struct *task,
+ const int res, const unsigned long wanted, const int gt)
+{
++ const struct cred *cred = __task_cred(task);
++
+ if (res == RLIMIT_NPROC &&
-+ (cap_raised(task->cap_effective, CAP_SYS_ADMIN) ||
-+ cap_raised(task->cap_effective, CAP_SYS_RESOURCE)))
++ (cap_raised(cred->cap_effective, CAP_SYS_ADMIN) ||
++ cap_raised(cred->cap_effective, CAP_SYS_RESOURCE)))
+ return;
+ else if (res == RLIMIT_MEMLOCK &&
-+ cap_raised(task->cap_effective, CAP_IPC_LOCK))
++ cap_raised(cred->cap_effective, CAP_IPC_LOCK))
++ return;
++ else if (res == RLIMIT_NICE && cap_raised(cred->cap_effective, CAP_SYS_NICE))
+ return;
+
+ if (!gr_acl_is_enabled() && !grsec_resource_logging)
+ return;
+
++ // not yet supported resource
++ if (!restab_log[res])
++ return;
++
+ preempt_disable();
+
+ if (unlikely(((gt && wanted > task->signal->rlim[res].rlim_cur) ||
@@ -25214,10 +28212,10 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl_res.c linux-2.6.28.8/grsecurity/gracl
+
+ return;
+}
-diff -urNp linux-2.6.28.8/grsecurity/gracl_segv.c linux-2.6.28.8/grsecurity/gracl_segv.c
---- linux-2.6.28.8/grsecurity/gracl_segv.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/grsecurity/gracl_segv.c 2009-02-21 09:37:49.000000000 -0500
-@@ -0,0 +1,304 @@
+diff -urNp linux-2.6.29.5/grsecurity/gracl_segv.c linux-2.6.29.5/grsecurity/gracl_segv.c
+--- linux-2.6.29.5/grsecurity/gracl_segv.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/grsecurity/gracl_segv.c 2009-06-12 23:57:32.000000000 -0400
+@@ -0,0 +1,307 @@
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <asm/uaccess.h>
@@ -25368,13 +28366,13 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl_segv.c linux-2.6.28.8/grsecurity/grac
+}
+
+static __inline__ int
-+proc_is_setxid(const struct task_struct *task)
++proc_is_setxid(const struct cred *cred)
+{
-+ if (task->uid != task->euid || task->uid != task->suid ||
-+ task->uid != task->fsuid)
++ if (cred->uid != cred->euid || cred->uid != cred->suid ||
++ cred->uid != cred->fsuid)
+ return 1;
-+ if (task->gid != task->egid || task->gid != task->sgid ||
-+ task->gid != task->fsgid)
++ if (cred->gid != cred->egid || cred->gid != cred->sgid ||
++ cred->gid != cred->fsgid)
+ return 1;
+
+ return 0;
@@ -25412,6 +28410,8 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl_segv.c linux-2.6.28.8/grsecurity/grac
+ struct acl_subject_label *curr;
+ struct acl_subject_label *curr2;
+ struct task_struct *tsk, *tsk2;
++ const struct cred *cred = __task_cred(task);
++ const struct cred *cred2;
+
+ if (sig != SIGSEGV && sig != SIGKILL && sig != SIGBUS && sig != SIGILL)
+ return;
@@ -25436,16 +28436,17 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl_segv.c linux-2.6.28.8/grsecurity/grac
+
+ if ((curr->crashes >= curr->res[GR_CRASH_RES].rlim_cur) &&
+ time_after(curr->expires, get_seconds())) {
-+ if (task->uid && proc_is_setxid(task)) {
++ if (cred->uid && proc_is_setxid(cred)) {
+ gr_log_crash1(GR_DONT_AUDIT, GR_SEGVSTART_ACL_MSG, task, curr->res[GR_CRASH_RES].rlim_max);
+ spin_lock(&gr_uid_lock);
-+ gr_insert_uid(task->uid, curr->expires);
++ gr_insert_uid(cred->uid, curr->expires);
+ spin_unlock(&gr_uid_lock);
+ curr->expires = 0;
+ curr->crashes = 0;
+ read_lock(&tasklist_lock);
+ do_each_thread(tsk2, tsk) {
-+ if (tsk != task && tsk->uid == task->uid)
++ cred2 = __task_cred(tsk);
++ if (tsk != task && cred2->uid == cred->uid)
+ gr_fake_force_sig(SIGKILL, tsk);
+ } while_each_thread(tsk2, tsk);
+ read_unlock(&tasklist_lock);
@@ -25522,10 +28523,10 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl_segv.c linux-2.6.28.8/grsecurity/grac
+
+ return;
+}
-diff -urNp linux-2.6.28.8/grsecurity/gracl_shm.c linux-2.6.28.8/grsecurity/gracl_shm.c
---- linux-2.6.28.8/grsecurity/gracl_shm.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/grsecurity/gracl_shm.c 2009-02-21 09:37:49.000000000 -0500
-@@ -0,0 +1,33 @@
+diff -urNp linux-2.6.29.5/grsecurity/gracl_shm.c linux-2.6.29.5/grsecurity/gracl_shm.c
+--- linux-2.6.29.5/grsecurity/gracl_shm.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/grsecurity/gracl_shm.c 2009-06-12 23:57:32.000000000 -0400
+@@ -0,0 +1,37 @@
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
@@ -25544,6 +28545,8 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl_shm.c linux-2.6.28.8/grsecurity/gracl
+ if (!gr_acl_is_enabled())
+ return 1;
+
++ read_lock(&tasklist_lock);
++
+ task = find_task_by_vpid(shm_cprid);
+
+ if (unlikely(!task))
@@ -25553,15 +28556,17 @@ diff -urNp linux-2.6.28.8/grsecurity/gracl_shm.c linux-2.6.28.8/grsecurity/gracl
+ (task->pid == shm_lapid)) &&
+ (task->acl->mode & GR_PROTSHM) &&
+ (task->acl != current->acl))) {
++ read_unlock(&tasklist_lock);
+ gr_log_int3(GR_DONT_AUDIT, GR_SHMAT_ACL_MSG, cuid, shm_cprid, shmid);
+ return 0;
+ }
++ read_unlock(&tasklist_lock);
+
+ return 1;
+}
-diff -urNp linux-2.6.28.8/grsecurity/grsec_chdir.c linux-2.6.28.8/grsecurity/grsec_chdir.c
---- linux-2.6.28.8/grsecurity/grsec_chdir.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/grsecurity/grsec_chdir.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/grsecurity/grsec_chdir.c linux-2.6.29.5/grsecurity/grsec_chdir.c
+--- linux-2.6.29.5/grsecurity/grsec_chdir.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/grsecurity/grsec_chdir.c 2009-06-12 23:57:32.000000000 -0400
@@ -0,0 +1,19 @@
+#include <linux/kernel.h>
+#include <linux/sched.h>
@@ -25582,10 +28587,10 @@ diff -urNp linux-2.6.28.8/grsecurity/grsec_chdir.c linux-2.6.28.8/grsecurity/grs
+#endif
+ return;
+}
-diff -urNp linux-2.6.28.8/grsecurity/grsec_chroot.c linux-2.6.28.8/grsecurity/grsec_chroot.c
---- linux-2.6.28.8/grsecurity/grsec_chroot.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/grsecurity/grsec_chroot.c 2009-02-21 09:37:49.000000000 -0500
-@@ -0,0 +1,336 @@
+diff -urNp linux-2.6.29.5/grsecurity/grsec_chroot.c linux-2.6.29.5/grsecurity/grsec_chroot.c
+--- linux-2.6.29.5/grsecurity/grsec_chroot.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/grsecurity/grsec_chroot.c 2009-06-12 23:57:32.000000000 -0400
+@@ -0,0 +1,350 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
@@ -25866,21 +28871,35 @@ diff -urNp linux-2.6.28.8/grsecurity/grsec_chroot.c linux-2.6.28.8/grsecurity/gr
+ return 0;
+}
+
-+void
-+gr_handle_chroot_caps(struct task_struct *task)
++int
++gr_handle_chroot_caps(struct path *path)
+{
+#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS
-+ if (grsec_enable_chroot_caps && proc_is_chrooted(task)) {
++ if (grsec_enable_chroot_caps && current->pid > 1 && current->fs != NULL &&
++ ((current->nsproxy->pid_ns->child_reaper->fs->root.dentry->d_inode->i_sb !=
++ path->dentry->d_inode->i_sb) ||
++ (current->nsproxy->pid_ns->child_reaper->fs->root.dentry->d_inode->i_ino !=
++ path->dentry->d_inode->i_ino))) {
++
+ kernel_cap_t chroot_caps = GR_CHROOT_CAPS;
-+ task->cap_permitted =
-+ cap_drop(task->cap_permitted, chroot_caps);
-+ task->cap_inheritable =
-+ cap_drop(task->cap_inheritable, chroot_caps);
-+ task->cap_effective =
-+ cap_drop(task->cap_effective, chroot_caps);
++ const struct cred *old = current_cred();
++ struct cred *new = prepare_creds();
++ if (new == NULL)
++ return 1;
++
++ new->cap_permitted = cap_drop(old->cap_permitted,
++ chroot_caps);
++ new->cap_inheritable = cap_drop(old->cap_inheritable,
++ chroot_caps);
++ new->cap_effective = cap_drop(old->cap_effective,
++ chroot_caps);
++
++ commit_creds(new);
++
++ return 0;
+ }
+#endif
-+ return;
++ return 0;
+}
+
+int
@@ -25922,10 +28941,10 @@ diff -urNp linux-2.6.28.8/grsecurity/grsec_chroot.c linux-2.6.28.8/grsecurity/gr
+#ifdef CONFIG_SECURITY
+EXPORT_SYMBOL(gr_handle_chroot_caps);
+#endif
-diff -urNp linux-2.6.28.8/grsecurity/grsec_disabled.c linux-2.6.28.8/grsecurity/grsec_disabled.c
---- linux-2.6.28.8/grsecurity/grsec_disabled.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/grsecurity/grsec_disabled.c 2009-03-07 14:23:04.000000000 -0500
-@@ -0,0 +1,418 @@
+diff -urNp linux-2.6.29.5/grsecurity/grsec_disabled.c linux-2.6.29.5/grsecurity/grsec_disabled.c
+--- linux-2.6.29.5/grsecurity/grsec_disabled.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/grsecurity/grsec_disabled.c 2009-06-12 23:57:32.000000000 -0400
+@@ -0,0 +1,419 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
@@ -26022,7 +29041,8 @@ diff -urNp linux-2.6.28.8/grsecurity/grsec_disabled.c linux-2.6.28.8/grsecurity/
+}
+
+int
-+gr_set_proc_label(const struct dentry *dentry, const struct vfsmount *mnt)
++gr_set_proc_label(const struct dentry *dentry, const struct vfsmount *mnt,
++ const int unsafe_share)
+{
+ return 0;
+}
@@ -26080,7 +29100,7 @@ diff -urNp linux-2.6.28.8/grsecurity/grsec_disabled.c linux-2.6.28.8/grsecurity/
+}
+
+int
-+gr_task_is_capable(struct task_struct *task, const int cap)
++gr_is_capable(const int cap)
+{
+ return 1;
+}
@@ -26336,7 +29356,7 @@ diff -urNp linux-2.6.28.8/grsecurity/grsec_disabled.c linux-2.6.28.8/grsecurity/
+}
+
+
-+EXPORT_SYMBOL(gr_task_is_capable);
++EXPORT_SYMBOL(gr_is_capable);
+EXPORT_SYMBOL(gr_is_capable_nolog);
+EXPORT_SYMBOL(gr_learn_resource);
+EXPORT_SYMBOL(gr_set_kernel_label);
@@ -26344,10 +29364,10 @@ diff -urNp linux-2.6.28.8/grsecurity/grsec_disabled.c linux-2.6.28.8/grsecurity/
+EXPORT_SYMBOL(gr_check_user_change);
+EXPORT_SYMBOL(gr_check_group_change);
+#endif
-diff -urNp linux-2.6.28.8/grsecurity/grsec_exec.c linux-2.6.28.8/grsecurity/grsec_exec.c
---- linux-2.6.28.8/grsecurity/grsec_exec.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/grsecurity/grsec_exec.c 2009-02-21 09:37:49.000000000 -0500
-@@ -0,0 +1,88 @@
+diff -urNp linux-2.6.29.5/grsecurity/grsec_exec.c linux-2.6.29.5/grsecurity/grsec_exec.c
+--- linux-2.6.29.5/grsecurity/grsec_exec.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/grsecurity/grsec_exec.c 2009-06-12 23:57:32.000000000 -0400
+@@ -0,0 +1,89 @@
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/file.h>
@@ -26370,8 +29390,9 @@ diff -urNp linux-2.6.28.8/grsecurity/grsec_exec.c linux-2.6.28.8/grsecurity/grse
+gr_handle_nproc(void)
+{
+#ifdef CONFIG_GRKERNSEC_EXECVE
-+ if (grsec_enable_execve && current->user &&
-+ (atomic_read(&current->user->processes) >
++ const struct cred *cred = current_cred();
++ if (grsec_enable_execve && cred->user &&
++ (atomic_read(&cred->user->processes) >
+ current->signal->rlim[RLIMIT_NPROC].rlim_cur) &&
+ !capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE)) {
+ gr_log_noargs(GR_DONT_AUDIT, GR_NPROC_MSG);
@@ -26436,10 +29457,10 @@ diff -urNp linux-2.6.28.8/grsecurity/grsec_exec.c linux-2.6.28.8/grsecurity/grse
+#endif
+ return;
+}
-diff -urNp linux-2.6.28.8/grsecurity/grsec_fifo.c linux-2.6.28.8/grsecurity/grsec_fifo.c
---- linux-2.6.28.8/grsecurity/grsec_fifo.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/grsecurity/grsec_fifo.c 2009-02-21 09:37:49.000000000 -0500
-@@ -0,0 +1,22 @@
+diff -urNp linux-2.6.29.5/grsecurity/grsec_fifo.c linux-2.6.29.5/grsecurity/grsec_fifo.c
+--- linux-2.6.29.5/grsecurity/grsec_fifo.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/grsecurity/grsec_fifo.c 2009-06-12 23:57:32.000000000 -0400
+@@ -0,0 +1,24 @@
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
@@ -26451,10 +29472,12 @@ diff -urNp linux-2.6.28.8/grsecurity/grsec_fifo.c linux-2.6.28.8/grsecurity/grse
+ const struct dentry *dir, const int flag, const int acc_mode)
+{
+#ifdef CONFIG_GRKERNSEC_FIFO
++ const struct cred *cred = current_cred();
++
+ if (grsec_enable_fifo && S_ISFIFO(dentry->d_inode->i_mode) &&
+ !(flag & O_EXCL) && (dir->d_inode->i_mode & S_ISVTX) &&
+ (dentry->d_inode->i_uid != dir->d_inode->i_uid) &&
-+ (current->fsuid != dentry->d_inode->i_uid)) {
++ (cred->fsuid != dentry->d_inode->i_uid)) {
+ if (!generic_permission(dentry->d_inode, acc_mode, NULL))
+ gr_log_fs_int2(GR_DONT_AUDIT, GR_FIFO_MSG, dentry, mnt, dentry->d_inode->i_uid, dentry->d_inode->i_gid);
+ return -EACCES;
@@ -26462,9 +29485,9 @@ diff -urNp linux-2.6.28.8/grsecurity/grsec_fifo.c linux-2.6.28.8/grsecurity/grse
+#endif
+ return 0;
+}
-diff -urNp linux-2.6.28.8/grsecurity/grsec_fork.c linux-2.6.28.8/grsecurity/grsec_fork.c
---- linux-2.6.28.8/grsecurity/grsec_fork.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/grsecurity/grsec_fork.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/grsecurity/grsec_fork.c linux-2.6.29.5/grsecurity/grsec_fork.c
+--- linux-2.6.29.5/grsecurity/grsec_fork.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/grsecurity/grsec_fork.c 2009-06-12 23:57:32.000000000 -0400
@@ -0,0 +1,15 @@
+#include <linux/kernel.h>
+#include <linux/sched.h>
@@ -26481,9 +29504,9 @@ diff -urNp linux-2.6.28.8/grsecurity/grsec_fork.c linux-2.6.28.8/grsecurity/grse
+#endif
+ return;
+}
-diff -urNp linux-2.6.28.8/grsecurity/grsec_init.c linux-2.6.28.8/grsecurity/grsec_init.c
---- linux-2.6.28.8/grsecurity/grsec_init.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/grsecurity/grsec_init.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/grsecurity/grsec_init.c linux-2.6.29.5/grsecurity/grsec_init.c
+--- linux-2.6.29.5/grsecurity/grsec_init.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/grsecurity/grsec_init.c 2009-06-12 23:57:32.000000000 -0400
@@ -0,0 +1,230 @@
+#include <linux/kernel.h>
+#include <linux/sched.h>
@@ -26715,9 +29738,9 @@ diff -urNp linux-2.6.28.8/grsecurity/grsec_init.c linux-2.6.28.8/grsecurity/grse
+
+ return;
+}
-diff -urNp linux-2.6.28.8/grsecurity/grsec_ipc.c linux-2.6.28.8/grsecurity/grsec_ipc.c
---- linux-2.6.28.8/grsecurity/grsec_ipc.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/grsecurity/grsec_ipc.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/grsecurity/grsec_ipc.c linux-2.6.29.5/grsecurity/grsec_ipc.c
+--- linux-2.6.29.5/grsecurity/grsec_ipc.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/grsecurity/grsec_ipc.c 2009-06-12 23:57:32.000000000 -0400
@@ -0,0 +1,81 @@
+#include <linux/kernel.h>
+#include <linux/sched.h>
@@ -26800,10 +29823,10 @@ diff -urNp linux-2.6.28.8/grsecurity/grsec_ipc.c linux-2.6.28.8/grsecurity/grsec
+#endif
+ return;
+}
-diff -urNp linux-2.6.28.8/grsecurity/grsec_link.c linux-2.6.28.8/grsecurity/grsec_link.c
---- linux-2.6.28.8/grsecurity/grsec_link.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/grsecurity/grsec_link.c 2009-02-21 09:37:49.000000000 -0500
-@@ -0,0 +1,39 @@
+diff -urNp linux-2.6.29.5/grsecurity/grsec_link.c linux-2.6.29.5/grsecurity/grsec_link.c
+--- linux-2.6.29.5/grsecurity/grsec_link.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/grsecurity/grsec_link.c 2009-06-12 23:57:32.000000000 -0400
+@@ -0,0 +1,43 @@
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
@@ -26816,9 +29839,11 @@ diff -urNp linux-2.6.28.8/grsecurity/grsec_link.c linux-2.6.28.8/grsecurity/grse
+ const struct dentry *dentry, const struct vfsmount *mnt)
+{
+#ifdef CONFIG_GRKERNSEC_LINK
++ const struct cred *cred = current_cred();
++
+ if (grsec_enable_link && S_ISLNK(inode->i_mode) &&
+ (parent->i_mode & S_ISVTX) && (parent->i_uid != inode->i_uid) &&
-+ (parent->i_mode & S_IWOTH) && (current->fsuid != inode->i_uid)) {
++ (parent->i_mode & S_IWOTH) && (cred->fsuid != inode->i_uid)) {
+ gr_log_fs_int2(GR_DONT_AUDIT, GR_SYMLINK_MSG, dentry, mnt, inode->i_uid, inode->i_gid);
+ return -EACCES;
+ }
@@ -26832,21 +29857,23 @@ diff -urNp linux-2.6.28.8/grsecurity/grsec_link.c linux-2.6.28.8/grsecurity/grse
+ struct inode *inode, const int mode, const char *to)
+{
+#ifdef CONFIG_GRKERNSEC_LINK
-+ if (grsec_enable_link && current->fsuid != inode->i_uid &&
++ const struct cred *cred = current_cred();
++
++ if (grsec_enable_link && cred->fsuid != inode->i_uid &&
+ (!S_ISREG(mode) || (mode & S_ISUID) ||
+ ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) ||
+ (generic_permission(inode, MAY_READ | MAY_WRITE, NULL))) &&
-+ !capable(CAP_FOWNER) && current->uid) {
++ !capable(CAP_FOWNER) && cred->uid) {
+ gr_log_fs_int2_str(GR_DONT_AUDIT, GR_HARDLINK_MSG, dentry, mnt, inode->i_uid, inode->i_gid, to);
+ return -EPERM;
+ }
+#endif
+ return 0;
+}
-diff -urNp linux-2.6.28.8/grsecurity/grsec_log.c linux-2.6.28.8/grsecurity/grsec_log.c
---- linux-2.6.28.8/grsecurity/grsec_log.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/grsecurity/grsec_log.c 2009-02-21 09:37:49.000000000 -0500
-@@ -0,0 +1,269 @@
+diff -urNp linux-2.6.29.5/grsecurity/grsec_log.c linux-2.6.29.5/grsecurity/grsec_log.c
+--- linux-2.6.29.5/grsecurity/grsec_log.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/grsecurity/grsec_log.c 2009-06-12 23:57:32.000000000 -0400
+@@ -0,0 +1,288 @@
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/file.h>
@@ -26923,6 +29950,9 @@ diff -urNp linux-2.6.28.8/grsecurity/grsec_log.c linux-2.6.28.8/grsecurity/grsec
+}
+
+static void gr_log_middle(int audit, const char *msg, va_list ap)
++ __attribute__ ((format (printf, 2, 0)));
++
++static void gr_log_middle(int audit, const char *msg, va_list ap)
+{
+ char *buf = (audit == GR_DO_AUDIT) ? gr_audit_log_buf : gr_alert_log_buf;
+ unsigned int len = strlen(buf);
@@ -26933,6 +29963,9 @@ diff -urNp linux-2.6.28.8/grsecurity/grsec_log.c linux-2.6.28.8/grsecurity/grsec
+}
+
+static void gr_log_middle_varargs(int audit, const char *msg, ...)
++ __attribute__ ((format (printf, 2, 3)));
++
++static void gr_log_middle_varargs(int audit, const char *msg, ...)
+{
+ char *buf = (audit == GR_DO_AUDIT) ? gr_audit_log_buf : gr_alert_log_buf;
+ unsigned int len = strlen(buf);
@@ -26950,7 +29983,7 @@ diff -urNp linux-2.6.28.8/grsecurity/grsec_log.c linux-2.6.28.8/grsecurity/grsec
+ char *buf = (audit == GR_DO_AUDIT) ? gr_audit_log_buf : gr_alert_log_buf;
+ unsigned int len = strlen(buf);
+
-+ snprintf(buf + len, PAGE_SIZE - len - 1, DEFAULTSECMSG, DEFAULTSECARGS(current));
++ snprintf(buf + len, PAGE_SIZE - len - 1, DEFAULTSECMSG, DEFAULTSECARGS(current, current_cred(), __task_cred(current->parent)));
+ printk("%s\n", buf);
+
+ return;
@@ -26967,6 +30000,7 @@ diff -urNp linux-2.6.28.8/grsecurity/grsec_log.c linux-2.6.28.8/grsecurity/grsec
+ struct vfsmount *mnt;
+ struct file *file;
+ struct task_struct *task;
++ const struct cred *cred, *pcred;
+ va_list ap;
+
+ BEGIN_LOCKS(audit);
@@ -27061,30 +30095,40 @@ diff -urNp linux-2.6.28.8/grsecurity/grsec_log.c linux-2.6.28.8/grsecurity/grsec
+ break;
+ case GR_RESOURCE:
+ task = va_arg(ap, struct task_struct *);
++ cred = __task_cred(task);
++ pcred = __task_cred(task->parent);
+ ulong1 = va_arg(ap, unsigned long);
+ str1 = va_arg(ap, char *);
+ ulong2 = va_arg(ap, unsigned long);
-+ gr_log_middle_varargs(audit, msg, ulong1, str1, ulong2, gr_task_fullpath(task), task->comm, task->pid, task->uid, task->euid, task->gid, task->egid, gr_parent_task_fullpath(task), task->parent->comm, task->parent->pid, task->parent->uid, task->parent->euid, task->parent->gid, task->parent->egid);
++ gr_log_middle_varargs(audit, msg, ulong1, str1, ulong2, gr_task_fullpath(task), task->comm, task->pid, cred->uid, cred->euid, cred->gid, cred->egid, gr_parent_task_fullpath(task), task->parent->comm, task->parent->pid, pcred->uid, pcred->euid, pcred->gid, pcred->egid);
+ break;
+ case GR_CAP:
+ task = va_arg(ap, struct task_struct *);
++ cred = __task_cred(task);
++ pcred = __task_cred(task->parent);
+ str1 = va_arg(ap, char *);
-+ gr_log_middle_varargs(audit, msg, str1, gr_task_fullpath(task), task->comm, task->pid, task->uid, task->euid, task->gid, task->egid, gr_parent_task_fullpath(task), task->parent->comm, task->parent->pid, task->parent->uid, task->parent->euid, task->parent->gid, task->parent->egid);
++ gr_log_middle_varargs(audit, msg, str1, gr_task_fullpath(task), task->comm, task->pid, cred->uid, cred->euid, cred->gid, cred->egid, gr_parent_task_fullpath(task), task->parent->comm, task->parent->pid, pcred->uid, pcred->euid, pcred->gid, pcred->egid);
+ break;
+ case GR_SIG:
+ task = va_arg(ap, struct task_struct *);
++ cred = __task_cred(task);
++ pcred = __task_cred(task->parent);
+ num1 = va_arg(ap, int);
-+ gr_log_middle_varargs(audit, msg, num1, gr_task_fullpath0(task), task->comm, task->pid, task->uid, task->euid, task->gid, task->egid, gr_parent_task_fullpath0(task), task->parent->comm, task->parent->pid, task->parent->uid, task->parent->euid, task->parent->gid, task->parent->egid);
++ gr_log_middle_varargs(audit, msg, num1, gr_task_fullpath0(task), task->comm, task->pid, cred->uid, cred->euid, cred->gid, cred->egid, gr_parent_task_fullpath0(task), task->parent->comm, task->parent->pid, pcred->uid, pcred->euid, pcred->gid, pcred->egid);
+ break;
+ case GR_CRASH1:
+ task = va_arg(ap, struct task_struct *);
++ cred = __task_cred(task);
++ pcred = __task_cred(task->parent);
+ ulong1 = va_arg(ap, unsigned long);
-+ gr_log_middle_varargs(audit, msg, gr_task_fullpath(task), task->comm, task->pid, task->uid, task->euid, task->gid, task->egid, gr_parent_task_fullpath(task), task->parent->comm, task->parent->pid, task->parent->uid, task->parent->euid, task->parent->gid, task->parent->egid, task->uid, ulong1);
++ gr_log_middle_varargs(audit, msg, gr_task_fullpath(task), task->comm, task->pid, cred->uid, cred->euid, cred->gid, cred->egid, gr_parent_task_fullpath(task), task->parent->comm, task->parent->pid, pcred->uid, pcred->euid, pcred->gid, pcred->egid, cred->uid, ulong1);
+ break;
+ case GR_CRASH2:
+ task = va_arg(ap, struct task_struct *);
++ cred = __task_cred(task);
++ pcred = __task_cred(task->parent);
+ ulong1 = va_arg(ap, unsigned long);
-+ gr_log_middle_varargs(audit, msg, gr_task_fullpath(task), task->comm, task->pid, task->uid, task->euid, task->gid, task->egid, gr_parent_task_fullpath(task), task->parent->comm, task->parent->pid, task->parent->uid, task->parent->euid, task->parent->gid, task->parent->egid, ulong1);
++ gr_log_middle_varargs(audit, msg, gr_task_fullpath(task), task->comm, task->pid, cred->uid, cred->euid, cred->gid, cred->egid, gr_parent_task_fullpath(task), task->parent->comm, task->parent->pid, pcred->uid, pcred->euid, pcred->gid, pcred->egid, ulong1);
+ break;
+ case GR_PSACCT:
+ {
@@ -27105,8 +30149,10 @@ diff -urNp linux-2.6.28.8/grsecurity/grsec_log.c linux-2.6.28.8/grsecurity/grsec
+ wsec = va_arg(ap, int);
+ csec = va_arg(ap, int);
+ ulong1 = va_arg(ap, unsigned long);
++ cred = __task_cred(task);
++ pcred = __task_cred(task->parent);
+
-+ gr_log_middle_varargs(audit, msg, gr_task_fullpath(task), task->comm, task->pid, NIPQUAD(task->signal->curr_ip), tty_name(task->signal->tty, cur_tty), task->uid, task->euid, task->gid, task->egid, wday, whr, wmin, wsec, cday, chr, cmin, csec, (task->flags & PF_SIGNALED) ? "killed by signal" : "exited", ulong1, gr_parent_task_fullpath(task), task->parent->comm, task->parent->pid, NIPQUAD(task->parent->signal->curr_ip), tty_name(task->parent->signal->tty, parent_tty), task->parent->uid, task->parent->euid, task->parent->gid, task->parent->egid);
++ gr_log_middle_varargs(audit, msg, gr_task_fullpath(task), task->comm, task->pid, NIPQUAD(task->signal->curr_ip), tty_name(task->signal->tty, cur_tty), cred->uid, cred->euid, cred->gid, cred->egid, wday, whr, wmin, wsec, cday, chr, cmin, csec, (task->flags & PF_SIGNALED) ? "killed by signal" : "exited", ulong1, gr_parent_task_fullpath(task), task->parent->comm, task->parent->pid, NIPQUAD(task->parent->signal->curr_ip), tty_name(task->parent->signal->tty, parent_tty), pcred->uid, pcred->euid, pcred->gid, pcred->egid);
+ }
+ break;
+ default:
@@ -27116,9 +30162,9 @@ diff -urNp linux-2.6.28.8/grsecurity/grsec_log.c linux-2.6.28.8/grsecurity/grsec
+ gr_log_end(audit);
+ END_LOCKS(audit);
+}
-diff -urNp linux-2.6.28.8/grsecurity/grsec_mem.c linux-2.6.28.8/grsecurity/grsec_mem.c
---- linux-2.6.28.8/grsecurity/grsec_mem.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/grsecurity/grsec_mem.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/grsecurity/grsec_mem.c linux-2.6.29.5/grsecurity/grsec_mem.c
+--- linux-2.6.29.5/grsecurity/grsec_mem.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/grsecurity/grsec_mem.c 2009-06-12 23:57:32.000000000 -0400
@@ -0,0 +1,71 @@
+#include <linux/kernel.h>
+#include <linux/sched.h>
@@ -27191,9 +30237,9 @@ diff -urNp linux-2.6.28.8/grsecurity/grsec_mem.c linux-2.6.28.8/grsecurity/grsec
+
+ return 0;
+}
-diff -urNp linux-2.6.28.8/grsecurity/grsec_mount.c linux-2.6.28.8/grsecurity/grsec_mount.c
---- linux-2.6.28.8/grsecurity/grsec_mount.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/grsecurity/grsec_mount.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/grsecurity/grsec_mount.c linux-2.6.29.5/grsecurity/grsec_mount.c
+--- linux-2.6.29.5/grsecurity/grsec_mount.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/grsecurity/grsec_mount.c 2009-06-12 23:57:32.000000000 -0400
@@ -0,0 +1,34 @@
+#include <linux/kernel.h>
+#include <linux/sched.h>
@@ -27229,9 +30275,9 @@ diff -urNp linux-2.6.28.8/grsecurity/grsec_mount.c linux-2.6.28.8/grsecurity/grs
+#endif
+ return;
+}
-diff -urNp linux-2.6.28.8/grsecurity/grsec_sig.c linux-2.6.28.8/grsecurity/grsec_sig.c
---- linux-2.6.28.8/grsecurity/grsec_sig.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/grsecurity/grsec_sig.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/grsecurity/grsec_sig.c linux-2.6.29.5/grsecurity/grsec_sig.c
+--- linux-2.6.29.5/grsecurity/grsec_sig.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/grsecurity/grsec_sig.c 2009-06-12 23:57:32.000000000 -0400
@@ -0,0 +1,58 @@
+#include <linux/kernel.h>
+#include <linux/sched.h>
@@ -27291,10 +30337,10 @@ diff -urNp linux-2.6.28.8/grsecurity/grsec_sig.c linux-2.6.28.8/grsecurity/grsec
+ return;
+}
+
-diff -urNp linux-2.6.28.8/grsecurity/grsec_sock.c linux-2.6.28.8/grsecurity/grsec_sock.c
---- linux-2.6.28.8/grsecurity/grsec_sock.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/grsecurity/grsec_sock.c 2009-02-21 09:37:49.000000000 -0500
-@@ -0,0 +1,274 @@
+diff -urNp linux-2.6.29.5/grsecurity/grsec_sock.c linux-2.6.29.5/grsecurity/grsec_sock.c
+--- linux-2.6.29.5/grsecurity/grsec_sock.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/grsecurity/grsec_sock.c 2009-06-12 23:57:32.000000000 -0400
+@@ -0,0 +1,269 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
@@ -27308,11 +30354,6 @@ diff -urNp linux-2.6.28.8/grsecurity/grsec_sock.c linux-2.6.28.8/grsecurity/grse
+#include <linux/grinternal.h>
+#include <linux/gracl.h>
+
-+#if defined(CONFIG_IP_NF_MATCH_STEALTH_MODULE)
-+extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
-+EXPORT_SYMBOL(udp_v4_lookup);
-+#endif
-+
+kernel_cap_t gr_cap_rtnetlink(struct sock *sock);
+EXPORT_SYMBOL(gr_cap_rtnetlink);
+
@@ -27549,29 +30590,29 @@ diff -urNp linux-2.6.28.8/grsecurity/grsec_sock.c linux-2.6.28.8/grsecurity/grse
+{
+#ifdef CONFIG_GRKERNSEC
+ if (!gr_acl_is_enabled())
-+ return current->cap_effective;
++ return current_cap();
+ else if (sock->sk_protocol == NETLINK_ISCSI &&
-+ cap_raised(current->cap_effective, CAP_SYS_ADMIN) &&
-+ gr_task_is_capable(current, CAP_SYS_ADMIN))
-+ return current->cap_effective;
++ cap_raised(current_cap(), CAP_SYS_ADMIN) &&
++ gr_is_capable(CAP_SYS_ADMIN))
++ return current_cap();
+ else if (sock->sk_protocol == NETLINK_AUDIT &&
-+ cap_raised(current->cap_effective, CAP_AUDIT_WRITE) &&
-+ gr_task_is_capable(current, CAP_AUDIT_WRITE) &&
-+ cap_raised(current->cap_effective, CAP_AUDIT_CONTROL) &&
-+ gr_task_is_capable(current, CAP_AUDIT_CONTROL))
-+ return current->cap_effective;
-+ else if (cap_raised(current->cap_effective, CAP_NET_ADMIN) &&
-+ gr_task_is_capable(current, CAP_NET_ADMIN))
-+ return current->cap_effective;
++ cap_raised(current_cap(), CAP_AUDIT_WRITE) &&
++ gr_is_capable(CAP_AUDIT_WRITE) &&
++ cap_raised(current_cap(), CAP_AUDIT_CONTROL) &&
++ gr_is_capable(CAP_AUDIT_CONTROL))
++ return current_cap();
++ else if (cap_raised(current_cap(), CAP_NET_ADMIN) &&
++ gr_is_capable(CAP_NET_ADMIN))
++ return current_cap();
+ else
+ return __cap_empty_set;
+#else
-+ return current->cap_effective;
++ return current_cap();
+#endif
+}
-diff -urNp linux-2.6.28.8/grsecurity/grsec_sysctl.c linux-2.6.28.8/grsecurity/grsec_sysctl.c
---- linux-2.6.28.8/grsecurity/grsec_sysctl.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/grsecurity/grsec_sysctl.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/grsecurity/grsec_sysctl.c linux-2.6.29.5/grsecurity/grsec_sysctl.c
+--- linux-2.6.29.5/grsecurity/grsec_sysctl.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/grsecurity/grsec_sysctl.c 2009-06-12 23:57:32.000000000 -0400
@@ -0,0 +1,435 @@
+#include <linux/kernel.h>
+#include <linux/sched.h>
@@ -28008,9 +31049,9 @@ diff -urNp linux-2.6.28.8/grsecurity/grsec_sysctl.c linux-2.6.28.8/grsecurity/gr
+#endif
+ return 0;
+}
-diff -urNp linux-2.6.28.8/grsecurity/grsec_textrel.c linux-2.6.28.8/grsecurity/grsec_textrel.c
---- linux-2.6.28.8/grsecurity/grsec_textrel.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/grsecurity/grsec_textrel.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/grsecurity/grsec_textrel.c linux-2.6.29.5/grsecurity/grsec_textrel.c
+--- linux-2.6.29.5/grsecurity/grsec_textrel.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/grsecurity/grsec_textrel.c 2009-06-12 23:57:32.000000000 -0400
@@ -0,0 +1,16 @@
+#include <linux/kernel.h>
+#include <linux/sched.h>
@@ -28028,9 +31069,9 @@ diff -urNp linux-2.6.28.8/grsecurity/grsec_textrel.c linux-2.6.28.8/grsecurity/g
+#endif
+ return;
+}
-diff -urNp linux-2.6.28.8/grsecurity/grsec_time.c linux-2.6.28.8/grsecurity/grsec_time.c
---- linux-2.6.28.8/grsecurity/grsec_time.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/grsecurity/grsec_time.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/grsecurity/grsec_time.c linux-2.6.29.5/grsecurity/grsec_time.c
+--- linux-2.6.29.5/grsecurity/grsec_time.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/grsecurity/grsec_time.c 2009-06-12 23:57:32.000000000 -0400
@@ -0,0 +1,13 @@
+#include <linux/kernel.h>
+#include <linux/sched.h>
@@ -28045,10 +31086,10 @@ diff -urNp linux-2.6.28.8/grsecurity/grsec_time.c linux-2.6.28.8/grsecurity/grse
+#endif
+ return;
+}
-diff -urNp linux-2.6.28.8/grsecurity/grsec_tpe.c linux-2.6.28.8/grsecurity/grsec_tpe.c
---- linux-2.6.28.8/grsecurity/grsec_tpe.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/grsecurity/grsec_tpe.c 2009-02-21 09:37:49.000000000 -0500
-@@ -0,0 +1,37 @@
+diff -urNp linux-2.6.29.5/grsecurity/grsec_tpe.c linux-2.6.29.5/grsecurity/grsec_tpe.c
+--- linux-2.6.29.5/grsecurity/grsec_tpe.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/grsecurity/grsec_tpe.c 2009-06-12 23:57:32.000000000 -0400
+@@ -0,0 +1,38 @@
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/file.h>
@@ -28062,8 +31103,9 @@ diff -urNp linux-2.6.28.8/grsecurity/grsec_tpe.c linux-2.6.28.8/grsecurity/grsec
+{
+#ifdef CONFIG_GRKERNSEC
+ struct inode *inode = file->f_path.dentry->d_parent->d_inode;
++ const struct cred *cred = current_cred();
+
-+ if (current->uid && ((grsec_enable_tpe &&
++ if (cred->uid && ((grsec_enable_tpe &&
+#ifdef CONFIG_GRKERNSEC_TPE_INVERT
+ !in_group_p(grsec_tpe_gid)
+#else
@@ -28076,8 +31118,8 @@ diff -urNp linux-2.6.28.8/grsecurity/grsec_tpe.c linux-2.6.28.8/grsecurity/grsec
+ return 0;
+ }
+#ifdef CONFIG_GRKERNSEC_TPE_ALL
-+ if (current->uid && grsec_enable_tpe && grsec_enable_tpe_all &&
-+ ((inode->i_uid && (inode->i_uid != current->uid)) ||
++ if (cred->uid && grsec_enable_tpe && grsec_enable_tpe_all &&
++ ((inode->i_uid && (inode->i_uid != cred->uid)) ||
+ (inode->i_mode & S_IWGRP) || (inode->i_mode & S_IWOTH))) {
+ gr_log_fs_generic(GR_DONT_AUDIT, GR_EXEC_TPE_MSG, file->f_path.dentry, file->f_path.mnt);
+ return 0;
@@ -28086,9 +31128,9 @@ diff -urNp linux-2.6.28.8/grsecurity/grsec_tpe.c linux-2.6.28.8/grsecurity/grsec
+#endif
+ return 1;
+}
-diff -urNp linux-2.6.28.8/grsecurity/grsum.c linux-2.6.28.8/grsecurity/grsum.c
---- linux-2.6.28.8/grsecurity/grsum.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/grsecurity/grsum.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/grsecurity/grsum.c linux-2.6.29.5/grsecurity/grsum.c
+--- linux-2.6.29.5/grsecurity/grsum.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/grsecurity/grsum.c 2009-06-12 23:57:32.000000000 -0400
@@ -0,0 +1,59 @@
+#include <linux/err.h>
+#include <linux/kernel.h>
@@ -28149,10 +31191,10 @@ diff -urNp linux-2.6.28.8/grsecurity/grsum.c linux-2.6.28.8/grsecurity/grsum.c
+
+ return retval;
+}
-diff -urNp linux-2.6.28.8/grsecurity/Kconfig linux-2.6.28.8/grsecurity/Kconfig
---- linux-2.6.28.8/grsecurity/Kconfig 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/grsecurity/Kconfig 2009-03-07 14:50:21.000000000 -0500
-@@ -0,0 +1,868 @@
+diff -urNp linux-2.6.29.5/grsecurity/Kconfig linux-2.6.29.5/grsecurity/Kconfig
+--- linux-2.6.29.5/grsecurity/Kconfig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/grsecurity/Kconfig 2009-06-12 23:57:32.000000000 -0400
+@@ -0,0 +1,894 @@
+#
+# grecurity configuration
+#
@@ -28235,6 +31277,7 @@ diff -urNp linux-2.6.28.8/grsecurity/Kconfig linux-2.6.28.8/grsecurity/Kconfig
+ select PAX_ASLR
+ select PAX_RANDMMAP
+ select PAX_REFCOUNT if (X86)
++ select PAX_USERCOPY if (X86_32 && (SLAB || SLUB))
+
+ help
+ If you say Y here, several features in addition to those included
@@ -28259,6 +31302,7 @@ diff -urNp linux-2.6.28.8/grsecurity/Kconfig linux-2.6.28.8/grsecurity/Kconfig
+ - /proc restrictions with special GID set to 10 (usually wheel)
+ - Address Space Layout Randomization (ASLR)
+ - Prevent exploitation of most refcount overflows
++ - Bounds checking of copying between the kernel and userland
+
+config GRKERNSEC_HIGH
+ bool "High"
@@ -28315,6 +31359,7 @@ diff -urNp linux-2.6.28.8/grsecurity/Kconfig linux-2.6.28.8/grsecurity/Kconfig
+ select PAX_EMUSIGRT if (PARISC)
+ select PAX_ETEXECRELOCS if (ALPHA || IA64 || PARISC)
+ select PAX_REFCOUNT if (X86)
++ select PAX_USERCOPY if (X86_32 && (SLAB || SLUB))
+ help
+ If you say Y here, many of the features of grsecurity will be
+ enabled, which will protect you against many kinds of attacks
@@ -28382,6 +31427,8 @@ diff -urNp linux-2.6.28.8/grsecurity/Kconfig linux-2.6.28.8/grsecurity/Kconfig
+ depends on X86
+ select RTC_CLASS
+ select RTC_INTF_DEV
++ select RTC_DRV_CMOS
++
+ help
+ If you say Y here, all ioperm and iopl calls will return an error.
+ Ioperm and iopl can be used to modify the running kernel.
@@ -28455,6 +31502,16 @@ diff -urNp linux-2.6.28.8/grsecurity/Kconfig linux-2.6.28.8/grsecurity/Kconfig
+menu "Role Based Access Control Options"
+depends on GRKERNSEC
+
++config GRKERNSEC_NO_RBAC
++ bool "Disable RBAC system"
++ help
++ If you say Y here, the /dev/grsec device will be removed from the kernel,
++ preventing the RBAC system from being enabled. You should only say Y
++ here if you have no intention of using the RBAC system, so as to prevent
++ an attacker with root access from misusing the RBAC system to hide files
++ and processes when loadable module support and /dev/[k]mem have been
++ locked down.
++
+config GRKERNSEC_ACL_HIDEKERN
+ bool "Hide kernel processes"
+ help
@@ -28898,6 +31955,17 @@ diff -urNp linux-2.6.28.8/grsecurity/Kconfig linux-2.6.28.8/grsecurity/Kconfig
+ here. Saying Y here has a similar effect as modifying
+ /proc/sys/kernel/random/poolsize.
+
++config GRKERNSEC_BLACKHOLE
++ bool "TCP/UDP blackhole"
++ help
++ If you say Y here, neither TCP resets nor ICMP
++ destination-unreachable packets will be sent in response to packets
++ send to ports for which no associated listening process exists.
++ This feature supports both IPV4 and IPV6 and exempts the
++ loopback interface from blackholing. Enabling this feature
++ makes a host more resilient to DoS attacks and reduces network
++ visibility against scanners.
++
+config GRKERNSEC_SOCKET
+ bool "Socket restrictions"
+ help
@@ -29021,16 +32089,17 @@ diff -urNp linux-2.6.28.8/grsecurity/Kconfig linux-2.6.28.8/grsecurity/Kconfig
+endmenu
+
+endmenu
-diff -urNp linux-2.6.28.8/grsecurity/Makefile linux-2.6.28.8/grsecurity/Makefile
---- linux-2.6.28.8/grsecurity/Makefile 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/grsecurity/Makefile 2009-02-21 09:37:49.000000000 -0500
-@@ -0,0 +1,20 @@
+diff -urNp linux-2.6.29.5/grsecurity/Makefile linux-2.6.29.5/grsecurity/Makefile
+--- linux-2.6.29.5/grsecurity/Makefile 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/grsecurity/Makefile 2009-06-12 23:57:32.000000000 -0400
+@@ -0,0 +1,21 @@
+# grsecurity's ACL system was originally written in 2001 by Michael Dalton
+# during 2001-2005 it has been completely redesigned by Brad Spengler
+# into an RBAC system
+#
+# All code in this directory and various hooks inserted throughout the kernel
-+# are copyright Brad Spengler, and released under the GPL v2 or higher
++# are copyright Brad Spengler - Open Source Security, Inc., and released
++# under the GPL v2 or higher
+
+obj-y = grsec_chdir.o grsec_chroot.o grsec_exec.o grsec_fifo.o grsec_fork.o \
+ grsec_mount.o grsec_sig.o grsec_sock.o grsec_sysctl.o \
@@ -29045,9 +32114,23 @@ diff -urNp linux-2.6.28.8/grsecurity/Makefile linux-2.6.28.8/grsecurity/Makefile
+obj-y += grsec_disabled.o
+endif
+
-diff -urNp linux-2.6.28.8/include/asm-frv/kmap_types.h linux-2.6.28.8/include/asm-frv/kmap_types.h
---- linux-2.6.28.8/include/asm-frv/kmap_types.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/asm-frv/kmap_types.h 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/include/asm-frv/atomic.h linux-2.6.29.5/include/asm-frv/atomic.h
+--- linux-2.6.29.5/include/asm-frv/atomic.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/asm-frv/atomic.h 2009-06-12 23:57:32.000000000 -0400
+@@ -114,6 +114,10 @@ static inline void atomic_dec(atomic_t *
+ atomic_sub_return(1, v);
+ }
+
++#define atomic_inc_unchecked(v) atomic_inc(v)
++#define atomic_add_unchecked(i,v) atomic_add((i),(v))
++#define atomic_sub_unchecked(i,v) atomic_sub((i),(v))
++
+ #define atomic_dec_return(v) atomic_sub_return(1, (v))
+ #define atomic_inc_return(v) atomic_add_return(1, (v))
+
+diff -urNp linux-2.6.29.5/include/asm-frv/kmap_types.h linux-2.6.29.5/include/asm-frv/kmap_types.h
+--- linux-2.6.29.5/include/asm-frv/kmap_types.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/asm-frv/kmap_types.h 2009-06-12 23:57:32.000000000 -0400
@@ -23,6 +23,7 @@ enum km_type {
KM_IRQ1,
KM_SOFTIRQ0,
@@ -29056,9 +32139,9 @@ diff -urNp linux-2.6.28.8/include/asm-frv/kmap_types.h linux-2.6.28.8/include/as
KM_TYPE_NR
};
-diff -urNp linux-2.6.28.8/include/asm-generic/futex.h linux-2.6.28.8/include/asm-generic/futex.h
---- linux-2.6.28.8/include/asm-generic/futex.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/asm-generic/futex.h 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/include/asm-generic/futex.h linux-2.6.29.5/include/asm-generic/futex.h
+--- linux-2.6.29.5/include/asm-generic/futex.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/asm-generic/futex.h 2009-06-12 23:57:32.000000000 -0400
@@ -6,7 +6,7 @@
#include <asm/errno.h>
@@ -29077,10 +32160,34 @@ diff -urNp linux-2.6.28.8/include/asm-generic/futex.h linux-2.6.28.8/include/asm
{
return -ENOSYS;
}
-diff -urNp linux-2.6.28.8/include/asm-generic/vmlinux.lds.h linux-2.6.28.8/include/asm-generic/vmlinux.lds.h
---- linux-2.6.28.8/include/asm-generic/vmlinux.lds.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/asm-generic/vmlinux.lds.h 2009-02-21 09:37:49.000000000 -0500
-@@ -69,6 +69,7 @@
+diff -urNp linux-2.6.29.5/include/asm-generic/int-l64.h linux-2.6.29.5/include/asm-generic/int-l64.h
+--- linux-2.6.29.5/include/asm-generic/int-l64.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/asm-generic/int-l64.h 2009-06-12 23:57:32.000000000 -0400
+@@ -44,6 +44,8 @@ typedef unsigned int u32;
+ typedef signed long s64;
+ typedef unsigned long u64;
+
++typedef unsigned int intoverflow_t __attribute__ ((mode(TI)));
++
+ #define S8_C(x) x
+ #define U8_C(x) x ## U
+ #define S16_C(x) x
+diff -urNp linux-2.6.29.5/include/asm-generic/int-ll64.h linux-2.6.29.5/include/asm-generic/int-ll64.h
+--- linux-2.6.29.5/include/asm-generic/int-ll64.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/asm-generic/int-ll64.h 2009-06-12 23:57:32.000000000 -0400
+@@ -49,6 +49,8 @@ typedef unsigned int u32;
+ typedef signed long long s64;
+ typedef unsigned long long u64;
+
++typedef unsigned long long intoverflow_t;
++
+ #define S8_C(x) x
+ #define U8_C(x) x ## U
+ #define S16_C(x) x
+diff -urNp linux-2.6.29.5/include/asm-generic/vmlinux.lds.h linux-2.6.29.5/include/asm-generic/vmlinux.lds.h
+--- linux-2.6.29.5/include/asm-generic/vmlinux.lds.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/asm-generic/vmlinux.lds.h 2009-06-12 23:57:32.000000000 -0400
+@@ -88,6 +88,7 @@
.rodata : AT(ADDR(.rodata) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__start_rodata) = .; \
*(.rodata) *(.rodata.*) \
@@ -29088,9 +32195,23 @@ diff -urNp linux-2.6.28.8/include/asm-generic/vmlinux.lds.h linux-2.6.28.8/inclu
*(__vermagic) /* Kernel version magic */ \
*(__markers_strings) /* Markers: strings */ \
*(__tracepoints_strings)/* Tracepoints: strings */ \
-diff -urNp linux-2.6.28.8/include/asm-m32r/kmap_types.h linux-2.6.28.8/include/asm-m32r/kmap_types.h
---- linux-2.6.28.8/include/asm-m32r/kmap_types.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/asm-m32r/kmap_types.h 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/include/asm-m32r/atomic.h linux-2.6.29.5/include/asm-m32r/atomic.h
+--- linux-2.6.29.5/include/asm-m32r/atomic.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/asm-m32r/atomic.h 2009-06-12 23:57:32.000000000 -0400
+@@ -308,6 +308,10 @@ static __inline__ void atomic_set_mask(u
+ local_irq_restore(flags);
+ }
+
++#define atomic_inc_unchecked(v) atomic_inc(v)
++#define atomic_add_unchecked(i,v) atomic_add((i),(v))
++#define atomic_sub_unchecked(i,v) atomic_sub((i),(v))
++
+ /* Atomic operations are already serializing on m32r */
+ #define smp_mb__before_atomic_dec() barrier()
+ #define smp_mb__after_atomic_dec() barrier()
+diff -urNp linux-2.6.29.5/include/asm-m32r/kmap_types.h linux-2.6.29.5/include/asm-m32r/kmap_types.h
+--- linux-2.6.29.5/include/asm-m32r/kmap_types.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/asm-m32r/kmap_types.h 2009-06-12 23:57:32.000000000 -0400
@@ -21,7 +21,8 @@ D(9) KM_IRQ0,
D(10) KM_IRQ1,
D(11) KM_SOFTIRQ0,
@@ -29101,20 +32222,23 @@ diff -urNp linux-2.6.28.8/include/asm-m32r/kmap_types.h linux-2.6.28.8/include/a
};
#undef D
-diff -urNp linux-2.6.28.8/include/asm-m68k/kmap_types.h linux-2.6.28.8/include/asm-m68k/kmap_types.h
---- linux-2.6.28.8/include/asm-m68k/kmap_types.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/asm-m68k/kmap_types.h 2009-02-21 09:37:49.000000000 -0500
-@@ -15,6 +15,7 @@ enum km_type {
- KM_IRQ1,
- KM_SOFTIRQ0,
- KM_SOFTIRQ1,
-+ KM_CLEARPAGE,
- KM_TYPE_NR
- };
-
-diff -urNp linux-2.6.28.8/include/asm-mn10300/kmap_types.h linux-2.6.28.8/include/asm-mn10300/kmap_types.h
---- linux-2.6.28.8/include/asm-mn10300/kmap_types.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/asm-mn10300/kmap_types.h 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/include/asm-mn10300/atomic.h linux-2.6.29.5/include/asm-mn10300/atomic.h
+--- linux-2.6.29.5/include/asm-mn10300/atomic.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/asm-mn10300/atomic.h 2009-06-12 23:57:32.000000000 -0400
+@@ -145,6 +145,10 @@ static inline void atomic_clear_mask(uns
+ #define atomic_xchg(ptr, v) (xchg(&(ptr)->counter, (v)))
+ #define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new)))
+
++#define atomic_inc_unchecked(v) atomic_inc(v)
++#define atomic_add_unchecked(i,v) atomic_add((i),(v))
++#define atomic_sub_unchecked(i,v) atomic_sub((i),(v))
++
+ /* Atomic operations are already serializing on MN10300??? */
+ #define smp_mb__before_atomic_dec() barrier()
+ #define smp_mb__after_atomic_dec() barrier()
+diff -urNp linux-2.6.29.5/include/asm-mn10300/kmap_types.h linux-2.6.29.5/include/asm-mn10300/kmap_types.h
+--- linux-2.6.29.5/include/asm-mn10300/kmap_types.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/asm-mn10300/kmap_types.h 2009-06-12 23:57:32.000000000 -0400
@@ -25,6 +25,7 @@ enum km_type {
KM_IRQ1,
KM_SOFTIRQ0,
@@ -29123,20 +32247,9 @@ diff -urNp linux-2.6.28.8/include/asm-mn10300/kmap_types.h linux-2.6.28.8/includ
KM_TYPE_NR
};
-diff -urNp linux-2.6.28.8/include/asm-xtensa/kmap_types.h linux-2.6.28.8/include/asm-xtensa/kmap_types.h
---- linux-2.6.28.8/include/asm-xtensa/kmap_types.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/asm-xtensa/kmap_types.h 2009-02-21 09:37:49.000000000 -0500
-@@ -25,6 +25,7 @@ enum km_type {
- KM_IRQ1,
- KM_SOFTIRQ0,
- KM_SOFTIRQ1,
-+ KM_CLEARPAGE,
- KM_TYPE_NR
- };
-
-diff -urNp linux-2.6.28.8/include/drm/drm_pciids.h linux-2.6.28.8/include/drm/drm_pciids.h
---- linux-2.6.28.8/include/drm/drm_pciids.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/drm/drm_pciids.h 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/include/drm/drm_pciids.h linux-2.6.29.5/include/drm/drm_pciids.h
+--- linux-2.6.29.5/include/drm/drm_pciids.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/drm/drm_pciids.h 2009-06-12 23:57:32.000000000 -0400
@@ -243,7 +243,7 @@
{0x1002, 0x796d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS740|RADEON_IS_IGP|RADEON_NEW_MEMMAP|RADEON_IS_IGPGART}, \
{0x1002, 0x796e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS740|RADEON_IS_IGP|RADEON_NEW_MEMMAP|RADEON_IS_IGPGART}, \
@@ -29233,15 +32346,36 @@ diff -urNp linux-2.6.28.8/include/drm/drm_pciids.h linux-2.6.28.8/include/drm/dr
#define i915_PCI_IDS \
{0x8086, 0x3577, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \
-@@ -418,4 +418,4 @@
- {0x8086, 0x2e02, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \
+@@ -419,4 +419,4 @@
{0x8086, 0x2e12, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \
{0x8086, 0x2e22, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \
+ {0x8086, 0x2e32, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \
- {0, 0, 0}
+ {0, 0, 0, 0, 0, 0}
-diff -urNp linux-2.6.28.8/include/linux/a.out.h linux-2.6.28.8/include/linux/a.out.h
---- linux-2.6.28.8/include/linux/a.out.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/linux/a.out.h 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/include/drm/drmP.h linux-2.6.29.5/include/drm/drmP.h
+--- linux-2.6.29.5/include/drm/drmP.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/drm/drmP.h 2009-06-12 23:57:32.000000000 -0400
+@@ -825,7 +825,7 @@ struct drm_device {
+
+ /** \name Usage Counters */
+ /*@{ */
+- int open_count; /**< Outstanding files open */
++ atomic_t open_count; /**< Outstanding files open */
+ atomic_t ioctl_count; /**< Outstanding IOCTLs pending */
+ atomic_t vma_count; /**< Outstanding vma areas open */
+ int buf_use; /**< Buffers in use -- cannot alloc */
+@@ -836,7 +836,7 @@ struct drm_device {
+ /*@{ */
+ unsigned long counters;
+ enum drm_stat_type types[15];
+- atomic_t counts[15];
++ atomic_unchecked_t counts[15];
+ /*@} */
+
+ struct list_head filelist;
+diff -urNp linux-2.6.29.5/include/linux/a.out.h linux-2.6.29.5/include/linux/a.out.h
+--- linux-2.6.29.5/include/linux/a.out.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/a.out.h 2009-06-12 23:57:32.000000000 -0400
@@ -39,6 +39,14 @@ enum machine_type {
M_MIPS2 = 152 /* MIPS R6000/R4000 binary */
};
@@ -29257,10 +32391,22 @@ diff -urNp linux-2.6.28.8/include/linux/a.out.h linux-2.6.28.8/include/linux/a.o
#if !defined (N_MAGIC)
#define N_MAGIC(exec) ((exec).a_info & 0xffff)
#endif
-diff -urNp linux-2.6.28.8/include/linux/binfmts.h linux-2.6.28.8/include/linux/binfmts.h
---- linux-2.6.28.8/include/linux/binfmts.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/linux/binfmts.h 2009-02-21 09:37:49.000000000 -0500
-@@ -74,6 +74,7 @@ struct linux_binfmt {
+diff -urNp linux-2.6.29.5/include/linux/atmdev.h linux-2.6.29.5/include/linux/atmdev.h
+--- linux-2.6.29.5/include/linux/atmdev.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/atmdev.h 2009-06-12 23:57:32.000000000 -0400
+@@ -237,7 +237,7 @@ struct compat_atm_iobuf {
+ #endif
+
+ struct k_atm_aal_stats {
+-#define __HANDLE_ITEM(i) atomic_t i
++#define __HANDLE_ITEM(i) atomic_unchecked_t i
+ __AAL_STAT_ITEMS
+ #undef __HANDLE_ITEM
+ };
+diff -urNp linux-2.6.29.5/include/linux/binfmts.h linux-2.6.29.5/include/linux/binfmts.h
+--- linux-2.6.29.5/include/linux/binfmts.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/binfmts.h 2009-06-12 23:57:32.000000000 -0400
+@@ -79,6 +79,7 @@ struct linux_binfmt {
int (*load_binary)(struct linux_binprm *, struct pt_regs * regs);
int (*load_shlib)(struct file *);
int (*core_dump)(long signr, struct pt_regs *regs, struct file *file, unsigned long limit);
@@ -29268,9 +32414,9 @@ diff -urNp linux-2.6.28.8/include/linux/binfmts.h linux-2.6.28.8/include/linux/b
unsigned long min_coredump; /* minimal dump size */
int hasvdso;
};
-diff -urNp linux-2.6.28.8/include/linux/cache.h linux-2.6.28.8/include/linux/cache.h
---- linux-2.6.28.8/include/linux/cache.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/linux/cache.h 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/include/linux/cache.h linux-2.6.29.5/include/linux/cache.h
+--- linux-2.6.29.5/include/linux/cache.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/cache.h 2009-06-12 23:57:32.000000000 -0400
@@ -16,6 +16,10 @@
#define __read_mostly
#endif
@@ -29282,31 +32428,31 @@ diff -urNp linux-2.6.28.8/include/linux/cache.h linux-2.6.28.8/include/linux/cac
#ifndef ____cacheline_aligned
#define ____cacheline_aligned __attribute__((__aligned__(SMP_CACHE_BYTES)))
#endif
-diff -urNp linux-2.6.28.8/include/linux/capability.h linux-2.6.28.8/include/linux/capability.h
---- linux-2.6.28.8/include/linux/capability.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/linux/capability.h 2009-02-21 09:37:49.000000000 -0500
-@@ -516,6 +516,7 @@ kernel_cap_t cap_set_effective(const ker
- #define has_capability(t, cap) (security_capable((t), (cap)) == 0)
+diff -urNp linux-2.6.29.5/include/linux/capability.h linux-2.6.29.5/include/linux/capability.h
+--- linux-2.6.29.5/include/linux/capability.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/capability.h 2009-06-12 23:57:32.000000000 -0400
+@@ -563,6 +563,7 @@ extern const kernel_cap_t __cap_init_eff
+ (security_real_capable_noaudit((t), (cap)) == 0)
extern int capable(int cap);
+int capable_nolog(int cap);
- #endif /* __KERNEL__ */
-
-diff -urNp linux-2.6.28.8/include/linux/cpumask.h linux-2.6.28.8/include/linux/cpumask.h
---- linux-2.6.28.8/include/linux/cpumask.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/linux/cpumask.h 2009-02-21 09:37:49.000000000 -0500
+ /* audit system wants to get cap info from files as well */
+ struct dentry;
+diff -urNp linux-2.6.29.5/include/linux/cpumask.h linux-2.6.29.5/include/linux/cpumask.h
+--- linux-2.6.29.5/include/linux/cpumask.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/cpumask.h 2009-06-12 23:57:32.000000000 -0400
@@ -142,7 +142,6 @@
#include <linux/bitmap.h>
typedef struct cpumask { DECLARE_BITMAP(bits, NR_CPUS); } cpumask_t;
-extern cpumask_t _unused_cpumask_arg_;
+ #ifndef CONFIG_DISABLE_OBSOLETE_CPUMASK_FUNCTIONS
#define cpu_set(cpu, dst) __cpu_set((cpu), &(dst))
- static inline void __cpu_set(int cpu, volatile cpumask_t *dstp)
-diff -urNp linux-2.6.28.8/include/linux/elf.h linux-2.6.28.8/include/linux/elf.h
---- linux-2.6.28.8/include/linux/elf.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/linux/elf.h 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/include/linux/elf.h linux-2.6.29.5/include/linux/elf.h
+--- linux-2.6.29.5/include/linux/elf.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/elf.h 2009-06-12 23:57:32.000000000 -0400
@@ -49,6 +49,17 @@ typedef __s64 Elf64_Sxword;
#define PT_GNU_EH_FRAME 0x6474e550
@@ -29363,7 +32509,7 @@ diff -urNp linux-2.6.28.8/include/linux/elf.h linux-2.6.28.8/include/linux/elf.h
#define ELFMAG0 0x7f /* EI_MAG */
#define ELFMAG1 'E'
#define ELFMAG2 'L'
-@@ -384,6 +412,7 @@ extern Elf32_Dyn _DYNAMIC [];
+@@ -385,6 +413,7 @@ extern Elf32_Dyn _DYNAMIC [];
#define elf_phdr elf32_phdr
#define elf_note elf32_note
#define elf_addr_t Elf32_Off
@@ -29371,7 +32517,7 @@ diff -urNp linux-2.6.28.8/include/linux/elf.h linux-2.6.28.8/include/linux/elf.h
#else
-@@ -392,6 +421,7 @@ extern Elf64_Dyn _DYNAMIC [];
+@@ -393,6 +422,7 @@ extern Elf64_Dyn _DYNAMIC [];
#define elf_phdr elf64_phdr
#define elf_note elf64_note
#define elf_addr_t Elf64_Off
@@ -29379,9 +32525,33 @@ diff -urNp linux-2.6.28.8/include/linux/elf.h linux-2.6.28.8/include/linux/elf.h
#endif
-diff -urNp linux-2.6.28.8/include/linux/gracl.h linux-2.6.28.8/include/linux/gracl.h
---- linux-2.6.28.8/include/linux/gracl.h 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/include/linux/gracl.h 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/include/linux/fs_struct.h linux-2.6.29.5/include/linux/fs_struct.h
+--- linux-2.6.29.5/include/linux/fs_struct.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/fs_struct.h 2009-06-12 23:57:32.000000000 -0400
+@@ -4,7 +4,7 @@
+ #include <linux/path.h>
+
+ struct fs_struct {
+- int users;
++ atomic_t users;
+ rwlock_t lock;
+ int umask;
+ int in_exec;
+diff -urNp linux-2.6.29.5/include/linux/genhd.h linux-2.6.29.5/include/linux/genhd.h
+--- linux-2.6.29.5/include/linux/genhd.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/genhd.h 2009-06-12 23:57:32.000000000 -0400
+@@ -159,7 +159,7 @@ struct gendisk {
+
+ struct timer_rand_state *random;
+
+- atomic_t sync_io; /* RAID */
++ atomic_unchecked_t sync_io; /* RAID */
+ struct work_struct async_notify;
+ #ifdef CONFIG_BLK_DEV_INTEGRITY
+ struct blk_integrity *integrity;
+diff -urNp linux-2.6.29.5/include/linux/gracl.h linux-2.6.29.5/include/linux/gracl.h
+--- linux-2.6.29.5/include/linux/gracl.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/include/linux/gracl.h 2009-06-12 23:57:32.000000000 -0400
@@ -0,0 +1,318 @@
+#ifndef GR_ACL_H
+#define GR_ACL_H
@@ -29394,8 +32564,8 @@ diff -urNp linux-2.6.28.8/include/linux/gracl.h linux-2.6.28.8/include/linux/gra
+
+/* Major status information */
+
-+#define GR_VERSION "grsecurity 2.1.13"
-+#define GRSECURITY_VERSION 0x2113
++#define GR_VERSION "grsecurity 2.1.14"
++#define GRSECURITY_VERSION 0x2114
+
+enum {
+ GR_SHUTDOWN = 0,
@@ -29421,7 +32591,7 @@ diff -urNp linux-2.6.28.8/include/linux/gracl.h linux-2.6.28.8/include/linux/gra
+ GR_SPROLE_LEN = 64,
+};
+
-+#define GR_NLIMITS (RLIMIT_LOCKS + 2)
++#define GR_NLIMITS 32
+
+/* Begin Data Structures */
+
@@ -29488,7 +32658,7 @@ diff -urNp linux-2.6.28.8/include/linux/gracl.h linux-2.6.28.8/include/linux/gra
+ kernel_cap_t cap_lower;
+
+ struct rlimit res[GR_NLIMITS];
-+ __u16 resmask;
++ __u32 resmask;
+
+ __u8 user_trans_type;
+ __u8 group_trans_type;
@@ -29701,22 +32871,23 @@ diff -urNp linux-2.6.28.8/include/linux/gracl.h linux-2.6.28.8/include/linux/gra
+
+#endif
+
-diff -urNp linux-2.6.28.8/include/linux/gralloc.h linux-2.6.28.8/include/linux/gralloc.h
---- linux-2.6.28.8/include/linux/gralloc.h 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/include/linux/gralloc.h 2009-02-21 09:37:49.000000000 -0500
-@@ -0,0 +1,8 @@
+diff -urNp linux-2.6.29.5/include/linux/gralloc.h linux-2.6.29.5/include/linux/gralloc.h
+--- linux-2.6.29.5/include/linux/gralloc.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/include/linux/gralloc.h 2009-06-12 23:57:32.000000000 -0400
+@@ -0,0 +1,9 @@
+#ifndef __GRALLOC_H
+#define __GRALLOC_H
+
+void acl_free_all(void);
+int acl_alloc_stack_init(unsigned long size);
+void *acl_alloc(unsigned long len);
++void *acl_alloc_num(unsigned long num, unsigned long len);
+
+#endif
-diff -urNp linux-2.6.28.8/include/linux/grdefs.h linux-2.6.28.8/include/linux/grdefs.h
---- linux-2.6.28.8/include/linux/grdefs.h 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/include/linux/grdefs.h 2009-02-21 09:37:49.000000000 -0500
-@@ -0,0 +1,131 @@
+diff -urNp linux-2.6.29.5/include/linux/grdefs.h linux-2.6.29.5/include/linux/grdefs.h
+--- linux-2.6.29.5/include/linux/grdefs.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/include/linux/grdefs.h 2009-06-12 23:57:32.000000000 -0400
+@@ -0,0 +1,136 @@
+#ifndef GRDEFS_H
+#define GRDEFS_H
+
@@ -29829,7 +33000,7 @@ diff -urNp linux-2.6.28.8/include/linux/grdefs.h linux-2.6.28.8/include/linux/gr
+ GR_ID_DENY = 0x02,
+};
+
-+#define GR_CRASH_RES 11
++#define GR_CRASH_RES 31
+#define GR_UIDTABLE_MAX 500
+
+/* begin resource learning section */
@@ -29844,14 +33015,19 @@ diff -urNp linux-2.6.28.8/include/linux/grdefs.h linux-2.6.28.8/include/linux/gr
+ GR_RLIM_NOFILE_BUMP = 5,
+ GR_RLIM_MEMLOCK_BUMP = 50000,
+ GR_RLIM_AS_BUMP = 500000,
-+ GR_RLIM_LOCKS_BUMP = 2
++ GR_RLIM_LOCKS_BUMP = 2,
++ GR_RLIM_SIGPENDING_BUMP = 5,
++ GR_RLIM_MSGQUEUE_BUMP = 10000,
++ GR_RLIM_NICE_BUMP = 1,
++ GR_RLIM_RTPRIO_BUMP = 1,
++ GR_RLIM_RTTIME_BUMP = 1000000
+};
+
+#endif
-diff -urNp linux-2.6.28.8/include/linux/grinternal.h linux-2.6.28.8/include/linux/grinternal.h
---- linux-2.6.28.8/include/linux/grinternal.h 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/include/linux/grinternal.h 2009-02-21 09:37:49.000000000 -0500
-@@ -0,0 +1,210 @@
+diff -urNp linux-2.6.29.5/include/linux/grinternal.h linux-2.6.29.5/include/linux/grinternal.h
+--- linux-2.6.29.5/include/linux/grinternal.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/include/linux/grinternal.h 2009-06-12 23:57:32.000000000 -0400
+@@ -0,0 +1,211 @@
+#ifndef __GRINTERNAL_H
+#define __GRINTERNAL_H
+
@@ -29862,7 +33038,8 @@ diff -urNp linux-2.6.28.8/include/linux/grinternal.h linux-2.6.28.8/include/linu
+#include <linux/grdefs.h>
+#include <linux/grmsg.h>
+
-+void gr_add_learn_entry(const char *fmt, ...);
++void gr_add_learn_entry(const char *fmt, ...)
++ __attribute__ ((format (printf, 1, 2)));
+__u32 gr_search_file(const struct dentry *dentry, const __u32 mode,
+ const struct vfsmount *mnt);
+__u32 gr_check_create(const struct dentry *new_dentry,
@@ -29962,13 +33139,13 @@ diff -urNp linux-2.6.28.8/include/linux/grinternal.h linux-2.6.28.8/include/linu
+ (tsk_a->fs->root.dentry->d_inode->i_ino == \
+ tsk_b->fs->root.dentry->d_inode->i_ino))
+
-+#define DEFAULTSECARGS(task) gr_task_fullpath(task), task->comm, \
-+ task->pid, task->uid, \
-+ task->euid, task->gid, task->egid, \
++#define DEFAULTSECARGS(task, cred, pcred) gr_task_fullpath(task), task->comm, \
++ task->pid, cred->uid, \
++ cred->euid, cred->gid, cred->egid, \
+ gr_parent_task_fullpath(task), \
+ task->parent->comm, task->parent->pid, \
-+ task->parent->uid, task->parent->euid, \
-+ task->parent->gid, task->parent->egid
++ pcred->uid, pcred->euid, \
++ pcred->gid, pcred->egid
+
+#define GR_CHROOT_CAPS {{ \
+ CAP_TO_MASK(CAP_LINUX_IMMUTABLE) | CAP_TO_MASK(CAP_NET_ADMIN) | \
@@ -30062,9 +33239,9 @@ diff -urNp linux-2.6.28.8/include/linux/grinternal.h linux-2.6.28.8/include/linu
+#endif
+
+#endif
-diff -urNp linux-2.6.28.8/include/linux/grmsg.h linux-2.6.28.8/include/linux/grmsg.h
---- linux-2.6.28.8/include/linux/grmsg.h 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/include/linux/grmsg.h 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/include/linux/grmsg.h linux-2.6.29.5/include/linux/grmsg.h
+--- linux-2.6.29.5/include/linux/grmsg.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/include/linux/grmsg.h 2009-06-12 23:57:32.000000000 -0400
@@ -0,0 +1,108 @@
+#define DEFAULTSECMSG "%.256s[%.16s:%d] uid/euid:%u/%u gid/egid:%u/%u, parent %.256s[%.16s:%d] uid/euid:%u/%u gid/egid:%u/%u"
+#define GR_ACL_PROCACCT_MSG "%.256s[%.16s:%d] IP:%u.%u.%u.%u TTY:%.64s uid/euid:%u/%u gid/egid:%u/%u run time:[%ud %uh %um %us] cpu time:[%ud %uh %um %us] %s with exit code %ld, parent %.256s[%.16s:%d] IP:%u.%u.%u.%u TTY:%.64s uid/euid:%u/%u gid/egid:%u/%u"
@@ -30174,10 +33351,10 @@ diff -urNp linux-2.6.28.8/include/linux/grmsg.h linux-2.6.28.8/include/linux/grm
+#define GR_SHMR_AUDIT_MSG "shared memory of uid:%u euid:%u removed by "
+#define GR_RESOURCE_MSG "denied resource overstep by requesting %lu for %.16s against limit %lu for "
+#define GR_TEXTREL_AUDIT_MSG "text relocation in %s, VMA:0x%08lx 0x%08lx by "
-diff -urNp linux-2.6.28.8/include/linux/grsecurity.h linux-2.6.28.8/include/linux/grsecurity.h
---- linux-2.6.28.8/include/linux/grsecurity.h 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/include/linux/grsecurity.h 2009-02-21 09:37:49.000000000 -0500
-@@ -0,0 +1,200 @@
+diff -urNp linux-2.6.29.5/include/linux/grsecurity.h linux-2.6.29.5/include/linux/grsecurity.h
+--- linux-2.6.29.5/include/linux/grsecurity.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/include/linux/grsecurity.h 2009-06-12 23:57:32.000000000 -0400
+@@ -0,0 +1,201 @@
+#ifndef GR_SECURITY_H
+#define GR_SECURITY_H
+#include <linux/fs.h>
@@ -30219,7 +33396,7 @@ diff -urNp linux-2.6.28.8/include/linux/grsecurity.h linux-2.6.28.8/include/linu
+int gr_chroot_fchdir(struct dentry *u_dentry, struct vfsmount *u_mnt);
+int gr_handle_chroot_chroot(const struct dentry *dentry,
+ const struct vfsmount *mnt);
-+void gr_handle_chroot_caps(struct task_struct *task);
++int gr_handle_chroot_caps(struct path *path);
+void gr_handle_chroot_chdir(struct path *path);
+int gr_handle_chroot_chmod(const struct dentry *dentry,
+ const struct vfsmount *mnt, const int mode);
@@ -30273,7 +33450,7 @@ diff -urNp linux-2.6.28.8/include/linux/grsecurity.h linux-2.6.28.8/include/linu
+ struct inode *inode,
+ const int mode, const char *to);
+
-+int gr_task_is_capable(struct task_struct *task, const int cap);
++int gr_is_capable(const int cap);
+int gr_is_capable_nolog(const int cap);
+void gr_learn_resource(const struct task_struct *task, const int limit,
+ const unsigned long wanted, const int gt);
@@ -30309,9 +33486,10 @@ diff -urNp linux-2.6.28.8/include/linux/grsecurity.h linux-2.6.28.8/include/linu
+void gr_set_role_label(struct task_struct *task, const uid_t uid,
+ const gid_t gid);
+int gr_set_proc_label(const struct dentry *dentry,
-+ const struct vfsmount *mnt);
++ const struct vfsmount *mnt,
++ const int unsafe_share);
+__u32 gr_acl_handle_hidden_file(const struct dentry *dentry,
-+ const struct vfsmount *mnt);
++ const struct vfsmount *mnt);
+__u32 gr_acl_handle_open(const struct dentry *dentry,
+ const struct vfsmount *mnt, const int fmode);
+__u32 gr_acl_handle_creat(const struct dentry *dentry,
@@ -30378,9 +33556,9 @@ diff -urNp linux-2.6.28.8/include/linux/grsecurity.h linux-2.6.28.8/include/linu
+#endif
+
+#endif
-diff -urNp linux-2.6.28.8/include/linux/highmem.h linux-2.6.28.8/include/linux/highmem.h
---- linux-2.6.28.8/include/linux/highmem.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/linux/highmem.h 2009-03-07 10:35:39.000000000 -0500
+diff -urNp linux-2.6.29.5/include/linux/highmem.h linux-2.6.29.5/include/linux/highmem.h
+--- linux-2.6.29.5/include/linux/highmem.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/highmem.h 2009-06-12 23:57:32.000000000 -0400
@@ -124,6 +124,18 @@ static inline void clear_highpage(struct
kunmap_atomic(kaddr, KM_USER0);
}
@@ -30400,9 +33578,9 @@ diff -urNp linux-2.6.28.8/include/linux/highmem.h linux-2.6.28.8/include/linux/h
static inline void zero_user_segments(struct page *page,
unsigned start1, unsigned end1,
unsigned start2, unsigned end2)
-diff -urNp linux-2.6.28.8/include/linux/jbd2.h linux-2.6.28.8/include/linux/jbd2.h
---- linux-2.6.28.8/include/linux/jbd2.h 2009-03-07 10:24:49.000000000 -0500
-+++ linux-2.6.28.8/include/linux/jbd2.h 2009-03-07 10:29:51.000000000 -0500
+diff -urNp linux-2.6.29.5/include/linux/jbd2.h linux-2.6.29.5/include/linux/jbd2.h
+--- linux-2.6.29.5/include/linux/jbd2.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/jbd2.h 2009-06-12 23:57:32.000000000 -0400
@@ -66,7 +66,7 @@ extern u8 jbd2_journal_enable_debug;
} \
} while (0)
@@ -30412,9 +33590,9 @@ diff -urNp linux-2.6.28.8/include/linux/jbd2.h linux-2.6.28.8/include/linux/jbd2
#endif
static inline void *jbd2_alloc(size_t size, gfp_t flags)
-diff -urNp linux-2.6.28.8/include/linux/jbd.h linux-2.6.28.8/include/linux/jbd.h
---- linux-2.6.28.8/include/linux/jbd.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/linux/jbd.h 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/include/linux/jbd.h linux-2.6.29.5/include/linux/jbd.h
+--- linux-2.6.29.5/include/linux/jbd.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/jbd.h 2009-06-12 23:57:32.000000000 -0400
@@ -66,7 +66,7 @@ extern u8 journal_enable_debug;
} \
} while (0)
@@ -30424,10 +33602,10 @@ diff -urNp linux-2.6.28.8/include/linux/jbd.h linux-2.6.28.8/include/linux/jbd.h
#endif
static inline void *jbd_alloc(size_t size, gfp_t flags)
-diff -urNp linux-2.6.28.8/include/linux/kvm_host.h linux-2.6.28.8/include/linux/kvm_host.h
---- linux-2.6.28.8/include/linux/kvm_host.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/linux/kvm_host.h 2009-02-21 09:37:49.000000000 -0500
-@@ -150,7 +150,7 @@ void kvm_vcpu_uninit(struct kvm_vcpu *vc
+diff -urNp linux-2.6.29.5/include/linux/kvm_host.h linux-2.6.29.5/include/linux/kvm_host.h
+--- linux-2.6.29.5/include/linux/kvm_host.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/kvm_host.h 2009-06-12 23:57:32.000000000 -0400
+@@ -155,7 +155,7 @@ void kvm_vcpu_uninit(struct kvm_vcpu *vc
void vcpu_load(struct kvm_vcpu *vcpu);
void vcpu_put(struct kvm_vcpu *vcpu);
@@ -30436,7 +33614,7 @@ diff -urNp linux-2.6.28.8/include/linux/kvm_host.h linux-2.6.28.8/include/linux/
struct module *module);
void kvm_exit(void);
-@@ -258,7 +258,7 @@ int kvm_arch_vcpu_ioctl_debug_guest(stru
+@@ -263,7 +263,7 @@ int kvm_arch_vcpu_ioctl_debug_guest(stru
struct kvm_debug_guest *dbg);
int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run);
@@ -30445,9 +33623,9 @@ diff -urNp linux-2.6.28.8/include/linux/kvm_host.h linux-2.6.28.8/include/linux/
void kvm_arch_exit(void);
int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu);
-diff -urNp linux-2.6.28.8/include/linux/libata.h linux-2.6.28.8/include/linux/libata.h
---- linux-2.6.28.8/include/linux/libata.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/linux/libata.h 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/include/linux/libata.h linux-2.6.29.5/include/linux/libata.h
+--- linux-2.6.29.5/include/linux/libata.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/libata.h 2009-06-12 23:57:32.000000000 -0400
@@ -64,11 +64,11 @@
#ifdef ATA_VERBOSE_DEBUG
#define VPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args)
@@ -30463,9 +33641,9 @@ diff -urNp linux-2.6.28.8/include/linux/libata.h linux-2.6.28.8/include/linux/li
#endif /* ATA_DEBUG */
#define BPRINTK(fmt, args...) if (ap->flags & ATA_FLAG_DEBUGMSG) printk(KERN_ERR "%s: " fmt, __func__, ## args)
-diff -urNp linux-2.6.28.8/include/linux/mm.h linux-2.6.28.8/include/linux/mm.h
---- linux-2.6.28.8/include/linux/mm.h 2009-03-07 10:24:49.000000000 -0500
-+++ linux-2.6.28.8/include/linux/mm.h 2009-03-07 10:29:51.000000000 -0500
+diff -urNp linux-2.6.29.5/include/linux/mm.h linux-2.6.29.5/include/linux/mm.h
+--- linux-2.6.29.5/include/linux/mm.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/mm.h 2009-06-12 23:57:32.000000000 -0400
@@ -39,6 +39,7 @@ extern unsigned long mmap_min_addr;
#include <asm/page.h>
#include <asm/pgtable.h>
@@ -30474,7 +33652,7 @@ diff -urNp linux-2.6.28.8/include/linux/mm.h linux-2.6.28.8/include/linux/mm.h
#define nth_page(page,n) pfn_to_page(page_to_pfn((page)) + (n))
-@@ -115,6 +116,10 @@ extern unsigned int kobjsize(const void
+@@ -105,6 +106,10 @@ extern unsigned int kobjsize(const void
#define VM_MIXEDMAP 0x10000000 /* Can contain "struct page" and pure PFN pages */
#define VM_SAO 0x20000000 /* Strong Access Ordering (powerpc) */
@@ -30485,7 +33663,7 @@ diff -urNp linux-2.6.28.8/include/linux/mm.h linux-2.6.28.8/include/linux/mm.h
#ifndef VM_STACK_DEFAULT_FLAGS /* arch can override this */
#define VM_STACK_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS
#endif
-@@ -873,6 +878,8 @@ struct shrinker {
+@@ -899,6 +904,8 @@ struct shrinker {
extern void register_shrinker(struct shrinker *);
extern void unregister_shrinker(struct shrinker *);
@@ -30494,7 +33672,7 @@ diff -urNp linux-2.6.28.8/include/linux/mm.h linux-2.6.28.8/include/linux/mm.h
int vma_wants_writenotify(struct vm_area_struct *vma);
extern pte_t *get_locked_pte(struct mm_struct *mm, unsigned long addr, spinlock_t **ptl);
-@@ -1141,6 +1148,7 @@ out:
+@@ -1170,6 +1177,7 @@ out:
}
extern int do_munmap(struct mm_struct *, unsigned long, size_t);
@@ -30502,7 +33680,7 @@ diff -urNp linux-2.6.28.8/include/linux/mm.h linux-2.6.28.8/include/linux/mm.h
extern unsigned long do_brk(unsigned long, unsigned long);
-@@ -1193,6 +1201,10 @@ extern struct vm_area_struct * find_vma(
+@@ -1223,6 +1231,10 @@ extern struct vm_area_struct * find_vma(
extern struct vm_area_struct * find_vma_prev(struct mm_struct * mm, unsigned long addr,
struct vm_area_struct **pprev);
@@ -30513,7 +33691,7 @@ diff -urNp linux-2.6.28.8/include/linux/mm.h linux-2.6.28.8/include/linux/mm.h
/* Look up the first VMA which intersects the interval start_addr..end_addr-1,
NULL if none. Assume start_addr < end_addr. */
static inline struct vm_area_struct * find_vma_intersection(struct mm_struct * mm, unsigned long start_addr, unsigned long end_addr)
-@@ -1209,7 +1221,6 @@ static inline unsigned long vma_pages(st
+@@ -1239,7 +1251,6 @@ static inline unsigned long vma_pages(st
return (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
}
@@ -30521,10 +33699,11 @@ diff -urNp linux-2.6.28.8/include/linux/mm.h linux-2.6.28.8/include/linux/mm.h
struct vm_area_struct *find_extend_vma(struct mm_struct *, unsigned long addr);
int remap_pfn_range(struct vm_area_struct *, unsigned long addr,
unsigned long pfn, unsigned long size, pgprot_t);
-@@ -1298,5 +1309,11 @@ int vmemmap_populate_basepages(struct pa
- int vmemmap_populate(struct page *start_page, unsigned long pages, int node);
- void vmemmap_populate_print_last(void);
-
+@@ -1331,5 +1342,12 @@ void vmemmap_populate_print_last(void);
+ extern void *alloc_locked_buffer(size_t size);
+ extern void free_locked_buffer(void *buffer, size_t size);
+ extern void release_locked_buffer(void *buffer, size_t size);
++
+#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
+extern void track_exec_limit(struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long prot);
+#else
@@ -30533,10 +33712,10 @@ diff -urNp linux-2.6.28.8/include/linux/mm.h linux-2.6.28.8/include/linux/mm.h
+
#endif /* __KERNEL__ */
#endif /* _LINUX_MM_H */
-diff -urNp linux-2.6.28.8/include/linux/mm_types.h linux-2.6.28.8/include/linux/mm_types.h
---- linux-2.6.28.8/include/linux/mm_types.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/linux/mm_types.h 2009-02-21 09:37:49.000000000 -0500
-@@ -157,6 +157,8 @@ struct vm_area_struct {
+diff -urNp linux-2.6.29.5/include/linux/mm_types.h linux-2.6.29.5/include/linux/mm_types.h
+--- linux-2.6.29.5/include/linux/mm_types.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/mm_types.h 2009-06-12 23:57:32.000000000 -0400
+@@ -174,6 +174,8 @@ struct vm_area_struct {
#ifdef CONFIG_NUMA
struct mempolicy *vm_policy; /* NUMA policy for the VMA */
#endif
@@ -30545,7 +33724,7 @@ diff -urNp linux-2.6.28.8/include/linux/mm_types.h linux-2.6.28.8/include/linux/
};
struct core_thread {
-@@ -256,6 +258,24 @@ struct mm_struct {
+@@ -274,6 +276,24 @@ struct mm_struct {
#ifdef CONFIG_MMU_NOTIFIER
struct mmu_notifier_mm *mmu_notifier_mm;
#endif
@@ -30569,11 +33748,11 @@ diff -urNp linux-2.6.28.8/include/linux/mm_types.h linux-2.6.28.8/include/linux/
+
};
- #endif /* _LINUX_MM_TYPES_H */
-diff -urNp linux-2.6.28.8/include/linux/module.h linux-2.6.28.8/include/linux/module.h
---- linux-2.6.28.8/include/linux/module.h 2009-02-07 16:10:45.000000000 -0500
-+++ linux-2.6.28.8/include/linux/module.h 2009-02-21 09:37:49.000000000 -0500
-@@ -283,16 +283,16 @@ struct module
+ /* Future-safe accessor for struct mm_struct's cpu_vm_mask. */
+diff -urNp linux-2.6.29.5/include/linux/module.h linux-2.6.29.5/include/linux/module.h
+--- linux-2.6.29.5/include/linux/module.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/module.h 2009-06-12 23:57:32.000000000 -0400
+@@ -278,16 +278,16 @@ struct module
int (*init)(void);
/* If this is non-NULL, vfree after init() returns */
@@ -30592,12 +33771,75 @@ diff -urNp linux-2.6.28.8/include/linux/module.h linux-2.6.28.8/include/linux/mo
- unsigned int init_text_size, core_text_size;
+ unsigned int init_size_rx, core_size_rx;
- /* The handle returned from unwind_add_table. */
- void *unwind_info;
-diff -urNp linux-2.6.28.8/include/linux/moduleloader.h linux-2.6.28.8/include/linux/moduleloader.h
---- linux-2.6.28.8/include/linux/moduleloader.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/linux/moduleloader.h 2009-02-21 09:37:49.000000000 -0500
-@@ -17,9 +17,21 @@ int module_frob_arch_sections(Elf_Ehdr *
+ /* Arch-specific module values */
+ struct mod_arch_specific arch;
+@@ -363,16 +363,46 @@ struct module *module_text_address(unsig
+ struct module *__module_text_address(unsigned long addr);
+ int is_module_address(unsigned long addr);
+
++static inline int within_module_range(unsigned long addr, void *start, unsigned long size)
++{
++
++#ifdef CONFIG_PAX_KERNEXEC
++ if (ktla_ktva(addr) >= (unsigned long)start &&
++ ktla_ktva(addr) < (unsigned long)start + size)
++ return 1;
++#endif
++
++ return ((void *)addr >= start && (void *)addr < start + size);
++}
++
++static inline int within_module_core_rx(unsigned long addr, struct module *mod)
++{
++ return within_module_range(addr, mod->module_core_rx, mod->core_size_rx);
++}
++
++static inline int within_module_core_rw(unsigned long addr, struct module *mod)
++{
++ return within_module_range(addr, mod->module_core_rw, mod->core_size_rw);
++}
++
++static inline int within_module_init_rx(unsigned long addr, struct module *mod)
++{
++ return within_module_range(addr, mod->module_init_rx, mod->init_size_rx);
++}
++
++static inline int within_module_init_rw(unsigned long addr, struct module *mod)
++{
++ return within_module_range(addr, mod->module_init_rw, mod->init_size_rw);
++}
++
+ static inline int within_module_core(unsigned long addr, struct module *mod)
+ {
+- return (unsigned long)mod->module_core <= addr &&
+- addr < (unsigned long)mod->module_core + mod->core_size;
++ return within_module_core_rx(addr, mod) || within_module_core_rw(addr, mod);
+ }
+
+ static inline int within_module_init(unsigned long addr, struct module *mod)
+ {
+- return (unsigned long)mod->module_init <= addr &&
+- addr < (unsigned long)mod->module_init + mod->init_size;
++ return within_module_init_rx(addr, mod) || within_module_init_rw(addr, mod);
+ }
+
+ /* Returns 0 and fills in value, defined and namebuf, or -ERANGE if
+@@ -396,7 +426,11 @@ void symbol_put_addr(void *addr);
+ static inline local_t *__module_ref_addr(struct module *mod, int cpu)
+ {
+ #ifdef CONFIG_SMP
++#ifdef CONFIG_X86_32
++ return (local_t *) (mod->refptr + __per_cpu_offset[cpu]);
++#else
+ return (local_t *) (mod->refptr + per_cpu_offset(cpu));
++#endif
+ #else
+ return &mod->ref;
+ #endif
+diff -urNp linux-2.6.29.5/include/linux/moduleloader.h linux-2.6.29.5/include/linux/moduleloader.h
+--- linux-2.6.29.5/include/linux/moduleloader.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/moduleloader.h 2009-06-12 23:57:32.000000000 -0400
+@@ -20,9 +20,21 @@ unsigned int arch_mod_section_prepend(st
sections. Returns NULL on failure. */
void *module_alloc(unsigned long size);
@@ -30619,9 +33861,9 @@ diff -urNp linux-2.6.28.8/include/linux/moduleloader.h linux-2.6.28.8/include/li
/* Apply the given relocation to the (simplified) ELF. Return -error
or 0. */
int apply_relocate(Elf_Shdr *sechdrs,
-diff -urNp linux-2.6.28.8/include/linux/namei.h linux-2.6.28.8/include/linux/namei.h
---- linux-2.6.28.8/include/linux/namei.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/linux/namei.h 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/include/linux/namei.h linux-2.6.29.5/include/linux/namei.h
+--- linux-2.6.29.5/include/linux/namei.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/namei.h 2009-06-12 23:57:32.000000000 -0400
@@ -21,7 +21,7 @@ struct nameidata {
unsigned int flags;
int last_type;
@@ -30646,9 +33888,9 @@ diff -urNp linux-2.6.28.8/include/linux/namei.h linux-2.6.28.8/include/linux/nam
{
return nd->saved_names[nd->depth];
}
-diff -urNp linux-2.6.28.8/include/linux/nodemask.h linux-2.6.28.8/include/linux/nodemask.h
---- linux-2.6.28.8/include/linux/nodemask.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/linux/nodemask.h 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/include/linux/nodemask.h linux-2.6.29.5/include/linux/nodemask.h
+--- linux-2.6.29.5/include/linux/nodemask.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/nodemask.h 2009-06-12 23:57:32.000000000 -0400
@@ -442,11 +442,11 @@ static inline int num_node_state(enum no
#define any_online_node(mask) \
@@ -30665,9 +33907,21 @@ diff -urNp linux-2.6.28.8/include/linux/nodemask.h linux-2.6.28.8/include/linux/
})
#define num_online_nodes() num_node_state(N_ONLINE)
-diff -urNp linux-2.6.28.8/include/linux/percpu.h linux-2.6.28.8/include/linux/percpu.h
---- linux-2.6.28.8/include/linux/percpu.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/linux/percpu.h 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/include/linux/oprofile.h linux-2.6.29.5/include/linux/oprofile.h
+--- linux-2.6.29.5/include/linux/oprofile.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/oprofile.h 2009-06-12 23:57:32.000000000 -0400
+@@ -128,7 +128,7 @@ int oprofilefs_create_ro_ulong(struct su
+
+ /** Create a file for read-only access to an atomic_t. */
+ int oprofilefs_create_ro_atomic(struct super_block * sb, struct dentry * root,
+- char const * name, atomic_t * val);
++ char const * name, atomic_unchecked_t * val);
+
+ /** create a directory */
+ struct dentry * oprofilefs_mkdir(struct super_block * sb, struct dentry * root,
+diff -urNp linux-2.6.29.5/include/linux/percpu.h linux-2.6.29.5/include/linux/percpu.h
+--- linux-2.6.29.5/include/linux/percpu.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/percpu.h 2009-06-12 23:57:32.000000000 -0400
@@ -50,7 +50,7 @@
#endif
@@ -30677,9 +33931,9 @@ diff -urNp linux-2.6.28.8/include/linux/percpu.h linux-2.6.28.8/include/linux/pe
#endif /* PERCPU_ENOUGH_ROOM */
/*
-diff -urNp linux-2.6.28.8/include/linux/poison.h linux-2.6.28.8/include/linux/poison.h
---- linux-2.6.28.8/include/linux/poison.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/linux/poison.h 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/include/linux/poison.h linux-2.6.29.5/include/linux/poison.h
+--- linux-2.6.29.5/include/linux/poison.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/poison.h 2009-06-12 23:57:32.000000000 -0400
@@ -7,8 +7,8 @@
* under normal circumstances, used to verify that nobody uses
* non-initialized list entries.
@@ -30691,9 +33945,9 @@ diff -urNp linux-2.6.28.8/include/linux/poison.h linux-2.6.28.8/include/linux/po
/********** include/linux/timer.h **********/
/*
-diff -urNp linux-2.6.28.8/include/linux/proc_fs.h linux-2.6.28.8/include/linux/proc_fs.h
---- linux-2.6.28.8/include/linux/proc_fs.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/linux/proc_fs.h 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/include/linux/proc_fs.h linux-2.6.29.5/include/linux/proc_fs.h
+--- linux-2.6.29.5/include/linux/proc_fs.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/proc_fs.h 2009-06-12 23:57:32.000000000 -0400
@@ -174,6 +174,19 @@ static inline struct proc_dir_entry *pro
return proc_create_data(name, mode, parent, proc_fops, NULL);
}
@@ -30714,10 +33968,22 @@ diff -urNp linux-2.6.28.8/include/linux/proc_fs.h linux-2.6.28.8/include/linux/p
static inline struct proc_dir_entry *create_proc_read_entry(const char *name,
mode_t mode, struct proc_dir_entry *base,
read_proc_t *read_proc, void * data)
-diff -urNp linux-2.6.28.8/include/linux/random.h linux-2.6.28.8/include/linux/random.h
---- linux-2.6.28.8/include/linux/random.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/linux/random.h 2009-02-21 09:37:49.000000000 -0500
-@@ -72,6 +72,11 @@ unsigned long randomize_range(unsigned l
+diff -urNp linux-2.6.29.5/include/linux/raid/md_k.h linux-2.6.29.5/include/linux/raid/md_k.h
+--- linux-2.6.29.5/include/linux/raid/md_k.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/raid/md_k.h 2009-06-12 23:57:32.000000000 -0400
+@@ -293,7 +293,7 @@ static inline void rdev_dec_pending(mdk_
+
+ static inline void md_sync_acct(struct block_device *bdev, unsigned long nr_sectors)
+ {
+- atomic_add(nr_sectors, &bdev->bd_contains->bd_disk->sync_io);
++ atomic_add_unchecked(nr_sectors, &bdev->bd_contains->bd_disk->sync_io);
+ }
+
+ struct mdk_personality
+diff -urNp linux-2.6.29.5/include/linux/random.h linux-2.6.29.5/include/linux/random.h
+--- linux-2.6.29.5/include/linux/random.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/random.h 2009-06-12 23:57:32.000000000 -0400
+@@ -74,6 +74,11 @@ unsigned long randomize_range(unsigned l
u32 random32(void);
void srandom32(u32 seed);
@@ -30729,18 +33995,30 @@ diff -urNp linux-2.6.28.8/include/linux/random.h linux-2.6.28.8/include/linux/ra
#endif /* __KERNEL___ */
#endif /* _LINUX_RANDOM_H */
-diff -urNp linux-2.6.28.8/include/linux/sched.h linux-2.6.28.8/include/linux/sched.h
---- linux-2.6.28.8/include/linux/sched.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/linux/sched.h 2009-02-21 09:37:49.000000000 -0500
-@@ -96,6 +96,7 @@ struct exec_domain;
- struct futex_pi_state;
+diff -urNp linux-2.6.29.5/include/linux/reiserfs_fs_sb.h linux-2.6.29.5/include/linux/reiserfs_fs_sb.h
+--- linux-2.6.29.5/include/linux/reiserfs_fs_sb.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/reiserfs_fs_sb.h 2009-06-12 23:57:32.000000000 -0400
+@@ -374,7 +374,7 @@ struct reiserfs_sb_info {
+ /* Comment? -Hans */
+ wait_queue_head_t s_wait;
+ /* To be obsoleted soon by per buffer seals.. -Hans */
+- atomic_t s_generation_counter; // increased by one every time the
++ atomic_unchecked_t s_generation_counter; // increased by one every time the
+ // tree gets re-balanced
+ unsigned long s_properties; /* File system properties. Currently holds
+ on-disk FS format */
+diff -urNp linux-2.6.29.5/include/linux/sched.h linux-2.6.29.5/include/linux/sched.h
+--- linux-2.6.29.5/include/linux/sched.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/sched.h 2009-06-12 23:57:32.000000000 -0400
+@@ -97,6 +97,7 @@ struct futex_pi_state;
struct robust_list_head;
struct bio;
+ struct bts_tracer;
+struct linux_binprm;
/*
* List of flags we want to share for kernel threads,
-@@ -588,6 +589,15 @@ struct signal_struct {
+@@ -606,6 +607,15 @@ struct signal_struct {
unsigned audit_tty;
struct tty_audit_buf *tty_audit_buf;
#endif
@@ -30756,7 +34034,7 @@ diff -urNp linux-2.6.28.8/include/linux/sched.h linux-2.6.28.8/include/linux/sch
};
/* Context switch must be unlocked if interrupts are to be enabled */
-@@ -1073,7 +1083,7 @@ struct sched_rt_entity {
+@@ -1114,7 +1124,7 @@ struct sched_rt_entity {
struct task_struct {
volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
@@ -30765,7 +34043,7 @@ diff -urNp linux-2.6.28.8/include/linux/sched.h linux-2.6.28.8/include/linux/sch
atomic_t usage;
unsigned int flags; /* per process flags, defined below */
unsigned int ptrace;
-@@ -1138,10 +1148,9 @@ struct task_struct {
+@@ -1179,10 +1189,9 @@ struct task_struct {
pid_t pid;
pid_t tgid;
@@ -30777,7 +34055,7 @@ diff -urNp linux-2.6.28.8/include/linux/sched.h linux-2.6.28.8/include/linux/sch
/*
* pointers to (original) parent process, youngest child, younger sibling,
* older sibling, respectively. (p->father can be replaced with
-@@ -1169,8 +1178,8 @@ struct task_struct {
+@@ -1223,8 +1232,8 @@ struct task_struct {
struct list_head thread_group;
struct completion *vfork_done; /* for vfork() */
@@ -30788,10 +34066,10 @@ diff -urNp linux-2.6.28.8/include/linux/sched.h linux-2.6.28.8/include/linux/sch
cputime_t utime, stime, utimescaled, stimescaled;
cputime_t gtime;
-@@ -1355,8 +1364,64 @@ struct task_struct {
- unsigned long default_timer_slack_ns;
-
- struct list_head *scm_work_list;
+@@ -1418,8 +1427,66 @@ struct task_struct {
+ /* state flags for use by tracers */
+ unsigned long trace;
+ #endif
+
+#ifdef CONFIG_GRKERNSEC
+ /* grsecurity */
@@ -30849,11 +34127,13 @@ diff -urNp linux-2.6.28.8/include/linux/sched.h linux-2.6.28.8/include/linux/sch
+void pax_report_fault(struct pt_regs *regs, void *pc, void *sp);
+void pax_report_insns(void *pc, void *sp);
+void pax_report_refcount_overflow(struct pt_regs *regs);
++void pax_report_leak_to_user(const void *ptr, unsigned long len);
++void pax_report_overflow_from_user(const void *ptr, unsigned long len);
+
- /*
- * Priority of a process goes from 0..MAX_PRIO-1, valid RT
- * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH
-@@ -1899,7 +1964,7 @@ extern void __cleanup_sighand(struct sig
+ /* Future-safe accessor for struct task_struct's cpus_allowed. */
+ #define tsk_cpumask(tsk) (&(tsk)->cpus_allowed)
+
+@@ -1961,7 +2028,7 @@ extern void __cleanup_sighand(struct sig
extern void exit_itimers(struct signal_struct *);
extern void flush_itimer_signals(void);
@@ -30862,7 +34142,7 @@ diff -urNp linux-2.6.28.8/include/linux/sched.h linux-2.6.28.8/include/linux/sch
extern void daemonize(const char *, ...);
extern int allow_signal(int);
-@@ -2002,8 +2067,8 @@ static inline void unlock_task_sighand(s
+@@ -2066,8 +2133,8 @@ static inline void unlock_task_sighand(s
#ifndef __HAVE_THREAD_FUNCTIONS
@@ -30873,9 +34153,9 @@ diff -urNp linux-2.6.28.8/include/linux/sched.h linux-2.6.28.8/include/linux/sch
static inline void setup_thread_stack(struct task_struct *p, struct task_struct *org)
{
-diff -urNp linux-2.6.28.8/include/linux/screen_info.h linux-2.6.28.8/include/linux/screen_info.h
---- linux-2.6.28.8/include/linux/screen_info.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/linux/screen_info.h 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/include/linux/screen_info.h linux-2.6.29.5/include/linux/screen_info.h
+--- linux-2.6.29.5/include/linux/screen_info.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/screen_info.h 2009-06-12 23:57:32.000000000 -0400
@@ -42,7 +42,8 @@ struct screen_info {
__u16 pages; /* 0x32 */
__u16 vesa_attributes; /* 0x34 */
@@ -30886,9 +34166,9 @@ diff -urNp linux-2.6.28.8/include/linux/screen_info.h linux-2.6.28.8/include/lin
} __attribute__((packed));
#define VIDEO_TYPE_MDA 0x10 /* Monochrome Text Display */
-diff -urNp linux-2.6.28.8/include/linux/security.h linux-2.6.28.8/include/linux/security.h
---- linux-2.6.28.8/include/linux/security.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/linux/security.h 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/include/linux/security.h linux-2.6.29.5/include/linux/security.h
+--- linux-2.6.29.5/include/linux/security.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/security.h 2009-06-12 23:57:32.000000000 -0400
@@ -32,6 +32,7 @@
#include <linux/sched.h>
#include <linux/key.h>
@@ -30897,9 +34177,9 @@ diff -urNp linux-2.6.28.8/include/linux/security.h linux-2.6.28.8/include/linux/
#include <net/flow.h>
/* Maximum number of letters for an LSM name string */
-diff -urNp linux-2.6.28.8/include/linux/shm.h linux-2.6.28.8/include/linux/shm.h
---- linux-2.6.28.8/include/linux/shm.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/linux/shm.h 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/include/linux/shm.h linux-2.6.29.5/include/linux/shm.h
+--- linux-2.6.29.5/include/linux/shm.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/shm.h 2009-06-12 23:57:32.000000000 -0400
@@ -95,6 +95,10 @@ struct shmid_kernel /* private to the ke
pid_t shm_cprid;
pid_t shm_lprid;
@@ -30911,9 +34191,9 @@ diff -urNp linux-2.6.28.8/include/linux/shm.h linux-2.6.28.8/include/linux/shm.h
};
/* shm_mode upper byte flags */
-diff -urNp linux-2.6.28.8/include/linux/slab.h linux-2.6.28.8/include/linux/slab.h
---- linux-2.6.28.8/include/linux/slab.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/linux/slab.h 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/include/linux/slab.h linux-2.6.29.5/include/linux/slab.h
+--- linux-2.6.29.5/include/linux/slab.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/slab.h 2009-06-12 23:57:32.000000000 -0400
@@ -73,10 +73,9 @@
* ZERO_SIZE_PTR can be passed to kfree though in the same way that NULL can.
* Both make kfree a no-op.
@@ -30927,9 +34207,65 @@ diff -urNp linux-2.6.28.8/include/linux/slab.h linux-2.6.28.8/include/linux/slab
/*
* struct kmem_cache related prototypes
-diff -urNp linux-2.6.28.8/include/linux/sysctl.h linux-2.6.28.8/include/linux/sysctl.h
---- linux-2.6.28.8/include/linux/sysctl.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/linux/sysctl.h 2009-02-21 09:37:49.000000000 -0500
+@@ -129,6 +128,7 @@ void * __must_check krealloc(const void
+ void kfree(const void *);
+ void kzfree(const void *);
+ size_t ksize(const void *);
++void check_object_size(const void *ptr, unsigned long n, bool to);
+
+ /*
+ * Allocator specific definitions. These are mainly used to establish optimized
+@@ -317,4 +317,35 @@ static inline void *kzalloc_node(size_t
+ return kmalloc_node(size, flags | __GFP_ZERO, node);
+ }
+
++#define kmalloc(x,y) \
++ ({ \
++ void *___retval; \
++ intoverflow_t ___x = (intoverflow_t)x; \
++ if (likely(___x <= ULONG_MAX)) \
++ ___retval = kmalloc((size_t)___x, y); \
++ else \
++ ___retval = NULL; \
++ ___retval; \
++ })
++#define kmalloc_node(x,y,z) \
++ ({ \
++ void *___retval; \
++ intoverflow_t ___x = (intoverflow_t)x; \
++ if (likely(___x <= ULONG_MAX)) \
++ ___retval = kmalloc_node((size_t)___x, y, z); \
++ else \
++ ___retval = NULL; \
++ ___retval; \
++ })
++#define kzalloc(x,y) \
++ ({ \
++ void *___retval; \
++ intoverflow_t ___x = (intoverflow_t)x; \
++ if (likely(___x <= ULONG_MAX)) \
++ ___retval = kzalloc((size_t)___x, y); \
++ else \
++ ___retval = NULL; \
++ ___retval; \
++ })
++
+ #endif /* _LINUX_SLAB_H */
+diff -urNp linux-2.6.29.5/include/linux/slub_def.h linux-2.6.29.5/include/linux/slub_def.h
+--- linux-2.6.29.5/include/linux/slub_def.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/slub_def.h 2009-06-12 23:57:32.000000000 -0400
+@@ -85,7 +85,7 @@ struct kmem_cache {
+ struct kmem_cache_order_objects max;
+ struct kmem_cache_order_objects min;
+ gfp_t allocflags; /* gfp flags to use on each alloc */
+- int refcount; /* Refcount for slab cache destroy */
++ atomic_t refcount; /* Refcount for slab cache destroy */
+ void (*ctor)(void *);
+ int inuse; /* Offset to metadata */
+ int align; /* Alignment */
+diff -urNp linux-2.6.29.5/include/linux/sysctl.h linux-2.6.29.5/include/linux/sysctl.h
+--- linux-2.6.29.5/include/linux/sysctl.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/sysctl.h 2009-06-12 23:57:32.000000000 -0400
@@ -165,7 +165,11 @@ enum
KERN_PANIC_ON_NMI=76, /* int: whether we will panic on an unrecovered */
};
@@ -30943,9 +34279,9 @@ diff -urNp linux-2.6.28.8/include/linux/sysctl.h linux-2.6.28.8/include/linux/sy
/* CTL_VM names: */
enum
-diff -urNp linux-2.6.28.8/include/linux/thread_info.h linux-2.6.28.8/include/linux/thread_info.h
---- linux-2.6.28.8/include/linux/thread_info.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/linux/thread_info.h 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/include/linux/thread_info.h linux-2.6.29.5/include/linux/thread_info.h
+--- linux-2.6.29.5/include/linux/thread_info.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/thread_info.h 2009-06-12 23:57:32.000000000 -0400
@@ -23,7 +23,7 @@ struct restart_block {
};
/* For futex_wait */
@@ -30955,9 +34291,57 @@ diff -urNp linux-2.6.28.8/include/linux/thread_info.h linux-2.6.28.8/include/lin
u32 val;
u32 flags;
u32 bitset;
-diff -urNp linux-2.6.28.8/include/linux/uaccess.h linux-2.6.28.8/include/linux/uaccess.h
---- linux-2.6.28.8/include/linux/uaccess.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/linux/uaccess.h 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/include/linux/tty_ldisc.h linux-2.6.29.5/include/linux/tty_ldisc.h
+--- linux-2.6.29.5/include/linux/tty_ldisc.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/tty_ldisc.h 2009-06-12 23:57:32.000000000 -0400
+@@ -139,12 +139,12 @@ struct tty_ldisc_ops {
+
+ struct module *owner;
+
+- int refcount;
++ atomic_t refcount;
+ };
+
+ struct tty_ldisc {
+ struct tty_ldisc_ops *ops;
+- int refcount;
++ atomic_t refcount;
+ };
+
+ #define TTY_LDISC_MAGIC 0x5403
+diff -urNp linux-2.6.29.5/include/linux/types.h linux-2.6.29.5/include/linux/types.h
+--- linux-2.6.29.5/include/linux/types.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/types.h 2009-06-12 23:57:32.000000000 -0400
+@@ -198,10 +198,26 @@ typedef struct {
+ volatile int counter;
+ } atomic_t;
+
++#ifdef CONFIG_PAX_REFCOUNT
++typedef struct {
++ volatile int counter;
++} atomic_unchecked_t;
++#else
++typedef atomic_t atomic_unchecked_t;
++#endif
++
+ #ifdef CONFIG_64BIT
+ typedef struct {
+ volatile long counter;
+ } atomic64_t;
++
++#ifdef CONFIG_PAX_REFCOUNT
++typedef struct {
++ volatile long counter;
++} atomic64_unchecked_t;
++#else
++typedef atomic64_t atomic64_unchecked_t;
++#endif
+ #endif
+
+ struct ustat {
+diff -urNp linux-2.6.29.5/include/linux/uaccess.h linux-2.6.29.5/include/linux/uaccess.h
+--- linux-2.6.29.5/include/linux/uaccess.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/uaccess.h 2009-06-12 23:57:32.000000000 -0400
@@ -76,11 +76,11 @@ static inline unsigned long __copy_from_
long ret; \
mm_segment_t old_fs = get_fs(); \
@@ -30965,16 +34349,16 @@ diff -urNp linux-2.6.28.8/include/linux/uaccess.h linux-2.6.28.8/include/linux/u
- set_fs(KERNEL_DS); \
pagefault_disable(); \
+ set_fs(KERNEL_DS); \
- ret = __get_user(retval, (__force typeof(retval) __user *)(addr)); \
+ ret = __copy_from_user_inatomic(&(retval), (__force typeof(retval) __user *)(addr), sizeof(retval)); \
- pagefault_enable(); \
set_fs(old_fs); \
+ pagefault_enable(); \
ret; \
})
-diff -urNp linux-2.6.28.8/include/linux/vmalloc.h linux-2.6.28.8/include/linux/vmalloc.h
---- linux-2.6.28.8/include/linux/vmalloc.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/linux/vmalloc.h 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/include/linux/vmalloc.h linux-2.6.29.5/include/linux/vmalloc.h
+--- linux-2.6.29.5/include/linux/vmalloc.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/linux/vmalloc.h 2009-06-12 23:57:32.000000000 -0400
@@ -13,6 +13,11 @@ struct vm_area_struct; /* vma defining
#define VM_MAP 0x00000004 /* vmap()ed pages */
#define VM_USERMAP 0x00000008 /* suitable for remap_vmalloc_range */
@@ -30987,10 +34371,86 @@ diff -urNp linux-2.6.28.8/include/linux/vmalloc.h linux-2.6.28.8/include/linux/v
/* bits [20..32] reserved for arch specific ioremap internals */
/*
-diff -urNp linux-2.6.28.8/include/net/sctp/sctp.h linux-2.6.28.8/include/net/sctp/sctp.h
---- linux-2.6.28.8/include/net/sctp/sctp.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/net/sctp/sctp.h 2009-02-21 09:37:49.000000000 -0500
-@@ -309,8 +309,8 @@ extern int sctp_debug_flag;
+@@ -111,4 +116,75 @@ extern long vwrite(char *buf, char *addr
+ extern rwlock_t vmlist_lock;
+ extern struct vm_struct *vmlist;
+
++#define vmalloc(x) \
++ ({ \
++ void *___retval; \
++ intoverflow_t ___x = (intoverflow_t)x; \
++ if (likely(___x <= ULONG_MAX)) \
++ ___retval = vmalloc((unsigned long)___x); \
++ else \
++ ___retval = NULL; \
++ ___retval; \
++ })
++#define __vmalloc(x,y,z) \
++ ({ \
++ void *___retval; \
++ intoverflow_t ___x = (intoverflow_t)x; \
++ if (likely(___x <= ULONG_MAX)) \
++ ___retval = __vmalloc((unsigned long)___x, y, z); \
++ else \
++ ___retval = NULL; \
++ ___retval; \
++ })
++#define vmalloc_user(x) \
++ ({ \
++ void *___retval; \
++ intoverflow_t ___x = (intoverflow_t)x; \
++ if (likely(___x <= ULONG_MAX)) \
++ ___retval = vmalloc_user((unsigned long)___x); \
++ else \
++ ___retval = NULL; \
++ ___retval; \
++ })
++#define vmalloc_exec(x) \
++ ({ \
++ void *___retval; \
++ intoverflow_t ___x = (intoverflow_t)x; \
++ if (likely(___x <= ULONG_MAX)) \
++ ___retval = vmalloc_exec((unsigned long)___x); \
++ else \
++ ___retval = NULL; \
++ ___retval; \
++ })
++#define vmalloc_node(x,y) \
++ ({ \
++ void *___retval; \
++ intoverflow_t ___x = (intoverflow_t)x; \
++ if (likely(___x <= ULONG_MAX)) \
++ ___retval = vmalloc_node((unsigned long)___x,y); \
++ else \
++ ___retval = NULL; \
++ ___retval; \
++ })
++#define vmalloc_32(x) \
++ ({ \
++ void *___retval; \
++ intoverflow_t ___x = (intoverflow_t)x; \
++ if (likely(___x <= ULONG_MAX)) \
++ ___retval = vmalloc_32((unsigned long)___x); \
++ else \
++ ___retval = NULL; \
++ ___retval; \
++ })
++#define vmalloc_32_user(x) \
++ ({ \
++ void *___retval; \
++ intoverflow_t ___x = (intoverflow_t)x; \
++ if (likely(___x <= ULONG_MAX)) \
++ ___retval = vmalloc_32_user((unsigned long)___x); \
++ else \
++ ___retval = NULL; \
++ ___retval; \
++ })
++
+ #endif /* _LINUX_VMALLOC_H */
+diff -urNp linux-2.6.29.5/include/net/sctp/sctp.h linux-2.6.29.5/include/net/sctp/sctp.h
+--- linux-2.6.29.5/include/net/sctp/sctp.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/net/sctp/sctp.h 2009-06-12 23:57:32.000000000 -0400
+@@ -310,8 +310,8 @@ extern int sctp_debug_flag;
#else /* SCTP_DEBUG */
@@ -31001,10 +34461,10 @@ diff -urNp linux-2.6.28.8/include/net/sctp/sctp.h linux-2.6.28.8/include/net/sct
#define SCTP_ENABLE_DEBUG
#define SCTP_DISABLE_DEBUG
#define SCTP_ASSERT(expr, str, func)
-diff -urNp linux-2.6.28.8/include/sound/core.h linux-2.6.28.8/include/sound/core.h
---- linux-2.6.28.8/include/sound/core.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/sound/core.h 2009-02-21 09:37:49.000000000 -0500
-@@ -405,7 +405,7 @@ static inline int __snd_bug_on(void)
+diff -urNp linux-2.6.29.5/include/sound/core.h linux-2.6.29.5/include/sound/core.h
+--- linux-2.6.29.5/include/sound/core.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/sound/core.h 2009-06-12 23:57:32.000000000 -0400
+@@ -427,7 +427,7 @@ static inline int __snd_bug_on(int cond)
*/
#define snd_printdd(format, args...) snd_printk(format, ##args)
#else
@@ -31013,10 +34473,10 @@ diff -urNp linux-2.6.28.8/include/sound/core.h linux-2.6.28.8/include/sound/core
#endif
-diff -urNp linux-2.6.28.8/include/video/uvesafb.h linux-2.6.28.8/include/video/uvesafb.h
---- linux-2.6.28.8/include/video/uvesafb.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/include/video/uvesafb.h 2009-02-21 09:37:49.000000000 -0500
-@@ -175,6 +175,7 @@ struct uvesafb_par {
+diff -urNp linux-2.6.29.5/include/video/uvesafb.h linux-2.6.29.5/include/video/uvesafb.h
+--- linux-2.6.29.5/include/video/uvesafb.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/include/video/uvesafb.h 2009-06-12 23:57:32.000000000 -0400
+@@ -177,6 +177,7 @@ struct uvesafb_par {
u8 ypan; /* 0 - nothing, 1 - ypan, 2 - ywrap */
u8 pmi_setpal; /* PMI for palette changes */
u16 *pmi_base; /* protected mode interface location */
@@ -31024,10 +34484,10 @@ diff -urNp linux-2.6.28.8/include/video/uvesafb.h linux-2.6.28.8/include/video/u
void *pmi_start;
void *pmi_pal;
u8 *vbe_state_orig; /*
-diff -urNp linux-2.6.28.8/init/do_mounts.c linux-2.6.28.8/init/do_mounts.c
---- linux-2.6.28.8/init/do_mounts.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/init/do_mounts.c 2009-02-21 09:37:49.000000000 -0500
-@@ -214,11 +214,11 @@ static void __init get_fs_names(char *pa
+diff -urNp linux-2.6.29.5/init/do_mounts.c linux-2.6.29.5/init/do_mounts.c
+--- linux-2.6.29.5/init/do_mounts.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/init/do_mounts.c 2009-06-12 23:57:32.000000000 -0400
+@@ -215,11 +215,11 @@ static void __init get_fs_names(char *pa
static int __init do_mount_root(char *name, char *fs, int flags, void *data)
{
@@ -31039,9 +34499,9 @@ diff -urNp linux-2.6.28.8/init/do_mounts.c linux-2.6.28.8/init/do_mounts.c
- sys_chdir("/root");
+ sys_chdir((char __user *)"/root");
ROOT_DEV = current->fs->pwd.mnt->mnt_sb->s_dev;
- printk("VFS: Mounted root (%s filesystem)%s.\n",
+ printk("VFS: Mounted root (%s filesystem)%s on device %u:%u.\n",
current->fs->pwd.mnt->mnt_sb->s_type->name,
-@@ -308,18 +308,18 @@ void __init change_floppy(char *fmt, ...
+@@ -309,18 +309,18 @@ void __init change_floppy(char *fmt, ...
va_start(args, fmt);
vsprintf(buf, fmt, args);
va_end(args);
@@ -31063,7 +34523,7 @@ diff -urNp linux-2.6.28.8/init/do_mounts.c linux-2.6.28.8/init/do_mounts.c
termios.c_lflag |= ICANON;
sys_ioctl(fd, TCSETSF, (long)&termios);
sys_close(fd);
-@@ -406,7 +406,7 @@ void __init prepare_namespace(void)
+@@ -413,7 +413,7 @@ void __init prepare_namespace(void)
mount_root();
out:
@@ -31073,9 +34533,9 @@ diff -urNp linux-2.6.28.8/init/do_mounts.c linux-2.6.28.8/init/do_mounts.c
+ sys_chroot((char __user *)".");
}
-diff -urNp linux-2.6.28.8/init/do_mounts.h linux-2.6.28.8/init/do_mounts.h
---- linux-2.6.28.8/init/do_mounts.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/init/do_mounts.h 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/init/do_mounts.h linux-2.6.29.5/init/do_mounts.h
+--- linux-2.6.29.5/init/do_mounts.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/init/do_mounts.h 2009-06-12 23:57:32.000000000 -0400
@@ -14,15 +14,15 @@ extern int root_mountflags;
static inline int create_dev(char *name, dev_t dev)
@@ -31095,9 +34555,9 @@ diff -urNp linux-2.6.28.8/init/do_mounts.h linux-2.6.28.8/init/do_mounts.h
return 0;
if (!S_ISBLK(stat.st_mode))
return 0;
-diff -urNp linux-2.6.28.8/init/do_mounts_initrd.c linux-2.6.28.8/init/do_mounts_initrd.c
---- linux-2.6.28.8/init/do_mounts_initrd.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/init/do_mounts_initrd.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/init/do_mounts_initrd.c linux-2.6.29.5/init/do_mounts_initrd.c
+--- linux-2.6.29.5/init/do_mounts_initrd.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/init/do_mounts_initrd.c 2009-06-12 23:57:32.000000000 -0400
@@ -32,7 +32,7 @@ static int __init do_linuxrc(void * shel
sys_close(old_fd);sys_close(root_fd);
sys_close(0);sys_close(1);sys_close(2);
@@ -31181,9 +34641,9 @@ diff -urNp linux-2.6.28.8/init/do_mounts_initrd.c linux-2.6.28.8/init/do_mounts_
+ sys_unlink((const char __user *)"/initrd.image");
return 0;
}
-diff -urNp linux-2.6.28.8/init/do_mounts_md.c linux-2.6.28.8/init/do_mounts_md.c
---- linux-2.6.28.8/init/do_mounts_md.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/init/do_mounts_md.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/init/do_mounts_md.c linux-2.6.29.5/init/do_mounts_md.c
+--- linux-2.6.29.5/init/do_mounts_md.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/init/do_mounts_md.c 2009-06-12 23:57:32.000000000 -0400
@@ -171,7 +171,7 @@ static void __init md_setup_drive(void)
partitioned ? "_d" : "", minor,
md_setup_args[ent].device_names);
@@ -31202,18 +34662,18 @@ diff -urNp linux-2.6.28.8/init/do_mounts_md.c linux-2.6.28.8/init/do_mounts_md.c
sys_ioctl(fd, BLKRRPART, 0);
}
sys_close(fd);
-@@ -283,7 +283,7 @@ static void autodetect_raid(void)
- printk(KERN_INFO "md: If you don't use raid, use raid=noautodetect\n");
- while (driver_probe_done() < 0)
- msleep(100);
+@@ -284,7 +284,7 @@ static void __init autodetect_raid(void)
+
+ wait_for_device_probe();
+
- fd = sys_open("/dev/md0", 0, 0);
+ fd = sys_open((char __user *)"/dev/md0", 0, 0);
if (fd >= 0) {
sys_ioctl(fd, RAID_AUTORUN, raid_autopart);
sys_close(fd);
-diff -urNp linux-2.6.28.8/init/initramfs.c linux-2.6.28.8/init/initramfs.c
---- linux-2.6.28.8/init/initramfs.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/init/initramfs.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/init/initramfs.c linux-2.6.29.5/init/initramfs.c
+--- linux-2.6.29.5/init/initramfs.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/init/initramfs.c 2009-06-12 23:57:32.000000000 -0400
@@ -276,7 +276,7 @@ static int __init maybe_link(void)
if (nlink >= 2) {
char *old = find_link(major, minor, ino, mode, collected);
@@ -31247,7 +34707,7 @@ diff -urNp linux-2.6.28.8/init/initramfs.c linux-2.6.28.8/init/initramfs.c
if (wfd >= 0) {
sys_fchown(wfd, uid, gid);
-@@ -322,16 +322,16 @@ static int __init do_name(void)
+@@ -323,16 +323,16 @@ static int __init do_name(void)
}
}
} else if (S_ISDIR(mode)) {
@@ -31270,7 +34730,7 @@ diff -urNp linux-2.6.28.8/init/initramfs.c linux-2.6.28.8/init/initramfs.c
do_utime(collected, mtime);
}
}
-@@ -341,7 +341,7 @@ static int __init do_name(void)
+@@ -342,7 +342,7 @@ static int __init do_name(void)
static int __init do_copy(void)
{
if (count >= body_len) {
@@ -31279,7 +34739,7 @@ diff -urNp linux-2.6.28.8/init/initramfs.c linux-2.6.28.8/init/initramfs.c
sys_close(wfd);
do_utime(vcollected, mtime);
kfree(vcollected);
-@@ -349,7 +349,7 @@ static int __init do_copy(void)
+@@ -350,7 +350,7 @@ static int __init do_copy(void)
state = SkipIt;
return 0;
} else {
@@ -31288,7 +34748,7 @@ diff -urNp linux-2.6.28.8/init/initramfs.c linux-2.6.28.8/init/initramfs.c
body_len -= count;
eat(count);
return 1;
-@@ -360,8 +360,8 @@ static int __init do_symlink(void)
+@@ -361,8 +361,8 @@ static int __init do_symlink(void)
{
collected[N_ALIGN(name_len) + body_len] = '\0';
clean_path(collected, 0);
@@ -31299,10 +34759,10 @@ diff -urNp linux-2.6.28.8/init/initramfs.c linux-2.6.28.8/init/initramfs.c
do_utime(collected, mtime);
state = SkipIt;
next_state = Reset;
-diff -urNp linux-2.6.28.8/init/Kconfig linux-2.6.28.8/init/Kconfig
---- linux-2.6.28.8/init/Kconfig 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/init/Kconfig 2009-02-21 09:37:49.000000000 -0500
-@@ -572,6 +572,7 @@ config SYSCTL_SYSCALL
+diff -urNp linux-2.6.29.5/init/Kconfig linux-2.6.29.5/init/Kconfig
+--- linux-2.6.29.5/init/Kconfig 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/init/Kconfig 2009-06-12 23:57:32.000000000 -0400
+@@ -712,6 +712,7 @@ config SYSCTL_SYSCALL
config KALLSYMS
bool "Load all symbols for debugging/ksymoops" if EMBEDDED
default y
@@ -31310,7 +34770,16 @@ diff -urNp linux-2.6.28.8/init/Kconfig linux-2.6.28.8/init/Kconfig
help
Say Y here to let the kernel print out symbolic crash information and
symbolic stack backtraces. This increases the size of the kernel
-@@ -822,9 +823,9 @@ config HAVE_GENERIC_DMA_COHERENT
+@@ -887,7 +888,7 @@ config SLUB_DEBUG
+
+ config COMPAT_BRK
+ bool "Disable heap randomization"
+- default y
++ default n
+ help
+ Randomizing heap placement makes heap exploits harder, but it
+ also breaks ancient binaries (including anything libc5 based).
+@@ -960,9 +961,9 @@ config HAVE_GENERIC_DMA_COHERENT
config SLABINFO
bool
@@ -31322,18 +34791,18 @@ diff -urNp linux-2.6.28.8/init/Kconfig linux-2.6.28.8/init/Kconfig
config RT_MUTEXES
boolean
-diff -urNp linux-2.6.28.8/init/main.c linux-2.6.28.8/init/main.c
---- linux-2.6.28.8/init/main.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/init/main.c 2009-02-21 09:37:49.000000000 -0500
-@@ -104,6 +104,7 @@ static inline void mark_rodata_ro(void)
+diff -urNp linux-2.6.29.5/init/main.c linux-2.6.29.5/init/main.c
+--- linux-2.6.29.5/init/main.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/init/main.c 2009-06-12 23:57:32.000000000 -0400
+@@ -96,6 +96,7 @@ static inline void mark_rodata_ro(void)
#ifdef CONFIG_TC
extern void tc_init(void);
#endif
+extern void grsecurity_init(void);
- enum system_states system_state;
+ enum system_states system_state __read_mostly;
EXPORT_SYMBOL(system_state);
-@@ -190,6 +191,40 @@ static int __init set_reset_devices(char
+@@ -182,6 +183,40 @@ static int __init set_reset_devices(char
__setup("reset_devices", set_reset_devices);
@@ -31374,7 +34843,7 @@ diff -urNp linux-2.6.28.8/init/main.c linux-2.6.28.8/init/main.c
static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, };
char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, };
static const char *panic_later, *panic_param;
-@@ -388,7 +423,7 @@ static void __init setup_nr_cpu_ids(void
+@@ -375,7 +410,7 @@ static void __init setup_nr_cpu_ids(void
}
#ifndef CONFIG_HAVE_SETUP_PER_CPU_AREA
@@ -31383,16 +34852,16 @@ diff -urNp linux-2.6.28.8/init/main.c linux-2.6.28.8/init/main.c
EXPORT_SYMBOL(__per_cpu_offset);
-@@ -704,6 +739,7 @@ int do_one_initcall(initcall_t fn)
+@@ -694,6 +729,7 @@ int do_one_initcall(initcall_t fn)
{
int count = preempt_count();
- ktime_t delta;
+ ktime_t calltime, delta, rettime;
+ const char *msg1 = "", *msg2 = "";
char msgbuf[64];
- struct boot_trace it;
-
-@@ -730,15 +766,15 @@ int do_one_initcall(initcall_t fn)
- sprintf(msgbuf, "error code %d ", it.result);
+ struct boot_trace_call call;
+ struct boot_trace_ret ret;
+@@ -724,15 +760,15 @@ int do_one_initcall(initcall_t fn)
+ sprintf(msgbuf, "error code %d ", ret.result);
if (preempt_count() != count) {
- strlcat(msgbuf, "preemption imbalance ", sizeof(msgbuf));
@@ -31410,8 +34879,8 @@ diff -urNp linux-2.6.28.8/init/main.c linux-2.6.28.8/init/main.c
+ printk("initcall %pF returned with %s%s%s\n", fn, msgbuf, msg1, msg2);
}
- return it.result;
-@@ -877,6 +913,8 @@ static int __init kernel_init(void * unu
+ return ret.result;
+@@ -873,6 +909,8 @@ static int __init kernel_init(void * unu
prepare_namespace();
}
@@ -31420,9 +34889,9 @@ diff -urNp linux-2.6.28.8/init/main.c linux-2.6.28.8/init/main.c
/*
* Ok, we have completed the initial bootup, and
* we're essentially up and running. Get rid of the
-diff -urNp linux-2.6.28.8/init/noinitramfs.c linux-2.6.28.8/init/noinitramfs.c
---- linux-2.6.28.8/init/noinitramfs.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/init/noinitramfs.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/init/noinitramfs.c linux-2.6.29.5/init/noinitramfs.c
+--- linux-2.6.29.5/init/noinitramfs.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/init/noinitramfs.c 2009-06-12 23:57:32.000000000 -0400
@@ -29,7 +29,7 @@ static int __init default_rootfs(void)
{
int err;
@@ -31441,9 +34910,9 @@ diff -urNp linux-2.6.28.8/init/noinitramfs.c linux-2.6.28.8/init/noinitramfs.c
if (err < 0)
goto out;
-diff -urNp linux-2.6.28.8/ipc/ipc_sysctl.c linux-2.6.28.8/ipc/ipc_sysctl.c
---- linux-2.6.28.8/ipc/ipc_sysctl.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/ipc/ipc_sysctl.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/ipc/ipc_sysctl.c linux-2.6.29.5/ipc/ipc_sysctl.c
+--- linux-2.6.29.5/ipc/ipc_sysctl.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/ipc/ipc_sysctl.c 2009-06-12 23:57:32.000000000 -0400
@@ -267,7 +267,7 @@ static struct ctl_table ipc_kern_table[]
.extra1 = &zero,
.extra2 = &one,
@@ -31462,9 +34931,20 @@ diff -urNp linux-2.6.28.8/ipc/ipc_sysctl.c linux-2.6.28.8/ipc/ipc_sysctl.c
};
static int __init ipc_sysctl_init(void)
-diff -urNp linux-2.6.28.8/ipc/msg.c linux-2.6.28.8/ipc/msg.c
---- linux-2.6.28.8/ipc/msg.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/ipc/msg.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/ipc/mqueue.c linux-2.6.29.5/ipc/mqueue.c
+--- linux-2.6.29.5/ipc/mqueue.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/ipc/mqueue.c 2009-06-12 23:57:32.000000000 -0400
+@@ -151,6 +151,7 @@ static struct inode *mqueue_get_inode(st
+ mq_bytes = (mq_msg_tblsz +
+ (info->attr.mq_maxmsg * info->attr.mq_msgsize));
+
++ gr_learn_resource(current, RLIMIT_MSGQUEUE, u->mq_bytes + mq_bytes, 1);
+ spin_lock(&mq_lock);
+ if (u->mq_bytes + mq_bytes < u->mq_bytes ||
+ u->mq_bytes + mq_bytes >
+diff -urNp linux-2.6.29.5/ipc/msg.c linux-2.6.29.5/ipc/msg.c
+--- linux-2.6.29.5/ipc/msg.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/ipc/msg.c 2009-06-12 23:57:32.000000000 -0400
@@ -314,6 +314,7 @@ SYSCALL_DEFINE2(msgget, key_t, key, int,
struct ipc_namespace *ns;
struct ipc_ops msg_ops;
@@ -31494,9 +34974,9 @@ diff -urNp linux-2.6.28.8/ipc/msg.c linux-2.6.28.8/ipc/msg.c
freeque(ns, ipcp);
goto out_up;
case IPC_SET:
-diff -urNp linux-2.6.28.8/ipc/sem.c linux-2.6.28.8/ipc/sem.c
---- linux-2.6.28.8/ipc/sem.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/ipc/sem.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/ipc/sem.c linux-2.6.29.5/ipc/sem.c
+--- linux-2.6.29.5/ipc/sem.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/ipc/sem.c 2009-06-12 23:57:32.000000000 -0400
@@ -313,6 +313,7 @@ SYSCALL_DEFINE3(semget, key_t, key, int,
struct ipc_namespace *ns;
struct ipc_ops sem_ops;
@@ -31526,9 +35006,9 @@ diff -urNp linux-2.6.28.8/ipc/sem.c linux-2.6.28.8/ipc/sem.c
freeary(ns, ipcp);
goto out_up;
case IPC_SET:
-diff -urNp linux-2.6.28.8/ipc/shm.c linux-2.6.28.8/ipc/shm.c
---- linux-2.6.28.8/ipc/shm.c 2009-02-07 16:10:45.000000000 -0500
-+++ linux-2.6.28.8/ipc/shm.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/ipc/shm.c linux-2.6.29.5/ipc/shm.c
+--- linux-2.6.29.5/ipc/shm.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/ipc/shm.c 2009-06-12 23:57:32.000000000 -0400
@@ -69,6 +69,14 @@ static void shm_destroy (struct ipc_name
static int sysvipc_shm_proc_show(struct seq_file *s, void *it);
#endif
@@ -31553,7 +35033,7 @@ diff -urNp linux-2.6.28.8/ipc/shm.c linux-2.6.28.8/ipc/shm.c
if (shp->shm_nattch){
shp->shm_perm.mode |= SHM_DEST;
/* Do not find it any more */
-@@ -392,6 +402,14 @@ static int newseg(struct ipc_namespace *
+@@ -394,6 +404,14 @@ static int newseg(struct ipc_namespace *
shp->shm_lprid = 0;
shp->shm_atim = shp->shm_dtim = 0;
shp->shm_ctim = get_seconds();
@@ -31568,7 +35048,7 @@ diff -urNp linux-2.6.28.8/ipc/shm.c linux-2.6.28.8/ipc/shm.c
shp->shm_segsz = size;
shp->shm_nattch = 0;
shp->shm_file = file;
-@@ -445,6 +463,7 @@ SYSCALL_DEFINE3(shmget, key_t, key, size
+@@ -447,6 +465,7 @@ SYSCALL_DEFINE3(shmget, key_t, key, size
struct ipc_namespace *ns;
struct ipc_ops shm_ops;
struct ipc_params shm_params;
@@ -31576,7 +35056,7 @@ diff -urNp linux-2.6.28.8/ipc/shm.c linux-2.6.28.8/ipc/shm.c
ns = current->nsproxy->ipc_ns;
-@@ -456,7 +475,11 @@ SYSCALL_DEFINE3(shmget, key_t, key, size
+@@ -458,7 +477,11 @@ SYSCALL_DEFINE3(shmget, key_t, key, size
shm_params.flg = shmflg;
shm_params.u.size = size;
@@ -31589,7 +35069,7 @@ diff -urNp linux-2.6.28.8/ipc/shm.c linux-2.6.28.8/ipc/shm.c
}
static inline unsigned long copy_shmid_to_user(void __user *buf, struct shmid64_ds *in, int version)
-@@ -877,9 +900,21 @@ long do_shmat(int shmid, char __user *sh
+@@ -873,9 +896,21 @@ long do_shmat(int shmid, char __user *sh
if (err)
goto out_unlock;
@@ -31611,10 +35091,10 @@ diff -urNp linux-2.6.28.8/ipc/shm.c linux-2.6.28.8/ipc/shm.c
size = i_size_read(path.dentry->d_inode);
shm_unlock(shp);
-diff -urNp linux-2.6.28.8/kernel/acct.c linux-2.6.28.8/kernel/acct.c
---- linux-2.6.28.8/kernel/acct.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/kernel/acct.c 2009-02-21 09:37:49.000000000 -0500
-@@ -573,7 +573,7 @@ static void do_acct_process(struct bsd_a
+diff -urNp linux-2.6.29.5/kernel/acct.c linux-2.6.29.5/kernel/acct.c
+--- linux-2.6.29.5/kernel/acct.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/kernel/acct.c 2009-06-12 23:57:32.000000000 -0400
+@@ -572,7 +572,7 @@ static void do_acct_process(struct bsd_a
*/
flim = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
current->signal->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
@@ -31623,15 +35103,15 @@ diff -urNp linux-2.6.28.8/kernel/acct.c linux-2.6.28.8/kernel/acct.c
sizeof(acct_t), &file->f_pos);
current->signal->rlim[RLIMIT_FSIZE].rlim_cur = flim;
set_fs(fs);
-diff -urNp linux-2.6.28.8/kernel/capability.c linux-2.6.28.8/kernel/capability.c
---- linux-2.6.28.8/kernel/capability.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/kernel/capability.c 2009-02-21 09:37:49.000000000 -0500
-@@ -498,10 +498,21 @@ SYSCALL_DEFINE2(capset, cap_user_header_
- */
- int capable(int cap)
- {
-- if (has_capability(current, cap)) {
-+ if (has_capability(current, cap) && gr_task_is_capable(current, cap)) {
+diff -urNp linux-2.6.29.5/kernel/capability.c linux-2.6.29.5/kernel/capability.c
+--- linux-2.6.29.5/kernel/capability.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/kernel/capability.c 2009-06-12 23:57:32.000000000 -0400
+@@ -306,10 +306,21 @@ int capable(int cap)
+ BUG();
+ }
+
+- if (security_capable(cap) == 0) {
++ if (security_capable(cap) == 0 && gr_is_capable(cap)) {
current->flags |= PF_SUPERPRIV;
return 1;
}
@@ -31640,7 +35120,7 @@ diff -urNp linux-2.6.28.8/kernel/capability.c linux-2.6.28.8/kernel/capability.c
+
+int capable_nolog(int cap)
+{
-+ if (has_capability(current, cap) && gr_is_capable_nolog(cap)) {
++ if (security_capable(cap) == 0 && gr_is_capable_nolog(cap)) {
+ current->flags |= PF_SUPERPRIV;
+ return 1;
+ }
@@ -31649,9 +35129,9 @@ diff -urNp linux-2.6.28.8/kernel/capability.c linux-2.6.28.8/kernel/capability.c
+
EXPORT_SYMBOL(capable);
+EXPORT_SYMBOL(capable_nolog);
-diff -urNp linux-2.6.28.8/kernel/configs.c linux-2.6.28.8/kernel/configs.c
---- linux-2.6.28.8/kernel/configs.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/kernel/configs.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/kernel/configs.c linux-2.6.29.5/kernel/configs.c
+--- linux-2.6.29.5/kernel/configs.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/kernel/configs.c 2009-06-12 23:57:32.000000000 -0400
@@ -73,8 +73,19 @@ static int __init ikconfig_init(void)
struct proc_dir_entry *entry;
@@ -31672,11 +35152,11 @@ diff -urNp linux-2.6.28.8/kernel/configs.c linux-2.6.28.8/kernel/configs.c
if (!entry)
return -ENOMEM;
-diff -urNp linux-2.6.28.8/kernel/cpu.c linux-2.6.28.8/kernel/cpu.c
---- linux-2.6.28.8/kernel/cpu.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/kernel/cpu.c 2009-02-21 09:37:49.000000000 -0500
-@@ -40,7 +40,7 @@ EXPORT_SYMBOL(cpu_possible_map);
- /* Serializes the updates to cpu_online_map, cpu_present_map */
+diff -urNp linux-2.6.29.5/kernel/cpu.c linux-2.6.29.5/kernel/cpu.c
+--- linux-2.6.29.5/kernel/cpu.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/kernel/cpu.c 2009-06-12 23:57:32.000000000 -0400
+@@ -19,7 +19,7 @@
+ /* Serializes the updates to cpu_online_mask, cpu_present_mask */
static DEFINE_MUTEX(cpu_add_remove_lock);
-static __cpuinitdata RAW_NOTIFIER_HEAD(cpu_chain);
@@ -31684,12 +35164,24 @@ diff -urNp linux-2.6.28.8/kernel/cpu.c linux-2.6.28.8/kernel/cpu.c
/* If set, cpu_up and cpu_down will return -EBUSY and do nothing.
* Should always be manipulated under cpu_add_remove_lock
-diff -urNp linux-2.6.28.8/kernel/exit.c linux-2.6.28.8/kernel/exit.c
---- linux-2.6.28.8/kernel/exit.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/kernel/exit.c 2009-03-07 04:29:14.000000000 -0500
-@@ -53,6 +53,10 @@
- #include <asm/pgtable.h>
- #include <asm/mmu_context.h>
+diff -urNp linux-2.6.29.5/kernel/cred.c linux-2.6.29.5/kernel/cred.c
+--- linux-2.6.29.5/kernel/cred.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/kernel/cred.c 2009-06-12 23:57:32.000000000 -0400
+@@ -366,6 +366,8 @@ int commit_creds(struct cred *new)
+
+ get_cred(new); /* we will require a ref for the subj creds too */
+
++ gr_set_role_label(task, new->uid, new->gid);
++
+ /* dumpability changes */
+ if (old->euid != new->euid ||
+ old->egid != new->egid ||
+diff -urNp linux-2.6.29.5/kernel/exit.c linux-2.6.29.5/kernel/exit.c
+--- linux-2.6.29.5/kernel/exit.c 2009-06-12 23:55:00.000000000 -0400
++++ linux-2.6.29.5/kernel/exit.c 2009-06-12 23:57:32.000000000 -0400
+@@ -59,6 +59,10 @@ DEFINE_TRACE(sched_process_free);
+ DEFINE_TRACE(sched_process_exit);
+ DEFINE_TRACE(sched_process_wait);
+#ifdef CONFIG_GRKERNSEC
+extern rwlock_t grsec_exec_file_lock;
@@ -31698,16 +35190,16 @@ diff -urNp linux-2.6.28.8/kernel/exit.c linux-2.6.28.8/kernel/exit.c
static void exit_mm(struct task_struct * tsk);
static inline int task_detached(struct task_struct *p)
-@@ -163,6 +167,8 @@ void release_task(struct task_struct * p
+@@ -172,6 +176,8 @@ void release_task(struct task_struct * p
struct task_struct *leader;
int zap_leader;
repeat:
+ gr_del_task_from_ip_table(p);
+
tracehook_prepare_release_task(p);
- atomic_dec(&p->user->processes);
- proc_flush_task(p);
-@@ -326,11 +332,22 @@ static void reparent_to_kthreadd(void)
+ /* don't need to get the RCU readlock here - the process is dead and
+ * can't be modifying its own credentials */
+@@ -338,11 +344,22 @@ static void reparent_to_kthreadd(void)
{
write_lock_irq(&tasklist_lock);
@@ -31730,7 +35222,7 @@ diff -urNp linux-2.6.28.8/kernel/exit.c linux-2.6.28.8/kernel/exit.c
/* Set the exit signal to SIGCHLD so we signal init on exit */
current->exit_signal = SIGCHLD;
-@@ -424,6 +441,17 @@ void daemonize(const char *name, ...)
+@@ -435,6 +452,17 @@ void daemonize(const char *name, ...)
vsnprintf(current->comm, sizeof(current->comm), name, args);
va_end(args);
@@ -31748,7 +35240,7 @@ diff -urNp linux-2.6.28.8/kernel/exit.c linux-2.6.28.8/kernel/exit.c
/*
* If we were started as result of loading a module, close all of the
* user space pages. We don't need them, and if we didn't close them
-@@ -1066,6 +1094,9 @@ NORET_TYPE void do_exit(long code)
+@@ -1034,6 +1062,9 @@ NORET_TYPE void do_exit(long code)
tsk->exit_code = code;
taskstats_exit(tsk, group_dead);
@@ -31758,19 +35250,19 @@ diff -urNp linux-2.6.28.8/kernel/exit.c linux-2.6.28.8/kernel/exit.c
exit_mm(tsk);
if (group_dead)
-@@ -1272,7 +1303,7 @@ static int wait_task_zombie(struct task_
+@@ -1238,7 +1269,7 @@ static int wait_task_zombie(struct task_
+
if (unlikely(options & WNOWAIT)) {
- uid_t uid = p->uid;
int exit_code = p->exit_code;
- int why, status;
+ int why;
get_task_struct(p);
read_unlock(&tasklist_lock);
-diff -urNp linux-2.6.28.8/kernel/fork.c linux-2.6.28.8/kernel/fork.c
---- linux-2.6.28.8/kernel/fork.c 2009-03-07 10:24:49.000000000 -0500
-+++ linux-2.6.28.8/kernel/fork.c 2009-03-07 10:29:51.000000000 -0500
-@@ -236,7 +236,7 @@ static struct task_struct *dup_task_stru
+diff -urNp linux-2.6.29.5/kernel/fork.c linux-2.6.29.5/kernel/fork.c
+--- linux-2.6.29.5/kernel/fork.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/kernel/fork.c 2009-06-12 23:57:32.000000000 -0400
+@@ -239,7 +239,7 @@ static struct task_struct *dup_task_stru
setup_thread_stack(tsk, orig);
#ifdef CONFIG_CC_STACKPROTECTOR
@@ -31779,7 +35271,7 @@ diff -urNp linux-2.6.28.8/kernel/fork.c linux-2.6.28.8/kernel/fork.c
#endif
/* One for us, one for whoever does the "release_task()" (usually parent) */
-@@ -273,8 +273,8 @@ static int dup_mmap(struct mm_struct *mm
+@@ -276,8 +276,8 @@ static int dup_mmap(struct mm_struct *mm
mm->locked_vm = 0;
mm->mmap = NULL;
mm->mmap_cache = NULL;
@@ -31790,7 +35282,7 @@ diff -urNp linux-2.6.28.8/kernel/fork.c linux-2.6.28.8/kernel/fork.c
mm->map_count = 0;
cpus_clear(mm->cpu_vm_mask);
mm->mm_rb = RB_ROOT;
-@@ -311,6 +311,7 @@ static int dup_mmap(struct mm_struct *mm
+@@ -314,6 +314,7 @@ static int dup_mmap(struct mm_struct *mm
tmp->vm_flags &= ~VM_LOCKED;
tmp->vm_mm = mm;
tmp->vm_next = NULL;
@@ -31798,7 +35290,7 @@ diff -urNp linux-2.6.28.8/kernel/fork.c linux-2.6.28.8/kernel/fork.c
anon_vma_link(tmp);
file = tmp->vm_file;
if (file) {
-@@ -358,6 +359,31 @@ static int dup_mmap(struct mm_struct *mm
+@@ -361,6 +362,31 @@ static int dup_mmap(struct mm_struct *mm
if (retval)
goto out;
}
@@ -31830,7 +35322,7 @@ diff -urNp linux-2.6.28.8/kernel/fork.c linux-2.6.28.8/kernel/fork.c
/* a new mm has just been created */
arch_dup_mmap(oldmm, mm);
retval = 0;
-@@ -527,9 +553,11 @@ void mm_release(struct task_struct *tsk,
+@@ -541,9 +567,11 @@ void mm_release(struct task_struct *tsk,
#ifdef CONFIG_FUTEX
if (unlikely(tsk->robust_list))
exit_robust_list(tsk);
@@ -31842,7 +35334,7 @@ diff -urNp linux-2.6.28.8/kernel/fork.c linux-2.6.28.8/kernel/fork.c
#endif
#endif
-@@ -551,7 +579,7 @@ void mm_release(struct task_struct *tsk,
+@@ -565,7 +593,7 @@ void mm_release(struct task_struct *tsk,
if (tsk->clear_child_tid
&& !(tsk->flags & PF_SIGNALED)
&& atomic_read(&mm->mm_users) > 1) {
@@ -31851,7 +35343,7 @@ diff -urNp linux-2.6.28.8/kernel/fork.c linux-2.6.28.8/kernel/fork.c
tsk->clear_child_tid = NULL;
/*
-@@ -559,7 +587,7 @@ void mm_release(struct task_struct *tsk,
+@@ -573,7 +601,7 @@ void mm_release(struct task_struct *tsk,
* not set up a proper pointer then tough luck.
*/
put_user(0, tidptr);
@@ -31860,18 +35352,27 @@ diff -urNp linux-2.6.28.8/kernel/fork.c linux-2.6.28.8/kernel/fork.c
}
}
-@@ -984,6 +1012,9 @@ static struct task_struct *copy_process(
+@@ -686,7 +714,7 @@ static int copy_fs(unsigned long clone_f
+ write_unlock(&fs->lock);
+ return -EAGAIN;
+ }
+- fs->users++;
++ atomic_inc(&fs->users);
+ write_unlock(&fs->lock);
+ return 0;
+ }
+@@ -978,6 +1006,9 @@ static struct task_struct *copy_process(
DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled);
#endif
retval = -EAGAIN;
+
-+ gr_learn_resource(p, RLIMIT_NPROC, atomic_read(&p->user->processes), 0);
++ gr_learn_resource(p, RLIMIT_NPROC, atomic_read(&p->real_cred->user->processes), 0);
+
- if (atomic_read(&p->user->processes) >=
+ if (atomic_read(&p->real_cred->user->processes) >=
p->signal->rlim[RLIMIT_NPROC].rlim_cur) {
if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) &&
-@@ -1147,6 +1178,8 @@ static struct task_struct *copy_process(
- goto bad_fork_free_pid;
+@@ -1138,6 +1169,8 @@ static struct task_struct *copy_process(
+ goto bad_fork_free_graph;
}
+ gr_copy_label(p);
@@ -31879,7 +35380,7 @@ diff -urNp linux-2.6.28.8/kernel/fork.c linux-2.6.28.8/kernel/fork.c
p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL;
/*
* Clear TID on mm_release()?
-@@ -1317,6 +1350,8 @@ bad_fork_cleanup_count:
+@@ -1306,6 +1339,8 @@ bad_fork_cleanup_count:
bad_fork_free:
free_task(p);
fork_out:
@@ -31888,7 +35389,7 @@ diff -urNp linux-2.6.28.8/kernel/fork.c linux-2.6.28.8/kernel/fork.c
return ERR_PTR(retval);
}
-@@ -1395,6 +1430,8 @@ long do_fork(unsigned long clone_flags,
+@@ -1399,6 +1434,8 @@ long do_fork(unsigned long clone_flags,
if (clone_flags & CLONE_PARENT_SETTID)
put_user(nr, parent_tidptr);
@@ -31897,10 +35398,28 @@ diff -urNp linux-2.6.28.8/kernel/fork.c linux-2.6.28.8/kernel/fork.c
if (clone_flags & CLONE_VFORK) {
p->vfork_done = &vfork;
init_completion(&vfork);
-diff -urNp linux-2.6.28.8/kernel/futex.c linux-2.6.28.8/kernel/futex.c
---- linux-2.6.28.8/kernel/futex.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/kernel/futex.c 2009-02-21 09:37:49.000000000 -0500
-@@ -188,6 +188,11 @@ static int get_futex_key(u32 __user *uad
+@@ -1530,7 +1567,7 @@ static int unshare_fs(unsigned long unsh
+ return 0;
+
+ /* don't need lock here; in the worst case we'll do useless copy */
+- if (fs->users == 1)
++ if (atomic_read(&fs->users) == 1)
+ return 0;
+
+ *new_fsp = copy_fs_struct(fs);
+@@ -1653,7 +1690,7 @@ SYSCALL_DEFINE1(unshare, unsigned long,
+ fs = current->fs;
+ write_lock(&fs->lock);
+ current->fs = new_fs;
+- if (--fs->users)
++ if (atomic_dec_return(&fs->users))
+ new_fs = NULL;
+ else
+ new_fs = fs;
+diff -urNp linux-2.6.29.5/kernel/futex.c linux-2.6.29.5/kernel/futex.c
+--- linux-2.6.29.5/kernel/futex.c 2009-06-12 23:55:00.000000000 -0400
++++ linux-2.6.29.5/kernel/futex.c 2009-06-12 23:57:32.000000000 -0400
+@@ -213,6 +213,11 @@ get_futex_key(u32 __user *uaddr, int fsh
struct page *page;
int err;
@@ -31912,27 +35431,16 @@ diff -urNp linux-2.6.28.8/kernel/futex.c linux-2.6.28.8/kernel/futex.c
/*
* The futex address must be "naturally" aligned.
*/
-@@ -214,8 +219,8 @@ static int get_futex_key(u32 __user *uad
- * The futex is hashed differently depending on whether
- * it's in a shared or private mapping. So check vma first.
- */
-- vma = find_extend_vma(mm, address);
-- if (unlikely(!vma))
-+ vma = find_vma(mm, address);
-+ if (unlikely(!vma || address < vma->vm_start))
- return -EFAULT;
-
- /*
-@@ -1348,7 +1353,7 @@ static int futex_wait(u32 __user *uaddr,
- struct restart_block *restart;
- restart = &current_thread_info()->restart_block;
- restart->fn = futex_wait_restart;
-- restart->futex.uaddr = (u32 *)uaddr;
-+ restart->futex.uaddr = uaddr;
- restart->futex.val = val;
- restart->futex.time = abs_time->tv64;
- restart->futex.bitset = bitset;
-@@ -1908,7 +1913,7 @@ retry:
+@@ -1306,7 +1311,7 @@ retry:
+
+ restart = &current_thread_info()->restart_block;
+ restart->fn = futex_wait_restart;
+- restart->futex.uaddr = (u32 *)uaddr;
++ restart->futex.uaddr = uaddr;
+ restart->futex.val = val;
+ restart->futex.time = abs_time->tv64;
+ restart->futex.bitset = bitset;
+@@ -1848,7 +1853,7 @@ retry:
*/
static inline int fetch_robust_entry(struct robust_list __user **entry,
struct robust_list __user * __user *head,
@@ -31941,10 +35449,10 @@ diff -urNp linux-2.6.28.8/kernel/futex.c linux-2.6.28.8/kernel/futex.c
{
unsigned long uentry;
-diff -urNp linux-2.6.28.8/kernel/irq/handle.c linux-2.6.28.8/kernel/irq/handle.c
---- linux-2.6.28.8/kernel/irq/handle.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/kernel/irq/handle.c 2009-02-21 09:37:49.000000000 -0500
-@@ -57,7 +57,8 @@ struct irq_desc irq_desc[NR_IRQS] __cach
+diff -urNp linux-2.6.29.5/kernel/irq/handle.c linux-2.6.29.5/kernel/irq/handle.c
+--- linux-2.6.29.5/kernel/irq/handle.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/kernel/irq/handle.c 2009-06-12 23:57:32.000000000 -0400
+@@ -222,7 +222,8 @@ struct irq_desc irq_desc[NR_IRQS] __cach
.depth = 1,
.lock = __SPIN_LOCK_UNLOCKED(irq_desc->lock),
#ifdef CONFIG_SMP
@@ -31954,9 +35462,9 @@ diff -urNp linux-2.6.28.8/kernel/irq/handle.c linux-2.6.28.8/kernel/irq/handle.c
#endif
}
};
-diff -urNp linux-2.6.28.8/kernel/kallsyms.c linux-2.6.28.8/kernel/kallsyms.c
---- linux-2.6.28.8/kernel/kallsyms.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/kernel/kallsyms.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/kernel/kallsyms.c linux-2.6.29.5/kernel/kallsyms.c
+--- linux-2.6.29.5/kernel/kallsyms.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/kernel/kallsyms.c 2009-06-12 23:57:32.000000000 -0400
@@ -62,6 +62,18 @@ static inline int is_kernel_text(unsigne
static inline int is_kernel(unsigned long addr)
@@ -32009,9 +35517,9 @@ diff -urNp linux-2.6.28.8/kernel/kallsyms.c linux-2.6.28.8/kernel/kallsyms.c
return 0;
}
__initcall(kallsyms_init);
-diff -urNp linux-2.6.28.8/kernel/kmod.c linux-2.6.28.8/kernel/kmod.c
---- linux-2.6.28.8/kernel/kmod.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/kernel/kmod.c 2009-02-21 09:37:49.000000000 -0500
+diff -urNp linux-2.6.29.5/kernel/kmod.c linux-2.6.29.5/kernel/kmod.c
+--- linux-2.6.29.5/kernel/kmod.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/kernel/kmod.c 2009-06-12 23:57:32.000000000 -0400
@@ -108,7 +108,7 @@ int request_module(const char *fmt, ...)
return -ENOMEM;
}
@@ -32021,10 +35529,10 @@ diff -urNp linux-2.6.28.8/kernel/kmod.c linux-2.6.28.8/kernel/kmod.c
atomic_dec(&kmod_concurrent);
return ret;
}
-diff -urNp linux-2.6.28.8/kernel/kprobes.c linux-2.6.28.8/kernel/kprobes.c
---- linux-2.6.28.8/kernel/kprobes.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/kernel/kprobes.c 2009-02-21 09:37:49.000000000 -0500
-@@ -182,7 +182,7 @@ kprobe_opcode_t __kprobes *get_insn_slot
+diff -urNp linux-2.6.29.5/kernel/kprobes.c linux-2.6.29.5/kernel/kprobes.c
+--- linux-2.6.29.5/kernel/kprobes.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/kernel/kprobes.c 2009-06-12 23:57:32.000000000 -0400
+@@ -183,7 +183,7 @@ static kprobe_opcode_t __kprobes *__get_
* kernel image and loaded module images reside. This is required
* so x86_64 can correctly handle the %rip-relative fixups.
*/
@@ -32033,7 +35541,7 @@ diff -urNp linux-2.6.28.8/kernel/kprobes.c linux-2.6.28.8/kernel/kprobes.c
if (!kip->insns) {
kfree(kip);
return NULL;
-@@ -214,7 +214,7 @@ static int __kprobes collect_one_slot(st
+@@ -224,7 +224,7 @@ static int __kprobes collect_one_slot(st
hlist_add_head(&kip->hlist,
&kprobe_insn_pages);
} else {
@@ -32042,10 +35550,10 @@ diff -urNp linux-2.6.28.8/kernel/kprobes.c linux-2.6.28.8/kernel/kprobes.c
kfree(kip);
}
return 1;
-diff -urNp linux-2.6.28.8/kernel/lockdep.c linux-2.6.28.8/kernel/lockdep.c
---- linux-2.6.28.8/kernel/lockdep.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/kernel/lockdep.c 2009-02-21 09:37:49.000000000 -0500
-@@ -627,6 +627,10 @@ static int static_obj(void *obj)
+diff -urNp linux-2.6.29.5/kernel/lockdep.c linux-2.6.29.5/kernel/lockdep.c
+--- linux-2.6.29.5/kernel/lockdep.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/kernel/lockdep.c 2009-06-12 23:57:32.000000000 -0400
+@@ -631,6 +631,10 @@ static int static_obj(void *obj)
int i;
#endif
@@ -32056,7 +35564,7 @@ diff -urNp linux-2.6.28.8/kernel/lockdep.c linux-2.6.28.8/kernel/lockdep.c
/*
* static variable?
*/
-@@ -638,9 +642,12 @@ static int static_obj(void *obj)
+@@ -642,9 +646,12 @@ static int static_obj(void *obj)
* percpu var?
*/
for_each_possible_cpu(i) {
@@ -32071,10 +35579,10 @@ diff -urNp linux-2.6.28.8/kernel/lockdep.c linux-2.6.28.8/kernel/lockdep.c
if ((addr >= start) && (addr < end))
return 1;
-diff -urNp linux-2.6.28.8/kernel/module.c linux-2.6.28.8/kernel/module.c
---- linux-2.6.28.8/kernel/module.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/kernel/module.c 2009-02-21 09:37:50.000000000 -0500
-@@ -47,6 +47,11 @@
+diff -urNp linux-2.6.29.5/kernel/module.c linux-2.6.29.5/kernel/module.c
+--- linux-2.6.29.5/kernel/module.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/kernel/module.c 2009-06-12 23:57:32.000000000 -0400
+@@ -46,6 +46,11 @@
#include <linux/rculist.h>
#include <asm/uaccess.h>
#include <asm/cacheflush.h>
@@ -32146,7 +35654,7 @@ diff -urNp linux-2.6.28.8/kernel/module.c linux-2.6.28.8/kernel/module.c
}
static int percpu_modinit(void)
-@@ -750,6 +764,9 @@ SYSCALL_DEFINE2(delete_module, const cha
+@@ -751,6 +765,9 @@ SYSCALL_DEFINE2(delete_module, const cha
char name[MODULE_NAME_LEN];
int ret, forced = 0;
@@ -32156,7 +35664,7 @@ diff -urNp linux-2.6.28.8/kernel/module.c linux-2.6.28.8/kernel/module.c
if (!capable(CAP_SYS_MODULE))
return -EPERM;
-@@ -1448,19 +1465,22 @@ static void free_module(struct module *m
+@@ -1458,10 +1475,11 @@ static void free_module(struct module *m
module_unload_free(mod);
/* release any pointers to mcount in this module */
@@ -32170,7 +35678,9 @@ diff -urNp linux-2.6.28.8/kernel/module.c linux-2.6.28.8/kernel/module.c
kfree(mod->args);
if (mod->percpu)
percpu_modfree(mod->percpu);
-
+@@ -1470,10 +1488,12 @@ static void free_module(struct module *m
+ percpu_modfree(mod->refptr);
+ #endif
/* Free lock-classes: */
- lockdep_free_key_range(mod->module_core, mod->core_size);
+ lockdep_free_key_range(mod->module_core_rx, mod->core_size_rx);
@@ -32183,7 +35693,7 @@ diff -urNp linux-2.6.28.8/kernel/module.c linux-2.6.28.8/kernel/module.c
}
void *__symbol_get(const char *symbol)
-@@ -1526,10 +1546,14 @@ static int simplify_symbols(Elf_Shdr *se
+@@ -1539,10 +1559,14 @@ static int simplify_symbols(Elf_Shdr *se
struct module *mod)
{
Elf_Sym *sym = (void *)sechdrs[symindex].sh_addr;
@@ -32199,7 +35709,7 @@ diff -urNp linux-2.6.28.8/kernel/module.c linux-2.6.28.8/kernel/module.c
for (i = 1; i < n; i++) {
switch (sym[i].st_shndx) {
case SHN_COMMON:
-@@ -1548,10 +1572,19 @@ static int simplify_symbols(Elf_Shdr *se
+@@ -1561,10 +1585,19 @@ static int simplify_symbols(Elf_Shdr *se
break;
case SHN_UNDEF:
@@ -32221,7 +35731,7 @@ diff -urNp linux-2.6.28.8/kernel/module.c linux-2.6.28.8/kernel/module.c
/* Ok if resolved. */
if (!IS_ERR_VALUE(sym[i].st_value))
break;
-@@ -1566,11 +1599,27 @@ static int simplify_symbols(Elf_Shdr *se
+@@ -1579,11 +1612,27 @@ static int simplify_symbols(Elf_Shdr *se
default:
/* Divert to percpu allocation if a percpu var. */
@@ -32251,15 +35761,15 @@ diff -urNp linux-2.6.28.8/kernel/module.c linux-2.6.28.8/kernel/module.c
break;
}
}
-@@ -1622,11 +1671,12 @@ static void layout_sections(struct modul
+@@ -1645,11 +1694,12 @@ static void layout_sections(struct modul
|| strncmp(secstrings + s->sh_name,
".init", 5) == 0)
continue;
-- s->sh_entsize = get_offset(&mod->core_size, s);
+- s->sh_entsize = get_offset(mod, &mod->core_size, s, i);
+ if ((s->sh_flags & SHF_WRITE) || !(s->sh_flags & SHF_ALLOC))
-+ s->sh_entsize = get_offset(&mod->core_size_rw, s);
++ s->sh_entsize = get_offset(mod, &mod->core_size_rw, s, i);
+ else
-+ s->sh_entsize = get_offset(&mod->core_size_rx, s);
++ s->sh_entsize = get_offset(mod, &mod->core_size_rx, s, i);
DEBUGP("\t%s\n", secstrings + s->sh_name);
}
- if (m == 0)
@@ -32267,16 +35777,16 @@ diff -urNp linux-2.6.28.8/kernel/module.c linux-2.6.28.8/kernel/module.c
}
DEBUGP("Init section allocation order:\n");
-@@ -1640,12 +1690,13 @@ static void layout_sections(struct modul
+@@ -1663,12 +1713,13 @@ static void layout_sections(struct modul
|| strncmp(secstrings + s->sh_name,
".init", 5) != 0)
continue;
-- s->sh_entsize = (get_offset(&mod->init_size, s)
+- s->sh_entsize = (get_offset(mod, &mod->init_size, s, i)
- | INIT_OFFSET_MASK);
+ if ((s->sh_flags & SHF_WRITE) || !(s->sh_flags & SHF_ALLOC))
-+ s->sh_entsize = get_offset(&mod->init_size_rw, s);
++ s->sh_entsize = get_offset(mod, &mod->init_size_rw, s, i);
+ else
-+ s->sh_entsize = get_offset(&mod->init_size_rx, s);
++ s->sh_entsize = get_offset(mod, &mod->init_size_rx, s, i);
+ s->sh_entsize |= INIT_OFFSET_MASK;
DEBUGP("\t%s\n", secstrings + s->sh_name);
}
@@ -32285,7 +35795,7 @@ diff -urNp linux-2.6.28.8/kernel/module.c linux-2.6.28.8/kernel/module.c
}
}
-@@ -1785,14 +1836,31 @@ static void add_kallsyms(struct module *
+@@ -1808,14 +1859,31 @@ static void add_kallsyms(struct module *
{
unsigned int i;
@@ -32320,7 +35830,7 @@ diff -urNp linux-2.6.28.8/kernel/module.c linux-2.6.28.8/kernel/module.c
}
#else
static inline void add_kallsyms(struct module *mod,
-@@ -1819,16 +1887,30 @@ static void dynamic_printk_setup(struct
+@@ -1842,16 +1910,30 @@ static void dynamic_printk_setup(struct
#endif /* CONFIG_DYNAMIC_PRINTK_DEBUG */
}
@@ -32356,7 +35866,7 @@ diff -urNp linux-2.6.28.8/kernel/module.c linux-2.6.28.8/kernel/module.c
}
return ret;
}
-@@ -1856,6 +1938,10 @@ static noinline struct module *load_modu
+@@ -1878,6 +1960,10 @@ static noinline struct module *load_modu
unsigned long *mseg;
mm_segment_t old_fs;
@@ -32367,7 +35877,7 @@ diff -urNp linux-2.6.28.8/kernel/module.c linux-2.6.28.8/kernel/module.c
DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n",
umod, len, uargs);
if (len < sizeof(*hdr))
-@@ -2010,22 +2096,57 @@ static noinline struct module *load_modu
+@@ -2034,22 +2120,57 @@ static noinline struct module *load_modu
layout_sections(mod, hdr, sechdrs, secstrings);
/* Do the allocs. */
@@ -32381,17 +35891,12 @@ diff -urNp linux-2.6.28.8/kernel/module.c linux-2.6.28.8/kernel/module.c
- mod->module_core = ptr;
+ memset(ptr, 0, mod->core_size_rw);
+ mod->module_core_rw = ptr;
-
-- ptr = module_alloc_update_bounds(mod->init_size);
-- if (!ptr && mod->init_size) {
++
+ ptr = module_alloc_update_bounds_rw(mod->init_size_rw);
+ if (!ptr && mod->init_size_rw) {
- err = -ENOMEM;
-- goto free_core;
++ err = -ENOMEM;
+ goto free_core_rw;
- }
-- memset(ptr, 0, mod->init_size);
-- mod->module_init = ptr;
++ }
+ memset(ptr, 0, mod->init_size_rw);
+ mod->module_init_rw = ptr;
+
@@ -32404,9 +35909,11 @@ diff -urNp linux-2.6.28.8/kernel/module.c linux-2.6.28.8/kernel/module.c
+#ifdef CONFIG_PAX_KERNEXEC
+ pax_open_kernel(cr0);
+#endif
-
-+ memset(ptr, 0, mod->core_size_rx);
+
++ memset(ptr, 0, mod->core_size_rx);
+
+- ptr = module_alloc_update_bounds(mod->init_size);
+- if (!ptr && mod->init_size) {
+#ifdef CONFIG_PAX_KERNEXEC
+ pax_close_kernel(cr0);
+#endif
@@ -32415,10 +35922,13 @@ diff -urNp linux-2.6.28.8/kernel/module.c linux-2.6.28.8/kernel/module.c
+
+ ptr = module_alloc_update_bounds_rx(mod->init_size_rx);
+ if (!ptr && mod->init_size_rx) {
-+ err = -ENOMEM;
+ err = -ENOMEM;
+- goto free_core;
+ goto free_core_rx;
-+ }
-+
+ }
+- memset(ptr, 0, mod->init_size);
+- mod->module_init = ptr;
+
+#ifdef CONFIG_PAX_KERNEXEC
+ pax_open_kernel(cr0);
+#endif
@@ -32433,7 +35943,7 @@ diff -urNp linux-2.6.28.8/kernel/module.c linux-2.6.28.8/kernel/module.c
/* Transfer each section which specifies SHF_ALLOC */
DEBUGP("final section addresses:\n");
for (i = 0; i < hdr->e_shnum; i++) {
-@@ -2034,17 +2155,41 @@ static noinline struct module *load_modu
+@@ -2058,17 +2179,41 @@ static noinline struct module *load_modu
if (!(sechdrs[i].sh_flags & SHF_ALLOC))
continue;
@@ -32455,12 +35965,12 @@ diff -urNp linux-2.6.28.8/kernel/module.c linux-2.6.28.8/kernel/module.c
+ else
+ dest = mod->module_core_rx + sechdrs[i].sh_entsize;
+ }
-+
-+ if (sechdrs[i].sh_type != SHT_NOBITS) {
- if (sechdrs[i].sh_type != SHT_NOBITS)
- memcpy(dest, (void *)sechdrs[i].sh_addr,
- sechdrs[i].sh_size);
++ if (sechdrs[i].sh_type != SHT_NOBITS) {
++
+#ifdef CONFIG_PAX_KERNEXEC
+ if (!(sechdrs[i].sh_flags & SHF_WRITE) && (sechdrs[i].sh_flags & SHF_ALLOC)) {
+ pax_open_kernel(cr0);
@@ -32484,7 +35994,16 @@ diff -urNp linux-2.6.28.8/kernel/module.c linux-2.6.28.8/kernel/module.c
DEBUGP("\t0x%lx %s\n", sechdrs[i].sh_addr, secstrings + sechdrs[i].sh_name);
}
/* Module has been moved. */
-@@ -2144,8 +2289,8 @@ static noinline struct module *load_modu
+@@ -2079,7 +2224,7 @@ static noinline struct module *load_modu
+ mod->name);
+ if (!mod->refptr) {
+ err = -ENOMEM;
+- goto free_init;
++ goto free_init_rx;
+ }
+ #endif
+ /* Now we've moved module, initialize linked lists, etc. */
+@@ -2176,8 +2321,8 @@ static noinline struct module *load_modu
/* Now do relocations. */
for (i = 1; i < hdr->e_shnum; i++) {
@@ -32494,7 +36013,7 @@ diff -urNp linux-2.6.28.8/kernel/module.c linux-2.6.28.8/kernel/module.c
/* Not a valid relocation section? */
if (info >= hdr->e_shnum)
-@@ -2216,12 +2361,12 @@ static noinline struct module *load_modu
+@@ -2239,12 +2384,12 @@ static noinline struct module *load_modu
* Do it before processing of module parameters, so the module
* can provide parameter accessor functions of its own.
*/
@@ -32513,7 +36032,7 @@ diff -urNp linux-2.6.28.8/kernel/module.c linux-2.6.28.8/kernel/module.c
set_fs(old_fs);
-@@ -2266,12 +2411,16 @@ static noinline struct module *load_modu
+@@ -2285,16 +2430,20 @@ static noinline struct module *load_modu
cleanup:
kobject_del(&mod->mkobj.kobj);
kobject_put(&mod->mkobj.kobj);
@@ -32521,6 +36040,11 @@ diff -urNp linux-2.6.28.8/kernel/module.c linux-2.6.28.8/kernel/module.c
+ ftrace_release(mod->module_core_rx, mod->core_size_rx);
free_unload:
module_unload_free(mod);
+- free_init:
++ free_init_rx:
+ #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP)
+ percpu_modfree(mod->refptr);
+ #endif
- module_free(mod, mod->module_init);
- free_core:
- module_free(mod, mod->module_core);
@@ -32531,10 +36055,10 @@ diff -urNp linux-2.6.28.8/kernel/module.c linux-2.6.28.8/kernel/module.c
+ module_free(mod, mod->module_init_rw);
+ free_core_rw:
+ module_free(mod, mod->module_core_rw);
+ /* mod will be freed with core. Don't access it beyond this line! */
free_percpu:
if (percpu)
- percpu_modfree(percpu);
-@@ -2294,6 +2443,9 @@ SYSCALL_DEFINE3(init_module, void __user
+@@ -2319,6 +2468,9 @@ SYSCALL_DEFINE3(init_module, void __user
struct module *mod;
int ret = 0;
@@ -32544,10 +36068,10 @@ diff -urNp linux-2.6.28.8/kernel/module.c linux-2.6.28.8/kernel/module.c
/* Must have permission */
if (!capable(CAP_SYS_MODULE))
return -EPERM;
-@@ -2349,10 +2501,12 @@ SYSCALL_DEFINE3(init_module, void __user
+@@ -2375,20 +2527,17 @@ SYSCALL_DEFINE3(init_module, void __user
+ mutex_lock(&module_mutex);
/* Drop initial reference. */
module_put(mod);
- unwind_remove_table(mod->unwind_info, 1);
- module_free(mod, mod->module_init);
- mod->module_init = NULL;
- mod->init_size = 0;
@@ -32561,78 +36085,37 @@ diff -urNp linux-2.6.28.8/kernel/module.c linux-2.6.28.8/kernel/module.c
mutex_unlock(&module_mutex);
return 0;
-@@ -2360,6 +2514,13 @@ SYSCALL_DEFINE3(init_module, void __user
-
- static inline int within(unsigned long addr, void *start, unsigned long size)
- {
-+
-+#ifdef CONFIG_PAX_KERNEXEC
-+ if (ktla_ktva(addr) >= (unsigned long)start &&
-+ ktla_ktva(addr) < (unsigned long)start + size)
-+ return 1;
-+#endif
-+
- return ((void *)addr >= start && (void *)addr < start + size);
}
-@@ -2383,10 +2544,14 @@ static const char *get_ksymbol(struct mo
+-static inline int within(unsigned long addr, void *start, unsigned long size)
+-{
+- return ((void *)addr >= start && (void *)addr < start + size);
+-}
+-
+ #ifdef CONFIG_KALLSYMS
+ /*
+ * This ignores the intensely annoying "mapping symbols" found
+@@ -2409,10 +2558,16 @@ static const char *get_ksymbol(struct mo
unsigned long nextval;
/* At worse, next value is at end of module */
-- if (within(addr, mod->module_init, mod->init_size))
+- if (within_module_init(addr, mod))
- nextval = (unsigned long)mod->module_init+mod->init_text_size;
-+ if (within(addr, mod->module_init_rx, mod->init_size_rx))
++ if (within_module_init_rx(addr, mod))
+ nextval = (unsigned long)mod->module_init_rx+mod->init_size_rx;
-+ else if (within(addr, mod->module_init_rw, mod->init_size_rw))
++ else if (within_module_init_rw(addr, mod))
+ nextval = (unsigned long)mod->module_init_rw+mod->init_size_rw;
-+ else if (within(addr, mod->module_core_rx, mod->core_size_rx))
++ else if (within_module_core_rx(addr, mod))
+ nextval = (unsigned long)mod->module_core_rx+mod->core_size_rx;
++ else if (within_module_core_rw(addr, mod))
++ nextval = (unsigned long)mod->module_core_rw+mod->core_size_rw;
else
- nextval = (unsigned long)mod->module_core+mod->core_text_size;
-+ nextval = (unsigned long)mod->module_core_rw+mod->core_size_rw;
++ return NULL;
/* Scan for closest preceeding symbol, and next symbol. (ELF
starts real symbols at 1). */
-@@ -2431,8 +2596,10 @@ const char *module_address_lookup(unsign
-
- preempt_disable();
- list_for_each_entry_rcu(mod, &modules, list) {
-- if (within(addr, mod->module_init, mod->init_size)
-- || within(addr, mod->module_core, mod->core_size)) {
-+ if (within(addr, mod->module_init_rx, mod->init_size_rx) ||
-+ within(addr, mod->module_init_rw, mod->init_size_rw) ||
-+ within(addr, mod->module_core_rx, mod->core_size_rx) ||
-+ within(addr, mod->module_core_rw, mod->core_size_rw)) {
- if (modname)
- *modname = mod->name;
- ret = get_ksymbol(mod, addr, size, offset);
-@@ -2454,8 +2621,10 @@ int lookup_module_symbol_name(unsigned l
-
- preempt_disable();
- list_for_each_entry_rcu(mod, &modules, list) {
-- if (within(addr, mod->module_init, mod->init_size) ||
-- within(addr, mod->module_core, mod->core_size)) {
-+ if (within(addr, mod->module_init_rx, mod->init_size_rx) ||
-+ within(addr, mod->module_init_rw, mod->init_size_rw) ||
-+ within(addr, mod->module_core_rx, mod->core_size_rx) ||
-+ within(addr, mod->module_core_rw, mod->core_size_rw)) {
- const char *sym;
-
- sym = get_ksymbol(mod, addr, NULL, NULL);
-@@ -2478,8 +2647,10 @@ int lookup_module_symbol_attrs(unsigned
-
- preempt_disable();
- list_for_each_entry_rcu(mod, &modules, list) {
-- if (within(addr, mod->module_init, mod->init_size) ||
-- within(addr, mod->module_core, mod->core_size)) {
-+ if (within(addr, mod->module_init_rx, mod->init_size_rx) ||
-+ within(addr, mod->module_init_rw, mod->init_size_rw) ||
-+ within(addr, mod->module_core_rx, mod->core_size_rx) ||
-+ within(addr, mod->module_core_rw, mod->core_size_rw)) {
- const char *sym;
-
- sym = get_ksymbol(mod, addr, size, offset);
-@@ -2613,7 +2784,7 @@ static int m_show(struct seq_file *m, vo
+@@ -2639,7 +2794,7 @@ static int m_show(struct seq_file *m, vo
char buf[8];
seq_printf(m, "%s %u",
@@ -32641,7 +36124,7 @@ diff -urNp linux-2.6.28.8/kernel/module.c linux-2.6.28.8/kernel/module.c
print_unload_info(m, mod);
/* Informative for users. */
-@@ -2622,7 +2793,7 @@ static int m_show(struct seq_file *m, vo
+@@ -2648,7 +2803,7 @@ static int m_show(struct seq_file *m, vo
mod->state == MODULE_STATE_COMING ? "Loading":
"Live");
/* Used by oprofile and other similar tools. */
@@ -32650,18 +36133,7 @@ diff -urNp linux-2.6.28.8/kernel/module.c linux-2.6.28.8/kernel/module.c
/* Taints info */
if (mod->taints)
-@@ -2698,8 +2869,8 @@ int is_module_address(unsigned long addr
- preempt_disable();
-
- list_for_each_entry_rcu(mod, &modules, list) {
-- if (within(addr, mod->module_core, mod->core_size)) {
-- preempt_enable();
-+ if (within(addr, mod->module_core_rx, mod->core_size_rx) ||
-+ within(addr, mod->module_core_rw, mod->core_size_rw)) {
- return 1;
- }
- }
-@@ -2715,12 +2886,16 @@ struct module *__module_text_address(uns
+@@ -2741,12 +2896,15 @@ __notrace_funcgraph struct module *__mod
{
struct module *mod;
@@ -32676,14 +36148,13 @@ diff -urNp linux-2.6.28.8/kernel/module.c linux-2.6.28.8/kernel/module.c
list_for_each_entry_rcu(mod, &modules, list)
- if (within(addr, mod->module_init, mod->init_text_size)
- || within(addr, mod->module_core, mod->core_text_size))
-+ if (within(addr, mod->module_init_rx, mod->init_size_rx)
-+ || within(addr, mod->module_core_rx, mod->core_size_rx))
++ if (within_module_init_rx(addr, mod) || within_module_core_rx(addr, mod))
return mod;
return NULL;
}
-diff -urNp linux-2.6.28.8/kernel/mutex.c linux-2.6.28.8/kernel/mutex.c
---- linux-2.6.28.8/kernel/mutex.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/kernel/mutex.c 2009-02-21 09:37:50.000000000 -0500
+diff -urNp linux-2.6.29.5/kernel/mutex.c linux-2.6.29.5/kernel/mutex.c
+--- linux-2.6.29.5/kernel/mutex.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/kernel/mutex.c 2009-06-12 23:57:32.000000000 -0400
@@ -83,7 +83,7 @@ __mutex_lock_slowpath(atomic_t *lock_cou
*
* This function is similar to (but not equivalent to) down().
@@ -32693,10 +36164,10 @@ diff -urNp linux-2.6.28.8/kernel/mutex.c linux-2.6.28.8/kernel/mutex.c
{
might_sleep();
/*
-diff -urNp linux-2.6.28.8/kernel/panic.c linux-2.6.28.8/kernel/panic.c
---- linux-2.6.28.8/kernel/panic.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/kernel/panic.c 2009-02-21 09:37:50.000000000 -0500
-@@ -367,6 +367,8 @@ EXPORT_SYMBOL(warn_slowpath);
+diff -urNp linux-2.6.29.5/kernel/panic.c linux-2.6.29.5/kernel/panic.c
+--- linux-2.6.29.5/kernel/panic.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/kernel/panic.c 2009-06-12 23:57:32.000000000 -0400
+@@ -361,6 +361,8 @@ EXPORT_SYMBOL(warn_slowpath);
*/
void __stack_chk_fail(void)
{
@@ -32705,9 +36176,9 @@ diff -urNp linux-2.6.28.8/kernel/panic.c linux-2.6.28.8/kernel/panic.c
panic("stack-protector: Kernel stack is corrupted");
}
EXPORT_SYMBOL(__stack_chk_fail);
-diff -urNp linux-2.6.28.8/kernel/pid.c linux-2.6.28.8/kernel/pid.c
---- linux-2.6.28.8/kernel/pid.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/kernel/pid.c 2009-02-21 09:37:50.000000000 -0500
+diff -urNp linux-2.6.29.5/kernel/pid.c linux-2.6.29.5/kernel/pid.c
+--- linux-2.6.29.5/kernel/pid.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/kernel/pid.c 2009-06-12 23:57:32.000000000 -0400
@@ -33,6 +33,7 @@
#include <linux/rculist.h>
#include <linux/bootmem.h>
@@ -32741,9 +36212,9 @@ diff -urNp linux-2.6.28.8/kernel/pid.c linux-2.6.28.8/kernel/pid.c
}
EXPORT_SYMBOL(find_task_by_pid_type_ns);
-diff -urNp linux-2.6.28.8/kernel/posix-cpu-timers.c linux-2.6.28.8/kernel/posix-cpu-timers.c
---- linux-2.6.28.8/kernel/posix-cpu-timers.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/kernel/posix-cpu-timers.c 2009-02-21 09:37:50.000000000 -0500
+diff -urNp linux-2.6.29.5/kernel/posix-cpu-timers.c linux-2.6.29.5/kernel/posix-cpu-timers.c
+--- linux-2.6.29.5/kernel/posix-cpu-timers.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/kernel/posix-cpu-timers.c 2009-06-12 23:57:32.000000000 -0400
@@ -6,6 +6,7 @@
#include <linux/posix-timers.h>
#include <linux/errno.h>
@@ -32752,15 +36223,23 @@ diff -urNp linux-2.6.28.8/kernel/posix-cpu-timers.c linux-2.6.28.8/kernel/posix-
#include <asm/uaccess.h>
#include <linux/kernel_stat.h>
-@@ -1157,6 +1158,7 @@ static void check_process_timers(struct
+@@ -1040,6 +1041,7 @@ static void check_thread_timers(struct t
+ __group_send_sig_info(SIGKILL, SEND_SIG_PRIV, tsk);
+ return;
+ }
++ gr_learn_resource(tsk, RLIMIT_RTTIME, tsk->rt.timeout, 1);
+ if (tsk->rt.timeout > DIV_ROUND_UP(*soft, USEC_PER_SEC/HZ)) {
+ /*
+ * At the soft limit, send a SIGXCPU every second.
+@@ -1195,6 +1197,7 @@ static void check_process_timers(struct
__group_send_sig_info(SIGKILL, SEND_SIG_PRIV, tsk);
return;
}
-+ gr_learn_resource(tsk, RLIMIT_CPU, psecs, 1);
++ gr_learn_resource(tsk, RLIMIT_CPU, psecs, 0);
if (psecs >= sig->rlim[RLIMIT_CPU].rlim_cur) {
/*
* At the soft limit, send a SIGXCPU every second.
-@@ -1381,17 +1383,17 @@ void run_posix_cpu_timers(struct task_st
+@@ -1419,17 +1422,17 @@ void run_posix_cpu_timers(struct task_st
* timer call will interfere.
*/
list_for_each_entry_safe(timer, next, &firing, it.cpu.entry) {
@@ -32781,9 +36260,9 @@ diff -urNp linux-2.6.28.8/kernel/posix-cpu-timers.c linux-2.6.28.8/kernel/posix-
cpu_timer_fire(timer);
}
spin_unlock(&timer->it_lock);
-diff -urNp linux-2.6.28.8/kernel/power/poweroff.c linux-2.6.28.8/kernel/power/poweroff.c
---- linux-2.6.28.8/kernel/power/poweroff.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/kernel/power/poweroff.c 2009-02-21 09:37:50.000000000 -0500
+diff -urNp linux-2.6.29.5/kernel/power/poweroff.c linux-2.6.29.5/kernel/power/poweroff.c
+--- linux-2.6.29.5/kernel/power/poweroff.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/kernel/power/poweroff.c 2009-06-12 23:57:32.000000000 -0400
@@ -37,7 +37,7 @@ static struct sysrq_key_op sysrq_powerof
.enable_mask = SYSRQ_ENABLE_BOOT,
};
@@ -32793,10 +36272,10 @@ diff -urNp linux-2.6.28.8/kernel/power/poweroff.c linux-2.6.28.8/kernel/power/po
{
register_sysrq_key('o', &sysrq_poweroff_op);
return 0;
-diff -urNp linux-2.6.28.8/kernel/printk.c linux-2.6.28.8/kernel/printk.c
---- linux-2.6.28.8/kernel/printk.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/kernel/printk.c 2009-02-21 09:37:50.000000000 -0500
-@@ -254,6 +254,11 @@ int do_syslog(int type, char __user *buf
+diff -urNp linux-2.6.29.5/kernel/printk.c linux-2.6.29.5/kernel/printk.c
+--- linux-2.6.29.5/kernel/printk.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/kernel/printk.c 2009-06-12 23:57:32.000000000 -0400
+@@ -253,6 +253,11 @@ int do_syslog(int type, char __user *buf
char c;
int error = 0;
@@ -32808,16 +36287,19 @@ diff -urNp linux-2.6.28.8/kernel/printk.c linux-2.6.28.8/kernel/printk.c
error = security_syslog(type);
if (error)
return error;
-diff -urNp linux-2.6.28.8/kernel/ptrace.c linux-2.6.28.8/kernel/ptrace.c
---- linux-2.6.28.8/kernel/ptrace.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/kernel/ptrace.c 2009-02-21 09:37:50.000000000 -0500
-@@ -132,12 +132,12 @@ int __ptrace_may_access(struct task_stru
- (current->uid != task->uid) ||
- (current->gid != task->egid) ||
- (current->gid != task->sgid) ||
-- (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
-+ (current->gid != task->gid)) && !capable_nolog(CAP_SYS_PTRACE))
+diff -urNp linux-2.6.29.5/kernel/ptrace.c linux-2.6.29.5/kernel/ptrace.c
+--- linux-2.6.29.5/kernel/ptrace.c 2009-06-12 23:55:00.000000000 -0400
++++ linux-2.6.29.5/kernel/ptrace.c 2009-06-12 23:57:32.000000000 -0400
+@@ -149,7 +149,7 @@ int __ptrace_may_access(struct task_stru
+ cred->gid != tcred->egid ||
+ cred->gid != tcred->sgid ||
+ cred->gid != tcred->gid) &&
+- !capable(CAP_SYS_PTRACE)) {
++ !capable_nolog(CAP_SYS_PTRACE)) {
+ rcu_read_unlock();
return -EPERM;
+ }
+@@ -157,7 +157,7 @@ int __ptrace_may_access(struct task_stru
smp_rmb();
if (task->mm)
dumpable = get_dumpable(task->mm);
@@ -32826,7 +36308,7 @@ diff -urNp linux-2.6.28.8/kernel/ptrace.c linux-2.6.28.8/kernel/ptrace.c
return -EPERM;
return security_ptrace_may_access(task, mode);
-@@ -193,7 +193,7 @@ repeat:
+@@ -221,7 +221,7 @@ repeat:
/* Go */
task->ptrace |= PT_PTRACED;
@@ -32835,7 +36317,7 @@ diff -urNp linux-2.6.28.8/kernel/ptrace.c linux-2.6.28.8/kernel/ptrace.c
task->ptrace |= PT_PTRACE_CAP;
__ptrace_link(task, current);
-@@ -582,6 +582,11 @@ SYSCALL_DEFINE4(ptrace, long, request, l
+@@ -612,6 +612,11 @@ SYSCALL_DEFINE4(ptrace, long, request, l
if (ret < 0)
goto out_put_task_struct;
@@ -32847,9 +36329,9 @@ diff -urNp linux-2.6.28.8/kernel/ptrace.c linux-2.6.28.8/kernel/ptrace.c
ret = arch_ptrace(child, request, addr, data);
if (ret < 0)
goto out_put_task_struct;
-diff -urNp linux-2.6.28.8/kernel/relay.c linux-2.6.28.8/kernel/relay.c
---- linux-2.6.28.8/kernel/relay.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/kernel/relay.c 2009-02-21 09:37:50.000000000 -0500
+diff -urNp linux-2.6.29.5/kernel/relay.c linux-2.6.29.5/kernel/relay.c
+--- linux-2.6.29.5/kernel/relay.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/kernel/relay.c 2009-06-12 23:57:32.000000000 -0400
@@ -1292,7 +1292,7 @@ static int subbuf_splice_actor(struct fi
return 0;
@@ -32859,9 +36341,9 @@ diff -urNp linux-2.6.28.8/kernel/relay.c linux-2.6.28.8/kernel/relay.c
return ret;
if (read_start + ret == nonpad_end)
-diff -urNp linux-2.6.28.8/kernel/resource.c linux-2.6.28.8/kernel/resource.c
---- linux-2.6.28.8/kernel/resource.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/kernel/resource.c 2009-02-21 09:37:50.000000000 -0500
+diff -urNp linux-2.6.29.5/kernel/resource.c linux-2.6.29.5/kernel/resource.c
+--- linux-2.6.29.5/kernel/resource.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/kernel/resource.c 2009-06-12 23:57:32.000000000 -0400
@@ -132,8 +132,18 @@ static const struct file_operations proc
static int __init ioresources_init(void)
@@ -32881,10 +36363,19 @@ diff -urNp linux-2.6.28.8/kernel/resource.c linux-2.6.28.8/kernel/resource.c
return 0;
}
__initcall(ioresources_init);
-diff -urNp linux-2.6.28.8/kernel/sched.c linux-2.6.28.8/kernel/sched.c
---- linux-2.6.28.8/kernel/sched.c 2009-02-07 16:10:45.000000000 -0500
-+++ linux-2.6.28.8/kernel/sched.c 2009-02-21 09:37:50.000000000 -0500
-@@ -5045,7 +5045,8 @@ SYSCALL_DEFINE1(nice, int, increment)
+diff -urNp linux-2.6.29.5/kernel/sched.c linux-2.6.29.5/kernel/sched.c
+--- linux-2.6.29.5/kernel/sched.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/kernel/sched.c 2009-06-12 23:57:32.000000000 -0400
+@@ -5175,6 +5175,8 @@ int can_nice(const struct task_struct *p
+ /* convert nice value [19,-20] to rlimit style value [1,40] */
+ int nice_rlim = 20 - nice;
+
++ gr_learn_resource(p, RLIMIT_NICE, nice_rlim, 1);
++
+ return (nice_rlim <= p->signal->rlim[RLIMIT_NICE].rlim_cur ||
+ capable(CAP_SYS_NICE));
+ }
+@@ -5208,7 +5210,8 @@ SYSCALL_DEFINE1(nice, int, increment)
if (nice > 19)
nice = 19;
@@ -32894,7 +36385,16 @@ diff -urNp linux-2.6.28.8/kernel/sched.c linux-2.6.28.8/kernel/sched.c
return -EPERM;
retval = security_task_setnice(current, nice);
-@@ -6310,7 +6311,7 @@ static struct ctl_table sd_ctl_dir[] = {
+@@ -5350,6 +5353,8 @@ recheck:
+ if (rt_policy(policy)) {
+ unsigned long rlim_rtprio;
+
++ gr_learn_resource(p, RLIMIT_RTPRIO, param->sched_priority, 1);
++
+ if (!lock_task_sighand(p, &flags))
+ return -ESRCH;
+ rlim_rtprio = p->signal->rlim[RLIMIT_RTPRIO].rlim_cur;
+@@ -6497,7 +6502,7 @@ static struct ctl_table sd_ctl_dir[] = {
.procname = "sched_domain",
.mode = 0555,
},
@@ -32903,7 +36403,7 @@ diff -urNp linux-2.6.28.8/kernel/sched.c linux-2.6.28.8/kernel/sched.c
};
static struct ctl_table sd_ctl_root[] = {
-@@ -6320,7 +6321,7 @@ static struct ctl_table sd_ctl_root[] =
+@@ -6507,7 +6512,7 @@ static struct ctl_table sd_ctl_root[] =
.mode = 0555,
.child = sd_ctl_dir,
},
@@ -32912,10 +36412,20 @@ diff -urNp linux-2.6.28.8/kernel/sched.c linux-2.6.28.8/kernel/sched.c
};
static struct ctl_table *sd_alloc_ctl_entry(int n)
-diff -urNp linux-2.6.28.8/kernel/signal.c linux-2.6.28.8/kernel/signal.c
---- linux-2.6.28.8/kernel/signal.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/kernel/signal.c 2009-03-07 14:17:22.000000000 -0500
-@@ -596,6 +596,9 @@ static int check_kill_permission(int sig
+diff -urNp linux-2.6.29.5/kernel/signal.c linux-2.6.29.5/kernel/signal.c
+--- linux-2.6.29.5/kernel/signal.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/kernel/signal.c 2009-06-12 23:57:32.000000000 -0400
+@@ -198,6 +198,9 @@ static struct sigqueue *__sigqueue_alloc
+ */
+ user = get_uid(__task_cred(t)->user);
+ atomic_inc(&user->sigpending);
++
++ if (!override_rlimit)
++ gr_learn_resource(t, RLIMIT_SIGPENDING, atomic_read(&user->sigpending), 1);
+ if (override_rlimit ||
+ atomic_read(&user->sigpending) <=
+ t->signal->rlim[RLIMIT_SIGPENDING].rlim_cur)
+@@ -611,6 +614,9 @@ static int check_kill_permission(int sig
}
}
@@ -32925,7 +36435,7 @@ diff -urNp linux-2.6.28.8/kernel/signal.c linux-2.6.28.8/kernel/signal.c
return security_task_kill(t, info, sig, 0);
}
-@@ -887,8 +890,8 @@ static void print_fatal_signal(struct pt
+@@ -903,8 +909,8 @@ static void print_fatal_signal(struct pt
for (i = 0; i < 16; i++) {
unsigned char insn;
@@ -32936,7 +36446,7 @@ diff -urNp linux-2.6.28.8/kernel/signal.c linux-2.6.28.8/kernel/signal.c
}
}
#endif
-@@ -911,7 +914,7 @@ __group_send_sig_info(int sig, struct si
+@@ -929,7 +935,7 @@ __group_send_sig_info(int sig, struct si
return send_signal(sig, info, p, 1);
}
@@ -32945,7 +36455,7 @@ diff -urNp linux-2.6.28.8/kernel/signal.c linux-2.6.28.8/kernel/signal.c
specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t)
{
return send_signal(sig, info, t, 0);
-@@ -951,6 +954,9 @@ force_sig_info(int sig, struct siginfo *
+@@ -969,6 +975,9 @@ force_sig_info(int sig, struct siginfo *
ret = specific_send_sig_info(sig, info, t);
spin_unlock_irqrestore(&t->sighand->siglock, flags);
@@ -32955,7 +36465,7 @@ diff -urNp linux-2.6.28.8/kernel/signal.c linux-2.6.28.8/kernel/signal.c
return ret;
}
-@@ -1021,6 +1027,8 @@ int group_send_sig_info(int sig, struct
+@@ -1043,6 +1052,8 @@ int group_send_sig_info(int sig, struct
ret = __group_send_sig_info(sig, info, p);
unlock_task_sighand(p, &flags);
}
@@ -32964,10 +36474,10 @@ diff -urNp linux-2.6.28.8/kernel/signal.c linux-2.6.28.8/kernel/signal.c
}
return ret;
-diff -urNp linux-2.6.28.8/kernel/softirq.c linux-2.6.28.8/kernel/softirq.c
---- linux-2.6.28.8/kernel/softirq.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/kernel/softirq.c 2009-02-21 09:37:50.000000000 -0500
-@@ -463,9 +463,9 @@ void tasklet_kill(struct tasklet_struct
+diff -urNp linux-2.6.29.5/kernel/softirq.c linux-2.6.29.5/kernel/softirq.c
+--- linux-2.6.29.5/kernel/softirq.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/kernel/softirq.c 2009-06-12 23:57:32.000000000 -0400
+@@ -450,9 +450,9 @@ void tasklet_kill(struct tasklet_struct
printk("Attempt to kill tasklet from interrupt\n");
while (test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) {
@@ -32979,10 +36489,10 @@ diff -urNp linux-2.6.28.8/kernel/softirq.c linux-2.6.28.8/kernel/softirq.c
}
tasklet_unlock_wait(t);
clear_bit(TASKLET_STATE_SCHED, &t->state);
-diff -urNp linux-2.6.28.8/kernel/sys.c linux-2.6.28.8/kernel/sys.c
---- linux-2.6.28.8/kernel/sys.c 2009-02-07 16:10:45.000000000 -0500
-+++ linux-2.6.28.8/kernel/sys.c 2009-02-21 09:37:50.000000000 -0500
-@@ -125,6 +125,12 @@ static int set_one_prio(struct task_stru
+diff -urNp linux-2.6.29.5/kernel/sys.c linux-2.6.29.5/kernel/sys.c
+--- linux-2.6.29.5/kernel/sys.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/kernel/sys.c 2009-06-12 23:57:32.000000000 -0400
+@@ -131,6 +131,12 @@ static int set_one_prio(struct task_stru
error = -EACCES;
goto out;
}
@@ -32995,162 +36505,99 @@ diff -urNp linux-2.6.28.8/kernel/sys.c linux-2.6.28.8/kernel/sys.c
no_nice = security_task_setnice(p, niceval);
if (no_nice) {
error = no_nice;
-@@ -181,10 +187,10 @@ SYSCALL_DEFINE3(setpriority, int, which,
- if ((who != current->uid) && !(user = find_user(who)))
- goto out_unlock; /* No processes for this user */
-
-- do_each_thread(g, p)
-+ do_each_thread(g, p) {
- if (p->uid == who)
- error = set_one_prio(p, niceval, error);
-- while_each_thread(g, p);
-+ } while_each_thread(g, p);
- if (who != current->uid)
- free_uid(user); /* For find_user() */
- break;
-@@ -243,13 +249,13 @@ SYSCALL_DEFINE2(getpriority, int, which,
- if ((who != current->uid) && !(user = find_user(who)))
- goto out_unlock; /* No processes for this user */
-
-- do_each_thread(g, p)
-+ do_each_thread(g, p) {
- if (p->uid == who) {
- niceval = 20 - task_nice(p);
- if (niceval > retval)
- retval = niceval;
- }
-- while_each_thread(g, p);
-+ } while_each_thread(g, p);
- if (who != current->uid)
- free_uid(user); /* for find_user() */
- break;
-@@ -500,6 +506,10 @@ SYSCALL_DEFINE2(setregid, gid_t, rgid, g
+@@ -503,6 +509,7 @@ SYSCALL_DEFINE2(setregid, gid_t, rgid, g
else
- return -EPERM;
+ goto error;
}
+
-+ if (gr_check_group_change(new_rgid, new_egid, -1))
-+ return -EPERM;
+ if (egid != (gid_t) -1) {
+ if (old->gid == egid ||
+ old->egid == egid ||
+@@ -513,6 +520,9 @@ SYSCALL_DEFINE2(setregid, gid_t, rgid, g
+ goto error;
+ }
+
++ if (gr_check_group_change(new->gid, new->egid, -1))
++ goto error;
+
- if (new_egid != old_egid) {
- set_dumpable(current->mm, suid_dumpable);
- smp_wmb();
-@@ -507,6 +517,9 @@ SYSCALL_DEFINE2(setregid, gid_t, rgid, g
if (rgid != (gid_t) -1 ||
- (egid != (gid_t) -1 && egid != old_rgid))
- current->sgid = new_egid;
-+
-+ gr_set_role_label(current, current->uid, new_rgid);
-+
- current->fsgid = new_egid;
- current->egid = new_egid;
- current->gid = new_rgid;
-@@ -529,11 +542,17 @@ SYSCALL_DEFINE1(setgid, gid_t, gid)
- if (retval)
- return retval;
+ (egid != (gid_t) -1 && egid != old->gid))
+ new->sgid = new->egid;
+@@ -546,6 +556,10 @@ SYSCALL_DEFINE1(setgid, gid_t, gid)
+ goto error;
-+ if (gr_check_group_change(gid, gid, gid))
-+ return -EPERM;
-+
- if (capable(CAP_SETGID)) {
- if (old_egid != gid) {
- set_dumpable(current->mm, suid_dumpable);
- smp_wmb();
- }
-+
-+ gr_set_role_label(current, current->uid, gid);
-+
- current->gid = current->egid = current->sgid = current->fsgid = gid;
- } else if ((gid == current->gid) || (gid == current->sgid)) {
- if (old_egid != gid) {
-@@ -571,6 +590,9 @@ static int set_user(uid_t new_ruid, int
- set_dumpable(current->mm, suid_dumpable);
- smp_wmb();
- }
+ retval = -EPERM;
+
-+ gr_set_role_label(current, new_ruid, current->gid);
++ if (gr_check_group_change(gid, gid, gid))
++ goto error;
+
- current->uid = new_ruid;
- return 0;
- }
-@@ -620,6 +642,9 @@ SYSCALL_DEFINE2(setreuid, uid_t, ruid, u
- return -EPERM;
+ if (capable(CAP_SETGID))
+ new->gid = new->egid = new->sgid = new->fsgid = gid;
+ else if (gid == old->gid || gid == old->sgid)
+@@ -636,6 +650,9 @@ SYSCALL_DEFINE2(setreuid, uid_t, ruid, u
+ goto error;
}
-+ if (gr_check_user_change(new_ruid, new_euid, -1))
-+ return -EPERM;
++ if (gr_check_user_change(new->uid, new->euid, -1))
++ goto error;
+
- if (new_ruid != old_ruid && set_user(new_ruid, new_euid != old_euid) < 0)
- return -EAGAIN;
+ if (new->uid != old->uid) {
+ retval = set_user(new);
+ if (retval < 0)
+@@ -684,6 +701,12 @@ SYSCALL_DEFINE1(setuid, uid_t, uid)
+ goto error;
-@@ -666,6 +691,12 @@ SYSCALL_DEFINE1(setuid, uid_t, uid)
- old_suid = current->suid;
- new_suid = old_suid;
-
-+ if (gr_check_crash_uid(uid))
-+ return -EPERM;
+ retval = -EPERM;
+
++ if (gr_check_crash_uid(uid))
++ goto error;
+ if (gr_check_user_change(uid, uid, uid))
-+ return -EPERM;
++ goto error;
+
if (capable(CAP_SETUID)) {
- if (uid != old_ruid && set_user(uid, old_euid != uid) < 0)
- return -EAGAIN;
-@@ -713,6 +744,10 @@ SYSCALL_DEFINE3(setresuid, uid_t, ruid,
- (suid != current->euid) && (suid != current->suid))
- return -EPERM;
+ new->suid = new->uid = uid;
+ if (uid != old->uid) {
+@@ -741,6 +764,9 @@ SYSCALL_DEFINE3(setresuid, uid_t, ruid,
+ goto error;
}
-+
+
+ if (gr_check_user_change(ruid, euid, -1))
-+ return -EPERM;
++ goto error;
+
if (ruid != (uid_t) -1) {
- if (ruid != current->uid && set_user(ruid, euid != current->euid) < 0)
- return -EAGAIN;
-@@ -767,6 +802,10 @@ SYSCALL_DEFINE3(setresgid, gid_t, rgid,
- (sgid != current->egid) && (sgid != current->sgid))
- return -EPERM;
+ new->uid = ruid;
+ if (ruid != old->uid) {
+@@ -809,6 +835,9 @@ SYSCALL_DEFINE3(setresgid, gid_t, rgid,
+ goto error;
}
-+
+
+ if (gr_check_group_change(rgid, egid, -1))
-+ return -EPERM;
++ goto error;
+
- if (egid != (gid_t) -1) {
- if (egid != current->egid) {
- set_dumpable(current->mm, suid_dumpable);
-@@ -775,8 +814,10 @@ SYSCALL_DEFINE3(setresgid, gid_t, rgid,
- current->egid = egid;
- }
- current->fsgid = current->egid;
-- if (rgid != (gid_t) -1)
-+ if (rgid != (gid_t) -1) {
-+ gr_set_role_label(current, current->uid, rgid);
- current->gid = rgid;
-+ }
- if (sgid != (gid_t) -1)
- current->sgid = sgid;
-
-@@ -811,6 +852,9 @@ SYSCALL_DEFINE1(setfsuid, uid_t, uid)
- if (security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS))
- return old_fsuid;
+ if (rgid != (gid_t) -1)
+ new->gid = rgid;
+ if (egid != (gid_t) -1)
+@@ -858,6 +887,9 @@ SYSCALL_DEFINE1(setfsuid, uid_t, uid)
+ if (security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS) < 0)
+ goto error;
+ if (gr_check_user_change(-1, -1, uid))
-+ return old_fsuid;
++ goto error;
+
- if (uid == current->uid || uid == current->euid ||
- uid == current->suid || uid == current->fsuid ||
+ if (uid == old->uid || uid == old->euid ||
+ uid == old->suid || uid == old->fsuid ||
capable(CAP_SETUID)) {
-@@ -843,6 +887,9 @@ SYSCALL_DEFINE1(setfsgid, gid_t, gid)
- if (gid == current->gid || gid == current->egid ||
- gid == current->sgid || gid == current->fsgid ||
+@@ -898,6 +930,9 @@ SYSCALL_DEFINE1(setfsgid, gid_t, gid)
+ if (gid == old->gid || gid == old->egid ||
+ gid == old->sgid || gid == old->fsgid ||
capable(CAP_SETGID)) {
+ if (gr_check_group_change(-1, -1, gid))
-+ return old_fsgid;
++ goto error;
+
if (gid != old_fsgid) {
- set_dumpable(current->mm, suid_dumpable);
- smp_wmb();
-@@ -914,7 +961,10 @@ SYSCALL_DEFINE2(setpgid, pid_t, pid, pid
+ new->fsgid = gid;
+ goto change_okay;
+@@ -974,7 +1009,10 @@ SYSCALL_DEFINE2(setpgid, pid_t, pid, pid
write_lock_irq(&tasklist_lock);
err = -ESRCH;
@@ -33162,8 +36609,8 @@ diff -urNp linux-2.6.28.8/kernel/sys.c linux-2.6.28.8/kernel/sys.c
if (!p)
goto out;
-@@ -1640,7 +1690,7 @@ SYSCALL_DEFINE5(prctl, int, option, unsi
- error = get_dumpable(current->mm);
+@@ -1732,7 +1770,7 @@ SYSCALL_DEFINE5(prctl, int, option, unsi
+ error = get_dumpable(me->mm);
break;
case PR_SET_DUMPABLE:
- if (arg2 < 0 || arg2 > 1) {
@@ -33171,9 +36618,9 @@ diff -urNp linux-2.6.28.8/kernel/sys.c linux-2.6.28.8/kernel/sys.c
error = -EINVAL;
break;
}
-diff -urNp linux-2.6.28.8/kernel/sysctl.c linux-2.6.28.8/kernel/sysctl.c
---- linux-2.6.28.8/kernel/sysctl.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/kernel/sysctl.c 2009-03-07 04:29:14.000000000 -0500
+diff -urNp linux-2.6.29.5/kernel/sysctl.c linux-2.6.29.5/kernel/sysctl.c
+--- linux-2.6.29.5/kernel/sysctl.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/kernel/sysctl.c 2009-06-12 23:57:32.000000000 -0400
@@ -61,6 +61,13 @@
static int deprecated_sysctl_warning(struct __sysctl_args *args);
@@ -33188,7 +36635,7 @@ diff -urNp linux-2.6.28.8/kernel/sysctl.c linux-2.6.28.8/kernel/sysctl.c
/* External variables not in a header file. */
extern int C_A_D;
-@@ -152,6 +159,7 @@ static int proc_do_cad_pid(struct ctl_ta
+@@ -155,6 +162,7 @@ static int proc_do_cad_pid(struct ctl_ta
static int proc_taint(struct ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos);
#endif
@@ -33196,7 +36643,7 @@ diff -urNp linux-2.6.28.8/kernel/sysctl.c linux-2.6.28.8/kernel/sysctl.c
static struct ctl_table root_table[];
static struct ctl_table_root sysctl_table_root;
-@@ -184,6 +192,21 @@ extern struct ctl_table epoll_table[];
+@@ -187,6 +195,21 @@ extern struct ctl_table epoll_table[];
int sysctl_legacy_va_layout;
#endif
@@ -33218,7 +36665,7 @@ diff -urNp linux-2.6.28.8/kernel/sysctl.c linux-2.6.28.8/kernel/sysctl.c
extern int prove_locking;
extern int lock_stat;
-@@ -856,6 +879,25 @@ static struct ctl_table kern_table[] = {
+@@ -897,6 +920,25 @@ static struct ctl_table kern_table[] = {
.proc_handler = &scan_unevictable_handler,
},
#endif
@@ -33244,7 +36691,7 @@ diff -urNp linux-2.6.28.8/kernel/sysctl.c linux-2.6.28.8/kernel/sysctl.c
/*
* NOTE: do not add new entries to this table unless you have read
* Documentation/sysctl/ctl_unnumbered.txt
-@@ -1562,6 +1604,8 @@ static int do_sysctl_strategy(struct ctl
+@@ -1634,6 +1676,8 @@ static int do_sysctl_strategy(struct ctl
return 0;
}
@@ -33253,7 +36700,7 @@ diff -urNp linux-2.6.28.8/kernel/sysctl.c linux-2.6.28.8/kernel/sysctl.c
static int parse_table(int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen,
-@@ -1580,7 +1624,7 @@ repeat:
+@@ -1652,7 +1696,7 @@ repeat:
if (n == table->ctl_name) {
int error;
if (table->child) {
@@ -33262,7 +36709,7 @@ diff -urNp linux-2.6.28.8/kernel/sysctl.c linux-2.6.28.8/kernel/sysctl.c
return -EPERM;
name++;
nlen--;
-@@ -1665,6 +1709,33 @@ int sysctl_perm(struct ctl_table_root *r
+@@ -1737,6 +1781,33 @@ int sysctl_perm(struct ctl_table_root *r
int error;
int mode;
@@ -33296,22 +36743,22 @@ diff -urNp linux-2.6.28.8/kernel/sysctl.c linux-2.6.28.8/kernel/sysctl.c
error = security_sysctl(table, op & (MAY_READ | MAY_WRITE | MAY_EXEC));
if (error)
return error;
-diff -urNp linux-2.6.28.8/kernel/time/tick-broadcast.c linux-2.6.28.8/kernel/time/tick-broadcast.c
---- linux-2.6.28.8/kernel/time/tick-broadcast.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/kernel/time/tick-broadcast.c 2009-02-21 09:37:50.000000000 -0500
-@@ -114,7 +114,7 @@ int tick_device_uses_broadcast(struct cl
+diff -urNp linux-2.6.29.5/kernel/time/tick-broadcast.c linux-2.6.29.5/kernel/time/tick-broadcast.c
+--- linux-2.6.29.5/kernel/time/tick-broadcast.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/kernel/time/tick-broadcast.c 2009-06-12 23:57:32.000000000 -0400
+@@ -116,7 +116,7 @@ int tick_device_uses_broadcast(struct cl
* then clear the broadcast bit.
*/
if (!(dev->features & CLOCK_EVT_FEAT_C3STOP)) {
- int cpu = smp_processor_id();
+ cpu = smp_processor_id();
- cpu_clear(cpu, tick_broadcast_mask);
+ cpumask_clear_cpu(cpu, tick_get_broadcast_mask());
tick_broadcast_clear_oneshot(cpu);
-diff -urNp linux-2.6.28.8/kernel/time.c linux-2.6.28.8/kernel/time.c
---- linux-2.6.28.8/kernel/time.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/kernel/time.c 2009-02-21 09:37:50.000000000 -0500
-@@ -92,6 +92,9 @@ SYSCALL_DEFINE1(stime, time_t __user *,
+diff -urNp linux-2.6.29.5/kernel/time.c linux-2.6.29.5/kernel/time.c
+--- linux-2.6.29.5/kernel/time.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/kernel/time.c 2009-06-12 23:57:32.000000000 -0400
+@@ -94,6 +94,9 @@ SYSCALL_DEFINE1(stime, time_t __user *,
return err;
do_settimeofday(&tv);
@@ -33321,7 +36768,7 @@ diff -urNp linux-2.6.28.8/kernel/time.c linux-2.6.28.8/kernel/time.c
return 0;
}
-@@ -200,6 +203,8 @@ SYSCALL_DEFINE2(settimeofday, struct tim
+@@ -202,6 +205,8 @@ SYSCALL_DEFINE2(settimeofday, struct tim
return -EFAULT;
}
@@ -33330,7 +36777,7 @@ diff -urNp linux-2.6.28.8/kernel/time.c linux-2.6.28.8/kernel/time.c
return do_sys_settimeofday(tv ? &new_ts : NULL, tz ? &new_tz : NULL);
}
-@@ -238,7 +243,7 @@ EXPORT_SYMBOL(current_fs_time);
+@@ -240,7 +245,7 @@ EXPORT_SYMBOL(current_fs_time);
* Avoid unnecessary multiplications/divisions in the
* two most common HZ cases:
*/
@@ -33339,7 +36786,7 @@ diff -urNp linux-2.6.28.8/kernel/time.c linux-2.6.28.8/kernel/time.c
{
#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ)
return (MSEC_PER_SEC / HZ) * j;
-@@ -254,7 +259,7 @@ unsigned int inline jiffies_to_msecs(con
+@@ -256,7 +261,7 @@ unsigned int inline jiffies_to_msecs(con
}
EXPORT_SYMBOL(jiffies_to_msecs);
@@ -33348,9 +36795,21 @@ diff -urNp linux-2.6.28.8/kernel/time.c linux-2.6.28.8/kernel/time.c
{
#if HZ <= USEC_PER_SEC && !(USEC_PER_SEC % HZ)
return (USEC_PER_SEC / HZ) * j;
-diff -urNp linux-2.6.28.8/kernel/utsname_sysctl.c linux-2.6.28.8/kernel/utsname_sysctl.c
---- linux-2.6.28.8/kernel/utsname_sysctl.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/kernel/utsname_sysctl.c 2009-02-21 09:37:50.000000000 -0500
+diff -urNp linux-2.6.29.5/kernel/trace/trace.c linux-2.6.29.5/kernel/trace/trace.c
+--- linux-2.6.29.5/kernel/trace/trace.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/kernel/trace/trace.c 2009-06-12 23:57:32.000000000 -0400
+@@ -442,7 +442,7 @@ trace_seq_path(struct trace_seq *s, stru
+ return 0;
+ p = d_path(path, s->buffer + s->len, PAGE_SIZE - s->len);
+ if (!IS_ERR(p)) {
+- p = mangle_path(s->buffer + s->len, p, "\n");
++ p = mangle_path(s->buffer + s->len, p, "\n\\");
+ if (p) {
+ s->len = p - s->buffer;
+ return 1;
+diff -urNp linux-2.6.29.5/kernel/utsname_sysctl.c linux-2.6.29.5/kernel/utsname_sysctl.c
+--- linux-2.6.29.5/kernel/utsname_sysctl.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/kernel/utsname_sysctl.c 2009-06-12 23:57:32.000000000 -0400
@@ -123,7 +123,7 @@ static struct ctl_table uts_kern_table[]
.proc_handler = proc_do_uts_string,
.strategy = sysctl_uts_string,
@@ -33369,27 +36828,63 @@ diff -urNp linux-2.6.28.8/kernel/utsname_sysctl.c linux-2.6.28.8/kernel/utsname_
};
static int __init utsname_sysctl_init(void)
-diff -urNp linux-2.6.28.8/lib/radix-tree.c linux-2.6.28.8/lib/radix-tree.c
---- linux-2.6.28.8/lib/radix-tree.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/lib/radix-tree.c 2009-02-21 09:37:50.000000000 -0500
+diff -urNp linux-2.6.29.5/lib/Kconfig.debug linux-2.6.29.5/lib/Kconfig.debug
+--- linux-2.6.29.5/lib/Kconfig.debug 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/lib/Kconfig.debug 2009-06-12 23:57:32.000000000 -0400
+@@ -783,7 +783,7 @@ config LATENCYTOP
+ select STACKTRACE
+ select SCHEDSTATS
+ select SCHED_DEBUG
+- depends on HAVE_LATENCYTOP_SUPPORT
++ depends on HAVE_LATENCYTOP_SUPPORT && !GRKERNSEC_HIDESYM
+ help
+ Enable this option if you want to use the LatencyTOP tool
+ to find out which userspace is blocking on what kernel operations.
+diff -urNp linux-2.6.29.5/lib/parser.c linux-2.6.29.5/lib/parser.c
+--- linux-2.6.29.5/lib/parser.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/lib/parser.c 2009-06-12 23:57:32.000000000 -0400
+@@ -126,7 +126,7 @@ static int match_number(substring_t *s,
+ char *buf;
+ int ret;
+
+- buf = kmalloc(s->to - s->from + 1, GFP_KERNEL);
++ buf = kmalloc((s->to - s->from) + 1, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+ memcpy(buf, s->from, s->to - s->from);
+diff -urNp linux-2.6.29.5/lib/radix-tree.c linux-2.6.29.5/lib/radix-tree.c
+--- linux-2.6.29.5/lib/radix-tree.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/lib/radix-tree.c 2009-06-12 23:57:32.000000000 -0400
@@ -81,7 +81,7 @@ struct radix_tree_preload {
int nr;
struct radix_tree_node *nodes[RADIX_TREE_MAX_PATH];
};
--DEFINE_PER_CPU(struct radix_tree_preload, radix_tree_preloads) = { 0, };
-+DEFINE_PER_CPU(struct radix_tree_preload, radix_tree_preloads);
+-static DEFINE_PER_CPU(struct radix_tree_preload, radix_tree_preloads) = { 0, };
++static DEFINE_PER_CPU(struct radix_tree_preload, radix_tree_preloads);
static inline gfp_t root_gfp_mask(struct radix_tree_root *root)
{
-diff -urNp linux-2.6.28.8/localversion-grsec linux-2.6.28.8/localversion-grsec
---- linux-2.6.28.8/localversion-grsec 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/localversion-grsec 2009-02-21 09:37:50.000000000 -0500
+diff -urNp linux-2.6.29.5/lib/random32.c linux-2.6.29.5/lib/random32.c
+--- linux-2.6.29.5/lib/random32.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/lib/random32.c 2009-06-12 23:57:32.000000000 -0400
+@@ -61,7 +61,7 @@ static u32 __random32(struct rnd_state *
+ */
+ static inline u32 __seed(u32 x, u32 m)
+ {
+- return (x < m) ? x + m : x;
++ return (x <= m) ? x + m + 1 : x;
+ }
+
+ /**
+diff -urNp linux-2.6.29.5/localversion-grsec linux-2.6.29.5/localversion-grsec
+--- linux-2.6.29.5/localversion-grsec 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.29.5/localversion-grsec 2009-06-12 23:57:32.000000000 -0400
@@ -0,0 +1 @@
+-grsec
-diff -urNp linux-2.6.28.8/Makefile linux-2.6.28.8/Makefile
---- linux-2.6.28.8/Makefile 2009-03-07 10:24:49.000000000 -0500
-+++ linux-2.6.28.8/Makefile 2009-03-07 10:29:51.000000000 -0500
-@@ -221,7 +221,7 @@ CONFIG_SHELL := $(shell if [ -x "$$BASH"
+diff -urNp linux-2.6.29.5/Makefile linux-2.6.29.5/Makefile
+--- linux-2.6.29.5/Makefile 2009-06-12 23:55:00.000000000 -0400
++++ linux-2.6.29.5/Makefile 2009-06-12 23:57:31.000000000 -0400
+@@ -226,7 +226,7 @@ CONFIG_SHELL := $(shell if [ -x "$$BASH"
HOSTCC = gcc
HOSTCXX = g++
@@ -33398,7 +36893,7 @@ diff -urNp linux-2.6.28.8/Makefile linux-2.6.28.8/Makefile
HOSTCXXFLAGS = -O2
# Decide whether to build built-in, modular, or both.
-@@ -619,7 +619,7 @@ export mod_strip_cmd
+@@ -636,7 +636,7 @@ export mod_strip_cmd
ifeq ($(KBUILD_EXTMOD),)
@@ -33407,10 +36902,10 @@ diff -urNp linux-2.6.28.8/Makefile linux-2.6.28.8/Makefile
vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
$(core-y) $(core-m) $(drivers-y) $(drivers-m) \
-diff -urNp linux-2.6.28.8/mm/filemap.c linux-2.6.28.8/mm/filemap.c
---- linux-2.6.28.8/mm/filemap.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/mm/filemap.c 2009-02-21 09:37:50.000000000 -0500
-@@ -1609,7 +1609,7 @@ int generic_file_mmap(struct file * file
+diff -urNp linux-2.6.29.5/mm/filemap.c linux-2.6.29.5/mm/filemap.c
+--- linux-2.6.29.5/mm/filemap.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/mm/filemap.c 2009-06-12 23:57:32.000000000 -0400
+@@ -1615,7 +1615,7 @@ int generic_file_mmap(struct file * file
struct address_space *mapping = file->f_mapping;
if (!mapping->a_ops->readpage)
@@ -33419,7 +36914,7 @@ diff -urNp linux-2.6.28.8/mm/filemap.c linux-2.6.28.8/mm/filemap.c
file_accessed(file);
vma->vm_ops = &generic_file_vm_ops;
vma->vm_flags |= VM_CAN_NONLINEAR;
-@@ -1970,6 +1970,7 @@ inline int generic_write_checks(struct f
+@@ -1976,6 +1976,7 @@ inline int generic_write_checks(struct f
*pos = i_size_read(inode);
if (limit != RLIM_INFINITY) {
@@ -33427,27 +36922,25 @@ diff -urNp linux-2.6.28.8/mm/filemap.c linux-2.6.28.8/mm/filemap.c
if (*pos >= limit) {
send_sig(SIGXFSZ, current, 0);
return -EFBIG;
-diff -urNp linux-2.6.28.8/mm/fremap.c linux-2.6.28.8/mm/fremap.c
---- linux-2.6.28.8/mm/fremap.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/mm/fremap.c 2009-02-21 09:37:50.000000000 -0500
-@@ -153,6 +153,13 @@ SYSCALL_DEFINE5(remap_file_pages, unsign
+diff -urNp linux-2.6.29.5/mm/fremap.c linux-2.6.29.5/mm/fremap.c
+--- linux-2.6.29.5/mm/fremap.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/mm/fremap.c 2009-06-12 23:57:32.000000000 -0400
+@@ -153,6 +153,11 @@ SYSCALL_DEFINE5(remap_file_pages, unsign
retry:
vma = find_vma(mm, start);
+#ifdef CONFIG_PAX_SEGMEXEC
-+ if (vma && (mm->pax_flags & MF_PAX_SEGMEXEC) && (vma->vm_flags & VM_MAYEXEC)) {
-+ up_read(&mm->mmap_sem);
-+ return err;
-+ }
++ if (vma && (mm->pax_flags & MF_PAX_SEGMEXEC) && (vma->vm_flags & VM_MAYEXEC))
++ goto out;
+#endif
+
/*
* Make sure the vma is shared, that it supports prefaulting,
* and that the remapped range is valid and fully within
-diff -urNp linux-2.6.28.8/mm/hugetlb.c linux-2.6.28.8/mm/hugetlb.c
---- linux-2.6.28.8/mm/hugetlb.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/mm/hugetlb.c 2009-02-21 09:37:50.000000000 -0500
-@@ -1832,6 +1832,26 @@ static int unmap_ref_private(struct mm_s
+diff -urNp linux-2.6.29.5/mm/hugetlb.c linux-2.6.29.5/mm/hugetlb.c
+--- linux-2.6.29.5/mm/hugetlb.c 2009-06-12 23:55:00.000000000 -0400
++++ linux-2.6.29.5/mm/hugetlb.c 2009-06-12 23:57:32.000000000 -0400
+@@ -1864,6 +1864,26 @@ static int unmap_ref_private(struct mm_s
return 1;
}
@@ -33474,7 +36967,7 @@ diff -urNp linux-2.6.28.8/mm/hugetlb.c linux-2.6.28.8/mm/hugetlb.c
static int hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma,
unsigned long address, pte_t *ptep, pte_t pte,
struct page *pagecache_page)
-@@ -1903,6 +1923,11 @@ retry_avoidcopy:
+@@ -1935,6 +1955,11 @@ retry_avoidcopy:
huge_ptep_clear_flush(vma, address, ptep);
set_huge_pte_at(mm, address, ptep,
make_huge_pte(vma, new_page, 1));
@@ -33486,7 +36979,7 @@ diff -urNp linux-2.6.28.8/mm/hugetlb.c linux-2.6.28.8/mm/hugetlb.c
/* Make the old page be freed below */
new_page = old_page;
}
-@@ -2012,6 +2037,10 @@ retry:
+@@ -2044,6 +2069,10 @@ retry:
&& (vma->vm_flags & VM_SHARED)));
set_huge_pte_at(mm, address, ptep, new_pte);
@@ -33497,7 +36990,7 @@ diff -urNp linux-2.6.28.8/mm/hugetlb.c linux-2.6.28.8/mm/hugetlb.c
if (write_access && !(vma->vm_flags & VM_SHARED)) {
/* Optimization, do the COW without a second fault */
ret = hugetlb_cow(mm, vma, address, ptep, new_pte, page);
-@@ -2040,6 +2069,28 @@ int hugetlb_fault(struct mm_struct *mm,
+@@ -2072,6 +2101,28 @@ int hugetlb_fault(struct mm_struct *mm,
static DEFINE_MUTEX(hugetlb_instantiation_mutex);
struct hstate *h = hstate_vma(vma);
@@ -33526,9 +37019,9 @@ diff -urNp linux-2.6.28.8/mm/hugetlb.c linux-2.6.28.8/mm/hugetlb.c
ptep = huge_pte_alloc(mm, address, huge_page_size(h));
if (!ptep)
return VM_FAULT_OOM;
-diff -urNp linux-2.6.28.8/mm/madvise.c linux-2.6.28.8/mm/madvise.c
---- linux-2.6.28.8/mm/madvise.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/mm/madvise.c 2009-02-21 09:37:50.000000000 -0500
+diff -urNp linux-2.6.29.5/mm/madvise.c linux-2.6.29.5/mm/madvise.c
+--- linux-2.6.29.5/mm/madvise.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/mm/madvise.c 2009-06-12 23:57:32.000000000 -0400
@@ -43,6 +43,10 @@ static long madvise_behavior(struct vm_a
pgoff_t pgoff;
int new_flags = vma->vm_flags;
@@ -33554,7 +37047,7 @@ diff -urNp linux-2.6.28.8/mm/madvise.c linux-2.6.28.8/mm/madvise.c
vma->vm_flags = new_flags;
out:
-@@ -236,6 +247,17 @@ madvise_vma(struct vm_area_struct *vma,
+@@ -244,6 +255,17 @@ madvise_vma(struct vm_area_struct *vma,
case MADV_DONTNEED:
error = madvise_dontneed(vma, prev, start, end);
@@ -33572,7 +37065,7 @@ diff -urNp linux-2.6.28.8/mm/madvise.c linux-2.6.28.8/mm/madvise.c
break;
default:
-@@ -308,6 +330,16 @@ SYSCALL_DEFINE3(madvise, unsigned long,
+@@ -316,6 +338,16 @@ SYSCALL_DEFINE3(madvise, unsigned long,
if (end < start)
goto out;
@@ -33589,9 +37082,9 @@ diff -urNp linux-2.6.28.8/mm/madvise.c linux-2.6.28.8/mm/madvise.c
error = 0;
if (end == start)
goto out;
-diff -urNp linux-2.6.28.8/mm/memory.c linux-2.6.28.8/mm/memory.c
---- linux-2.6.28.8/mm/memory.c 2009-02-07 16:10:45.000000000 -0500
-+++ linux-2.6.28.8/mm/memory.c 2009-02-21 09:37:50.000000000 -0500
+diff -urNp linux-2.6.29.5/mm/memory.c linux-2.6.29.5/mm/memory.c
+--- linux-2.6.29.5/mm/memory.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/mm/memory.c 2009-06-12 23:57:32.000000000 -0400
@@ -47,6 +47,7 @@
#include <linux/pagemap.h>
#include <linux/rmap.h>
@@ -33600,7 +37093,7 @@ diff -urNp linux-2.6.28.8/mm/memory.c linux-2.6.28.8/mm/memory.c
#include <linux/delayacct.h>
#include <linux/init.h>
#include <linux/writeback.h>
-@@ -1151,11 +1152,11 @@ int __get_user_pages(struct task_struct
+@@ -1222,11 +1223,11 @@ int __get_user_pages(struct task_struct
vm_flags &= force ? (VM_MAYREAD | VM_MAYWRITE) : (VM_READ | VM_WRITE);
i = 0;
@@ -33614,7 +37107,7 @@ diff -urNp linux-2.6.28.8/mm/memory.c linux-2.6.28.8/mm/memory.c
if (!vma && in_gate_area(tsk, start)) {
unsigned long pg = start & PAGE_MASK;
struct vm_area_struct *gate_vma = get_gate_vma(tsk);
-@@ -1197,7 +1198,7 @@ int __get_user_pages(struct task_struct
+@@ -1268,7 +1269,7 @@ int __get_user_pages(struct task_struct
continue;
}
@@ -33623,7 +37116,7 @@ diff -urNp linux-2.6.28.8/mm/memory.c linux-2.6.28.8/mm/memory.c
(vma->vm_flags & (VM_IO | VM_PFNMAP)) ||
(!ignore && !(vm_flags & vma->vm_flags)))
return i ? : -EFAULT;
-@@ -1271,7 +1272,7 @@ int __get_user_pages(struct task_struct
+@@ -1351,7 +1352,7 @@ int __get_user_pages(struct task_struct
start += PAGE_SIZE;
len--;
} while (len && start < vma->vm_end);
@@ -33632,7 +37125,7 @@ diff -urNp linux-2.6.28.8/mm/memory.c linux-2.6.28.8/mm/memory.c
return i;
}
-@@ -1760,6 +1761,186 @@ static inline void cow_user_page(struct
+@@ -1869,6 +1870,186 @@ static inline void cow_user_page(struct
copy_user_highpage(dst, src, va, vma);
}
@@ -33664,7 +37157,7 @@ diff -urNp linux-2.6.28.8/mm/memory.c linux-2.6.28.8/mm/memory.c
+ dec_mm_counter(mm, anon_rss);
+ else
+ dec_mm_counter(mm, file_rss);
-+ page_remove_rmap(page, vma);
++ page_remove_rmap(page);
+ page_cache_release(page);
+ }
+ }
@@ -33819,7 +37312,7 @@ diff -urNp linux-2.6.28.8/mm/memory.c linux-2.6.28.8/mm/memory.c
/*
* This routine handles present pages, when users try to write
* to a shared page. It is done by copying the page to a new address
-@@ -1897,6 +2078,12 @@ gotten:
+@@ -2041,6 +2222,12 @@ gotten:
*/
page_table = pte_offset_map_lock(mm, pmd, address, &ptl);
if (likely(pte_same(*page_table, orig_pte))) {
@@ -33832,8 +37325,8 @@ diff -urNp linux-2.6.28.8/mm/memory.c linux-2.6.28.8/mm/memory.c
if (old_page) {
if (!PageAnon(old_page)) {
dec_mm_counter(mm, file_rss);
-@@ -1947,6 +2134,10 @@ gotten:
- page_remove_rmap(old_page, vma);
+@@ -2087,6 +2274,10 @@ gotten:
+ page_remove_rmap(old_page);
}
+#ifdef CONFIG_PAX_SEGMEXEC
@@ -33843,7 +37336,7 @@ diff -urNp linux-2.6.28.8/mm/memory.c linux-2.6.28.8/mm/memory.c
/* Free the old page.. */
new_page = old_page;
ret |= VM_FAULT_WRITE;
-@@ -2206,6 +2397,7 @@ int vmtruncate(struct inode * inode, lof
+@@ -2368,6 +2559,7 @@ int vmtruncate(struct inode * inode, lof
unsigned long limit;
limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
@@ -33851,10 +37344,10 @@ diff -urNp linux-2.6.28.8/mm/memory.c linux-2.6.28.8/mm/memory.c
if (limit != RLIM_INFINITY && offset > limit)
goto out_sig;
if (offset > inode->i_sb->s_maxbytes)
-@@ -2357,6 +2549,11 @@ static int do_swap_page(struct mm_struct
+@@ -2533,6 +2725,11 @@ static int do_swap_page(struct mm_struct
swap_free(entry);
if (vm_swap_full() || (vma->vm_flags & VM_LOCKED) || PageMlocked(page))
- remove_exclusive_swap_page(page);
+ try_to_free_swap(page);
+
+#ifdef CONFIG_PAX_SEGMEXEC
+ if (write_access || !pax_find_mirror_vma(vma))
@@ -33863,7 +37356,7 @@ diff -urNp linux-2.6.28.8/mm/memory.c linux-2.6.28.8/mm/memory.c
unlock_page(page);
if (write_access) {
-@@ -2368,6 +2565,11 @@ static int do_swap_page(struct mm_struct
+@@ -2544,6 +2741,11 @@ static int do_swap_page(struct mm_struct
/* No need to invalidate - it was non-present before */
update_mmu_cache(vma, address, pte);
@@ -33875,7 +37368,7 @@ diff -urNp linux-2.6.28.8/mm/memory.c linux-2.6.28.8/mm/memory.c
unlock:
pte_unmap_unlock(page_table, ptl);
out:
-@@ -2412,6 +2614,12 @@ static int do_anonymous_page(struct mm_s
+@@ -2588,12 +2790,23 @@ static int do_anonymous_page(struct mm_s
page_table = pte_offset_map_lock(mm, pmd, address, &ptl);
if (!pte_none(*page_table))
goto release;
@@ -33886,9 +37379,8 @@ diff -urNp linux-2.6.28.8/mm/memory.c linux-2.6.28.8/mm/memory.c
+#endif
+
inc_mm_counter(mm, anon_rss);
- SetPageSwapBacked(page);
- lru_cache_add_active_or_unevictable(page, vma);
-@@ -2420,6 +2628,11 @@ static int do_anonymous_page(struct mm_s
+ page_add_new_anon_rmap(page, vma, address);
+ set_pte_at(mm, address, page_table, entry);
/* No need to invalidate - it was non-present before */
update_mmu_cache(vma, address, entry);
@@ -33900,7 +37392,7 @@ diff -urNp linux-2.6.28.8/mm/memory.c linux-2.6.28.8/mm/memory.c
unlock:
pte_unmap_unlock(page_table, ptl);
return 0;
-@@ -2556,6 +2769,12 @@ static int __do_fault(struct mm_struct *
+@@ -2730,6 +2943,12 @@ static int __do_fault(struct mm_struct *
*/
/* Only go through if we didn't race with anybody else... */
if (likely(pte_same(*page_table, orig_pte))) {
@@ -33913,7 +37405,7 @@ diff -urNp linux-2.6.28.8/mm/memory.c linux-2.6.28.8/mm/memory.c
flush_icache_page(vma, page);
entry = mk_pte(page, vma->vm_page_prot);
if (flags & FAULT_FLAG_WRITE)
-@@ -2578,6 +2797,14 @@ static int __do_fault(struct mm_struct *
+@@ -2749,6 +2968,14 @@ static int __do_fault(struct mm_struct *
/* no need to invalidate: a not-present page won't be cached */
update_mmu_cache(vma, address, entry);
@@ -33928,7 +37420,7 @@ diff -urNp linux-2.6.28.8/mm/memory.c linux-2.6.28.8/mm/memory.c
} else {
if (charged)
mem_cgroup_uncharge_page(page);
-@@ -2711,6 +2938,12 @@ static inline int handle_pte_fault(struc
+@@ -2897,6 +3124,12 @@ static inline int handle_pte_fault(struc
if (write_access)
flush_tlb_page(vma, address);
}
@@ -33941,7 +37433,7 @@ diff -urNp linux-2.6.28.8/mm/memory.c linux-2.6.28.8/mm/memory.c
unlock:
pte_unmap_unlock(pte, ptl);
return 0;
-@@ -2727,6 +2960,10 @@ int handle_mm_fault(struct mm_struct *mm
+@@ -2913,6 +3146,10 @@ int handle_mm_fault(struct mm_struct *mm
pmd_t *pmd;
pte_t *pte;
@@ -33952,7 +37444,7 @@ diff -urNp linux-2.6.28.8/mm/memory.c linux-2.6.28.8/mm/memory.c
__set_current_state(TASK_RUNNING);
count_vm_event(PGFAULT);
-@@ -2734,6 +2971,34 @@ int handle_mm_fault(struct mm_struct *mm
+@@ -2920,6 +3157,34 @@ int handle_mm_fault(struct mm_struct *mm
if (unlikely(is_vm_hugetlb_page(vma)))
return hugetlb_fault(mm, vma, address, write_access);
@@ -33987,7 +37479,7 @@ diff -urNp linux-2.6.28.8/mm/memory.c linux-2.6.28.8/mm/memory.c
pgd = pgd_offset(mm, address);
pud = pud_alloc(mm, pgd, address);
if (!pud)
-@@ -2831,7 +3096,7 @@ static int __init gate_vma_init(void)
+@@ -3017,7 +3282,7 @@ static int __init gate_vma_init(void)
gate_vma.vm_start = FIXADDR_USER_START;
gate_vma.vm_end = FIXADDR_USER_END;
gate_vma.vm_flags = VM_READ | VM_MAYREAD | VM_EXEC | VM_MAYEXEC;
@@ -33996,9 +37488,9 @@ diff -urNp linux-2.6.28.8/mm/memory.c linux-2.6.28.8/mm/memory.c
/*
* Make sure the vDSO gets into every core dump.
* Dumping its contents makes post-mortem fully interpretable later
-diff -urNp linux-2.6.28.8/mm/mempolicy.c linux-2.6.28.8/mm/mempolicy.c
---- linux-2.6.28.8/mm/mempolicy.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/mm/mempolicy.c 2009-02-21 09:37:50.000000000 -0500
+diff -urNp linux-2.6.29.5/mm/mempolicy.c linux-2.6.29.5/mm/mempolicy.c
+--- linux-2.6.29.5/mm/mempolicy.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/mm/mempolicy.c 2009-06-12 23:57:32.000000000 -0400
@@ -551,6 +551,10 @@ static int mbind_range(struct vm_area_st
struct vm_area_struct *next;
int err;
@@ -34045,21 +37537,18 @@ diff -urNp linux-2.6.28.8/mm/mempolicy.c linux-2.6.28.8/mm/mempolicy.c
if (end == start)
return 0;
-diff -urNp linux-2.6.28.8/mm/migrate.c linux-2.6.28.8/mm/migrate.c
---- linux-2.6.28.8/mm/migrate.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/mm/migrate.c 2009-02-21 09:37:50.000000000 -0500
-@@ -1139,7 +1139,7 @@ int migrate_vmas(struct mm_struct *mm, c
- struct vm_area_struct *vma;
- int err = 0;
-
-- for(vma = mm->mmap; vma->vm_next && !err; vma = vma->vm_next) {
-+ for(vma = mm->mmap; vma && !err; vma = vma->vm_next) {
- if (vma->vm_ops && vma->vm_ops->migrate) {
- err = vma->vm_ops->migrate(vma, to, from, flags);
- if (err)
-diff -urNp linux-2.6.28.8/mm/mlock.c linux-2.6.28.8/mm/mlock.c
---- linux-2.6.28.8/mm/mlock.c 2009-02-07 16:10:45.000000000 -0500
-+++ linux-2.6.28.8/mm/mlock.c 2009-02-21 09:37:50.000000000 -0500
+@@ -2290,7 +2315,7 @@ int show_numa_map(struct seq_file *m, vo
+
+ if (file) {
+ seq_printf(m, " file=");
+- seq_path(m, &file->f_path, "\n\t= ");
++ seq_path(m, &file->f_path, "\n\t\\= ");
+ } else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) {
+ seq_printf(m, " heap");
+ } else if (vma->vm_start <= mm->start_stack &&
+diff -urNp linux-2.6.29.5/mm/mlock.c linux-2.6.29.5/mm/mlock.c
+--- linux-2.6.29.5/mm/mlock.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/mm/mlock.c 2009-06-12 23:57:32.000000000 -0400
@@ -13,6 +13,7 @@
#include <linux/pagemap.h>
#include <linux/mempolicy.h>
@@ -34068,7 +37557,7 @@ diff -urNp linux-2.6.28.8/mm/mlock.c linux-2.6.28.8/mm/mlock.c
#include <linux/sched.h>
#include <linux/module.h>
#include <linux/rmap.h>
-@@ -452,6 +453,17 @@ static int do_mlock(unsigned long start,
+@@ -453,6 +454,17 @@ static int do_mlock(unsigned long start,
return -EINVAL;
if (end == start)
return 0;
@@ -34086,7 +37575,7 @@ diff -urNp linux-2.6.28.8/mm/mlock.c linux-2.6.28.8/mm/mlock.c
vma = find_vma_prev(current->mm, start, &prev);
if (!vma || vma->vm_start > start)
return -ENOMEM;
-@@ -511,6 +523,7 @@ SYSCALL_DEFINE2(mlock, unsigned long, st
+@@ -512,6 +524,7 @@ SYSCALL_DEFINE2(mlock, unsigned long, st
lock_limit >>= PAGE_SHIFT;
/* check against resource limits */
@@ -34094,7 +37583,7 @@ diff -urNp linux-2.6.28.8/mm/mlock.c linux-2.6.28.8/mm/mlock.c
if ((locked <= lock_limit) || capable(CAP_IPC_LOCK))
error = do_mlock(start, len, 1);
up_write(&current->mm->mmap_sem);
-@@ -532,10 +545,10 @@ SYSCALL_DEFINE2(munlock, unsigned long,
+@@ -533,10 +546,10 @@ SYSCALL_DEFINE2(munlock, unsigned long,
static int do_mlockall(int flags)
{
struct vm_area_struct * vma, * prev = NULL;
@@ -34107,7 +37596,7 @@ diff -urNp linux-2.6.28.8/mm/mlock.c linux-2.6.28.8/mm/mlock.c
current->mm->def_flags = def_flags;
if (flags == MCL_FUTURE)
goto out;
-@@ -543,6 +556,12 @@ static int do_mlockall(int flags)
+@@ -544,6 +557,12 @@ static int do_mlockall(int flags)
for (vma = current->mm->mmap; vma ; vma = prev->vm_next) {
unsigned int newflags;
@@ -34120,7 +37609,7 @@ diff -urNp linux-2.6.28.8/mm/mlock.c linux-2.6.28.8/mm/mlock.c
newflags = vma->vm_flags | VM_LOCKED;
if (!(flags & MCL_CURRENT))
newflags &= ~VM_LOCKED;
-@@ -574,6 +593,7 @@ SYSCALL_DEFINE1(mlockall, int, flags)
+@@ -575,6 +594,7 @@ SYSCALL_DEFINE1(mlockall, int, flags)
lock_limit >>= PAGE_SHIFT;
ret = -ENOMEM;
@@ -34128,9 +37617,9 @@ diff -urNp linux-2.6.28.8/mm/mlock.c linux-2.6.28.8/mm/mlock.c
if (!(flags & MCL_CURRENT) || (current->mm->total_vm <= lock_limit) ||
capable(CAP_IPC_LOCK))
ret = do_mlockall(flags);
-diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
---- linux-2.6.28.8/mm/mmap.c 2009-02-08 00:54:27.000000000 -0500
-+++ linux-2.6.28.8/mm/mmap.c 2009-02-21 09:37:50.000000000 -0500
+diff -urNp linux-2.6.29.5/mm/mmap.c linux-2.6.29.5/mm/mmap.c
+--- linux-2.6.29.5/mm/mmap.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/mm/mmap.c 2009-06-12 23:57:32.000000000 -0400
@@ -43,6 +43,16 @@
#define arch_rebalance_pgtables(addr, len) (addr)
#endif
@@ -34176,7 +37665,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
}
EXPORT_SYMBOL(vm_get_page_prot);
-@@ -233,6 +252,7 @@ static struct vm_area_struct *remove_vma
+@@ -229,6 +248,7 @@ static struct vm_area_struct *remove_vma
struct vm_area_struct *next = vma->vm_next;
might_sleep();
@@ -34184,7 +37673,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
if (vma->vm_ops && vma->vm_ops->close)
vma->vm_ops->close(vma);
if (vma->vm_file) {
-@@ -269,6 +289,7 @@ SYSCALL_DEFINE1(brk, unsigned long, brk)
+@@ -265,6 +285,7 @@ SYSCALL_DEFINE1(brk, unsigned long, brk)
* not page aligned -Ram Gupta
*/
rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
@@ -34192,7 +37681,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
if (rlim < RLIM_INFINITY && (brk - mm->start_brk) +
(mm->end_data - mm->start_data) > rlim)
goto out;
-@@ -696,6 +717,12 @@ static int
+@@ -694,6 +715,12 @@ static int
can_vma_merge_before(struct vm_area_struct *vma, unsigned long vm_flags,
struct anon_vma *anon_vma, struct file *file, pgoff_t vm_pgoff)
{
@@ -34205,7 +37694,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
if (is_mergeable_vma(vma, file, vm_flags) &&
is_mergeable_anon_vma(anon_vma, vma->anon_vma)) {
if (vma->vm_pgoff == vm_pgoff)
-@@ -715,6 +742,12 @@ static int
+@@ -713,6 +740,12 @@ static int
can_vma_merge_after(struct vm_area_struct *vma, unsigned long vm_flags,
struct anon_vma *anon_vma, struct file *file, pgoff_t vm_pgoff)
{
@@ -34218,7 +37707,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
if (is_mergeable_vma(vma, file, vm_flags) &&
is_mergeable_anon_vma(anon_vma, vma->anon_vma)) {
pgoff_t vm_pglen;
-@@ -757,12 +790,19 @@ can_vma_merge_after(struct vm_area_struc
+@@ -755,12 +788,19 @@ can_vma_merge_after(struct vm_area_struc
struct vm_area_struct *vma_merge(struct mm_struct *mm,
struct vm_area_struct *prev, unsigned long addr,
unsigned long end, unsigned long vm_flags,
@@ -34239,7 +37728,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
/*
* We later require that vma->vm_flags == vm_flags,
* so this tests vma->vm_flags & VM_SPECIAL, too.
-@@ -778,6 +818,15 @@ struct vm_area_struct *vma_merge(struct
+@@ -776,6 +816,15 @@ struct vm_area_struct *vma_merge(struct
if (next && next->vm_end == end) /* cases 6, 7, 8 */
next = next->vm_next;
@@ -34255,7 +37744,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
/*
* Can it merge with the predecessor?
*/
-@@ -797,9 +846,24 @@ struct vm_area_struct *vma_merge(struct
+@@ -795,9 +844,24 @@ struct vm_area_struct *vma_merge(struct
/* cases 1, 6 */
vma_adjust(prev, prev->vm_start,
next->vm_end, prev->vm_pgoff, NULL);
@@ -34281,7 +37770,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
return prev;
}
-@@ -810,12 +874,27 @@ struct vm_area_struct *vma_merge(struct
+@@ -808,12 +872,27 @@ struct vm_area_struct *vma_merge(struct
mpol_equal(policy, vma_policy(next)) &&
can_vma_merge_before(next, vm_flags,
anon_vma, file, pgoff+pglen)) {
@@ -34311,7 +37800,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
return area;
}
-@@ -890,14 +969,11 @@ none:
+@@ -888,14 +967,11 @@ none:
void vm_stat_account(struct mm_struct *mm, unsigned long flags,
struct file *file, long pages)
{
@@ -34327,7 +37816,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
mm->stack_vm += pages;
if (flags & (VM_RESERVED|VM_IO))
mm->reserved_vm += pages;
-@@ -925,7 +1001,7 @@ unsigned long do_mmap_pgoff(struct file
+@@ -922,7 +998,7 @@ unsigned long do_mmap_pgoff(struct file
* (the exception is when the underlying filesystem is noexec
* mounted, in which case we dont add PROT_EXEC.)
*/
@@ -34336,7 +37825,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
if (!(file && (file->f_path.mnt->mnt_flags & MNT_NOEXEC)))
prot |= PROT_EXEC;
-@@ -935,15 +1011,15 @@ unsigned long do_mmap_pgoff(struct file
+@@ -932,15 +1008,15 @@ unsigned long do_mmap_pgoff(struct file
if (!(flags & MAP_FIXED))
addr = round_hint_to_min(addr);
@@ -34356,7 +37845,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
/* offset overflow? */
if ((pgoff + (len >> PAGE_SHIFT)) < pgoff)
return -EOVERFLOW;
-@@ -955,7 +1031,7 @@ unsigned long do_mmap_pgoff(struct file
+@@ -952,7 +1028,7 @@ unsigned long do_mmap_pgoff(struct file
/* Obtain the address to map to. we verify (or select) it and ensure
* that it represents a valid section of the address space.
*/
@@ -34365,7 +37854,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
if (addr & ~PAGE_MASK)
return addr;
-@@ -966,6 +1042,26 @@ unsigned long do_mmap_pgoff(struct file
+@@ -963,6 +1039,26 @@ unsigned long do_mmap_pgoff(struct file
vm_flags = calc_vm_prot_bits(prot) | calc_vm_flag_bits(flags) |
mm->def_flags | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
@@ -34392,7 +37881,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
if (flags & MAP_LOCKED) {
if (!can_do_mlock())
return -EPERM;
-@@ -979,6 +1075,7 @@ unsigned long do_mmap_pgoff(struct file
+@@ -976,6 +1072,7 @@ unsigned long do_mmap_pgoff(struct file
locked += mm->locked_vm;
lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
lock_limit >>= PAGE_SHIFT;
@@ -34400,17 +37889,17 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
if (locked > lock_limit && !capable(CAP_IPC_LOCK))
return -EAGAIN;
}
-@@ -1051,6 +1148,9 @@ unsigned long do_mmap_pgoff(struct file
+@@ -1046,6 +1143,9 @@ unsigned long do_mmap_pgoff(struct file
if (error)
return error;
+ if (!gr_acl_handle_mmap(file, prot))
+ return -EACCES;
+
- return mmap_region(file, addr, len, flags, vm_flags, pgoff,
- accountable);
+ return mmap_region(file, addr, len, flags, vm_flags, pgoff);
}
-@@ -1064,10 +1164,10 @@ EXPORT_SYMBOL(do_mmap_pgoff);
+ EXPORT_SYMBOL(do_mmap_pgoff);
+@@ -1058,10 +1158,10 @@ EXPORT_SYMBOL(do_mmap_pgoff);
*/
int vma_wants_writenotify(struct vm_area_struct *vma)
{
@@ -34423,7 +37912,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
return 0;
/* The backer wishes to know when pages are first written to? */
-@@ -1102,14 +1202,24 @@ unsigned long mmap_region(struct file *f
+@@ -1110,14 +1210,24 @@ unsigned long mmap_region(struct file *f
unsigned long charged = 0;
struct inode *inode = file ? file->f_path.dentry->d_inode : NULL;
@@ -34450,7 +37939,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
}
/* Check against address space limit. */
-@@ -1158,6 +1268,16 @@ munmap_back:
+@@ -1166,6 +1276,16 @@ munmap_back:
goto unacct_error;
}
@@ -34467,7 +37956,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
vma->vm_mm = mm;
vma->vm_start = addr;
vma->vm_end = addr + len;
-@@ -1180,6 +1300,19 @@ munmap_back:
+@@ -1188,6 +1308,19 @@ munmap_back:
error = file->f_op->mmap(file, vma);
if (error)
goto unmap_and_free_vma;
@@ -34487,38 +37976,18 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
if (vm_flags & VM_EXECUTABLE)
added_exe_file_vma(mm);
} else if (vm_flags & VM_SHARED) {
-@@ -1215,13 +1348,30 @@ munmap_back:
- if (merged_vma) {
- mpol_put(vma_policy(vma));
- kmem_cache_free(vm_area_cachep, vma);
-+ vma = NULL;
- fput(file);
-+
-+#ifdef CONFIG_PAX_SEGMEXEC
-+ if (vma_m) {
-+ kmem_cache_free(vm_area_cachep, vma_m);
-+
-+ if (vm_flags & VM_EXECUTABLE)
-+ removed_exe_file_vma(mm);
-+ }
-+#endif
-+
- if (vm_flags & VM_EXECUTABLE)
- removed_exe_file_vma(mm);
- vma = merged_vma;
- } else {
- vma_link(mm, vma, prev, rb_link, rb_parent);
- file = vma->vm_file;
-+
+@@ -1211,12 +1344,18 @@ munmap_back:
+ vma_link(mm, vma, prev, rb_link, rb_parent);
+ file = vma->vm_file;
+
+#ifdef CONFIG_PAX_SEGMEXEC
-+ if (vma_m)
-+ pax_mirror_vma(vma_m, vma);
++ if (vma_m)
++ pax_mirror_vma(vma_m, vma);
+#endif
+
- }
-
/* Once vma denies write, undo our temporary denial count */
-@@ -1230,6 +1380,7 @@ munmap_back:
+ if (correct_wcount)
+ atomic_inc(&inode->i_writecount);
out:
mm->total_vm += len >> PAGE_SHIFT;
vm_stat_account(mm, vm_flags, file, len >> PAGE_SHIFT);
@@ -34526,7 +37995,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
if (vm_flags & VM_LOCKED) {
/*
* makes pages present; downgrades, drops, reacquires mmap_sem
-@@ -1252,6 +1403,12 @@ unmap_and_free_vma:
+@@ -1239,6 +1378,12 @@ unmap_and_free_vma:
unmap_region(mm, vma, prev, vma->vm_start, vma->vm_end);
charged = 0;
free_vma:
@@ -34539,7 +38008,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
kmem_cache_free(vm_area_cachep, vma);
unacct_error:
if (charged)
-@@ -1285,6 +1442,10 @@ arch_get_unmapped_area(struct file *filp
+@@ -1272,6 +1417,10 @@ arch_get_unmapped_area(struct file *filp
if (flags & MAP_FIXED)
return addr;
@@ -34550,7 +38019,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
if (addr) {
addr = PAGE_ALIGN(addr);
vma = find_vma(mm, addr);
-@@ -1293,10 +1454,10 @@ arch_get_unmapped_area(struct file *filp
+@@ -1280,10 +1429,10 @@ arch_get_unmapped_area(struct file *filp
return addr;
}
if (len > mm->cached_hole_size) {
@@ -34564,7 +38033,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
}
full_search:
-@@ -1307,9 +1468,8 @@ full_search:
+@@ -1294,9 +1443,8 @@ full_search:
* Start a new search - just in case we missed
* some holes.
*/
@@ -34576,7 +38045,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
mm->cached_hole_size = 0;
goto full_search;
}
-@@ -1331,10 +1491,16 @@ full_search:
+@@ -1318,10 +1466,16 @@ full_search:
void arch_unmap_area(struct mm_struct *mm, unsigned long addr)
{
@@ -34594,7 +38063,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
mm->free_area_cache = addr;
mm->cached_hole_size = ~0UL;
}
-@@ -1352,7 +1518,7 @@ arch_get_unmapped_area_topdown(struct fi
+@@ -1339,7 +1493,7 @@ arch_get_unmapped_area_topdown(struct fi
{
struct vm_area_struct *vma;
struct mm_struct *mm = current->mm;
@@ -34603,7 +38072,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
/* requested length too big for entire address space */
if (len > TASK_SIZE)
-@@ -1361,6 +1527,10 @@ arch_get_unmapped_area_topdown(struct fi
+@@ -1348,6 +1502,10 @@ arch_get_unmapped_area_topdown(struct fi
if (flags & MAP_FIXED)
return addr;
@@ -34614,7 +38083,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
/* requesting a specific address */
if (addr) {
addr = PAGE_ALIGN(addr);
-@@ -1418,13 +1588,21 @@ bottomup:
+@@ -1405,13 +1563,21 @@ bottomup:
* can happen with large stack limits and large mmap()
* allocations.
*/
@@ -34638,7 +38107,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
mm->cached_hole_size = ~0UL;
return addr;
-@@ -1433,6 +1611,12 @@ bottomup:
+@@ -1420,6 +1586,12 @@ bottomup:
void arch_unmap_area_topdown(struct mm_struct *mm, unsigned long addr)
{
@@ -34651,7 +38120,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
/*
* Is this a new hole at the highest possible address?
*/
-@@ -1440,8 +1624,10 @@ void arch_unmap_area_topdown(struct mm_s
+@@ -1427,8 +1599,10 @@ void arch_unmap_area_topdown(struct mm_s
mm->free_area_cache = addr;
/* dont allow allocations above current base */
@@ -34663,7 +38132,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
}
unsigned long
-@@ -1541,6 +1727,27 @@ out:
+@@ -1528,6 +1702,27 @@ out:
return prev ? prev->vm_next : vma;
}
@@ -34691,7 +38160,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
/*
* Verify that the stack growth is acceptable and
* update accounting. This is shared with both the
-@@ -1557,6 +1764,7 @@ static int acct_stack_growth(struct vm_a
+@@ -1544,6 +1739,7 @@ static int acct_stack_growth(struct vm_a
return -ENOMEM;
/* Stack limit test */
@@ -34699,7 +38168,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
if (size > rlim[RLIMIT_STACK].rlim_cur)
return -ENOMEM;
-@@ -1566,6 +1774,7 @@ static int acct_stack_growth(struct vm_a
+@@ -1553,6 +1749,7 @@ static int acct_stack_growth(struct vm_a
unsigned long limit;
locked = mm->locked_vm + grow;
limit = rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT;
@@ -34707,16 +38176,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
if (locked > limit && !capable(CAP_IPC_LOCK))
return -ENOMEM;
}
-@@ -1580,7 +1789,7 @@ static int acct_stack_growth(struct vm_a
- * Overcommit.. This must be the final test, as it will
- * update security statistics.
- */
-- if (security_vm_enough_memory(grow))
-+ if (security_vm_enough_memory_mm(mm, grow))
- return -ENOMEM;
-
- /* Ok, everything looks good - let it rip */
-@@ -1601,35 +1810,40 @@ static
+@@ -1588,35 +1785,40 @@ static
#endif
int expand_upwards(struct vm_area_struct *vma, unsigned long address)
{
@@ -34767,7 +38227,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
unsigned long size, grow;
size = address - vma->vm_start;
-@@ -1639,6 +1853,8 @@ int expand_upwards(struct vm_area_struct
+@@ -1626,6 +1828,8 @@ int expand_upwards(struct vm_area_struct
if (!error)
vma->vm_end = address;
}
@@ -34776,7 +38236,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
anon_vma_unlock(vma);
return error;
}
-@@ -1650,7 +1866,8 @@ int expand_upwards(struct vm_area_struct
+@@ -1637,7 +1841,8 @@ int expand_upwards(struct vm_area_struct
static int expand_downwards(struct vm_area_struct *vma,
unsigned long address)
{
@@ -34786,7 +38246,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
/*
* We must make sure the anon_vma is allocated
-@@ -1664,6 +1881,15 @@ static int expand_downwards(struct vm_ar
+@@ -1651,6 +1856,15 @@ static int expand_downwards(struct vm_ar
if (error)
return error;
@@ -34802,7 +38262,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
anon_vma_lock(vma);
/*
-@@ -1673,9 +1899,15 @@ static int expand_downwards(struct vm_ar
+@@ -1660,9 +1874,15 @@ static int expand_downwards(struct vm_ar
*/
/* Somebody else might have raced and expanded it already */
@@ -34819,7 +38279,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
size = vma->vm_end - address;
grow = (vma->vm_start - address) >> PAGE_SHIFT;
-@@ -1683,9 +1915,20 @@ static int expand_downwards(struct vm_ar
+@@ -1670,9 +1890,20 @@ static int expand_downwards(struct vm_ar
if (!error) {
vma->vm_start = address;
vma->vm_pgoff -= grow;
@@ -34840,7 +38300,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
return error;
}
-@@ -1761,6 +2004,13 @@ static void remove_vma_list(struct mm_st
+@@ -1748,6 +1979,13 @@ static void remove_vma_list(struct mm_st
do {
long nrpages = vma_pages(vma);
@@ -34854,7 +38314,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
mm->total_vm -= nrpages;
vm_stat_account(mm, vma->vm_flags, vma->vm_file, -nrpages);
vma = remove_vma(vma);
-@@ -1805,6 +2055,16 @@ detach_vmas_to_be_unmapped(struct mm_str
+@@ -1792,6 +2030,16 @@ detach_vmas_to_be_unmapped(struct mm_str
insertion_point = (prev ? &prev->vm_next : &mm->mmap);
do {
@@ -34871,7 +38331,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
rb_erase(&vma->vm_rb, &mm->mm_rb);
mm->map_count--;
tail_vma = vma;
-@@ -1824,6 +2084,108 @@ detach_vmas_to_be_unmapped(struct mm_str
+@@ -1811,6 +2059,108 @@ detach_vmas_to_be_unmapped(struct mm_str
* Split a vma into two pieces at address 'addr', a new vma is allocated
* either for the first part or the tail.
*/
@@ -34980,7 +38440,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
int split_vma(struct mm_struct * mm, struct vm_area_struct * vma,
unsigned long addr, int new_below)
{
-@@ -1875,17 +2237,37 @@ int split_vma(struct mm_struct * mm, str
+@@ -1862,17 +2212,37 @@ int split_vma(struct mm_struct * mm, str
return 0;
}
@@ -35018,7 +38478,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
if ((start & ~PAGE_MASK) || start > TASK_SIZE || len > TASK_SIZE-start)
return -EINVAL;
-@@ -1949,6 +2331,8 @@ int do_munmap(struct mm_struct *mm, unsi
+@@ -1936,6 +2306,8 @@ int do_munmap(struct mm_struct *mm, unsi
/* Fix up all other VM information */
remove_vma_list(mm, vma);
@@ -35027,7 +38487,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
return 0;
}
-@@ -1961,22 +2345,18 @@ SYSCALL_DEFINE2(munmap, unsigned long, a
+@@ -1948,22 +2320,18 @@ SYSCALL_DEFINE2(munmap, unsigned long, a
profile_munmap(addr);
@@ -35056,7 +38516,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
/*
* this is really a simplified "do_mmap". it only handles
* anonymous maps. eventually we may be able to do some
-@@ -1990,6 +2370,11 @@ unsigned long do_brk(unsigned long addr,
+@@ -1977,6 +2345,11 @@ unsigned long do_brk(unsigned long addr,
struct rb_node ** rb_link, * rb_parent;
pgoff_t pgoff = addr >> PAGE_SHIFT;
int error;
@@ -35068,7 +38528,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
len = PAGE_ALIGN(len);
if (!len)
-@@ -2007,19 +2392,34 @@ unsigned long do_brk(unsigned long addr,
+@@ -1994,19 +2367,34 @@ unsigned long do_brk(unsigned long addr,
flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags;
@@ -35104,7 +38564,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
if (locked > lock_limit && !capable(CAP_IPC_LOCK))
return -EAGAIN;
}
-@@ -2033,22 +2433,22 @@ unsigned long do_brk(unsigned long addr,
+@@ -2020,22 +2408,22 @@ unsigned long do_brk(unsigned long addr,
/*
* Clear old maps. this also does some error checking for us
*/
@@ -35131,7 +38591,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
return -ENOMEM;
/* Can we just expand an old private anonymous mapping? */
-@@ -2062,10 +2462,21 @@ unsigned long do_brk(unsigned long addr,
+@@ -2049,10 +2437,21 @@ unsigned long do_brk(unsigned long addr,
*/
vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
if (!vma) {
@@ -35154,7 +38614,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
vma->vm_mm = mm;
vma->vm_start = addr;
vma->vm_end = addr + len;
-@@ -2074,11 +2485,12 @@ unsigned long do_brk(unsigned long addr,
+@@ -2061,11 +2460,12 @@ unsigned long do_brk(unsigned long addr,
vma->vm_page_prot = vm_get_page_prot(flags);
vma_link(mm, vma, prev, rb_link, rb_parent);
out:
@@ -35169,7 +38629,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
return addr;
}
-@@ -2124,8 +2536,10 @@ void exit_mmap(struct mm_struct *mm)
+@@ -2111,8 +2511,10 @@ void exit_mmap(struct mm_struct *mm)
* Walk the list again, actually closing and freeing it,
* with preemption enabled, without holding any MM locks.
*/
@@ -35181,7 +38641,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
BUG_ON(mm->nr_ptes > (FIRST_USER_ADDRESS+PMD_SIZE-1)>>PMD_SHIFT);
}
-@@ -2139,6 +2553,10 @@ int insert_vm_struct(struct mm_struct *
+@@ -2126,6 +2528,10 @@ int insert_vm_struct(struct mm_struct *
struct vm_area_struct * __vma, * prev;
struct rb_node ** rb_link, * rb_parent;
@@ -35192,7 +38652,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
/*
* The vm_pgoff of a purely anonymous vma should be irrelevant
* until its first write fault, when page's anon_vma and index
-@@ -2161,7 +2579,22 @@ int insert_vm_struct(struct mm_struct *
+@@ -2148,7 +2554,22 @@ int insert_vm_struct(struct mm_struct *
if ((vma->vm_flags & VM_ACCOUNT) &&
security_vm_enough_memory_mm(mm, vma_pages(vma)))
return -ENOMEM;
@@ -35215,7 +38675,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
return 0;
}
-@@ -2179,6 +2612,8 @@ struct vm_area_struct *copy_vma(struct v
+@@ -2166,6 +2587,8 @@ struct vm_area_struct *copy_vma(struct v
struct rb_node **rb_link, *rb_parent;
struct mempolicy *pol;
@@ -35224,7 +38684,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
/*
* If anonymous vma has not yet been faulted, update new pgoff
* to match new location, to increase its chance of merging.
-@@ -2222,6 +2657,35 @@ struct vm_area_struct *copy_vma(struct v
+@@ -2209,6 +2632,35 @@ struct vm_area_struct *copy_vma(struct v
return new_vma;
}
@@ -35260,7 +38720,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
/*
* Return true if the calling process may expand its vm space by the passed
* number of pages
-@@ -2232,7 +2696,7 @@ int may_expand_vm(struct mm_struct *mm,
+@@ -2219,7 +2671,7 @@ int may_expand_vm(struct mm_struct *mm,
unsigned long lim;
lim = current->signal->rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT;
@@ -35269,7 +38729,7 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
if (cur + npages > lim)
return 0;
return 1;
-@@ -2301,6 +2765,15 @@ int install_special_mapping(struct mm_st
+@@ -2288,6 +2740,15 @@ int install_special_mapping(struct mm_st
vma->vm_start = addr;
vma->vm_end = addr + len;
@@ -35285,13 +38745,13 @@ diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c
vma->vm_flags = vm_flags | mm->def_flags | VM_DONTEXPAND;
vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
-diff -urNp linux-2.6.28.8/mm/mprotect.c linux-2.6.28.8/mm/mprotect.c
---- linux-2.6.28.8/mm/mprotect.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/mm/mprotect.c 2009-02-21 09:37:50.000000000 -0500
-@@ -22,10 +22,16 @@
- #include <linux/swap.h>
+diff -urNp linux-2.6.29.5/mm/mprotect.c linux-2.6.29.5/mm/mprotect.c
+--- linux-2.6.29.5/mm/mprotect.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/mm/mprotect.c 2009-06-12 23:57:32.000000000 -0400
+@@ -23,10 +23,16 @@
#include <linux/swapops.h>
#include <linux/mmu_notifier.h>
+ #include <linux/migrate.h>
+
+#ifdef CONFIG_PAX_MPROTECT
+#include <linux/elf.h>
@@ -35305,7 +38765,7 @@ diff -urNp linux-2.6.28.8/mm/mprotect.c linux-2.6.28.8/mm/mprotect.c
#ifndef pgprot_modify
static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot)
-@@ -133,6 +139,48 @@ static void change_protection(struct vm_
+@@ -131,6 +137,48 @@ static void change_protection(struct vm_
flush_tlb_range(vma, start, end);
}
@@ -35354,7 +38814,7 @@ diff -urNp linux-2.6.28.8/mm/mprotect.c linux-2.6.28.8/mm/mprotect.c
int
mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
unsigned long start, unsigned long end, unsigned long newflags)
-@@ -145,6 +193,14 @@ mprotect_fixup(struct vm_area_struct *vm
+@@ -143,6 +191,14 @@ mprotect_fixup(struct vm_area_struct *vm
int error;
int dirty_accountable = 0;
@@ -35369,7 +38829,7 @@ diff -urNp linux-2.6.28.8/mm/mprotect.c linux-2.6.28.8/mm/mprotect.c
if (newflags == oldflags) {
*pprev = vma;
return 0;
-@@ -165,6 +221,38 @@ mprotect_fixup(struct vm_area_struct *vm
+@@ -164,6 +220,38 @@ mprotect_fixup(struct vm_area_struct *vm
}
}
@@ -35408,7 +38868,7 @@ diff -urNp linux-2.6.28.8/mm/mprotect.c linux-2.6.28.8/mm/mprotect.c
/*
* First try to merge with previous and/or next vma.
*/
-@@ -196,8 +284,14 @@ success:
+@@ -195,8 +283,14 @@ success:
* held in write mode.
*/
vma->vm_flags = newflags;
@@ -35424,7 +38884,7 @@ diff -urNp linux-2.6.28.8/mm/mprotect.c linux-2.6.28.8/mm/mprotect.c
if (vma_wants_writenotify(vma)) {
vma->vm_page_prot = vm_get_page_prot(newflags & ~VM_SHARED);
-@@ -238,6 +332,17 @@ SYSCALL_DEFINE3(mprotect, unsigned long,
+@@ -237,6 +331,17 @@ SYSCALL_DEFINE3(mprotect, unsigned long,
end = start + len;
if (end <= start)
return -ENOMEM;
@@ -35442,7 +38902,7 @@ diff -urNp linux-2.6.28.8/mm/mprotect.c linux-2.6.28.8/mm/mprotect.c
if (!arch_validate_prot(prot))
return -EINVAL;
-@@ -245,7 +350,7 @@ SYSCALL_DEFINE3(mprotect, unsigned long,
+@@ -244,7 +349,7 @@ SYSCALL_DEFINE3(mprotect, unsigned long,
/*
* Does the application expect PROT_READ to imply PROT_EXEC:
*/
@@ -35451,7 +38911,7 @@ diff -urNp linux-2.6.28.8/mm/mprotect.c linux-2.6.28.8/mm/mprotect.c
prot |= PROT_EXEC;
vm_flags = calc_vm_prot_bits(prot);
-@@ -277,6 +382,16 @@ SYSCALL_DEFINE3(mprotect, unsigned long,
+@@ -276,6 +381,16 @@ SYSCALL_DEFINE3(mprotect, unsigned long,
if (start > vma->vm_start)
prev = vma;
@@ -35468,7 +38928,7 @@ diff -urNp linux-2.6.28.8/mm/mprotect.c linux-2.6.28.8/mm/mprotect.c
for (nstart = start ; ; ) {
unsigned long newflags;
-@@ -300,6 +415,9 @@ SYSCALL_DEFINE3(mprotect, unsigned long,
+@@ -299,6 +414,9 @@ SYSCALL_DEFINE3(mprotect, unsigned long,
error = mprotect_fixup(vma, &prev, nstart, tmp, newflags);
if (error)
goto out;
@@ -35478,9 +38938,9 @@ diff -urNp linux-2.6.28.8/mm/mprotect.c linux-2.6.28.8/mm/mprotect.c
nstart = tmp;
if (nstart < prev->vm_end)
-diff -urNp linux-2.6.28.8/mm/mremap.c linux-2.6.28.8/mm/mremap.c
---- linux-2.6.28.8/mm/mremap.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/mm/mremap.c 2009-02-21 09:37:50.000000000 -0500
+diff -urNp linux-2.6.29.5/mm/mremap.c linux-2.6.29.5/mm/mremap.c
+--- linux-2.6.29.5/mm/mremap.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/mm/mremap.c 2009-06-12 23:57:32.000000000 -0400
@@ -113,6 +113,12 @@ static void move_ptes(struct vm_area_str
continue;
pte = ptep_clear_flush(vma, old_addr, old_pte);
@@ -35592,14 +39052,13 @@ diff -urNp linux-2.6.28.8/mm/mremap.c linux-2.6.28.8/mm/mremap.c
}
out:
if (ret & ~PAGE_MASK)
-diff -urNp linux-2.6.28.8/mm/nommu.c linux-2.6.28.8/mm/nommu.c
---- linux-2.6.28.8/mm/nommu.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/mm/nommu.c 2009-02-21 09:37:50.000000000 -0500
-@@ -459,15 +459,6 @@ struct vm_area_struct *find_vma(struct m
- }
+diff -urNp linux-2.6.29.5/mm/nommu.c linux-2.6.29.5/mm/nommu.c
+--- linux-2.6.29.5/mm/nommu.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/mm/nommu.c 2009-06-12 23:57:32.000000000 -0400
+@@ -770,15 +770,6 @@ struct vm_area_struct *find_vma(struct m
EXPORT_SYMBOL(find_vma);
--/*
+ /*
- * find a VMA
- * - we don't extend stack VMAs under NOMMU conditions
- */
@@ -35608,24 +39067,25 @@ diff -urNp linux-2.6.28.8/mm/nommu.c linux-2.6.28.8/mm/nommu.c
- return find_vma(mm, addr);
-}
-
- int expand_stack(struct vm_area_struct *vma, unsigned long address)
- {
- return -ENOMEM;
-diff -urNp linux-2.6.28.8/mm/page_alloc.c linux-2.6.28.8/mm/page_alloc.c
---- linux-2.6.28.8/mm/page_alloc.c 2009-03-07 10:24:49.000000000 -0500
-+++ linux-2.6.28.8/mm/page_alloc.c 2009-03-07 10:29:51.000000000 -0500
-@@ -525,6 +525,10 @@ static void __free_pages_ok(struct page
+-/*
+ * expand a stack to a given address
+ * - not supported under NOMMU conditions
+ */
+diff -urNp linux-2.6.29.5/mm/page_alloc.c linux-2.6.29.5/mm/page_alloc.c
+--- linux-2.6.29.5/mm/page_alloc.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/mm/page_alloc.c 2009-06-12 23:57:32.000000000 -0400
+@@ -549,6 +549,10 @@ static void __free_pages_ok(struct page
int i;
- int reserved = 0;
+ int bad = 0;
+#ifdef CONFIG_PAX_MEMORY_SANITIZE
+ unsigned long index = 1UL << order;
+#endif
+
for (i = 0 ; i < (1 << order) ; ++i)
- reserved += free_pages_check(page + i);
- if (reserved)
-@@ -535,6 +539,12 @@ static void __free_pages_ok(struct page
+ bad += free_pages_check(page + i);
+ if (bad)
+@@ -559,6 +563,12 @@ static void __free_pages_ok(struct page
debug_check_no_obj_freed(page_address(page),
PAGE_SIZE << order);
}
@@ -35638,7 +39098,7 @@ diff -urNp linux-2.6.28.8/mm/page_alloc.c linux-2.6.28.8/mm/page_alloc.c
arch_free_page(page, order);
kernel_map_pages(page, 1 << order, 0);
-@@ -635,8 +645,10 @@ static int prep_new_page(struct page *pa
+@@ -647,8 +657,10 @@ static int prep_new_page(struct page *pa
arch_alloc_page(page, order);
kernel_map_pages(page, 1 << order, 1);
@@ -35649,7 +39109,7 @@ diff -urNp linux-2.6.28.8/mm/page_alloc.c linux-2.6.28.8/mm/page_alloc.c
if (order && (gfp_flags & __GFP_COMP))
prep_compound_page(page, order);
-@@ -997,6 +1009,11 @@ static void free_hot_cold_page(struct pa
+@@ -1009,6 +1021,11 @@ static void free_hot_cold_page(struct pa
debug_check_no_locks_freed(page_address(page), PAGE_SIZE);
debug_check_no_obj_freed(page_address(page), PAGE_SIZE);
}
@@ -35661,9 +39121,9 @@ diff -urNp linux-2.6.28.8/mm/page_alloc.c linux-2.6.28.8/mm/page_alloc.c
arch_free_page(page, 0);
kernel_map_pages(page, 1, 0);
-diff -urNp linux-2.6.28.8/mm/rmap.c linux-2.6.28.8/mm/rmap.c
---- linux-2.6.28.8/mm/rmap.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/mm/rmap.c 2009-02-21 09:37:50.000000000 -0500
+diff -urNp linux-2.6.29.5/mm/rmap.c linux-2.6.29.5/mm/rmap.c
+--- linux-2.6.29.5/mm/rmap.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/mm/rmap.c 2009-06-12 23:57:32.000000000 -0400
@@ -103,6 +103,10 @@ int anon_vma_prepare(struct vm_area_stru
struct mm_struct *mm = vma->vm_mm;
struct anon_vma *allocated;
@@ -35691,21 +39151,21 @@ diff -urNp linux-2.6.28.8/mm/rmap.c linux-2.6.28.8/mm/rmap.c
vma->anon_vma = anon_vma;
list_add_tail(&vma->anon_vma_node, &anon_vma->head);
allocated = NULL;
-diff -urNp linux-2.6.28.8/mm/shmem.c linux-2.6.28.8/mm/shmem.c
---- linux-2.6.28.8/mm/shmem.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/mm/shmem.c 2009-02-21 09:37:50.000000000 -0500
-@@ -2486,7 +2486,7 @@ static struct file_system_type tmpfs_fs_
- .get_sb = shmem_get_sb,
- .kill_sb = kill_litter_super,
- };
+diff -urNp linux-2.6.29.5/mm/shmem.c linux-2.6.29.5/mm/shmem.c
+--- linux-2.6.29.5/mm/shmem.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/mm/shmem.c 2009-06-12 23:57:32.000000000 -0400
+@@ -29,7 +29,7 @@
+ #include <linux/module.h>
+ #include <linux/swap.h>
+
-static struct vfsmount *shm_mnt;
+struct vfsmount *shm_mnt;
- static int __init init_tmpfs(void)
- {
-diff -urNp linux-2.6.28.8/mm/slab.c linux-2.6.28.8/mm/slab.c
---- linux-2.6.28.8/mm/slab.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/mm/slab.c 2009-02-21 09:37:50.000000000 -0500
+ #ifdef CONFIG_SHMEM
+ /*
+diff -urNp linux-2.6.29.5/mm/slab.c linux-2.6.29.5/mm/slab.c
+--- linux-2.6.29.5/mm/slab.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/mm/slab.c 2009-06-12 23:57:32.000000000 -0400
@@ -305,7 +305,7 @@ struct kmem_list3 {
* Need this for bootstrapping a per node allocator.
*/
@@ -35715,6 +39175,15 @@ diff -urNp linux-2.6.28.8/mm/slab.c linux-2.6.28.8/mm/slab.c
#define CACHE_CACHE 0
#define SIZE_AC MAX_NUMNODES
#define SIZE_L3 (2 * MAX_NUMNODES)
+@@ -628,7 +628,7 @@ static inline void *index_to_obj(struct
+ * reciprocal_divide(offset, cache->reciprocal_buffer_size)
+ */
+ static inline unsigned int obj_to_index(const struct kmem_cache *cache,
+- const struct slab *slab, void *obj)
++ const struct slab *slab, const void *obj)
+ {
+ u32 offset = (obj - slab->s_mem);
+ return reciprocal_divide(offset, cache->reciprocal_buffer_size);
@@ -654,14 +654,14 @@ struct cache_names {
static struct cache_names __initdata cache_names[] = {
#define CACHE(x) { .name = "size-" #x, .name_dma = "size-" #x "(DMA)" },
@@ -35733,16 +39202,7 @@ diff -urNp linux-2.6.28.8/mm/slab.c linux-2.6.28.8/mm/slab.c
/* internal cache of cache description objs */
static struct kmem_cache cache_cache = {
-@@ -2997,7 +2997,7 @@ retry:
- * there must be at least one object available for
- * allocation.
- */
-- BUG_ON(slabp->inuse < 0 || slabp->inuse >= cachep->num);
-+ BUG_ON(slabp->inuse >= cachep->num);
-
- while (slabp->inuse < cachep->num && batchcount--) {
- STATS_INC_ALLOCED(cachep);
-@@ -4491,10 +4491,12 @@ static const struct file_operations proc
+@@ -4428,15 +4428,60 @@ static const struct file_operations proc
static int __init slab_proc_init(void)
{
@@ -35755,10 +39215,477 @@ diff -urNp linux-2.6.28.8/mm/slab.c linux-2.6.28.8/mm/slab.c
return 0;
}
module_init(slab_proc_init);
-diff -urNp linux-2.6.28.8/mm/slub.c linux-2.6.28.8/mm/slub.c
---- linux-2.6.28.8/mm/slub.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/mm/slub.c 2009-02-21 09:37:50.000000000 -0500
-@@ -4508,7 +4508,9 @@ static const struct file_operations proc
+ #endif
+
++void check_object_size(const void *ptr, unsigned long n, bool to)
++{
++
++#ifdef CONFIG_PAX_USERCOPY
++ struct kmem_cache *cachep;
++ struct slab *slabp;
++ struct page *page;
++ unsigned int objnr;
++ unsigned long offset;
++
++ if (!n)
++ return;
++
++ if (ZERO_OR_NULL_PTR(ptr))
++ goto report;
++
++ if (!virt_addr_valid(ptr))
++ return;
++
++ page = virt_to_head_page(ptr);
++
++ if (!PageSlab(page))
++ /* TODO: check for stack based ptr */
++ return;
++
++ cachep = page_get_cache(page);
++ slabp = page_get_slab(page);
++ objnr = obj_to_index(cachep, slabp, ptr);
++ BUG_ON(objnr >= cachep->num);
++ offset = ptr - index_to_obj(cachep, slabp, objnr) - obj_offset(cachep);
++ if (offset <= obj_size(cachep) && n <= obj_size(cachep) - offset)
++ return;
++
++report:
++ if (to)
++ pax_report_leak_to_user(ptr, n);
++ else
++ pax_report_overflow_from_user(ptr, n);
++#endif
++
++}
++EXPORT_SYMBOL(check_object_size);
++
+ /**
+ * ksize - get the actual amount of memory allocated for a given object
+ * @objp: Pointer to the object
+diff -urNp linux-2.6.29.5/mm/slob.c linux-2.6.29.5/mm/slob.c
+--- linux-2.6.29.5/mm/slob.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/mm/slob.c 2009-06-12 23:57:32.000000000 -0400
+@@ -29,7 +29,7 @@
+ * If kmalloc is asked for objects of PAGE_SIZE or larger, it calls
+ * alloc_pages() directly, allocating compound pages so the page order
+ * does not have to be separately tracked, and also stores the exact
+- * allocation size in page->private so that it can be used to accurately
++ * allocation size in slob_page->size so that it can be used to accurately
+ * provide ksize(). These objects are detected in kfree() because slob_page()
+ * is false for them.
+ *
+@@ -58,6 +58,7 @@
+ */
+
+ #include <linux/kernel.h>
++#include <linux/sched.h>
+ #include <linux/slab.h>
+ #include <linux/mm.h>
+ #include <linux/cache.h>
+@@ -97,7 +98,8 @@ struct slob_page {
+ unsigned long flags; /* mandatory */
+ atomic_t _count; /* mandatory */
+ slobidx_t units; /* free units left in page */
+- unsigned long pad[2];
++ unsigned long pad[1];
++ unsigned long size; /* size when >=PAGE_SIZE */
+ slob_t *free; /* first free slob_t in page */
+ struct list_head list; /* linked list of free pages */
+ };
+@@ -130,7 +132,7 @@ static LIST_HEAD(free_slob_large);
+ */
+ static inline int slob_page(struct slob_page *sp)
+ {
+- return PageSlobPage((struct page *)sp);
++ return PageSlobPage((struct page *)sp) && !sp->size;
+ }
+
+ static inline void set_slob_page(struct slob_page *sp)
+@@ -200,7 +202,7 @@ static void set_slob(slob_t *s, slobidx_
+ /*
+ * Return the size of a slob block.
+ */
+-static slobidx_t slob_units(slob_t *s)
++static slobidx_t slob_units(const slob_t *s)
+ {
+ if (s->units > 0)
+ return s->units;
+@@ -210,7 +212,7 @@ static slobidx_t slob_units(slob_t *s)
+ /*
+ * Return the next free slob block pointer after this one.
+ */
+-static slob_t *slob_next(slob_t *s)
++static slob_t *slob_next(const slob_t *s)
+ {
+ slob_t *base = (slob_t *)((unsigned long)s & PAGE_MASK);
+ slobidx_t next;
+@@ -225,7 +227,7 @@ static slob_t *slob_next(slob_t *s)
+ /*
+ * Returns true if s is the last free block in its page.
+ */
+-static int slob_last(slob_t *s)
++static int slob_last(const slob_t *s)
+ {
+ return !((unsigned long)slob_next(s) & ~PAGE_MASK);
+ }
+@@ -244,6 +246,7 @@ static void *slob_new_page(gfp_t gfp, in
+ if (!page)
+ return NULL;
+
++ set_slob_page(page);
+ return page_address(page);
+ }
+
+@@ -353,11 +356,11 @@ static void *slob_alloc(size_t size, gfp
+ if (!b)
+ return 0;
+ sp = (struct slob_page *)virt_to_page(b);
+- set_slob_page(sp);
+
+ spin_lock_irqsave(&slob_lock, flags);
+ sp->units = SLOB_UNITS(PAGE_SIZE);
+ sp->free = b;
++ sp->size = 0;
+ INIT_LIST_HEAD(&sp->list);
+ set_slob(b, SLOB_UNITS(PAGE_SIZE), b + SLOB_UNITS(PAGE_SIZE));
+ set_slob_page_free(sp, slob_list);
+@@ -459,10 +462,9 @@ out:
+ #define ARCH_SLAB_MINALIGN __alignof__(unsigned long)
+ #endif
+
+-void *__kmalloc_node(size_t size, gfp_t gfp, int node)
++static void *__kmalloc_node_align(size_t size, gfp_t gfp, int node, int align)
+ {
+- unsigned int *m;
+- int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
++ slob_t *m;
+
+ if (size < PAGE_SIZE - align) {
+ if (!size)
+@@ -471,20 +473,30 @@ void *__kmalloc_node(size_t size, gfp_t
+ m = slob_alloc(size + align, gfp, align, node);
+ if (!m)
+ return NULL;
+- *m = size;
++ BUILD_BUG_ON(ARCH_KMALLOC_MINALIGN < 2 * SLOB_UNIT);
++ BUILD_BUG_ON(ARCH_SLAB_MINALIGN < 2 * SLOB_UNIT);
++ m[0].units = size;
++ m[1].units = align;
+ return (void *)m + align;
+ } else {
+ void *ret;
+
+ ret = slob_new_page(gfp | __GFP_COMP, get_order(size), node);
+ if (ret) {
+- struct page *page;
+- page = virt_to_page(ret);
+- page->private = size;
++ struct slob_page *sp;
++ sp = (struct slob_page *)virt_to_head_page(ret);
++ sp->size = size;
+ }
+ return ret;
+ }
+ }
++
++void *__kmalloc_node(size_t size, gfp_t gfp, int node)
++{
++ int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
++
++ return __kmalloc_node_align(size, gfp, node, align);
++}
+ EXPORT_SYMBOL(__kmalloc_node);
+
+ void kfree(const void *block)
+@@ -497,13 +509,81 @@ void kfree(const void *block)
+ sp = (struct slob_page *)virt_to_page(block);
+ if (slob_page(sp)) {
+ int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
+- unsigned int *m = (unsigned int *)(block - align);
+- slob_free(m, *m + align);
+- } else
++ slob_t *m = (slob_t *)(block - align);
++ slob_free(m, m[0].units + align);
++ } else {
++ clear_slob_page(sp);
++ free_slob_page(sp);
++ sp->size = 0;
+ put_page(&sp->page);
++ }
+ }
+ EXPORT_SYMBOL(kfree);
+
++void check_object_size(const void *ptr, unsigned long n, bool to)
++{
++
++#ifdef CONFIG_PAX_USERCOPY
++ struct slob_page *sp;
++ const slob_t *free;
++ const void *base;
++
++ if (!n)
++ return;
++
++ if (ZERO_OR_NULL_PTR(ptr))
++ goto report;
++
++ if (!virt_addr_valid(ptr))
++ return;
++
++ sp = (struct slob_page *)virt_to_head_page(ptr);
++ if (!PageSlobPage((struct page*)sp))
++ return;
++
++ if (sp->size) {
++ base = page_address(&sp->page);
++ if (base <= ptr && n <= sp->size - (ptr - base))
++ return;
++ goto report;
++ }
++
++ /* some tricky double walking to find the chunk */
++ base = (void *)((unsigned long)ptr & PAGE_MASK);
++ free = sp->free;
++
++ while (!slob_last(free) && (void *)free <= ptr) {
++ base = free + slob_units(free);
++ free = slob_next(free);
++ }
++
++ while (base < (void *)free) {
++ slobidx_t m = ((slob_t *)base)[0].units, align = ((slob_t *)base)[1].units;
++ int size = SLOB_UNIT * SLOB_UNITS(m + align);
++ int offset;
++
++ if (ptr < base + align)
++ goto report;
++
++ offset = ptr - base - align;
++ if (offset < m) {
++ if (n <= m - offset)
++ return;
++ goto report;
++ }
++ base += size;
++ }
++
++report:
++ if (to)
++ pax_report_leak_to_user(ptr, n);
++ else
++ pax_report_overflow_from_user(ptr, n);
++#endif
++
++}
++EXPORT_SYMBOL(check_object_size);
++
+ /* can't use ksize for kmem_cache_alloc memory, only kmalloc */
+ size_t ksize(const void *block)
+ {
+@@ -516,10 +596,10 @@ size_t ksize(const void *block)
+ sp = (struct slob_page *)virt_to_page(block);
+ if (slob_page(sp)) {
+ int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
+- unsigned int *m = (unsigned int *)(block - align);
+- return SLOB_UNITS(*m) * SLOB_UNIT;
++ slob_t *m = (slob_t *)(block - align);
++ return SLOB_UNITS(m[0].units) * SLOB_UNIT;
+ } else
+- return sp->page.private;
++ return sp->size;
+ }
+ EXPORT_SYMBOL(ksize);
+
+@@ -570,10 +650,19 @@ void *kmem_cache_alloc_node(struct kmem_
+ {
+ void *b;
+
++#ifdef CONFIG_PAX_USERCOPY
++ b = __kmalloc_node_align(c->size, flags, node, c->align);
++#else
+ if (c->size < PAGE_SIZE)
+ b = slob_alloc(c->size, flags, c->align, node);
+- else
++ else {
++ struct slob_page *sp;
++
+ b = slob_new_page(flags, get_order(c->size), node);
++ sp = (struct slob_page *)virt_to_head_page(b);
++ sp->size = c->size;
++ }
++#endif
+
+ if (c->ctor)
+ c->ctor(b);
+@@ -584,10 +673,16 @@ EXPORT_SYMBOL(kmem_cache_alloc_node);
+
+ static void __kmem_cache_free(void *b, int size)
+ {
+- if (size < PAGE_SIZE)
++ struct slob_page *sp = (struct slob_page *)virt_to_head_page(b);
++
++ if (slob_page(sp))
+ slob_free(b, size);
+- else
++ else {
++ clear_slob_page(sp);
++ free_slob_page(sp);
++ sp->size = 0;
+ free_pages((unsigned long)b, get_order(size));
++ }
+ }
+
+ static void kmem_rcu_free(struct rcu_head *head)
+@@ -600,14 +695,23 @@ static void kmem_rcu_free(struct rcu_hea
+
+ void kmem_cache_free(struct kmem_cache *c, void *b)
+ {
++ int size = c->size;
++
++#ifdef CONFIG_PAX_USERCOPY
++ if (size + c->align < PAGE_SIZE) {
++ size += c->align;
++ b -= c->align;
++ }
++#endif
++
+ if (unlikely(c->flags & SLAB_DESTROY_BY_RCU)) {
+ struct slob_rcu *slob_rcu;
+- slob_rcu = b + (c->size - sizeof(struct slob_rcu));
++ slob_rcu = b + (size - sizeof(struct slob_rcu));
+ INIT_RCU_HEAD(&slob_rcu->head);
+- slob_rcu->size = c->size;
++ slob_rcu->size = size;
+ call_rcu(&slob_rcu->head, kmem_rcu_free);
+ } else {
+- __kmem_cache_free(b, c->size);
++ __kmem_cache_free(b, size);
+ }
+ }
+ EXPORT_SYMBOL(kmem_cache_free);
+diff -urNp linux-2.6.29.5/mm/slub.c linux-2.6.29.5/mm/slub.c
+--- linux-2.6.29.5/mm/slub.c 2009-06-12 23:55:00.000000000 -0400
++++ linux-2.6.29.5/mm/slub.c 2009-06-12 23:57:32.000000000 -0400
+@@ -1786,7 +1786,7 @@ static int slub_min_objects;
+ * Merge control. If this is set then no merging of slab caches will occur.
+ * (Could be removed. This was introduced to pacify the merge skeptics.)
+ */
+-static int slub_nomerge;
++static int slub_nomerge = 1;
+
+ /*
+ * Calculate the order of allocation given an slab object size.
+@@ -2322,7 +2322,7 @@ static int kmem_cache_open(struct kmem_c
+ if (!calculate_sizes(s, -1))
+ goto error;
+
+- s->refcount = 1;
++ atomic_set(&s->refcount, 1);
+ #ifdef CONFIG_NUMA
+ s->remote_node_defrag_ratio = 1000;
+ #endif
+@@ -2459,8 +2459,7 @@ static inline int kmem_cache_close(struc
+ void kmem_cache_destroy(struct kmem_cache *s)
+ {
+ down_write(&slub_lock);
+- s->refcount--;
+- if (!s->refcount) {
++ if (atomic_dec_and_test(&s->refcount)) {
+ list_del(&s->list);
+ up_write(&slub_lock);
+ if (kmem_cache_close(s)) {
+@@ -2702,6 +2701,44 @@ void *__kmalloc_node(size_t size, gfp_t
+ EXPORT_SYMBOL(__kmalloc_node);
+ #endif
+
++void check_object_size(const void *ptr, unsigned long n, bool to)
++{
++
++#ifdef CONFIG_PAX_USERCOPY
++ struct page *page;
++ struct kmem_cache *s;
++ unsigned long offset;
++
++ if (!n)
++ return;
++
++ if (ZERO_OR_NULL_PTR(ptr))
++ goto report;
++
++ if (!virt_addr_valid(ptr))
++ return;
++
++ page = get_object_page(ptr);
++
++ if (!page)
++ /* TODO: check for stack based ptr */
++ return;
++
++ s = page->slab;
++ offset = (ptr - page_address(page)) % s->size;
++ if (offset <= s->objsize && n <= s->objsize - offset)
++ return;
++
++report:
++ if (to)
++ pax_report_leak_to_user(ptr, n);
++ else
++ pax_report_overflow_from_user(ptr, n);
++#endif
++
++}
++EXPORT_SYMBOL(check_object_size);
++
+ size_t ksize(const void *object)
+ {
+ struct page *page;
+@@ -2970,7 +3007,7 @@ void __init kmem_cache_init(void)
+ */
+ create_kmalloc_cache(&kmalloc_caches[0], "kmem_cache_node",
+ sizeof(struct kmem_cache_node), GFP_KERNEL);
+- kmalloc_caches[0].refcount = -1;
++ atomic_set(&kmalloc_caches[0].refcount, -1);
+ caches++;
+
+ hotplug_memory_notifier(slab_memory_callback, SLAB_CALLBACK_PRI);
+@@ -3060,7 +3097,7 @@ static int slab_unmergeable(struct kmem_
+ /*
+ * We may have set a slab to be unmergeable during bootstrap.
+ */
+- if (s->refcount < 0)
++ if (atomic_read(&s->refcount) < 0)
+ return 1;
+
+ return 0;
+@@ -3117,7 +3154,7 @@ struct kmem_cache *kmem_cache_create(con
+ if (s) {
+ int cpu;
+
+- s->refcount++;
++ atomic_inc(&s->refcount);
+ /*
+ * Adjust the object sizes so that we clear
+ * the complete object on kzalloc.
+@@ -3136,7 +3173,7 @@ struct kmem_cache *kmem_cache_create(con
+
+ if (sysfs_slab_alias(s, name)) {
+ down_write(&slub_lock);
+- s->refcount--;
++ atomic_dec(&s->refcount);
+ up_write(&slub_lock);
+ goto err;
+ }
+@@ -3852,7 +3889,7 @@ SLAB_ATTR_RO(ctor);
+
+ static ssize_t aliases_show(struct kmem_cache *s, char *buf)
+ {
+- return sprintf(buf, "%d\n", s->refcount - 1);
++ return sprintf(buf, "%d\n", atomic_read(&s->refcount) - 1);
+ }
+ SLAB_ATTR_RO(aliases);
+
+@@ -4530,7 +4567,9 @@ static const struct file_operations proc
static int __init slab_proc_init(void)
{
@@ -35768,22 +39695,10 @@ diff -urNp linux-2.6.28.8/mm/slub.c linux-2.6.28.8/mm/slub.c
return 0;
}
module_init(slab_proc_init);
-diff -urNp linux-2.6.28.8/mm/tiny-shmem.c linux-2.6.28.8/mm/tiny-shmem.c
---- linux-2.6.28.8/mm/tiny-shmem.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/mm/tiny-shmem.c 2009-02-21 09:37:50.000000000 -0500
-@@ -26,7 +26,7 @@ static struct file_system_type tmpfs_fs_
- .kill_sb = kill_litter_super,
- };
-
--static struct vfsmount *shm_mnt;
-+struct vfsmount *shm_mnt;
-
- static int __init init_tmpfs(void)
- {
-diff -urNp linux-2.6.28.8/mm/util.c linux-2.6.28.8/mm/util.c
---- linux-2.6.28.8/mm/util.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/mm/util.c 2009-02-21 09:37:50.000000000 -0500
-@@ -167,6 +167,12 @@ EXPORT_SYMBOL(strndup_user);
+diff -urNp linux-2.6.29.5/mm/util.c linux-2.6.29.5/mm/util.c
+--- linux-2.6.29.5/mm/util.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/mm/util.c 2009-06-12 23:57:32.000000000 -0400
+@@ -187,6 +187,12 @@ EXPORT_SYMBOL(strndup_user);
void arch_pick_mmap_layout(struct mm_struct *mm)
{
mm->mmap_base = TASK_UNMAPPED_BASE;
@@ -35796,9 +39711,9 @@ diff -urNp linux-2.6.28.8/mm/util.c linux-2.6.28.8/mm/util.c
mm->get_unmapped_area = arch_get_unmapped_area;
mm->unmap_area = arch_unmap_area;
}
-diff -urNp linux-2.6.28.8/mm/vmalloc.c linux-2.6.28.8/mm/vmalloc.c
---- linux-2.6.28.8/mm/vmalloc.c 2009-03-07 10:24:49.000000000 -0500
-+++ linux-2.6.28.8/mm/vmalloc.c 2009-03-07 10:29:51.000000000 -0500
+diff -urNp linux-2.6.29.5/mm/vmalloc.c linux-2.6.29.5/mm/vmalloc.c
+--- linux-2.6.29.5/mm/vmalloc.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/mm/vmalloc.c 2009-06-12 23:57:32.000000000 -0400
@@ -90,6 +90,11 @@ static int vmap_pte_range(pmd_t *pmd, un
unsigned long end, pgprot_t prot, struct page **pages, int *nr)
{
@@ -35850,7 +39765,7 @@ diff -urNp linux-2.6.28.8/mm/vmalloc.c linux-2.6.28.8/mm/vmalloc.c
}
static int vmap_pmd_range(pud_t *pud, unsigned long addr,
-@@ -1033,6 +1054,16 @@ static struct vm_struct *__get_vm_area_n
+@@ -1056,6 +1077,16 @@ static struct vm_struct *__get_vm_area_n
unsigned long align = 1;
BUG_ON(in_interrupt());
@@ -35867,7 +39782,7 @@ diff -urNp linux-2.6.28.8/mm/vmalloc.c linux-2.6.28.8/mm/vmalloc.c
if (flags & VM_IOREMAP) {
int bit = fls(size);
-@@ -1256,6 +1287,11 @@ void *vmap(struct page **pages, unsigned
+@@ -1289,6 +1320,11 @@ void *vmap(struct page **pages, unsigned
if (count > num_physpages)
return NULL;
@@ -35879,7 +39794,7 @@ diff -urNp linux-2.6.28.8/mm/vmalloc.c linux-2.6.28.8/mm/vmalloc.c
area = get_vm_area_caller((count << PAGE_SHIFT), flags,
__builtin_return_address(0));
if (!area)
-@@ -1352,6 +1388,13 @@ static void *__vmalloc_node(unsigned lon
+@@ -1385,6 +1421,13 @@ static void *__vmalloc_node(unsigned lon
if (!size || (size >> PAGE_SHIFT) > num_physpages)
return NULL;
@@ -35893,18 +39808,103 @@ diff -urNp linux-2.6.28.8/mm/vmalloc.c linux-2.6.28.8/mm/vmalloc.c
area = __get_vm_area_node(size, VM_ALLOC, VMALLOC_START, VMALLOC_END,
node, gfp_mask, caller);
-@@ -1441,7 +1484,7 @@ EXPORT_SYMBOL(vmalloc_node);
+@@ -1394,6 +1437,7 @@ static void *__vmalloc_node(unsigned lon
+ return __vmalloc_area_node(area, gfp_mask, prot, node, caller);
+ }
++#undef __vmalloc
+ void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot)
+ {
+ return __vmalloc_node(size, gfp_mask, prot, -1,
+@@ -1410,6 +1454,7 @@ EXPORT_SYMBOL(__vmalloc);
+ * For tight control over page level allocator and protection flags
+ * use __vmalloc() instead.
+ */
++#undef vmalloc
+ void *vmalloc(unsigned long size)
+ {
+ return __vmalloc_node(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL,
+@@ -1424,6 +1469,7 @@ EXPORT_SYMBOL(vmalloc);
+ * The resulting memory area is zeroed so it can be mapped to userspace
+ * without leaking data.
+ */
++#undef vmalloc_user
+ void *vmalloc_user(unsigned long size)
+ {
+ struct vm_struct *area;
+@@ -1450,6 +1496,7 @@ EXPORT_SYMBOL(vmalloc_user);
+ * For tight control over page level allocator and protection flags
+ * use __vmalloc() instead.
+ */
++#undef vmalloc_node
+ void *vmalloc_node(unsigned long size, int node)
+ {
+ return __vmalloc_node(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL,
+@@ -1472,10 +1519,10 @@ EXPORT_SYMBOL(vmalloc_node);
+ * For tight control over page level allocator and protection flags
+ * use __vmalloc() instead.
+ */
+-
++#undef vmalloc_exec
void *vmalloc_exec(unsigned long size)
{
-- return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL_EXEC);
-+ return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL_EXEC);
+- return __vmalloc_node(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL_EXEC,
++ return __vmalloc_node(size, GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL_EXEC,
+ -1, __builtin_return_address(0));
+ }
+
+@@ -1494,6 +1541,7 @@ void *vmalloc_exec(unsigned long size)
+ * Allocate enough 32bit PA addressable pages to cover @size from the
+ * page level allocator and map them into contiguous kernel virtual space.
+ */
++#undef vmalloc_32
+ void *vmalloc_32(unsigned long size)
+ {
+ return __vmalloc_node(size, GFP_VMALLOC32, PAGE_KERNEL,
+@@ -1508,6 +1556,7 @@ EXPORT_SYMBOL(vmalloc_32);
+ * The resulting memory area is 32bit addressable and zeroed so it can be
+ * mapped to userspace without leaking data.
+ */
++#undef vmalloc_32_user
+ void *vmalloc_32_user(unsigned long size)
+ {
+ struct vm_struct *area;
+diff -urNp linux-2.6.29.5/net/atm/atm_misc.c linux-2.6.29.5/net/atm/atm_misc.c
+--- linux-2.6.29.5/net/atm/atm_misc.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/net/atm/atm_misc.c 2009-06-12 23:57:32.000000000 -0400
+@@ -19,7 +19,7 @@ int atm_charge(struct atm_vcc *vcc,int t
+ if (atomic_read(&sk_atm(vcc)->sk_rmem_alloc) <= sk_atm(vcc)->sk_rcvbuf)
+ return 1;
+ atm_return(vcc,truesize);
+- atomic_inc(&vcc->stats->rx_drop);
++ atomic_inc_unchecked(&vcc->stats->rx_drop);
+ return 0;
}
- #if defined(CONFIG_64BIT) && defined(CONFIG_ZONE_DMA32)
-diff -urNp linux-2.6.28.8/net/bridge/br_stp_if.c linux-2.6.28.8/net/bridge/br_stp_if.c
---- linux-2.6.28.8/net/bridge/br_stp_if.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/net/bridge/br_stp_if.c 2009-02-21 09:37:50.000000000 -0500
+@@ -41,7 +41,7 @@ struct sk_buff *atm_alloc_charge(struct
+ }
+ }
+ atm_return(vcc,guess);
+- atomic_inc(&vcc->stats->rx_drop);
++ atomic_inc_unchecked(&vcc->stats->rx_drop);
+ return NULL;
+ }
+
+diff -urNp linux-2.6.29.5/net/atm/resources.c linux-2.6.29.5/net/atm/resources.c
+--- linux-2.6.29.5/net/atm/resources.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/net/atm/resources.c 2009-06-12 23:57:32.000000000 -0400
+@@ -170,7 +170,7 @@ static void copy_aal_stats(struct k_atm_
+ static void subtract_aal_stats(struct k_atm_aal_stats *from,
+ struct atm_aal_stats *to)
+ {
+-#define __HANDLE_ITEM(i) atomic_sub(to->i, &from->i)
++#define __HANDLE_ITEM(i) atomic_sub_unchecked(to->i, &from->i)
+ __AAL_STAT_ITEMS
+ #undef __HANDLE_ITEM
+ }
+diff -urNp linux-2.6.29.5/net/bridge/br_stp_if.c linux-2.6.29.5/net/bridge/br_stp_if.c
+--- linux-2.6.29.5/net/bridge/br_stp_if.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/net/bridge/br_stp_if.c 2009-06-12 23:57:32.000000000 -0400
@@ -146,7 +146,7 @@ static void br_stp_stop(struct net_bridg
char *envp[] = { NULL };
@@ -35914,9 +39914,9 @@ diff -urNp linux-2.6.28.8/net/bridge/br_stp_if.c linux-2.6.28.8/net/bridge/br_st
printk(KERN_INFO "%s: userspace STP stopped, return code %d\n",
br->dev->name, r);
-diff -urNp linux-2.6.28.8/net/core/flow.c linux-2.6.28.8/net/core/flow.c
---- linux-2.6.28.8/net/core/flow.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/net/core/flow.c 2009-02-21 09:37:50.000000000 -0500
+diff -urNp linux-2.6.29.5/net/core/flow.c linux-2.6.29.5/net/core/flow.c
+--- linux-2.6.29.5/net/core/flow.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/net/core/flow.c 2009-06-12 23:57:32.000000000 -0400
@@ -39,7 +39,7 @@ atomic_t flow_cache_genid = ATOMIC_INIT(
static u32 flow_hash_shift;
@@ -35944,9 +39944,9 @@ diff -urNp linux-2.6.28.8/net/core/flow.c linux-2.6.28.8/net/core/flow.c
#define flow_flush_tasklet(cpu) (&per_cpu(flow_flush_tasklets, cpu))
-diff -urNp linux-2.6.28.8/net/dccp/ccids/ccid3.c linux-2.6.28.8/net/dccp/ccids/ccid3.c
---- linux-2.6.28.8/net/dccp/ccids/ccid3.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/net/dccp/ccids/ccid3.c 2009-02-21 09:37:50.000000000 -0500
+diff -urNp linux-2.6.29.5/net/dccp/ccids/ccid3.c linux-2.6.29.5/net/dccp/ccids/ccid3.c
+--- linux-2.6.29.5/net/dccp/ccids/ccid3.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/net/dccp/ccids/ccid3.c 2009-06-12 23:57:32.000000000 -0400
@@ -43,7 +43,7 @@
static int ccid3_debug;
#define ccid3_pr_debug(format, a...) DCCP_PR_DEBUG(ccid3_debug, format, ##a)
@@ -35956,9 +39956,9 @@ diff -urNp linux-2.6.28.8/net/dccp/ccids/ccid3.c linux-2.6.28.8/net/dccp/ccids/c
#endif
/*
-diff -urNp linux-2.6.28.8/net/dccp/dccp.h linux-2.6.28.8/net/dccp/dccp.h
---- linux-2.6.28.8/net/dccp/dccp.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/net/dccp/dccp.h 2009-02-21 09:37:50.000000000 -0500
+diff -urNp linux-2.6.29.5/net/dccp/dccp.h linux-2.6.29.5/net/dccp/dccp.h
+--- linux-2.6.29.5/net/dccp/dccp.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/net/dccp/dccp.h 2009-06-12 23:57:32.000000000 -0400
@@ -43,8 +43,8 @@ extern int dccp_debug;
#define dccp_pr_debug(format, a...) DCCP_PR_DEBUG(dccp_debug, format, ##a)
#define dccp_pr_debug_cat(format, a...) DCCP_PRINTK(dccp_debug, format, ##a)
@@ -35970,9 +39970,9 @@ diff -urNp linux-2.6.28.8/net/dccp/dccp.h linux-2.6.28.8/net/dccp/dccp.h
#endif
extern struct inet_hashinfo dccp_hashinfo;
-diff -urNp linux-2.6.28.8/net/ipv4/inet_connection_sock.c linux-2.6.28.8/net/ipv4/inet_connection_sock.c
---- linux-2.6.28.8/net/ipv4/inet_connection_sock.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/net/ipv4/inet_connection_sock.c 2009-02-21 09:37:50.000000000 -0500
+diff -urNp linux-2.6.29.5/net/ipv4/inet_connection_sock.c linux-2.6.29.5/net/ipv4/inet_connection_sock.c
+--- linux-2.6.29.5/net/ipv4/inet_connection_sock.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/net/ipv4/inet_connection_sock.c 2009-06-12 23:57:32.000000000 -0400
@@ -15,6 +15,7 @@
#include <linux/module.h>
@@ -35981,9 +39981,9 @@ diff -urNp linux-2.6.28.8/net/ipv4/inet_connection_sock.c linux-2.6.28.8/net/ipv
#include <net/inet_connection_sock.h>
#include <net/inet_hashtables.h>
-diff -urNp linux-2.6.28.8/net/ipv4/inet_hashtables.c linux-2.6.28.8/net/ipv4/inet_hashtables.c
---- linux-2.6.28.8/net/ipv4/inet_hashtables.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/net/ipv4/inet_hashtables.c 2009-02-21 09:37:50.000000000 -0500
+diff -urNp linux-2.6.29.5/net/ipv4/inet_hashtables.c linux-2.6.29.5/net/ipv4/inet_hashtables.c
+--- linux-2.6.29.5/net/ipv4/inet_hashtables.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/net/ipv4/inet_hashtables.c 2009-06-12 23:57:32.000000000 -0400
@@ -18,11 +18,14 @@
#include <linux/sched.h>
#include <linux/slab.h>
@@ -35999,7 +39999,7 @@ diff -urNp linux-2.6.28.8/net/ipv4/inet_hashtables.c linux-2.6.28.8/net/ipv4/ine
/*
* Allocate and initialize a new local port bind bucket.
* The bindhash mutex for snum's hash chain must be held here.
-@@ -487,6 +490,8 @@ ok:
+@@ -481,6 +484,8 @@ ok:
}
spin_unlock(&head->lock);
@@ -36008,175 +40008,60 @@ diff -urNp linux-2.6.28.8/net/ipv4/inet_hashtables.c linux-2.6.28.8/net/ipv4/ine
if (tw) {
inet_twsk_deschedule(tw, death_row);
inet_twsk_put(tw);
-diff -urNp linux-2.6.28.8/net/ipv4/netfilter/ipt_stealth.c linux-2.6.28.8/net/ipv4/netfilter/ipt_stealth.c
---- linux-2.6.28.8/net/ipv4/netfilter/ipt_stealth.c 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.28.8/net/ipv4/netfilter/ipt_stealth.c 2009-02-21 09:37:50.000000000 -0500
-@@ -0,0 +1,114 @@
-+/* Kernel module to add stealth support.
-+ *
-+ * Copyright (C) 2002-2006 Brad Spengler <spender@grsecurity.net>
-+ *
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/skbuff.h>
-+#include <linux/net.h>
-+#include <linux/sched.h>
-+#include <linux/inet.h>
-+#include <linux/stddef.h>
-+
-+#include <net/ip.h>
-+#include <net/sock.h>
-+#include <net/tcp.h>
-+#include <net/udp.h>
-+#include <net/route.h>
-+#include <net/inet_common.h>
-+
-+#include <linux/netfilter_ipv4/ip_tables.h>
-+
-+MODULE_LICENSE("GPL");
-+
-+extern struct sock *udp_v4_lookup(struct net *net, u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
-+
-+static bool
-+match(const struct sk_buff *skb,
-+ const struct net_device *in,
-+ const struct net_device *out,
-+ const struct xt_match *match,
-+ const void *matchinfo,
-+ int offset,
-+ unsigned int protoff,
-+ bool *hotdrop)
-+{
-+ struct iphdr *ip = ip_hdr(skb);
-+ struct tcphdr th;
-+ struct udphdr uh;
-+ struct sock *sk = NULL;
-+
-+ if (!ip || offset) return false;
-+
-+ switch(ip->protocol) {
-+ case IPPROTO_TCP:
-+ if (skb_copy_bits(skb, (ip_hdr(skb))->ihl*4, &th, sizeof(th)) < 0) {
-+ *hotdrop = true;
-+ return false;
-+ }
-+ if (!(th.syn && !th.ack)) return false;
-+ sk = inet_lookup_listener(dev_net(skb->dev), &tcp_hashinfo, ip->daddr, th.dest, inet_iif(skb));
-+ break;
-+ case IPPROTO_UDP:
-+ if (skb_copy_bits(skb, (ip_hdr(skb))->ihl*4, &uh, sizeof(uh)) < 0) {
-+ *hotdrop = true;
-+ return false;
-+ }
-+ sk = udp_v4_lookup(dev_net(skb->dev), ip->saddr, uh.source, ip->daddr, uh.dest, skb->dev->ifindex);
-+ break;
-+ default:
-+ return false;
-+ }
-+
-+ if(!sk) // port is being listened on, match this
-+ return true;
-+ else {
-+ sock_put(sk);
-+ return false;
-+ }
-+}
-+
-+/* Called when user tries to insert an entry of this type. */
-+static bool
-+checkentry(const char *tablename,
-+ const void *nip,
-+ const struct xt_match *match,
-+ void *matchinfo,
-+ unsigned int hook_mask)
-+{
-+ const struct ipt_ip *ip = (const struct ipt_ip *)nip;
-+
-+ if(((ip->proto == IPPROTO_TCP && !(ip->invflags & IPT_INV_PROTO)) ||
-+ ((ip->proto == IPPROTO_UDP) && !(ip->invflags & IPT_INV_PROTO)))
-+ && (hook_mask & (1 << NF_INET_LOCAL_IN)))
-+ return true;
-+
-+ printk("stealth: Only works on TCP and UDP for the INPUT chain.\n");
-+
-+ return false;
-+}
-+
-+
-+static struct xt_match stealth_match __read_mostly = {
-+ .name = "stealth",
-+ .family = AF_INET,
-+ .match = match,
-+ .checkentry = checkentry,
-+ .destroy = NULL,
-+ .me = THIS_MODULE
-+};
-+
-+static int __init init(void)
-+{
-+ return xt_register_match(&stealth_match);
-+}
-+
-+static void __exit fini(void)
-+{
-+ xt_unregister_match(&stealth_match);
-+}
-+
-+module_init(init);
-+module_exit(fini);
-diff -urNp linux-2.6.28.8/net/ipv4/netfilter/Kconfig linux-2.6.28.8/net/ipv4/netfilter/Kconfig
---- linux-2.6.28.8/net/ipv4/netfilter/Kconfig 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/net/ipv4/netfilter/Kconfig 2009-03-07 04:29:14.000000000 -0500
-@@ -101,6 +101,21 @@ config IP_NF_MATCH_TTL
+diff -urNp linux-2.6.29.5/net/ipv4/netfilter/nf_nat_snmp_basic.c linux-2.6.29.5/net/ipv4/netfilter/nf_nat_snmp_basic.c
+--- linux-2.6.29.5/net/ipv4/netfilter/nf_nat_snmp_basic.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/net/ipv4/netfilter/nf_nat_snmp_basic.c 2009-06-12 23:57:32.000000000 -0400
+@@ -397,7 +397,7 @@ static unsigned char asn1_octets_decode(
+
+ *len = 0;
+
+- *octets = kmalloc(eoc - ctx->pointer, GFP_ATOMIC);
++ *octets = kmalloc((eoc - ctx->pointer), GFP_ATOMIC);
+ if (*octets == NULL) {
+ if (net_ratelimit())
+ printk("OOM in bsalg (%d)\n", __LINE__);
+diff -urNp linux-2.6.29.5/net/ipv4/tcp_ipv4.c linux-2.6.29.5/net/ipv4/tcp_ipv4.c
+--- linux-2.6.29.5/net/ipv4/tcp_ipv4.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/net/ipv4/tcp_ipv4.c 2009-06-12 23:57:32.000000000 -0400
+@@ -1512,6 +1512,9 @@ int tcp_v4_do_rcv(struct sock *sk, struc
+ return 0;
- To compile it as a module, choose M here. If unsure, say N.
+ reset:
++#ifdef CONFIG_GRKERNSEC_BLACKHOLE
++ if (!skb->dev || (skb->dev->flags & IFF_LOOPBACK))
++#endif
+ tcp_v4_send_reset(rsk, skb);
+ discard:
+ kfree_skb(skb);
+@@ -1620,6 +1623,9 @@ no_tcp_socket:
+ bad_packet:
+ TCP_INC_STATS_BH(net, TCP_MIB_INERRS);
+ } else {
++#ifdef CONFIG_GRKERNSEC_BLACKHOLE
++ if (skb->dev->flags & IFF_LOOPBACK)
++#endif
+ tcp_v4_send_reset(NULL, skb);
+ }
-+config IP_NF_MATCH_STEALTH
-+ tristate "stealth match support"
-+ depends on IP_NF_IPTABLES
-+ help
-+ Enabling this option will drop all syn packets coming to unserved tcp
-+ ports as well as all packets coming to unserved udp ports. If you
-+ are using your system to route any type of packets (ie. via NAT)
-+ you should put this module at the end of your ruleset, since it will
-+ drop packets that aren't going to ports that are listening on your
-+ machine itself, it doesn't take into account that the packet might be
-+ destined for someone on your internal network if you're using NAT for
-+ instance.
-+
-+ To compile it as a module, choose M here. If unsure, say N.
-+
- # `filter', generic and specific targets
- config IP_NF_FILTER
- tristate "Packet filtering"
-diff -urNp linux-2.6.28.8/net/ipv4/netfilter/Makefile linux-2.6.28.8/net/ipv4/netfilter/Makefile
---- linux-2.6.28.8/net/ipv4/netfilter/Makefile 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/net/ipv4/netfilter/Makefile 2009-02-21 09:37:50.000000000 -0500
-@@ -61,6 +61,7 @@ obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) +=
- obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
- obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
- obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
-+obj-$(CONFIG_IP_NF_MATCH_STEALTH) += ipt_stealth.o
- obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
- obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
-
-diff -urNp linux-2.6.28.8/net/ipv4/tcp_ipv4.c linux-2.6.28.8/net/ipv4/tcp_ipv4.c
---- linux-2.6.28.8/net/ipv4/tcp_ipv4.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/net/ipv4/tcp_ipv4.c 2009-02-21 09:37:50.000000000 -0500
-@@ -55,6 +55,7 @@
- #include <linux/fcntl.h>
- #include <linux/module.h>
- #include <linux/random.h>
-+#include <linux/security.h>
- #include <linux/cache.h>
- #include <linux/jhash.h>
- #include <linux/init.h>
-diff -urNp linux-2.6.28.8/net/ipv4/udp.c linux-2.6.28.8/net/ipv4/udp.c
---- linux-2.6.28.8/net/ipv4/udp.c 2009-02-08 00:54:28.000000000 -0500
-+++ linux-2.6.28.8/net/ipv4/udp.c 2009-02-21 09:37:50.000000000 -0500
-@@ -84,6 +84,7 @@
+diff -urNp linux-2.6.29.5/net/ipv4/tcp_minisocks.c linux-2.6.29.5/net/ipv4/tcp_minisocks.c
+--- linux-2.6.29.5/net/ipv4/tcp_minisocks.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/net/ipv4/tcp_minisocks.c 2009-06-12 23:57:32.000000000 -0400
+@@ -695,8 +695,11 @@ listen_overflow:
+
+ embryonic_reset:
+ NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_EMBRYONICRSTS);
++
++#ifndef CONFIG_GRKERNSEC_BLACKHOLE
+ if (!(flg & TCP_FLAG_RST))
+ req->rsk_ops->send_reset(sk, skb);
++#endif
+
+ inet_csk_reqsk_queue_drop(sk, req, prev);
+ return NULL;
+diff -urNp linux-2.6.29.5/net/ipv4/udp.c linux-2.6.29.5/net/ipv4/udp.c
+--- linux-2.6.29.5/net/ipv4/udp.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/net/ipv4/udp.c 2009-06-12 23:57:32.000000000 -0400
+@@ -86,6 +86,7 @@
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/module.h>
@@ -36184,31 +40069,17 @@ diff -urNp linux-2.6.28.8/net/ipv4/udp.c linux-2.6.28.8/net/ipv4/udp.c
#include <linux/socket.h>
#include <linux/sockios.h>
#include <linux/igmp.h>
-@@ -104,6 +105,9 @@
- #include <net/xfrm.h>
- #include "udp_impl.h"
+@@ -369,6 +370,9 @@ found:
+ return s;
+ }
+extern int gr_search_udp_recvmsg(struct sock *sk, const struct sk_buff *skb);
+extern int gr_search_udp_sendmsg(struct sock *sk, struct sockaddr_in *addr);
+
/*
- * Snmp MIB for the UDP layer
- */
-@@ -284,6 +288,13 @@ struct sock *udp4_lib_lookup(struct net
- }
- EXPORT_SYMBOL_GPL(udp4_lib_lookup);
-
-+struct sock *udp_v4_lookup(struct net *net, __be32 saddr, __be16 sport,
-+ __be32 daddr, __be16 dport, int dif)
-+{
-+ return __udp4_lib_lookup(net, saddr, sport, daddr, dport, dif, udp_hash);
-+}
-+
-+
- static inline struct sock *udp_v4_mcast_next(struct net *net, struct sock *sk,
- __be16 loc_port, __be32 loc_addr,
- __be16 rmt_port, __be32 rmt_addr,
-@@ -574,9 +585,18 @@ int udp_sendmsg(struct kiocb *iocb, stru
+ * This routine is called by the ICMP module when it gets some
+ * sort of error condition. If err < 0 then the socket should
+@@ -630,9 +634,18 @@ int udp_sendmsg(struct kiocb *iocb, stru
dport = usin->sin_port;
if (dport == 0)
return -EINVAL;
@@ -36227,7 +40098,7 @@ diff -urNp linux-2.6.28.8/net/ipv4/udp.c linux-2.6.28.8/net/ipv4/udp.c
daddr = inet->daddr;
dport = inet->dport;
/* Open fast path for connected socket.
-@@ -842,6 +862,10 @@ try_again:
+@@ -898,6 +911,10 @@ try_again:
if (!skb)
goto out;
@@ -36238,9 +40109,19 @@ diff -urNp linux-2.6.28.8/net/ipv4/udp.c linux-2.6.28.8/net/ipv4/udp.c
ulen = skb->len - sizeof(struct udphdr);
copied = len;
if (copied > ulen)
-diff -urNp linux-2.6.28.8/net/ipv6/exthdrs.c linux-2.6.28.8/net/ipv6/exthdrs.c
---- linux-2.6.28.8/net/ipv6/exthdrs.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/net/ipv6/exthdrs.c 2009-02-21 09:37:50.000000000 -0500
+@@ -1288,6 +1305,9 @@ int __udp4_lib_rcv(struct sk_buff *skb,
+ goto csum_error;
+
+ UDP_INC_STATS_BH(net, UDP_MIB_NOPORTS, proto == IPPROTO_UDPLITE);
++#ifdef CONFIG_GRKERNSEC_BLACKHOLE
++ if (skb->dev->flags & IFF_LOOPBACK)
++#endif
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
+
+ /*
+diff -urNp linux-2.6.29.5/net/ipv6/exthdrs.c linux-2.6.29.5/net/ipv6/exthdrs.c
+--- linux-2.6.29.5/net/ipv6/exthdrs.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/net/ipv6/exthdrs.c 2009-06-12 23:57:32.000000000 -0400
@@ -630,7 +630,7 @@ static struct tlvtype_proc tlvprochopopt
.type = IPV6_TLV_JUMBO,
.func = ipv6_hop_jumbo,
@@ -36250,9 +40131,9 @@ diff -urNp linux-2.6.28.8/net/ipv6/exthdrs.c linux-2.6.28.8/net/ipv6/exthdrs.c
};
int ipv6_parse_hopopts(struct sk_buff *skb)
-diff -urNp linux-2.6.28.8/net/ipv6/raw.c linux-2.6.28.8/net/ipv6/raw.c
---- linux-2.6.28.8/net/ipv6/raw.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/net/ipv6/raw.c 2009-02-21 09:37:50.000000000 -0500
+diff -urNp linux-2.6.29.5/net/ipv6/raw.c linux-2.6.29.5/net/ipv6/raw.c
+--- linux-2.6.29.5/net/ipv6/raw.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/net/ipv6/raw.c 2009-06-12 23:57:32.000000000 -0400
@@ -600,7 +600,7 @@ out:
return err;
}
@@ -36262,21 +40143,147 @@ diff -urNp linux-2.6.28.8/net/ipv6/raw.c linux-2.6.28.8/net/ipv6/raw.c
struct flowi *fl, struct rt6_info *rt,
unsigned int flags)
{
-diff -urNp linux-2.6.28.8/net/irda/ircomm/ircomm_tty.c linux-2.6.28.8/net/irda/ircomm/ircomm_tty.c
---- linux-2.6.28.8/net/irda/ircomm/ircomm_tty.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/net/irda/ircomm/ircomm_tty.c 2009-02-21 09:37:50.000000000 -0500
-@@ -371,7 +371,7 @@ static int ircomm_tty_open(struct tty_st
- IRDA_DEBUG(2, "%s()\n", __func__ );
+diff -urNp linux-2.6.29.5/net/ipv6/tcp_ipv6.c linux-2.6.29.5/net/ipv6/tcp_ipv6.c
+--- linux-2.6.29.5/net/ipv6/tcp_ipv6.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/net/ipv6/tcp_ipv6.c 2009-06-12 23:57:32.000000000 -0400
+@@ -1576,6 +1576,9 @@ static int tcp_v6_do_rcv(struct sock *sk
+ return 0;
- line = tty->index;
-- if ((line < 0) || (line >= IRCOMM_TTY_PORTS)) {
-+ if (line >= IRCOMM_TTY_PORTS) {
- return -ENODEV;
+ reset:
++#ifdef CONFIG_GRKERNSEC_BLACKHOLE
++ if (!skb->dev || (skb->dev->flags & IFF_LOOPBACK))
++#endif
+ tcp_v6_send_reset(sk, skb);
+ discard:
+ if (opt_skb)
+@@ -1699,6 +1702,9 @@ no_tcp_socket:
+ bad_packet:
+ TCP_INC_STATS_BH(net, TCP_MIB_INERRS);
+ } else {
++#ifdef CONFIG_GRKERNSEC_BLACKHOLE
++ if (skb->dev->flags & IFF_LOOPBACK)
++#endif
+ tcp_v6_send_reset(NULL, skb);
+ }
+
+diff -urNp linux-2.6.29.5/net/ipv6/udp.c linux-2.6.29.5/net/ipv6/udp.c
+--- linux-2.6.29.5/net/ipv6/udp.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/net/ipv6/udp.c 2009-06-12 23:57:32.000000000 -0400
+@@ -558,6 +558,9 @@ int __udp6_lib_rcv(struct sk_buff *skb,
+ UDP6_INC_STATS_BH(net, UDP_MIB_NOPORTS,
+ proto == IPPROTO_UDPLITE);
+
++#ifdef CONFIG_GRKERNSEC_BLACKHOLE
++ if (skb->dev->flags & IFF_LOOPBACK)
++#endif
+ icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, dev);
+
+ kfree_skb(skb);
+diff -urNp linux-2.6.29.5/net/mac80211/ieee80211_i.h linux-2.6.29.5/net/mac80211/ieee80211_i.h
+--- linux-2.6.29.5/net/mac80211/ieee80211_i.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/net/mac80211/ieee80211_i.h 2009-06-12 23:57:32.000000000 -0400
+@@ -562,7 +562,7 @@ struct ieee80211_local {
+ unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES];
+ spinlock_t queue_stop_reason_lock;
+ struct net_device *mdev; /* wmaster# - "master" 802.11 device */
+- int open_count;
++ atomic_t open_count;
+ int monitors, cooked_mntrs;
+ /* number of interfaces with corresponding FIF_ flags */
+ int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss;
+diff -urNp linux-2.6.29.5/net/mac80211/iface.c linux-2.6.29.5/net/mac80211/iface.c
+--- linux-2.6.29.5/net/mac80211/iface.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/net/mac80211/iface.c 2009-06-12 23:57:32.000000000 -0400
+@@ -146,7 +146,7 @@ static int ieee80211_open(struct net_dev
+ break;
+ }
+
+- if (local->open_count == 0) {
++ if (atomic_read(&local->open_count) == 0) {
+ res = 0;
+ if (local->ops->start)
+ res = local->ops->start(local_to_hw(local));
+@@ -182,7 +182,7 @@ static int ieee80211_open(struct net_dev
+ * Validate the MAC address for this device.
+ */
+ if (!is_valid_ether_addr(dev->dev_addr)) {
+- if (!local->open_count && local->ops->stop)
++ if (!atomic_read(&local->open_count) && local->ops->stop)
+ local->ops->stop(local_to_hw(local));
+ return -EADDRNOTAVAIL;
+ }
+@@ -267,7 +267,7 @@ static int ieee80211_open(struct net_dev
+ }
+ }
+
+- if (local->open_count == 0) {
++ if (atomic_read(&local->open_count) == 0) {
+ res = dev_open(local->mdev);
+ WARN_ON(res);
+ if (res)
+@@ -287,7 +287,7 @@ static int ieee80211_open(struct net_dev
+ if (sdata->flags & IEEE80211_SDATA_PROMISC)
+ atomic_inc(&local->iff_promiscs);
+
+- local->open_count++;
++ atomic_inc(&local->open_count);
+ if (hw_reconf_flags) {
+ ieee80211_hw_config(local, hw_reconf_flags);
+ /*
+@@ -316,7 +316,7 @@ static int ieee80211_open(struct net_dev
+ err_del_interface:
+ local->ops->remove_interface(local_to_hw(local), &conf);
+ err_stop:
+- if (!local->open_count && local->ops->stop)
++ if (!atomic_read(&local->open_count) && local->ops->stop)
+ local->ops->stop(local_to_hw(local));
+ err_del_bss:
+ sdata->bss = NULL;
+@@ -401,7 +401,7 @@ static int ieee80211_stop(struct net_dev
+ WARN_ON(!list_empty(&sdata->u.ap.vlans));
+ }
+
+- local->open_count--;
++ atomic_dec(&local->open_count);
+
+ switch (sdata->vif.type) {
+ case NL80211_IFTYPE_AP_VLAN:
+@@ -514,7 +514,7 @@ static int ieee80211_stop(struct net_dev
+
+ sdata->bss = NULL;
+
+- if (local->open_count == 0) {
++ if (atomic_read(&local->open_count) == 0) {
+ if (netif_running(local->mdev))
+ dev_close(local->mdev);
+
+diff -urNp linux-2.6.29.5/net/mac80211/main.c linux-2.6.29.5/net/mac80211/main.c
+--- linux-2.6.29.5/net/mac80211/main.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/net/mac80211/main.c 2009-06-12 23:57:32.000000000 -0400
+@@ -233,7 +233,7 @@ int ieee80211_hw_config(struct ieee80211
+ local->hw.conf.power_level = power;
}
-diff -urNp linux-2.6.28.8/net/sctp/socket.c linux-2.6.28.8/net/sctp/socket.c
---- linux-2.6.28.8/net/sctp/socket.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/net/sctp/socket.c 2009-02-21 09:37:50.000000000 -0500
+- if (changed && local->open_count) {
++ if (changed && atomic_read(&local->open_count)) {
+ ret = local->ops->config(local_to_hw(local), changed);
+ /*
+ * Goal:
+diff -urNp linux-2.6.29.5/net/mac80211/rate.c linux-2.6.29.5/net/mac80211/rate.c
+--- linux-2.6.29.5/net/mac80211/rate.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/net/mac80211/rate.c 2009-06-12 23:57:32.000000000 -0400
+@@ -256,7 +256,7 @@ int ieee80211_init_rate_ctrl_alg(struct
+ struct rate_control_ref *ref, *old;
+
+ ASSERT_RTNL();
+- if (local->open_count || netif_running(local->mdev))
++ if (atomic_read(&local->open_count) || netif_running(local->mdev))
+ return -EBUSY;
+
+ ref = rate_control_alloc(name, local);
+diff -urNp linux-2.6.29.5/net/sctp/socket.c linux-2.6.29.5/net/sctp/socket.c
+--- linux-2.6.29.5/net/sctp/socket.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/net/sctp/socket.c 2009-06-12 23:57:32.000000000 -0400
@@ -1434,7 +1434,7 @@ SCTP_STATIC int sctp_sendmsg(struct kioc
struct sctp_sndrcvinfo *sinfo;
struct sctp_initmsg *sinit;
@@ -36286,7 +40293,7 @@ diff -urNp linux-2.6.28.8/net/sctp/socket.c linux-2.6.28.8/net/sctp/socket.c
int err;
sctp_scope_t scope;
long timeo;
-@@ -5616,7 +5616,6 @@ pp_found:
+@@ -5756,7 +5756,6 @@ pp_found:
*/
int reuse = sk->sk_reuse;
struct sock *sk2;
@@ -36294,10 +40301,10 @@ diff -urNp linux-2.6.28.8/net/sctp/socket.c linux-2.6.28.8/net/sctp/socket.c
SCTP_DEBUG_PRINTK("sctp_get_port() found a possible match\n");
if (pp->fastreuse && sk->sk_reuse &&
-diff -urNp linux-2.6.28.8/net/socket.c linux-2.6.28.8/net/socket.c
---- linux-2.6.28.8/net/socket.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/net/socket.c 2009-03-07 04:29:14.000000000 -0500
-@@ -87,6 +87,7 @@
+diff -urNp linux-2.6.29.5/net/socket.c linux-2.6.29.5/net/socket.c
+--- linux-2.6.29.5/net/socket.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/net/socket.c 2009-06-12 23:57:32.000000000 -0400
+@@ -86,6 +86,7 @@
#include <linux/audit.h>
#include <linux/wireless.h>
#include <linux/nsproxy.h>
@@ -36305,7 +40312,7 @@ diff -urNp linux-2.6.28.8/net/socket.c linux-2.6.28.8/net/socket.c
#include <asm/uaccess.h>
#include <asm/unistd.h>
-@@ -97,6 +98,21 @@
+@@ -96,6 +97,21 @@
#include <net/sock.h>
#include <linux/netfilter.h>
@@ -36327,7 +40334,7 @@ diff -urNp linux-2.6.28.8/net/socket.c linux-2.6.28.8/net/socket.c
static int sock_no_open(struct inode *irrelevant, struct file *dontcare);
static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t pos);
-@@ -300,7 +316,7 @@ static int sockfs_get_sb(struct file_sys
+@@ -299,7 +315,7 @@ static int sockfs_get_sb(struct file_sys
mnt);
}
@@ -36336,7 +40343,7 @@ diff -urNp linux-2.6.28.8/net/socket.c linux-2.6.28.8/net/socket.c
static struct file_system_type sock_fs_type = {
.name = "sockfs",
-@@ -1235,6 +1251,16 @@ SYSCALL_DEFINE3(socket, int, family, int
+@@ -1234,6 +1250,16 @@ SYSCALL_DEFINE3(socket, int, family, int
if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
@@ -36353,7 +40360,7 @@ diff -urNp linux-2.6.28.8/net/socket.c linux-2.6.28.8/net/socket.c
retval = sock_create(family, type, protocol, &sock);
if (retval < 0)
goto out;
-@@ -1374,6 +1400,14 @@ SYSCALL_DEFINE3(bind, int, fd, struct so
+@@ -1366,6 +1392,14 @@ SYSCALL_DEFINE3(bind, int, fd, struct so
if (sock) {
err = move_addr_to_kernel(umyaddr, addrlen, (struct sockaddr *)&address);
if (err >= 0) {
@@ -36368,7 +40375,7 @@ diff -urNp linux-2.6.28.8/net/socket.c linux-2.6.28.8/net/socket.c
err = security_socket_bind(sock,
(struct sockaddr *)&address,
addrlen);
-@@ -1382,6 +1416,7 @@ SYSCALL_DEFINE3(bind, int, fd, struct so
+@@ -1374,6 +1408,7 @@ SYSCALL_DEFINE3(bind, int, fd, struct so
(struct sockaddr *)
&address, addrlen);
}
@@ -36376,7 +40383,7 @@ diff -urNp linux-2.6.28.8/net/socket.c linux-2.6.28.8/net/socket.c
fput_light(sock->file, fput_needed);
}
return err;
-@@ -1405,10 +1440,20 @@ SYSCALL_DEFINE2(listen, int, fd, int, ba
+@@ -1397,10 +1432,20 @@ SYSCALL_DEFINE2(listen, int, fd, int, ba
if ((unsigned)backlog > somaxconn)
backlog = somaxconn;
@@ -36397,7 +40404,7 @@ diff -urNp linux-2.6.28.8/net/socket.c linux-2.6.28.8/net/socket.c
fput_light(sock->file, fput_needed);
}
return err;
-@@ -1451,6 +1496,18 @@ SYSCALL_DEFINE4(accept4, int, fd, struct
+@@ -1443,6 +1488,18 @@ SYSCALL_DEFINE4(accept4, int, fd, struct
newsock->type = sock->type;
newsock->ops = sock->ops;
@@ -36416,7 +40423,7 @@ diff -urNp linux-2.6.28.8/net/socket.c linux-2.6.28.8/net/socket.c
/*
* We don't need try_module_get here, as the listening socket (sock)
* has the protocol module (sock->ops->owner) held.
-@@ -1494,6 +1551,7 @@ SYSCALL_DEFINE4(accept4, int, fd, struct
+@@ -1486,6 +1543,7 @@ SYSCALL_DEFINE4(accept4, int, fd, struct
err = newfd;
security_socket_post_accept(sock, newsock);
@@ -36424,7 +40431,7 @@ diff -urNp linux-2.6.28.8/net/socket.c linux-2.6.28.8/net/socket.c
out_put:
fput_light(sock->file, fput_needed);
-@@ -1532,6 +1590,7 @@ SYSCALL_DEFINE3(connect, int, fd, struct
+@@ -1524,6 +1582,7 @@ SYSCALL_DEFINE3(connect, int, fd, struct
int, addrlen)
{
struct socket *sock;
@@ -36432,7 +40439,7 @@ diff -urNp linux-2.6.28.8/net/socket.c linux-2.6.28.8/net/socket.c
struct sockaddr_storage address;
int err, fput_needed;
-@@ -1542,6 +1601,17 @@ SYSCALL_DEFINE3(connect, int, fd, struct
+@@ -1534,6 +1593,17 @@ SYSCALL_DEFINE3(connect, int, fd, struct
if (err < 0)
goto out_put;
@@ -36450,10 +40457,10 @@ diff -urNp linux-2.6.28.8/net/socket.c linux-2.6.28.8/net/socket.c
err =
security_socket_connect(sock, (struct sockaddr *)&address, addrlen);
if (err)
-diff -urNp linux-2.6.28.8/net/unix/af_unix.c linux-2.6.28.8/net/unix/af_unix.c
---- linux-2.6.28.8/net/unix/af_unix.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/net/unix/af_unix.c 2009-02-21 09:37:50.000000000 -0500
-@@ -727,6 +727,12 @@ static struct sock *unix_find_other(stru
+diff -urNp linux-2.6.29.5/net/unix/af_unix.c linux-2.6.29.5/net/unix/af_unix.c
+--- linux-2.6.29.5/net/unix/af_unix.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/net/unix/af_unix.c 2009-06-12 23:57:32.000000000 -0400
+@@ -734,6 +734,12 @@ static struct sock *unix_find_other(stru
err = -ECONNREFUSED;
if (!S_ISSOCK(inode->i_mode))
goto put_fail;
@@ -36466,7 +40473,7 @@ diff -urNp linux-2.6.28.8/net/unix/af_unix.c linux-2.6.28.8/net/unix/af_unix.c
u = unix_find_socket_byinode(net, inode);
if (!u)
goto put_fail;
-@@ -747,6 +753,13 @@ static struct sock *unix_find_other(stru
+@@ -754,6 +760,13 @@ static struct sock *unix_find_other(stru
if (u) {
struct dentry *dentry;
dentry = unix_sk(u)->dentry;
@@ -36480,18 +40487,16 @@ diff -urNp linux-2.6.28.8/net/unix/af_unix.c linux-2.6.28.8/net/unix/af_unix.c
if (dentry)
touch_atime(unix_sk(u)->mnt, dentry);
} else
-@@ -829,10 +842,20 @@ static int unix_bind(struct socket *sock
- err = mnt_want_write(nd.path.mnt);
+@@ -839,11 +852,18 @@ static int unix_bind(struct socket *sock
+ err = security_path_mknod(&nd.path, dentry, mode, 0);
if (err)
- goto out_mknod_dput;
-+
+ goto out_mknod_drop_write;
+ if (!gr_acl_handle_mknod(dentry, nd.path.dentry, nd.path.mnt, mode)) {
+ err = -EACCES;
-+ mnt_drop_write(nd.path.mnt);
-+ goto out_mknod_dput;
++ goto out_mknod_drop_write;
+ }
-+
err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, 0);
+ out_mknod_drop_write:
mnt_drop_write(nd.path.mnt);
if (err)
goto out_mknod_dput;
@@ -36501,7 +40506,7 @@ diff -urNp linux-2.6.28.8/net/unix/af_unix.c linux-2.6.28.8/net/unix/af_unix.c
mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
dput(nd.path.dentry);
nd.path.dentry = dentry;
-@@ -850,6 +873,10 @@ static int unix_bind(struct socket *sock
+@@ -861,6 +881,10 @@ out_mknod_drop_write:
goto out_unlock;
}
@@ -36512,9 +40517,48 @@ diff -urNp linux-2.6.28.8/net/unix/af_unix.c linux-2.6.28.8/net/unix/af_unix.c
list = &unix_socket_table[addr->hash];
} else {
list = &unix_socket_table[dentry->d_inode->i_ino & (UNIX_HASH_SIZE-1)];
-diff -urNp linux-2.6.28.8/scripts/pnmtologo.c linux-2.6.28.8/scripts/pnmtologo.c
---- linux-2.6.28.8/scripts/pnmtologo.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/scripts/pnmtologo.c 2009-02-21 09:37:50.000000000 -0500
+diff -urNp linux-2.6.29.5/scripts/mod/modpost.c linux-2.6.29.5/scripts/mod/modpost.c
+--- linux-2.6.29.5/scripts/mod/modpost.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/scripts/mod/modpost.c 2009-06-12 23:57:32.000000000 -0400
+@@ -830,6 +830,7 @@ enum mismatch {
+ INIT_TO_EXIT,
+ EXIT_TO_INIT,
+ EXPORT_TO_INIT_EXIT,
++ DATA_TO_TEXT
+ };
+
+ struct sectioncheck {
+@@ -891,6 +892,12 @@ const struct sectioncheck sectioncheck[]
+ .fromsec = { "__ksymtab*", NULL },
+ .tosec = { INIT_SECTIONS, EXIT_SECTIONS, NULL },
+ .mismatch = EXPORT_TO_INIT_EXIT
++},
++/* Do not reference code from writable data */
++{
++ .fromsec = { DATA_SECTIONS, NULL },
++ .tosec = { TEXT_SECTIONS, NULL },
++ .mismatch = DATA_TO_TEXT
+ }
+ };
+
+@@ -1249,6 +1256,14 @@ static void report_sec_mismatch(const ch
+ "Fix this by removing the %sannotation of %s "
+ "or drop the export.\n",
+ tosym, sec2annotation(tosec), sec2annotation(tosec), tosym);
++ case DATA_TO_TEXT:
++/*
++ fprintf(stderr,
++ "The variable %s references\n"
++ "the %s %s%s%s\n"
++ fromsym, to, sec2annotation(tosec), tosym, to_p);
++*/
++ break;
+ case NO_MISMATCH:
+ /* To get warnings on missing members */
+ break;
+diff -urNp linux-2.6.29.5/scripts/pnmtologo.c linux-2.6.29.5/scripts/pnmtologo.c
+--- linux-2.6.29.5/scripts/pnmtologo.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/scripts/pnmtologo.c 2009-06-12 23:57:32.000000000 -0400
@@ -237,14 +237,14 @@ static void write_header(void)
fprintf(out, " * Linux logo %s\n", logoname);
fputs(" */\n\n", out);
@@ -36541,10 +40585,10 @@ diff -urNp linux-2.6.28.8/scripts/pnmtologo.c linux-2.6.28.8/scripts/pnmtologo.c
logoname);
write_hex_cnt = 0;
for (i = 0; i < logo_clutsize; i++) {
-diff -urNp linux-2.6.28.8/security/commoncap.c linux-2.6.28.8/security/commoncap.c
---- linux-2.6.28.8/security/commoncap.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/security/commoncap.c 2009-03-07 04:29:14.000000000 -0500
-@@ -27,9 +27,11 @@
+diff -urNp linux-2.6.29.5/security/commoncap.c linux-2.6.29.5/security/commoncap.c
+--- linux-2.6.29.5/security/commoncap.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/security/commoncap.c 2009-06-12 23:57:32.000000000 -0400
+@@ -28,9 +28,11 @@
#include <linux/prctl.h>
#include <linux/securebits.h>
@@ -36552,62 +40596,15 @@ diff -urNp linux-2.6.28.8/security/commoncap.c linux-2.6.28.8/security/commoncap
+
int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
{
-- NETLINK_CB(skb).eff_cap = current->cap_effective;
+- NETLINK_CB(skb).eff_cap = current_cap();
+ NETLINK_CB(skb).eff_cap = gr_cap_rtnetlink(sk);
return 0;
}
-@@ -56,6 +58,14 @@ int cap_capable (struct task_struct *tsk
- return -EPERM;
- }
-
-+int cap_capable_nolog (struct task_struct *tsk, int cap)
-+{
-+ /* tsk = current for all callers */
-+ if (cap_raised(tsk->cap_effective, cap) && gr_is_capable_nolog(cap))
-+ return 0;
-+ return -EPERM;
-+}
-+
- int cap_settime(struct timespec *ts, struct timezone *tz)
- {
- if (!capable(CAP_SYS_TIME))
-@@ -379,8 +389,11 @@ void cap_bprm_apply_creds (struct linux_
- }
- }
-
-- current->suid = current->euid = current->fsuid = bprm->e_uid;
-- current->sgid = current->egid = current->fsgid = bprm->e_gid;
-+ if (!gr_check_user_change(-1, bprm->e_uid, bprm->e_uid))
-+ current->suid = current->euid = current->fsuid = bprm->e_uid;
-+
-+ if (!gr_check_group_change(-1, bprm->e_gid, bprm->e_gid))
-+ current->sgid = current->egid = current->fsgid = bprm->e_gid;
-
- /* For init, we want to retain the capabilities set
- * in the init_task struct. Thus we skip the usual
-@@ -393,6 +406,8 @@ void cap_bprm_apply_creds (struct linux_
- cap_clear(current->cap_effective);
- }
-
-+ gr_handle_chroot_caps(current);
-+
- /* AUD: Audit candidate if current->cap_effective is set */
-
- current->securebits &= ~issecure_mask(SECURE_KEEP_CAPS);
-@@ -705,7 +720,7 @@ int cap_vm_enough_memory(struct mm_struc
- {
- int cap_sys_admin = 0;
-
-- if (cap_capable(current, CAP_SYS_ADMIN) == 0)
-+ if (cap_capable_nolog(current, CAP_SYS_ADMIN) == 0)
- cap_sys_admin = 1;
- return __vm_enough_memory(mm, pages, cap_sys_admin);
- }
-diff -urNp linux-2.6.28.8/security/Kconfig linux-2.6.28.8/security/Kconfig
---- linux-2.6.28.8/security/Kconfig 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/security/Kconfig 2009-02-21 09:37:50.000000000 -0500
-@@ -4,6 +4,447 @@
+diff -urNp linux-2.6.29.5/security/Kconfig linux-2.6.29.5/security/Kconfig
+--- linux-2.6.29.5/security/Kconfig 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/security/Kconfig 2009-06-12 23:57:32.000000000 -0400
+@@ -4,6 +4,464 @@
menu "Security options"
@@ -37032,7 +41029,7 @@ diff -urNp linux-2.6.28.8/security/Kconfig linux-2.6.28.8/security/Kconfig
+
+config PAX_REFCOUNT
+ bool "Prevent various kernel object reference counter overflows"
-+ depends on X86
++ depends on GRKERNSEC && X86
+ help
+ By saying Y here the kernel will detect and prevent overflowing
+ various (but not all) kinds of object reference counters. Such
@@ -37048,6 +41045,23 @@ diff -urNp linux-2.6.28.8/security/Kconfig linux-2.6.28.8/security/Kconfig
+
+ Since this has a negligible performance impact, you should enable
+ this feature.
++
++config PAX_USERCOPY
++ bool "Bounds check heap object copies between kernel and userland"
++ depends on X86
++ depends on GRKERNSEC && (SLAB || SLUB || SLOB)
++ help
++ By saying Y here the kernel will enforce the size of heap objects
++ when they are copied in either direction between the kernel and
++ userland, even if only a part of the heap object is copied.
++
++ Specifically, this checking prevents information leaking from the
++ kernel heap during kernel to userland copies (if the kernel heap
++ object is otherwise fully initialized) and prevents kernel heap
++ overflows during userland to kernel copies.
++
++ Note that the current implementation provides the strictest checks
++ for the SLUB allocator.
+endmenu
+
+endmenu
@@ -37055,9 +41069,9 @@ diff -urNp linux-2.6.28.8/security/Kconfig linux-2.6.28.8/security/Kconfig
config KEYS
bool "Enable access key retention support"
help
-diff -urNp linux-2.6.28.8/sound/core/oss/pcm_oss.c linux-2.6.28.8/sound/core/oss/pcm_oss.c
---- linux-2.6.28.8/sound/core/oss/pcm_oss.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/sound/core/oss/pcm_oss.c 2009-02-21 09:37:50.000000000 -0500
+diff -urNp linux-2.6.29.5/sound/core/oss/pcm_oss.c linux-2.6.29.5/sound/core/oss/pcm_oss.c
+--- linux-2.6.29.5/sound/core/oss/pcm_oss.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/sound/core/oss/pcm_oss.c 2009-06-12 23:57:32.000000000 -0400
@@ -2929,8 +2929,8 @@ static void snd_pcm_oss_proc_done(struct
}
}
@@ -37069,9 +41083,9 @@ diff -urNp linux-2.6.28.8/sound/core/oss/pcm_oss.c linux-2.6.28.8/sound/core/oss
#endif /* CONFIG_SND_VERBOSE_PROCFS */
/*
-diff -urNp linux-2.6.28.8/sound/core/seq/seq_lock.h linux-2.6.28.8/sound/core/seq/seq_lock.h
---- linux-2.6.28.8/sound/core/seq/seq_lock.h 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/sound/core/seq/seq_lock.h 2009-02-21 09:37:50.000000000 -0500
+diff -urNp linux-2.6.29.5/sound/core/seq/seq_lock.h linux-2.6.29.5/sound/core/seq/seq_lock.h
+--- linux-2.6.29.5/sound/core/seq/seq_lock.h 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/sound/core/seq/seq_lock.h 2009-06-12 23:57:32.000000000 -0400
@@ -23,10 +23,10 @@ void snd_use_lock_sync_helper(snd_use_lo
#else /* SMP || CONFIG_SND_DEBUG */
@@ -37087,9 +41101,9 @@ diff -urNp linux-2.6.28.8/sound/core/seq/seq_lock.h linux-2.6.28.8/sound/core/se
#endif /* SMP || CONFIG_SND_DEBUG */
-diff -urNp linux-2.6.28.8/sound/pci/ac97/ac97_patch.c linux-2.6.28.8/sound/pci/ac97/ac97_patch.c
---- linux-2.6.28.8/sound/pci/ac97/ac97_patch.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/sound/pci/ac97/ac97_patch.c 2009-02-21 09:37:50.000000000 -0500
+diff -urNp linux-2.6.29.5/sound/pci/ac97/ac97_patch.c linux-2.6.29.5/sound/pci/ac97/ac97_patch.c
+--- linux-2.6.29.5/sound/pci/ac97/ac97_patch.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/sound/pci/ac97/ac97_patch.c 2009-06-12 23:57:32.000000000 -0400
@@ -1498,7 +1498,7 @@ static const struct snd_ac97_res_table a
{ AC97_VIDEO, 0x9f1f },
{ AC97_AUX, 0x9f1f },
@@ -37099,7 +41113,7 @@ diff -urNp linux-2.6.28.8/sound/pci/ac97/ac97_patch.c linux-2.6.28.8/sound/pci/a
};
static int patch_ad1819(struct snd_ac97 * ac97)
-@@ -3870,7 +3870,7 @@ static struct snd_ac97_res_table lm4550_
+@@ -3873,7 +3873,7 @@ static struct snd_ac97_res_table lm4550_
{ AC97_AUX, 0x1f1f },
{ AC97_PCM, 0x1f1f },
{ AC97_REC_GAIN, 0x0f0f },
@@ -37108,9 +41122,9 @@ diff -urNp linux-2.6.28.8/sound/pci/ac97/ac97_patch.c linux-2.6.28.8/sound/pci/a
};
static int patch_lm4550(struct snd_ac97 *ac97)
-diff -urNp linux-2.6.28.8/sound/pci/ens1370.c linux-2.6.28.8/sound/pci/ens1370.c
---- linux-2.6.28.8/sound/pci/ens1370.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/sound/pci/ens1370.c 2009-02-21 09:37:50.000000000 -0500
+diff -urNp linux-2.6.29.5/sound/pci/ens1370.c linux-2.6.29.5/sound/pci/ens1370.c
+--- linux-2.6.29.5/sound/pci/ens1370.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/sound/pci/ens1370.c 2009-06-12 23:57:32.000000000 -0400
@@ -452,7 +452,7 @@ static struct pci_device_id snd_audiopci
{ 0x1274, 0x5880, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* ES1373 - CT5880 */
{ 0x1102, 0x8938, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Ectiva EV1938 */
@@ -37120,9 +41134,9 @@ diff -urNp linux-2.6.28.8/sound/pci/ens1370.c linux-2.6.28.8/sound/pci/ens1370.c
};
MODULE_DEVICE_TABLE(pci, snd_audiopci_ids);
-diff -urNp linux-2.6.28.8/sound/pci/intel8x0.c linux-2.6.28.8/sound/pci/intel8x0.c
---- linux-2.6.28.8/sound/pci/intel8x0.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/sound/pci/intel8x0.c 2009-02-21 09:37:50.000000000 -0500
+diff -urNp linux-2.6.29.5/sound/pci/intel8x0.c linux-2.6.29.5/sound/pci/intel8x0.c
+--- linux-2.6.29.5/sound/pci/intel8x0.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/sound/pci/intel8x0.c 2009-06-12 23:57:32.000000000 -0400
@@ -443,7 +443,7 @@ static struct pci_device_id snd_intel8x0
{ 0x1022, 0x746d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* AMD8111 */
{ 0x1022, 0x7445, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* AMD768 */
@@ -37141,9 +41155,9 @@ diff -urNp linux-2.6.28.8/sound/pci/intel8x0.c linux-2.6.28.8/sound/pci/intel8x0
};
static int __devinit snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock,
-diff -urNp linux-2.6.28.8/sound/pci/intel8x0m.c linux-2.6.28.8/sound/pci/intel8x0m.c
---- linux-2.6.28.8/sound/pci/intel8x0m.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/sound/pci/intel8x0m.c 2009-02-21 09:37:50.000000000 -0500
+diff -urNp linux-2.6.29.5/sound/pci/intel8x0m.c linux-2.6.29.5/sound/pci/intel8x0m.c
+--- linux-2.6.29.5/sound/pci/intel8x0m.c 2009-05-18 19:52:34.000000000 -0400
++++ linux-2.6.29.5/sound/pci/intel8x0m.c 2009-06-12 23:57:32.000000000 -0400
@@ -239,7 +239,7 @@ static struct pci_device_id snd_intel8x0
{ 0x1022, 0x746d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* AMD8111 */
{ 0x10b9, 0x5455, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_ALI }, /* Ali5455 */
@@ -37162,10 +41176,10 @@ diff -urNp linux-2.6.28.8/sound/pci/intel8x0m.c linux-2.6.28.8/sound/pci/intel8x
};
static int __devinit snd_intel8x0m_probe(struct pci_dev *pci,
-diff -urNp linux-2.6.28.8/virt/kvm/kvm_main.c linux-2.6.28.8/virt/kvm/kvm_main.c
---- linux-2.6.28.8/virt/kvm/kvm_main.c 2009-02-06 16:47:45.000000000 -0500
-+++ linux-2.6.28.8/virt/kvm/kvm_main.c 2009-02-21 09:37:50.000000000 -0500
-@@ -1765,6 +1765,9 @@ static struct miscdevice kvm_dev = {
+diff -urNp linux-2.6.29.5/virt/kvm/kvm_main.c linux-2.6.29.5/virt/kvm/kvm_main.c
+--- linux-2.6.29.5/virt/kvm/kvm_main.c 2009-06-12 23:55:00.000000000 -0400
++++ linux-2.6.29.5/virt/kvm/kvm_main.c 2009-06-12 23:57:32.000000000 -0400
+@@ -2059,6 +2059,9 @@ static struct miscdevice kvm_dev = {
KVM_MINOR,
"kvm",
&kvm_chardev_ops,
@@ -37175,7 +41189,7 @@ diff -urNp linux-2.6.28.8/virt/kvm/kvm_main.c linux-2.6.28.8/virt/kvm/kvm_main.c
};
static void hardware_enable(void *junk)
-@@ -1996,7 +1999,7 @@ static void kvm_sched_out(struct preempt
+@@ -2290,7 +2293,7 @@ static void kvm_sched_out(struct preempt
kvm_arch_vcpu_put(vcpu);
}
diff --git a/core/linux-grsec/kernelconfig b/core/linux-grsec/kernelconfig
index f64fee1ad..425e5ceda 100644
--- a/core/linux-grsec/kernelconfig
+++ b/core/linux-grsec/kernelconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28.9
-# Tue Apr 14 09:36:21 2009
+# Linux kernel version: 2.6.29.5
+# Mon Jun 29 16:25:46 2009
#
# CONFIG_64BIT is not set
CONFIG_X86_32=y
@@ -60,7 +60,7 @@ CONFIG_EXPERIMENTAL=y
CONFIG_LOCK_KERNEL=y
CONFIG_INIT_ENV_ARG_LIMIT=32
CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
@@ -69,16 +69,25 @@ CONFIG_BSD_PROCESS_ACCT=y
CONFIG_BSD_PROCESS_ACCT_V3=y
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
CONFIG_IKCONFIG=m
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
# CONFIG_NAMESPACES is not set
@@ -112,7 +121,6 @@ CONFIG_PCI_QUIRKS=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -121,7 +129,6 @@ CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -129,12 +136,10 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
CONFIG_MODVERSIONS=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_STOP_MACHINE=y
CONFIG_BLOCK=y
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
CONFIG_BLK_DEV_BSG=y
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -151,7 +156,6 @@ CONFIG_IOSCHED_CFQ=m
CONFIG_DEFAULT_NOOP=y
CONFIG_DEFAULT_IOSCHED="noop"
CONFIG_PREEMPT_NOTIFIERS=y
-CONFIG_CLASSIC_RCU=y
CONFIG_FREEZER=y
#
@@ -162,6 +166,7 @@ CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
CONFIG_SMP=y
+# CONFIG_SPARSE_IRQ is not set
CONFIG_X86_FIND_SMP_CONFIG=y
CONFIG_X86_MPPARSE=y
CONFIG_X86_PC=y
@@ -170,7 +175,7 @@ CONFIG_X86_PC=y
# CONFIG_X86_GENERICARCH is not set
# CONFIG_X86_VSMP is not set
# CONFIG_X86_RDC321X is not set
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_PARAVIRT_GUEST=y
CONFIG_VMI=y
CONFIG_KVM_CLOCK=y
@@ -229,6 +234,7 @@ CONFIG_HPET_TIMER=y
CONFIG_HPET_EMULATE_RTC=y
CONFIG_DMI=y
# CONFIG_IOMMU_HELPER is not set
+# CONFIG_IOMMU_API is not set
CONFIG_NR_CPUS=8
# CONFIG_SCHED_SMT is not set
CONFIG_SCHED_MC=y
@@ -237,6 +243,7 @@ CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT is not set
CONFIG_X86_LOCAL_APIC=y
CONFIG_X86_IO_APIC=y
+# CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS is not set
# CONFIG_X86_MCE is not set
CONFIG_VM86=y
CONFIG_TOSHIBA=m
@@ -271,7 +278,6 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-CONFIG_RESOURCES_64BIT=y
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
@@ -329,14 +335,10 @@ CONFIG_ACPI_DOCK=y
CONFIG_ACPI_PROCESSOR=m
CONFIG_ACPI_HOTPLUG_CPU=y
CONFIG_ACPI_THERMAL=m
-CONFIG_ACPI_WMI=m
-CONFIG_ACPI_ASUS=m
-CONFIG_ACPI_TOSHIBA=m
# CONFIG_ACPI_CUSTOM_DSDT is not set
CONFIG_ACPI_BLACKLIST_YEAR=2000
# CONFIG_ACPI_DEBUG is not set
CONFIG_ACPI_PCI_SLOT=m
-CONFIG_ACPI_SYSTEM=y
CONFIG_X86_PM_TIMER=y
CONFIG_ACPI_CONTAINER=m
CONFIG_ACPI_SBS=m
@@ -384,10 +386,11 @@ CONFIG_X86_E_POWERSAVER=m
#
# shared options
#
-# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set
CONFIG_X86_SPEEDSTEP_LIB=m
CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK=y
-# CONFIG_CPU_IDLE is not set
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
#
# Bus options (PCI etc.)
@@ -410,6 +413,7 @@ CONFIG_PCIEASPM=y
CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
CONFIG_PCI_LEGACY=y
+CONFIG_PCI_STUB=m
CONFIG_HT_IRQ=y
CONFIG_ISA_DMA_API=y
CONFIG_ISA=y
@@ -467,6 +471,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=m
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -512,7 +517,7 @@ CONFIG_INET_DIAG=m
CONFIG_INET_TCP_DIAG=m
CONFIG_TCP_CONG_ADVANCED=y
CONFIG_TCP_CONG_BIC=m
-CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_CUBIC=y
CONFIG_TCP_CONG_WESTWOOD=m
CONFIG_TCP_CONG_HTCP=m
CONFIG_TCP_CONG_HSTCP=m
@@ -524,12 +529,12 @@ CONFIG_TCP_CONG_VENO=m
CONFIG_TCP_CONG_YEAH=m
CONFIG_TCP_CONG_ILLINOIS=m
# CONFIG_DEFAULT_BIC is not set
-# CONFIG_DEFAULT_CUBIC is not set
+CONFIG_DEFAULT_CUBIC=y
# CONFIG_DEFAULT_HTCP is not set
# CONFIG_DEFAULT_VEGAS is not set
# CONFIG_DEFAULT_WESTWOOD is not set
-CONFIG_DEFAULT_RENO=y
-CONFIG_DEFAULT_TCP_CONG="reno"
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="cubic"
CONFIG_TCP_MD5SIG=y
CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
@@ -679,7 +684,6 @@ CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_MATCH_AH=m
CONFIG_IP_NF_MATCH_ECN=m
CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_STEALTH=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
@@ -761,17 +765,15 @@ CONFIG_BRIDGE_EBT_ULOG=m
CONFIG_BRIDGE_EBT_NFLOG=m
CONFIG_IP_DCCP=m
CONFIG_INET_DCCP_DIAG=m
-CONFIG_IP_DCCP_ACKVEC=y
#
# DCCP CCIDs Configuration (EXPERIMENTAL)
#
-CONFIG_IP_DCCP_CCID2=m
# CONFIG_IP_DCCP_CCID2_DEBUG is not set
-CONFIG_IP_DCCP_CCID3=m
+CONFIG_IP_DCCP_CCID3=y
# CONFIG_IP_DCCP_CCID3_DEBUG is not set
CONFIG_IP_DCCP_CCID3_RTO=100
-CONFIG_IP_DCCP_TFRC_LIB=m
+CONFIG_IP_DCCP_TFRC_LIB=y
CONFIG_IP_SCTP=m
# CONFIG_SCTP_DBG_MSG is not set
# CONFIG_SCTP_DBG_OBJCNT is not set
@@ -832,6 +834,7 @@ CONFIG_NET_SCH_TBF=m
CONFIG_NET_SCH_GRED=m
CONFIG_NET_SCH_DSMARK=m
CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_DRR=m
CONFIG_NET_SCH_INGRESS=m
#
@@ -868,6 +871,7 @@ CONFIG_NET_ACT_SIMP=m
CONFIG_NET_ACT_SKBEDIT=m
# CONFIG_NET_CLS_IND is not set
CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
#
# Network testing
@@ -975,10 +979,16 @@ CONFIG_PHONET=m
CONFIG_FIB_RULES=y
CONFIG_WIRELESS=y
CONFIG_CFG80211=m
+# CONFIG_CFG80211_REG_DEBUG is not set
CONFIG_NL80211=y
CONFIG_WIRELESS_OLD_REGULATORY=y
CONFIG_WIRELESS_EXT=y
CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_LIB80211=m
+CONFIG_LIB80211_CRYPT_WEP=m
+CONFIG_LIB80211_CRYPT_CCMP=m
+CONFIG_LIB80211_CRYPT_TKIP=m
+# CONFIG_LIB80211_DEBUG is not set
CONFIG_MAC80211=m
#
@@ -992,11 +1002,8 @@ CONFIG_MAC80211_RC_DEFAULT="pid"
CONFIG_MAC80211_MESH=y
CONFIG_MAC80211_LEDS=y
# CONFIG_MAC80211_DEBUG_MENU is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_WIMAX=m
+CONFIG_WIMAX_DEBUG_LEVEL=8
CONFIG_RFKILL=m
CONFIG_RFKILL_INPUT=m
CONFIG_RFKILL_LEDS=y
@@ -1024,6 +1031,7 @@ CONFIG_MTD=m
# CONFIG_MTD_DEBUG is not set
CONFIG_MTD_CONCAT=m
CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_TESTS=m
CONFIG_MTD_REDBOOT_PARTS=m
CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
@@ -1076,9 +1084,7 @@ CONFIG_MTD_ABSENT=m
#
CONFIG_MTD_COMPLEX_MAPPINGS=y
CONFIG_MTD_PHYSMAP=m
-CONFIG_MTD_PHYSMAP_START=0x8000000
-CONFIG_MTD_PHYSMAP_LEN=0x4000000
-CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
CONFIG_MTD_SC520CDP=m
CONFIG_MTD_NETSC520=m
CONFIG_MTD_TS5500=m
@@ -1148,6 +1154,12 @@ CONFIG_MTD_ONENAND_2X_PROGRAM=y
CONFIG_MTD_ONENAND_SIM=m
#
+# LPDDR flash memory drivers
+#
+CONFIG_MTD_LPDDR=m
+CONFIG_MTD_QINFO_PROBE=m
+
+#
# UBI - Unsorted block images
#
CONFIG_MTD_UBI=m
@@ -1207,33 +1219,23 @@ CONFIG_VIRTIO_BLK=m
CONFIG_MISC_DEVICES=y
CONFIG_IBM_ASM=m
CONFIG_PHANTOM=m
-CONFIG_EEPROM_93CX6=m
CONFIG_SGI_IOC4=m
CONFIG_TIFM_CORE=m
CONFIG_TIFM_7XX1=m
-CONFIG_ACER_WMI=m
-CONFIG_ASUS_LAPTOP=m
-CONFIG_FUJITSU_LAPTOP=m
-# CONFIG_FUJITSU_LAPTOP_DEBUG is not set
-CONFIG_TC1100_WMI=m
-CONFIG_HP_WMI=m
CONFIG_ICS932S401=m
-CONFIG_MSI_LAPTOP=m
-CONFIG_PANASONIC_LAPTOP=m
-CONFIG_COMPAL_LAPTOP=m
-CONFIG_SONY_LAPTOP=m
-# CONFIG_SONYPI_COMPAT is not set
-CONFIG_THINKPAD_ACPI=m
-# CONFIG_THINKPAD_ACPI_DEBUG is not set
-CONFIG_THINKPAD_ACPI_BAY=y
-CONFIG_THINKPAD_ACPI_VIDEO=y
-CONFIG_THINKPAD_ACPI_HOTKEY_POLL=y
-CONFIG_INTEL_MENLOW=m
-CONFIG_EEEPC_LAPTOP=m
CONFIG_ENCLOSURE_SERVICES=m
CONFIG_HP_ILO=m
+CONFIG_DELL_LAPTOP=m
CONFIG_C2PORT=m
CONFIG_C2PORT_DURAMAR_2150=m
+
+#
+# EEPROM support
+#
+CONFIG_EEPROM_AT24=m
+CONFIG_EEPROM_AT25=m
+CONFIG_EEPROM_LEGACY=m
+CONFIG_EEPROM_93CX6=m
CONFIG_HAVE_IDE=y
CONFIG_IDE=m
@@ -1242,6 +1244,7 @@ CONFIG_IDE=m
#
CONFIG_IDE_TIMINGS=y
CONFIG_IDE_ATAPI=y
+CONFIG_IDE_LEGACY=y
# CONFIG_BLK_DEV_IDE_SATA is not set
CONFIG_IDE_GD=m
CONFIG_IDE_GD_ATA=y
@@ -1251,7 +1254,6 @@ CONFIG_BLK_DEV_DELKIN=m
CONFIG_BLK_DEV_IDECD=m
# CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS is not set
CONFIG_BLK_DEV_IDETAPE=m
-CONFIG_BLK_DEV_IDESCSI=m
CONFIG_BLK_DEV_IDEACPI=y
# CONFIG_IDE_TASK_IOCTL is not set
CONFIG_IDE_PROC_FS=y
@@ -1284,10 +1286,12 @@ CONFIG_BLK_DEV_TRIFLEX=m
CONFIG_BLK_DEV_CS5520=m
CONFIG_BLK_DEV_CS5530=m
CONFIG_BLK_DEV_CS5535=m
+CONFIG_BLK_DEV_CS5536=m
CONFIG_BLK_DEV_HPT366=m
CONFIG_BLK_DEV_JMICRON=m
CONFIG_BLK_DEV_SC1200=m
CONFIG_BLK_DEV_PIIX=m
+CONFIG_BLK_DEV_IT8172=m
CONFIG_BLK_DEV_IT8213=m
CONFIG_BLK_DEV_IT821X=m
CONFIG_BLK_DEV_NS87415=m
@@ -1363,6 +1367,7 @@ CONFIG_SCSI_SRP_ATTRS=m
CONFIG_SCSI_SRP_TGT_ATTRS=y
CONFIG_SCSI_LOWLEVEL=y
CONFIG_ISCSI_TCP=m
+CONFIG_SCSI_CXGB3_ISCSI=m
CONFIG_BLK_DEV_3W_XXXX_RAID=m
CONFIG_SCSI_3W_9XXX=m
CONFIG_SCSI_7000FASST=m
@@ -1399,6 +1404,8 @@ CONFIG_MEGARAID_SAS=m
CONFIG_SCSI_HPTIOP=m
CONFIG_SCSI_BUSLOGIC=m
CONFIG_SCSI_FLASHPOINT=y
+CONFIG_LIBFC=m
+CONFIG_FCOE=m
CONFIG_SCSI_DMX3191D=m
CONFIG_SCSI_DTC3280=m
CONFIG_SCSI_EATA=m
@@ -1622,7 +1629,11 @@ CONFIG_SMSC_PHY=m
CONFIG_BROADCOM_PHY=m
CONFIG_ICPLUS_PHY=m
CONFIG_REALTEK_PHY=m
+CONFIG_NATIONAL_PHY=m
+CONFIG_STE10XP=m
+CONFIG_LSI_ET1011C_PHY=m
CONFIG_MDIO_BITBANG=m
+CONFIG_MDIO_GPIO=m
CONFIG_NET_ETHERNET=y
CONFIG_MII=m
CONFIG_HAPPYMEAL=m
@@ -1647,6 +1658,7 @@ CONFIG_ENC28J60=m
CONFIG_NET_VENDOR_RACAL=y
CONFIG_NI52=m
CONFIG_NI65=m
+CONFIG_DNET=m
CONFIG_NET_TULIP=y
CONFIG_DE2104X=m
CONFIG_TULIP=m
@@ -1693,7 +1705,6 @@ CONFIG_B44_PCI=y
CONFIG_FORCEDETH=m
# CONFIG_FORCEDETH_NAPI is not set
CONFIG_CS89x0=m
-CONFIG_EEPRO100=m
CONFIG_E100=m
CONFIG_FEALNX=m
CONFIG_NATSEMI=m
@@ -1707,6 +1718,7 @@ CONFIG_8139TOO_PIO=y
CONFIG_R6040=m
CONFIG_SIS900=m
CONFIG_EPIC100=m
+CONFIG_SMSC9420=m
CONFIG_SUNDANCE=m
# CONFIG_SUNDANCE_MMIO is not set
CONFIG_TLAN=m
@@ -1741,10 +1753,12 @@ CONFIG_BNX2=m
CONFIG_QLA3XXX=m
CONFIG_ATL1=m
CONFIG_ATL1E=m
+CONFIG_ATL1C=m
CONFIG_JME=m
CONFIG_NETDEV_10000=y
CONFIG_CHELSIO_T1=m
CONFIG_CHELSIO_T1_1G=y
+CONFIG_CHELSIO_T3_DEPENDS=y
CONFIG_CHELSIO_T3=m
CONFIG_ENIC=m
CONFIG_IXGBE=m
@@ -1760,6 +1774,8 @@ CONFIG_TEHUTI=m
CONFIG_BNX2X=m
CONFIG_QLGE=m
CONFIG_SFC=m
+CONFIG_SFC_MTD=y
+CONFIG_BE2NET=m
# CONFIG_TR is not set
#
@@ -1773,15 +1789,6 @@ CONFIG_PCMCIA_WAVELAN=m
CONFIG_PCMCIA_NETWAVE=m
CONFIG_WLAN_80211=y
CONFIG_PCMCIA_RAYCS=m
-CONFIG_IPW2100=m
-CONFIG_IPW2100_MONITOR=y
-# CONFIG_IPW2100_DEBUG is not set
-CONFIG_IPW2200=m
-CONFIG_IPW2200_MONITOR=y
-CONFIG_IPW2200_RADIOTAP=y
-CONFIG_IPW2200_PROMISCUOUS=y
-CONFIG_IPW2200_QOS=y
-# CONFIG_IPW2200_DEBUG is not set
CONFIG_LIBERTAS=m
CONFIG_LIBERTAS_USB=m
CONFIG_LIBERTAS_CS=m
@@ -1791,6 +1798,7 @@ CONFIG_LIBERTAS_THINFIRM=m
CONFIG_LIBERTAS_THINFIRM_USB=m
CONFIG_AIRO=m
CONFIG_HERMES=m
+CONFIG_HERMES_CACHE_FW_ON_INIT=y
CONFIG_PLX_HERMES=m
CONFIG_TMD_HERMES=m
CONFIG_NORTEL_HERMES=m
@@ -1815,6 +1823,18 @@ CONFIG_P54_PCI=m
CONFIG_ATH5K=m
# CONFIG_ATH5K_DEBUG is not set
CONFIG_ATH9K=m
+# CONFIG_ATH9K_DEBUG is not set
+CONFIG_IPW2100=m
+CONFIG_IPW2100_MONITOR=y
+# CONFIG_IPW2100_DEBUG is not set
+CONFIG_IPW2200=m
+CONFIG_IPW2200_MONITOR=y
+CONFIG_IPW2200_RADIOTAP=y
+CONFIG_IPW2200_PROMISCUOUS=y
+CONFIG_IPW2200_QOS=y
+# CONFIG_IPW2200_DEBUG is not set
+CONFIG_LIBIPW=m
+# CONFIG_LIBIPW_DEBUG is not set
CONFIG_IWLWIFI=m
CONFIG_IWLCORE=m
# CONFIG_IWLWIFI_LEDS is not set
@@ -1873,6 +1893,14 @@ CONFIG_RT2X00_LIB_LEDS=y
# CONFIG_RT2X00_DEBUG is not set
#
+# WiMAX Wireless Broadband devices
+#
+CONFIG_WIMAX_I2400M=m
+CONFIG_WIMAX_I2400M_USB=m
+CONFIG_WIMAX_I2400M_SDIO=m
+CONFIG_WIMAX_I2400M_DEBUG_LEVEL=8
+
+#
# USB Network Adapters
#
CONFIG_USB_CATC=m
@@ -1969,6 +1997,7 @@ CONFIG_ATM_FORE200E_TX_RETRY=16
CONFIG_ATM_FORE200E_DEBUG=0
CONFIG_ATM_HE=m
CONFIG_ATM_HE_USE_SUNI=y
+CONFIG_ATM_SOLOS=m
CONFIG_FDDI=y
CONFIG_DEFXX=m
# CONFIG_DEFXX_MMIO is not set
@@ -2010,6 +2039,7 @@ CONFIG_MISDN_L1OIP=m
#
CONFIG_MISDN_HFCPCI=m
CONFIG_MISDN_HFCMULTI=m
+CONFIG_MISDN_HFCUSB=m
# CONFIG_ISDN_I4L is not set
CONFIG_ISDN_CAPI=m
# CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON is not set
@@ -2118,6 +2148,7 @@ CONFIG_JOYSTICK_JOYDUMP=m
CONFIG_JOYSTICK_XPAD=m
# CONFIG_JOYSTICK_XPAD_FF is not set
# CONFIG_JOYSTICK_XPAD_LEDS is not set
+CONFIG_JOYSTICK_WALKERA0701=m
CONFIG_INPUT_TABLET=y
CONFIG_TABLET_USB_ACECAD=m
CONFIG_TABLET_USB_AIPTEK=m
@@ -2129,6 +2160,7 @@ CONFIG_TOUCHSCREEN_ADS7846=m
CONFIG_TOUCHSCREEN_FUJITSU=m
CONFIG_TOUCHSCREEN_GUNZE=m
CONFIG_TOUCHSCREEN_ELO=m
+CONFIG_TOUCHSCREEN_WACOM_W8001=m
CONFIG_TOUCHSCREEN_MTOUCH=m
CONFIG_TOUCHSCREEN_INEXIO=m
CONFIG_TOUCHSCREEN_MK712=m
@@ -2154,6 +2186,7 @@ CONFIG_TOUCHSCREEN_USB_IDEALTEK=y
CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH=y
CONFIG_TOUCHSCREEN_USB_GOTOP=y
CONFIG_TOUCHSCREEN_TOUCHIT213=m
+CONFIG_TOUCHSCREEN_TSC2007=m
CONFIG_INPUT_MISC=y
CONFIG_INPUT_PCSPKR=m
CONFIG_INPUT_APANEL=m
@@ -2166,6 +2199,7 @@ CONFIG_INPUT_POWERMATE=m
CONFIG_INPUT_YEALINK=m
CONFIG_INPUT_CM109=m
CONFIG_INPUT_UINPUT=m
+CONFIG_INPUT_PCF50633_PMU=m
#
# Hardware I/O ports
@@ -2199,7 +2233,6 @@ CONFIG_ROCKETPORT=m
CONFIG_CYCLADES=m
# CONFIG_CYZ_INTR is not set
CONFIG_DIGIEPCA=m
-CONFIG_ESPSERIAL=m
CONFIG_MOXA_INTELLIO=m
CONFIG_MOXA_SMARTIO=m
CONFIG_ISI=m
@@ -2237,6 +2270,7 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_SERIAL_JSM=m
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
# CONFIG_LEGACY_PTYS is not set
CONFIG_PRINTER=m
# CONFIG_LP_CONSOLE is not set
@@ -2351,10 +2385,7 @@ CONFIG_SCx200_ACB=m
# Miscellaneous I2C Chip support
#
CONFIG_DS1682=m
-CONFIG_AT24=m
-CONFIG_SENSORS_EEPROM=m
CONFIG_SENSORS_PCF8591=m
-CONFIG_TPS65010=m
CONFIG_SENSORS_MAX6875=m
CONFIG_SENSORS_TSL2550=m
# CONFIG_I2C_DEBUG_CORE is not set
@@ -2369,12 +2400,12 @@ CONFIG_SPI_MASTER=y
#
CONFIG_SPI_BITBANG=m
CONFIG_SPI_BUTTERFLY=m
+CONFIG_SPI_GPIO=m
CONFIG_SPI_LM70_LLP=m
#
# SPI Protocol Masters
#
-CONFIG_SPI_AT25=m
CONFIG_SPI_SPIDEV=m
CONFIG_SPI_TLE62X0=m
CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
@@ -2417,6 +2448,7 @@ CONFIG_W1_MASTER_GPIO=m
#
CONFIG_W1_SLAVE_THERM=m
CONFIG_W1_SLAVE_SMEM=m
+CONFIG_W1_SLAVE_DS2431=m
CONFIG_W1_SLAVE_DS2433=m
# CONFIG_W1_SLAVE_DS2433_CRC is not set
CONFIG_W1_SLAVE_DS2760=m
@@ -2424,8 +2456,10 @@ CONFIG_W1_SLAVE_BQ27000=m
CONFIG_POWER_SUPPLY=y
# CONFIG_POWER_SUPPLY_DEBUG is not set
CONFIG_PDA_POWER=m
+CONFIG_WM8350_POWER=m
CONFIG_BATTERY_DS2760=m
CONFIG_BATTERY_BQ27x00=m
+CONFIG_CHARGER_PCF50633=m
CONFIG_HWMON=m
CONFIG_HWMON_VID=m
CONFIG_SENSORS_ABITUGURU=m
@@ -2442,6 +2476,7 @@ CONFIG_SENSORS_ADM9240=m
CONFIG_SENSORS_ADT7462=m
CONFIG_SENSORS_ADT7470=m
CONFIG_SENSORS_ADT7473=m
+CONFIG_SENSORS_ADT7475=m
CONFIG_SENSORS_K8TEMP=m
CONFIG_SENSORS_ASB100=m
CONFIG_SENSORS_ATXP1=m
@@ -2471,6 +2506,7 @@ CONFIG_SENSORS_LM87=m
CONFIG_SENSORS_LM90=m
CONFIG_SENSORS_LM92=m
CONFIG_SENSORS_LM93=m
+CONFIG_SENSORS_LTC4245=m
CONFIG_SENSORS_MAX1111=m
CONFIG_SENSORS_MAX1619=m
CONFIG_SENSORS_MAX6650=m
@@ -2506,6 +2542,7 @@ CONFIG_WATCHDOG=y
# Watchdog Device Drivers
#
CONFIG_SOFT_WATCHDOG=m
+CONFIG_WM8350_WATCHDOG=m
CONFIG_ACQUIRE_WDT=m
CONFIG_ADVANTECH_WDT=m
CONFIG_ALIM1535_WDT=m
@@ -2528,6 +2565,7 @@ CONFIG_60XX_WDT=m
CONFIG_SBC8360_WDT=m
CONFIG_SBC7240_WDT=m
CONFIG_CPU5_WDT=m
+CONFIG_SMSC_SCH311X_WDT=m
CONFIG_SMSC37B787_WDT=m
CONFIG_W83627HF_WDT=m
CONFIG_W83697HF_WDT=m
@@ -2577,15 +2615,19 @@ CONFIG_SSB_DRIVER_PCICORE=y
#
# Multifunction device drivers
#
-# CONFIG_MFD_CORE is not set
+CONFIG_MFD_CORE=m
CONFIG_MFD_SM501=m
# CONFIG_MFD_SM501_GPIO is not set
CONFIG_HTC_PASIC3=m
CONFIG_UCB1400_CORE=m
+CONFIG_TPS65010=m
# CONFIG_MFD_TMIO is not set
CONFIG_MFD_WM8400=m
CONFIG_MFD_WM8350=m
CONFIG_MFD_WM8350_I2C=m
+CONFIG_MFD_PCF50633=m
+CONFIG_PCF50633_ADC=m
+CONFIG_PCF50633_GPIO=m
CONFIG_REGULATOR=y
# CONFIG_REGULATOR_DEBUG is not set
# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
@@ -2593,6 +2635,7 @@ CONFIG_REGULATOR_VIRTUAL_CONSUMER=m
CONFIG_REGULATOR_BQ24022=m
CONFIG_REGULATOR_WM8350=m
CONFIG_REGULATOR_WM8400=m
+CONFIG_REGULATOR_PCF50633=m
#
# Multimedia devices
@@ -2637,7 +2680,6 @@ CONFIG_VIDEO_V4L1=m
CONFIG_VIDEOBUF_GEN=m
CONFIG_VIDEOBUF_DMA_SG=m
CONFIG_VIDEOBUF_VMALLOC=m
-CONFIG_VIDEOBUF_DMA_CONTIG=m
CONFIG_VIDEOBUF_DVB=m
CONFIG_VIDEO_BTCX=m
CONFIG_VIDEO_IR=m
@@ -2686,6 +2728,7 @@ CONFIG_VIDEO_SAA7114=m
CONFIG_VIDEO_SAA711X=m
CONFIG_VIDEO_SAA717X=m
CONFIG_VIDEO_SAA7191=m
+CONFIG_VIDEO_TVP514X=m
CONFIG_VIDEO_TVP5150=m
CONFIG_VIDEO_VPX3220=m
@@ -2744,6 +2787,7 @@ CONFIG_VIDEO_CX88=m
CONFIG_VIDEO_CX88_ALSA=m
CONFIG_VIDEO_CX88_BLACKBIRD=m
CONFIG_VIDEO_CX88_DVB=m
+CONFIG_VIDEO_CX88_MPEG=m
CONFIG_VIDEO_CX88_VP3054=m
CONFIG_VIDEO_CX23885=m
CONFIG_VIDEO_AU0828=m
@@ -2755,20 +2799,24 @@ CONFIG_SOC_CAMERA=m
CONFIG_SOC_CAMERA_MT9M001=m
# CONFIG_MT9M001_PCA9536_SWITCH is not set
CONFIG_SOC_CAMERA_MT9M111=m
+CONFIG_SOC_CAMERA_MT9T031=m
CONFIG_SOC_CAMERA_MT9V022=m
# CONFIG_MT9V022_PCA9536_SWITCH is not set
+CONFIG_SOC_CAMERA_TW9910=m
CONFIG_SOC_CAMERA_PLATFORM=m
-CONFIG_VIDEO_SH_MOBILE_CEU=m
+CONFIG_SOC_CAMERA_OV772X=m
CONFIG_V4L_USB_DRIVERS=y
CONFIG_USB_VIDEO_CLASS=m
CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
CONFIG_USB_GSPCA=m
CONFIG_USB_M5602=m
+CONFIG_USB_STV06XX=m
CONFIG_USB_GSPCA_CONEX=m
CONFIG_USB_GSPCA_ETOMS=m
CONFIG_USB_GSPCA_FINEPIX=m
CONFIG_USB_GSPCA_MARS=m
CONFIG_USB_GSPCA_OV519=m
+CONFIG_USB_GSPCA_OV534=m
CONFIG_USB_GSPCA_PAC207=m
CONFIG_USB_GSPCA_PAC7311=m
CONFIG_USB_GSPCA_SONIXB=m
@@ -2830,6 +2878,8 @@ CONFIG_RADIO_ZOLTRIX=m
CONFIG_USB_DSBR=m
CONFIG_USB_SI470X=m
CONFIG_USB_MR800=m
+CONFIG_RADIO_TEA5764=m
+# CONFIG_DVB_DYNAMIC_MINORS is not set
CONFIG_DVB_CAPTURE_DRIVERS=y
#
@@ -2903,6 +2953,13 @@ CONFIG_DVB_PLUTO2=m
CONFIG_DVB_DM1105=m
#
+# Supported FireWire (IEEE 1394) Adapters
+#
+CONFIG_DVB_FIREDTV=m
+CONFIG_DVB_FIREDTV_IEEE1394=y
+CONFIG_DVB_FIREDTV_INPUT=y
+
+#
# Supported DVB Frontends
#
@@ -2912,6 +2969,12 @@ CONFIG_DVB_DM1105=m
# CONFIG_DVB_FE_CUSTOMISE is not set
#
+# Multistandard (satellite) frontends
+#
+CONFIG_DVB_STB0899=m
+CONFIG_DVB_STB6100=m
+
+#
# DVB-S (satellite) frontends
#
CONFIG_DVB_CX24110=m
@@ -2923,8 +2986,10 @@ CONFIG_DVB_STB6000=m
CONFIG_DVB_STV0299=m
CONFIG_DVB_TDA8083=m
CONFIG_DVB_TDA10086=m
+CONFIG_DVB_TDA8261=m
CONFIG_DVB_VES1X93=m
CONFIG_DVB_TUNER_ITD1000=m
+CONFIG_DVB_TUNER_CX24113=m
CONFIG_DVB_TDA826X=m
CONFIG_DVB_TUA6100=m
CONFIG_DVB_CX24116=m
@@ -2965,11 +3030,17 @@ CONFIG_DVB_OR51211=m
CONFIG_DVB_OR51132=m
CONFIG_DVB_BCM3510=m
CONFIG_DVB_LGDT330X=m
+CONFIG_DVB_LGDT3304=m
CONFIG_DVB_S5H1409=m
CONFIG_DVB_AU8522=m
CONFIG_DVB_S5H1411=m
#
+# ISDB-T (terrestrial) frontends
+#
+CONFIG_DVB_S921=m
+
+#
# Digital terrestrial only tuners/PLL
#
CONFIG_DVB_PLL=m
@@ -3012,6 +3083,7 @@ CONFIG_DRM_RADEON=m
CONFIG_DRM_I810=m
CONFIG_DRM_I830=m
CONFIG_DRM_I915=m
+# CONFIG_DRM_I915_KMS is not set
CONFIG_DRM_MGA=m
CONFIG_DRM_SIS=m
CONFIG_DRM_VIA=m
@@ -3113,6 +3185,8 @@ CONFIG_FB_GEODE=y
CONFIG_FB_GEODE_LX=m
CONFIG_FB_GEODE_GX=m
CONFIG_FB_GEODE_GX1=m
+CONFIG_FB_TMIO=m
+CONFIG_FB_TMIO_ACCELL=y
CONFIG_FB_SM501=m
# CONFIG_FB_VIRTUAL is not set
CONFIG_FB_METRONOME=m
@@ -3126,7 +3200,7 @@ CONFIG_LCD_TDO24M=m
CONFIG_LCD_VGG2432A4=m
CONFIG_LCD_PLATFORM=m
CONFIG_BACKLIGHT_CLASS_DEVICE=m
-CONFIG_BACKLIGHT_CORGI=m
+CONFIG_BACKLIGHT_GENERIC=m
CONFIG_BACKLIGHT_PROGEAR=m
CONFIG_BACKLIGHT_CARILLO_RANCH=m
CONFIG_BACKLIGHT_MBP_NVIDIA=m
@@ -3162,6 +3236,7 @@ CONFIG_SND_TIMER=m
CONFIG_SND_PCM=m
CONFIG_SND_HWDEP=m
CONFIG_SND_RAWMIDI=m
+CONFIG_SND_JACK=y
CONFIG_SND_SEQUENCER=m
CONFIG_SND_SEQ_DUMMY=m
CONFIG_SND_OSSEMUL=y
@@ -3169,6 +3244,8 @@ CONFIG_SND_MIXER_OSS=m
CONFIG_SND_PCM_OSS=m
CONFIG_SND_PCM_OSS_PLUGINS=y
CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_HRTIMER=m
+CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
CONFIG_SND_DYNAMIC_MINORS=y
# CONFIG_SND_SUPPORT_OLD_API is not set
# CONFIG_SND_VERBOSE_PROCFS is not set
@@ -3273,6 +3350,7 @@ CONFIG_SND_FM801=m
# CONFIG_SND_FM801_TEA575X_BOOL is not set
CONFIG_SND_HDA_INTEL=m
CONFIG_SND_HDA_HWDEP=y
+# CONFIG_SND_HDA_RECONFIG is not set
CONFIG_SND_HDA_INPUT_BEEP=y
CONFIG_SND_HDA_CODEC_REALTEK=y
CONFIG_SND_HDA_CODEC_ANALOG=y
@@ -3280,6 +3358,8 @@ CONFIG_SND_HDA_CODEC_SIGMATEL=y
CONFIG_SND_HDA_CODEC_VIA=y
CONFIG_SND_HDA_CODEC_ATIHDMI=y
CONFIG_SND_HDA_CODEC_NVHDMI=y
+CONFIG_SND_HDA_CODEC_INTELHDMI=y
+CONFIG_SND_HDA_ELD=y
CONFIG_SND_HDA_CODEC_CONEXANT=y
CONFIG_SND_HDA_CODEC_CMEDIA=y
CONFIG_SND_HDA_CODEC_SI3054=y
@@ -3320,17 +3400,23 @@ CONFIG_SND_PCMCIA=y
CONFIG_SND_VXPOCKET=m
CONFIG_SND_PDAUDIOCF=m
CONFIG_SND_SOC=m
+CONFIG_SND_SOC_I2C_AND_SPI=m
CONFIG_SND_SOC_ALL_CODECS=m
CONFIG_SND_SOC_AD73311=m
CONFIG_SND_SOC_AK4535=m
CONFIG_SND_SOC_CS4270=m
+CONFIG_SND_SOC_L3=m
+CONFIG_SND_SOC_PCM3008=m
CONFIG_SND_SOC_SSM2602=m
CONFIG_SND_SOC_TLV320AIC23=m
CONFIG_SND_SOC_TLV320AIC26=m
CONFIG_SND_SOC_TLV320AIC3X=m
+CONFIG_SND_SOC_UDA134X=m
CONFIG_SND_SOC_UDA1380=m
+CONFIG_SND_SOC_WM8350=m
CONFIG_SND_SOC_WM8510=m
CONFIG_SND_SOC_WM8580=m
+CONFIG_SND_SOC_WM8728=m
CONFIG_SND_SOC_WM8731=m
CONFIG_SND_SOC_WM8750=m
CONFIG_SND_SOC_WM8753=m
@@ -3365,11 +3451,9 @@ CONFIG_USB_MOUSE=m
CONFIG_HID_A4TECH=m
CONFIG_HID_APPLE=m
CONFIG_HID_BELKIN=m
-CONFIG_HID_BRIGHT=m
CONFIG_HID_CHERRY=m
CONFIG_HID_CHICONY=m
CONFIG_HID_CYPRESS=m
-CONFIG_HID_DELL=m
CONFIG_HID_EZKEY=m
CONFIG_HID_GYRATION=m
CONFIG_HID_LOGITECH=m
@@ -3377,12 +3461,15 @@ CONFIG_HID_LOGITECH=m
# CONFIG_LOGIRUMBLEPAD2_FF is not set
CONFIG_HID_MICROSOFT=m
CONFIG_HID_MONTEREY=m
+CONFIG_HID_NTRIG=m
CONFIG_HID_PANTHERLORD=m
# CONFIG_PANTHERLORD_FF is not set
CONFIG_HID_PETALYNX=m
CONFIG_HID_SAMSUNG=m
CONFIG_HID_SONY=m
CONFIG_HID_SUNPLUS=m
+CONFIG_GREENASIA_FF=m
+CONFIG_HID_TOPSEED=m
CONFIG_THRUSTMASTER_FF=m
CONFIG_ZEROPLUS_FF=m
CONFIG_USB_SUPPORT=y
@@ -3403,7 +3490,7 @@ CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_OTG is not set
# CONFIG_USB_OTG_WHITELIST is not set
# CONFIG_USB_OTG_BLACKLIST_HUB is not set
-CONFIG_USB_MON=y
+CONFIG_USB_MON=m
CONFIG_USB_WUSB=m
CONFIG_USB_WUSB_CBAF=m
# CONFIG_USB_WUSB_CBAF_DEBUG is not set
@@ -3415,6 +3502,7 @@ CONFIG_USB_C67X00_HCD=m
CONFIG_USB_EHCI_HCD=m
# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_OXU210HP_HCD=m
CONFIG_USB_ISP116X_HCD=m
CONFIG_USB_ISP1760_HCD=m
CONFIG_USB_OHCI_HCD=m
@@ -3454,7 +3542,6 @@ CONFIG_USB_STORAGE=m
CONFIG_USB_STORAGE_DATAFAB=y
CONFIG_USB_STORAGE_FREECOM=y
CONFIG_USB_STORAGE_ISD200=y
-CONFIG_USB_STORAGE_DPCM=y
CONFIG_USB_STORAGE_USBAT=y
CONFIG_USB_STORAGE_SDDR09=y
CONFIG_USB_STORAGE_SDDR55=y
@@ -3512,12 +3599,14 @@ CONFIG_USB_SERIAL_SPCP8X5=m
CONFIG_USB_SERIAL_HP4X=m
CONFIG_USB_SERIAL_SAFE=m
CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_SIEMENS_MPI=m
CONFIG_USB_SERIAL_SIERRAWIRELESS=m
CONFIG_USB_SERIAL_TI=m
CONFIG_USB_SERIAL_CYBERJACK=m
CONFIG_USB_SERIAL_XIRCOM=m
CONFIG_USB_SERIAL_OPTION=m
CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
CONFIG_USB_SERIAL_DEBUG=m
#
@@ -3555,6 +3644,12 @@ CONFIG_USB_CXACRU=m
CONFIG_USB_UEAGLEATM=m
CONFIG_USB_XUSBATM=m
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+CONFIG_USB_GPIO_VBUS=m
CONFIG_UWB=m
CONFIG_UWB_HWA=m
CONFIG_UWB_WHCI=m
@@ -3604,11 +3699,12 @@ CONFIG_LEDS_CLASS=m
#
CONFIG_LEDS_NET48XX=m
CONFIG_LEDS_WRAP=m
+CONFIG_LEDS_ALIX2=m
CONFIG_LEDS_PCA9532=m
CONFIG_LEDS_GPIO=m
-CONFIG_LEDS_HP_DISK=m
CONFIG_LEDS_CLEVO_MAIL=m
CONFIG_LEDS_PCA955X=m
+CONFIG_LEDS_WM8350=m
#
# LED Triggers
@@ -3697,6 +3793,7 @@ CONFIG_RTC_DRV_M48T59=m
CONFIG_RTC_DRV_BQ4802=m
CONFIG_RTC_DRV_V3020=m
CONFIG_RTC_DRV_WM8350=m
+CONFIG_RTC_DRV_PCF50633=m
#
# on-CPU RTC drivers
@@ -3714,6 +3811,29 @@ CONFIG_UIO_PDRV_GENIRQ=m
CONFIG_UIO_SMX=m
CONFIG_UIO_SERCOS3=m
# CONFIG_STAGING is not set
+CONFIG_X86_PLATFORM_DEVICES=y
+CONFIG_ACER_WMI=m
+CONFIG_ASUS_LAPTOP=m
+CONFIG_FUJITSU_LAPTOP=m
+# CONFIG_FUJITSU_LAPTOP_DEBUG is not set
+CONFIG_TC1100_WMI=m
+CONFIG_HP_WMI=m
+CONFIG_MSI_LAPTOP=m
+CONFIG_PANASONIC_LAPTOP=m
+CONFIG_COMPAL_LAPTOP=m
+CONFIG_SONY_LAPTOP=m
+# CONFIG_SONYPI_COMPAT is not set
+CONFIG_THINKPAD_ACPI=m
+# CONFIG_THINKPAD_ACPI_DEBUGFACILITIES is not set
+# CONFIG_THINKPAD_ACPI_DEBUG is not set
+CONFIG_THINKPAD_ACPI_BAY=y
+CONFIG_THINKPAD_ACPI_VIDEO=y
+CONFIG_THINKPAD_ACPI_HOTKEY_POLL=y
+CONFIG_INTEL_MENLOW=m
+CONFIG_EEEPC_LAPTOP=m
+CONFIG_ACPI_WMI=m
+CONFIG_ACPI_ASUS=m
+CONFIG_ACPI_TOSHIBA=m
#
# Firmware Drivers
@@ -3741,8 +3861,8 @@ CONFIG_EXT3_FS_SECURITY=y
CONFIG_EXT4_FS=m
# CONFIG_EXT4DEV_COMPAT is not set
CONFIG_EXT4_FS_XATTR=y
-# CONFIG_EXT4_FS_POSIX_ACL is not set
-# CONFIG_EXT4_FS_SECURITY is not set
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
CONFIG_FS_XIP=y
CONFIG_JBD=m
CONFIG_JBD2=m
@@ -3765,19 +3885,24 @@ CONFIG_XFS_QUOTA=y
CONFIG_XFS_POSIX_ACL=y
CONFIG_XFS_RT=y
# CONFIG_XFS_DEBUG is not set
+CONFIG_GFS2_FS=m
+CONFIG_GFS2_FS_LOCKING_DLM=m
CONFIG_OCFS2_FS=m
CONFIG_OCFS2_FS_O2CB=m
CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
CONFIG_OCFS2_FS_STATS=y
CONFIG_OCFS2_DEBUG_MASKLOG=y
# CONFIG_OCFS2_DEBUG_FS is not set
-# CONFIG_OCFS2_COMPAT_JBD is not set
+CONFIG_OCFS2_FS_POSIX_ACL=y
+CONFIG_BTRFS_FS=m
+CONFIG_BTRFS_FS_POSIX_ACL=y
# CONFIG_DNOTIFY is not set
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_QUOTA_TREE=m
CONFIG_QFMT_V1=m
CONFIG_QFMT_V2=m
CONFIG_QUOTACTL=y
@@ -3817,10 +3942,7 @@ CONFIG_TMPFS=y
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_CONFIGFS_FS=m
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
CONFIG_ADFS_FS=m
# CONFIG_ADFS_FS_RW is not set
CONFIG_AFFS_FS=m
@@ -3855,6 +3977,9 @@ CONFIG_UBIFS_FS_LZO=y
CONFIG_UBIFS_FS_ZLIB=y
# CONFIG_UBIFS_FS_DEBUG is not set
CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
CONFIG_VXFS_FS=m
CONFIG_MINIX_FS=m
CONFIG_OMFS_FS=m
@@ -3972,10 +4097,15 @@ CONFIG_FRAME_WARN=1024
# CONFIG_DEBUG_KERNEL is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_DEBUG_MEMORY_INIT is not set
+CONFIG_ARCH_WANT_FRAME_POINTERS=y
+CONFIG_FRAME_POINTER=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_USER_STACKTRACE_SUPPORT=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
@@ -3993,6 +4123,7 @@ CONFIG_STRICT_DEVMEM=y
# CONFIG_EARLY_PRINTK is not set
# CONFIG_4KSTACKS is not set
# CONFIG_DOUBLEFAULT is not set
+CONFIG_HAVE_MMIOTRACE_SUPPORT=y
CONFIG_IO_DELAY_TYPE_0X80=0
CONFIG_IO_DELAY_TYPE_0XED=1
CONFIG_IO_DELAY_TYPE_UDELAY=2
@@ -4030,6 +4161,7 @@ CONFIG_GRKERNSEC_PROC_MEMMAP=y
#
# Role Based Access Control Options
#
+# CONFIG_GRKERNSEC_NO_RBAC is not set
CONFIG_GRKERNSEC_ACL_HIDEKERN=y
CONFIG_GRKERNSEC_ACL_MAXTRIES=3
CONFIG_GRKERNSEC_ACL_TIMEOUT=30
@@ -4084,6 +4216,7 @@ CONFIG_GRKERNSEC_EXECVE=y
# Network Protections
#
CONFIG_GRKERNSEC_RANDNET=y
+# CONFIG_GRKERNSEC_BLACKHOLE is not set
# CONFIG_GRKERNSEC_SOCKET is not set
#
@@ -4136,11 +4269,13 @@ CONFIG_PAX_RANDMMAP=y
# CONFIG_PAX_MEMORY_SANITIZE is not set
CONFIG_PAX_MEMORY_UDEREF=y
CONFIG_PAX_REFCOUNT=y
+# CONFIG_PAX_USERCOPY is not set
CONFIG_KEYS=y
# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
CONFIG_SECURITY=y
CONFIG_SECURITYFS=y
# CONFIG_SECURITY_NETWORK is not set
+# CONFIG_SECURITY_PATH is not set
CONFIG_SECURITY_FILE_CAPABILITIES=y
CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
CONFIG_XOR_BLOCKS=m
@@ -4159,7 +4294,7 @@ CONFIG_CRYPTO_AEAD=m
CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=m
CONFIG_CRYPTO_BLKCIPHER2=y
-CONFIG_CRYPTO_HASH=m
+CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_RNG=m
CONFIG_CRYPTO_RNG2=y
@@ -4254,11 +4389,12 @@ CONFIG_CRYPTO_DEV_GEODE=m
CONFIG_CRYPTO_DEV_HIFN_795X=m
CONFIG_CRYPTO_DEV_HIFN_795X_RNG=y
CONFIG_HAVE_KVM=y
+CONFIG_HAVE_KVM_IRQCHIP=y
CONFIG_VIRTUALIZATION=y
CONFIG_KVM=m
CONFIG_KVM_INTEL=m
CONFIG_KVM_AMD=m
-# CONFIG_LGUEST is not set
+CONFIG_LGUEST=m
CONFIG_VIRTIO=y
CONFIG_VIRTIO_RING=y
CONFIG_VIRTIO_PCI=m
@@ -4270,6 +4406,7 @@ CONFIG_VIRTIO_BALLOON=m
CONFIG_BITREVERSE=m
CONFIG_GENERIC_FIND_FIRST_BIT=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=m
CONFIG_CRC16=m
CONFIG_CRC_T10DIF=m
diff --git a/core/linux-grsec/linux-grsec.post-install b/core/linux-grsec/linux-grsec.post-install
new file mode 100644
index 000000000..626046f64
--- /dev/null
+++ b/core/linux-grsec/linux-grsec.post-install
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+# strip pkgrel from version
+ver=${1%-r[0-9]}
+
+mkinitfs $ver-grsec
+
diff --git a/core/linux-grsec/linux-grsec.post-upgrade b/core/linux-grsec/linux-grsec.post-upgrade
new file mode 120000
index 000000000..1e3bdc853
--- /dev/null
+++ b/core/linux-grsec/linux-grsec.post-upgrade
@@ -0,0 +1 @@
+linux-grsec.post-install \ No newline at end of file
diff --git a/core/linux-grsec/net-next-2.6.git-5ef12d98a19254ee5dc851bd83e214b43ec1f725.patch b/core/linux-grsec/net-next-2.6.git-5ef12d98a19254ee5dc851bd83e214b43ec1f725.patch
new file mode 100644
index 000000000..97983d79d
--- /dev/null
+++ b/core/linux-grsec/net-next-2.6.git-5ef12d98a19254ee5dc851bd83e214b43ec1f725.patch
@@ -0,0 +1,96 @@
+From: Timo Teras <timo.teras@iki.fi>
+Date: Thu, 11 Jun 2009 11:16:28 +0000 (-0700)
+Subject: neigh: fix state transition INCOMPLETE->FAILED via Netlink request
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fdavem%2Fnet-next-2.6.git;a=commitdiff_plain;h=5ef12d98a19254ee5dc851bd83e214b43ec1f725;hp=2b85a34e911bf483c27cfdd124aeb1605145dc80
+
+neigh: fix state transition INCOMPLETE->FAILED via Netlink request
+
+The current code errors out the INCOMPLETE neigh entry skb queue only from
+the timer if maximum probes have been attempted and there has been no reply.
+This also causes the transtion to FAILED state.
+
+However, the neigh entry can be also updated via Netlink to inform that the
+address is unavailable. Currently, neigh_update() just stops the timers and
+leaves the pending skb's unreleased. This results that the clean up code in
+the timer callback is never called, preventing also proper garbage collection.
+
+This fixes neigh_update() to process the pending skb queue immediately if
+INCOMPLETE -> FAILED state transtion occurs due to a Netlink request.
+
+Signed-off-by: Timo Teras <timo.teras@iki.fi>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+
+diff --git a/net/core/neighbour.c b/net/core/neighbour.c
+index c54229b..163b4f5 100644
+--- a/net/core/neighbour.c
++++ b/net/core/neighbour.c
+@@ -771,6 +771,28 @@ static __inline__ int neigh_max_probes(struct neighbour *n)
+ p->ucast_probes + p->app_probes + p->mcast_probes);
+ }
+
++static void neigh_invalidate(struct neighbour *neigh)
++{
++ struct sk_buff *skb;
++
++ NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed);
++ NEIGH_PRINTK2("neigh %p is failed.\n", neigh);
++ neigh->updated = jiffies;
++
++ /* It is very thin place. report_unreachable is very complicated
++ routine. Particularly, it can hit the same neighbour entry!
++
++ So that, we try to be accurate and avoid dead loop. --ANK
++ */
++ while (neigh->nud_state == NUD_FAILED &&
++ (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
++ write_unlock(&neigh->lock);
++ neigh->ops->error_report(neigh, skb);
++ write_lock(&neigh->lock);
++ }
++ skb_queue_purge(&neigh->arp_queue);
++}
++
+ /* Called when a timer expires for a neighbour entry. */
+
+ static void neigh_timer_handler(unsigned long arg)
+@@ -835,26 +857,9 @@ static void neigh_timer_handler(unsigned long arg)
+
+ if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
+ atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
+- struct sk_buff *skb;
+-
+ neigh->nud_state = NUD_FAILED;
+- neigh->updated = jiffies;
+ notify = 1;
+- NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed);
+- NEIGH_PRINTK2("neigh %p is failed.\n", neigh);
+-
+- /* It is very thin place. report_unreachable is very complicated
+- routine. Particularly, it can hit the same neighbour entry!
+-
+- So that, we try to be accurate and avoid dead loop. --ANK
+- */
+- while (neigh->nud_state == NUD_FAILED &&
+- (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
+- write_unlock(&neigh->lock);
+- neigh->ops->error_report(neigh, skb);
+- write_lock(&neigh->lock);
+- }
+- skb_queue_purge(&neigh->arp_queue);
++ neigh_invalidate(neigh);
+ }
+
+ if (neigh->nud_state & NUD_IN_TIMER) {
+@@ -1001,6 +1006,11 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
+ neigh->nud_state = new;
+ err = 0;
+ notify = old & NUD_VALID;
++ if ((old & (NUD_INCOMPLETE | NUD_PROBE)) &&
++ (new & NUD_FAILED)) {
++ neigh_invalidate(neigh);
++ notify = 1;
++ }
+ goto out;
+ }
+
diff --git a/core/linux-headers/APKBUILD b/core/linux-headers/APKBUILD
index d0db3617f..25bb30b38 100644
--- a/core/linux-headers/APKBUILD
+++ b/core/linux-headers/APKBUILD
@@ -1,19 +1,29 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=linux-headers
-pkgver=2.6.28.5
+pkgver=2.6.29.5
+_kernver=2.6.29
pkgrel=0
pkgdesc="Linux system headers"
url="http://kernel.org"
license='GPL-2'
-makedepends="linux-sources perl"
-options="!strip"
+makedepends="perl"
+options="!strip !tracedeps"
+source="ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-$_kernver.tar.bz2
+ ftp://ftp.kernel.org/pub/linux/kernel/v2.6/patch-$pkgver.bz2
+ linux-nbma-mroute-v4-2.6.29.diff
+ "
build() {
- mkdir -p "$srcdir/$pkgname"
+ cd $srcdir/linux-$_kernver
+ if [ "$_kernver" != "$pkgver" ]; then
+ bunzip2 -c < ../patch-$pkgver.bz2 | patch -p1 || return 1
+ fi
+
+ # opennhrp needs this ABI compat breaker
+ patch -p1 < ../linux-nbma-mroute-v4-2.6.29.diff || return 1
+
mkdir -p "$pkgdir/usr"
- make -C /usr/src/linux-$pkgver headers_install \
- INSTALL_HDR_PATH="$pkgdir/usr" \
- O="$srcdir/$pkgname"
+ make headers_install INSTALL_HDR_PATH="$pkgdir/usr"
find "$pkgdir/usr" \( -name .install -o -name ..install.cmd \) -exec \
rm -f {} \;
@@ -22,3 +32,6 @@ build() {
rm -rf "$pkgdir"/usr/include/drm
}
+md5sums="64921b5ff5cdadbccfcd3820f03be7d8 linux-2.6.29.tar.bz2
+bd23086872a85c9fd00163e9ab78038a patch-2.6.29.5.bz2
+0b9670600a6af0261f8c994fc585ef82 linux-nbma-mroute-v4-2.6.29.diff"
diff --git a/core/linux-headers/linux-nbma-mroute-v4-2.6.29.diff b/core/linux-headers/linux-nbma-mroute-v4-2.6.29.diff
new file mode 100644
index 000000000..a79adc281
--- /dev/null
+++ b/core/linux-headers/linux-nbma-mroute-v4-2.6.29.diff
@@ -0,0 +1,321 @@
+diff --git a/include/linux/mroute.h b/include/linux/mroute.h
+index 8a45569..13500a3 100644
+--- a/include/linux/mroute.h
++++ b/include/linux/mroute.h
+@@ -33,7 +33,7 @@
+ #define SIOCGETSGCNT (SIOCPROTOPRIVATE+1)
+ #define SIOCGETRPF (SIOCPROTOPRIVATE+2)
+
+-#define MAXVIFS 32
++#define MAXVIFS 256
+ typedef unsigned long vifbitmap_t; /* User mode code depends on this lot */
+ typedef unsigned short vifi_t;
+ #define ALL_VIFS ((vifi_t)(-1))
+@@ -41,7 +41,7 @@ typedef unsigned short vifi_t;
+ /*
+ * Same idea as select
+ */
+-
++
+ #define VIFM_SET(n,m) ((m)|=(1<<(n)))
+ #define VIFM_CLR(n,m) ((m)&=~(1<<(n)))
+ #define VIFM_ISSET(n,m) ((m)&(1<<(n)))
+@@ -53,7 +53,7 @@ typedef unsigned short vifi_t;
+ * Passed by mrouted for an MRT_ADD_VIF - again we use the
+ * mrouted 3.6 structures for compatibility
+ */
+-
++
+ struct vifctl {
+ vifi_t vifc_vifi; /* Index of VIF */
+ unsigned char vifc_flags; /* VIFF_ flags */
+@@ -66,11 +66,12 @@ struct vifctl {
+ #define VIFF_TUNNEL 0x1 /* IPIP tunnel */
+ #define VIFF_SRCRT 0x2 /* NI */
+ #define VIFF_REGISTER 0x4 /* register vif */
++#define VIFF_NBMA 0x10
+
+ /*
+ * Cache manipulation structures for mrouted and PIMd
+ */
+-
++
+ struct mfcctl
+ {
+ struct in_addr mfcc_origin; /* Origin of mcast */
+@@ -83,10 +84,10 @@ struct mfcctl
+ int mfcc_expire;
+ };
+
+-/*
++/*
+ * Group count retrieval for mrouted
+ */
+-
++
+ struct sioc_sg_req
+ {
+ struct in_addr src;
+@@ -113,7 +114,7 @@ struct sioc_vif_req
+ * This is the format the mroute daemon expects to see IGMP control
+ * data. Magically happens to be like an IP packet as per the original
+ */
+-
++
+ struct igmpmsg
+ {
+ __u32 unused1,unused2;
+@@ -190,7 +191,7 @@ struct vif_device
+
+ #define VIFF_STATIC 0x8000
+
+-struct mfc_cache
++struct mfc_cache
+ {
+ struct mfc_cache *next; /* Next entry on cache line */
+ __be32 mfc_mcastgrp; /* Group the entry belongs to */
+@@ -224,7 +225,7 @@ struct mfc_cache
+ #define MFC_HASH(a,b) (((((__force u32)(__be32)a)>>24)^(((__force u32)(__be32)b)>>26))&(MFC_LINES-1))
+ #else
+ #define MFC_HASH(a,b) ((((__force u32)(__be32)a)^(((__force u32)(__be32)b)>>2))&(MFC_LINES-1))
+-#endif
++#endif
+
+ #endif
+
+diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
+index 1466644..5adea03 100644
+--- a/net/ipv4/ipmr.c
++++ b/net/ipv4/ipmr.c
+@@ -116,6 +116,31 @@ static struct net_protocol pim_protocol;
+
+ static struct timer_list ipmr_expire_timer;
+
++static __be32 ipmr_get_skb_nbma(struct sk_buff *skb)
++{
++ union {
++ char addr[MAX_ADDR_LEN];
++ __be32 inaddr;
++ } u;
++
++ if (dev_parse_header(skb, u.addr) != 4)
++ return INADDR_ANY;
++
++ return u.inaddr;
++}
++
++static int ip_mr_match_vif_skb(struct vif_device *vif, struct sk_buff *skb)
++{
++ if (vif->dev != skb->dev)
++ return 0;
++
++ if (vif->flags & VIFF_NBMA)
++ return ipmr_get_skb_nbma(skb) == vif->remote;
++
++ return 1;
++}
++
++
+ /* Service routines creating virtual interfaces: DVMRP tunnels and PIMREG */
+
+ static void ipmr_del_tunnel(struct net_device *dev, struct vifctl *v)
+@@ -468,6 +493,7 @@ static int vif_add(struct vifctl *vifc, int mrtsock)
+ return err;
+ }
+ break;
++ case VIFF_NBMA:
+ case 0:
+ dev = ip_dev_find(&init_net, vifc->vifc_lcl_addr.s_addr);
+ if (!dev)
+@@ -502,7 +528,7 @@ static int vif_add(struct vifctl *vifc, int mrtsock)
+ v->pkt_in = 0;
+ v->pkt_out = 0;
+ v->link = dev->ifindex;
+- if (v->flags&(VIFF_TUNNEL|VIFF_REGISTER))
++ if (v->flags&(VIFF_TUNNEL|VIFF_REGISTER|VIFF_NBMA))
+ v->link = dev->iflink;
+
+ /* And finish update writing critical data */
+@@ -1191,12 +1217,15 @@ static inline int ipmr_forward_finish(struct sk_buff *skb)
+ {
+ struct ip_options * opt = &(IPCB(skb)->opt);
+
+- IP_INC_STATS_BH(dev_net(skb->dst->dev), IPSTATS_MIB_OUTFORWDATAGRAMS);
++ IP_INC_STATS_BH(dev_net(skb->dev), IPSTATS_MIB_OUTFORWDATAGRAMS);
+
+ if (unlikely(opt->optlen))
+ ip_forward_options(skb);
+
+- return dst_output(skb);
++ if (skb->dst != NULL)
++ return dst_output(skb);
++ else
++ return dev_queue_xmit(skb);
+ }
+
+ /*
+@@ -1208,7 +1237,8 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi)
+ const struct iphdr *iph = ip_hdr(skb);
+ struct vif_device *vif = &vif_table[vifi];
+ struct net_device *dev;
+- struct rtable *rt;
++ struct net_device *fromdev = skb->dev;
++ struct rtable *rt = NULL;
+ int encap = 0;
+
+ if (vif->dev == NULL)
+@@ -1236,6 +1266,19 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi)
+ if (ip_route_output_key(&init_net, &rt, &fl))
+ goto out_free;
+ encap = sizeof(struct iphdr);
++ dev = rt->u.dst.dev;
++ } else if (vif->flags&VIFF_NBMA) {
++ /* Fixme, we should take tunnel source address from the
++ * tunnel device binding if it exists */
++ struct flowi fl = { .oif = vif->link,
++ .nl_u = { .ip4_u =
++ { .daddr = vif->remote,
++ .tos = RT_TOS(iph->tos) } },
++ .proto = IPPROTO_GRE };
++ if (ip_route_output_key(&init_net, &rt, &fl))
++ goto out_free;
++ encap = LL_RESERVED_SPACE(rt->u.dst.dev);
++ dev = vif->dev;
+ } else {
+ struct flowi fl = { .oif = vif->link,
+ .nl_u = { .ip4_u =
+@@ -1244,34 +1287,39 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi)
+ .proto = IPPROTO_IPIP };
+ if (ip_route_output_key(&init_net, &rt, &fl))
+ goto out_free;
++ dev = rt->u.dst.dev;
+ }
+
+- dev = rt->u.dst.dev;
++ if (!(vif->flags & VIFF_NBMA)) {
++ if (skb->len+encap > dst_mtu(&rt->u.dst) && (ntohs(iph->frag_off) & IP_DF)) {
++ /* Do not fragment multicasts. Alas, IPv4 does not
++ allow to send ICMP, so that packets will disappear
++ to blackhole.
++ */
+
+- if (skb->len+encap > dst_mtu(&rt->u.dst) && (ntohs(iph->frag_off) & IP_DF)) {
+- /* Do not fragment multicasts. Alas, IPv4 does not
+- allow to send ICMP, so that packets will disappear
+- to blackhole.
+- */
+-
+- IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_FRAGFAILS);
+- ip_rt_put(rt);
+- goto out_free;
++ IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_FRAGFAILS);
++ goto out_free_rt;
++ }
+ }
+
+ encap += LL_RESERVED_SPACE(dev) + rt->u.dst.header_len;
+
+- if (skb_cow(skb, encap)) {
+- ip_rt_put(rt);
+- goto out_free;
+- }
++ if (skb_cow(skb, encap))
++ goto out_free_rt;
+
+ vif->pkt_out++;
+ vif->bytes_out += skb->len;
+
+ dst_release(skb->dst);
+- skb->dst = &rt->u.dst;
++ if (vif->flags & VIFF_NBMA) {
++ ip_rt_put(rt);
++ skb->dst = NULL;
++ rt = NULL;
++ } else {
++ skb->dst = &rt->u.dst;
++ }
+ ip_decrease_ttl(ip_hdr(skb));
++ skb->dev = dev;
+
+ /* FIXME: forward and output firewalls used to be called here.
+ * What do we do with netfilter? -- RR */
+@@ -1280,6 +1328,10 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi)
+ /* FIXME: extra output firewall step used to be here. --RR */
+ vif->dev->stats.tx_packets++;
+ vif->dev->stats.tx_bytes += skb->len;
++ } else if (vif->flags & VIFF_NBMA) {
++ if (dev_hard_header(skb, dev, ntohs(skb->protocol),
++ &vif->remote, NULL, 4) < 0)
++ goto out_free_rt;
+ }
+
+ IPCB(skb)->flags |= IPSKB_FORWARDED;
+@@ -1295,20 +1347,29 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi)
+ * not mrouter) cannot join to more than one interface - it will
+ * result in receiving multiple packets.
+ */
+- NF_HOOK(PF_INET, NF_INET_FORWARD, skb, skb->dev, dev,
++ NF_HOOK(PF_INET, NF_INET_FORWARD, skb, fromdev, dev,
+ ipmr_forward_finish);
+ return;
+
++out_free_rt:
++ if (rt != NULL)
++ ip_rt_put(rt);
+ out_free:
+ kfree_skb(skb);
+ return;
+ }
+
+-static int ipmr_find_vif(struct net_device *dev)
++static int ipmr_find_vif(struct net_device *dev, __be32 nbma_origin)
+ {
+ int ct;
+ for (ct=maxvif-1; ct>=0; ct--) {
+- if (vif_table[ct].dev == dev)
++ if (vif_table[ct].dev != dev)
++ continue;
++
++ if (vif_table[ct].flags & VIFF_NBMA) {
++ if (vif_table[ct].remote == nbma_origin)
++ break;
++ } else if (nbma_origin == INADDR_ANY)
+ break;
+ }
+ return ct;
+@@ -1328,7 +1389,7 @@ static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local
+ /*
+ * Wrong interface: drop packet and (maybe) send PIM assert.
+ */
+- if (vif_table[vif].dev != skb->dev) {
++ if (!ip_mr_match_vif_skb(&vif_table[vif], skb)) {
+ int true_vifi;
+
+ if (skb->rtable->fl.iif == 0) {
+@@ -1347,7 +1408,7 @@ static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local
+ }
+
+ cache->mfc_un.res.wrong_if++;
+- true_vifi = ipmr_find_vif(skb->dev);
++ true_vifi = ipmr_find_vif(skb->dev, ipmr_get_skb_nbma(skb));
+
+ if (true_vifi >= 0 && mroute_do_assert &&
+ /* pimsm uses asserts, when switching from RPT to SPT,
+@@ -1454,7 +1515,7 @@ int ip_mr_input(struct sk_buff *skb)
+ skb = skb2;
+ }
+
+- vif = ipmr_find_vif(skb->dev);
++ vif = ipmr_find_vif(skb->dev, ipmr_get_skb_nbma(skb));
+ if (vif >= 0) {
+ int err = ipmr_cache_unresolved(vif, skb);
+ read_unlock(&mrt_lock);
+@@ -1634,7 +1695,7 @@ int ipmr_get_route(struct sk_buff *skb, struct rtmsg *rtm, int nowait)
+ }
+
+ dev = skb->dev;
+- if (dev == NULL || (vif = ipmr_find_vif(dev)) < 0) {
++ if (dev == NULL || (vif = ipmr_find_vif(dev, INADDR_ANY)) < 0) {
+ read_unlock(&mrt_lock);
+ return -ENODEV;
+ }
diff --git a/core/linux-sources/APKBUILD b/core/linux-sources/APKBUILD
deleted file mode 100644
index 87ab39e37..000000000
--- a/core/linux-sources/APKBUILD
+++ /dev/null
@@ -1,26 +0,0 @@
-# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
-pkgname=linux-sources
-pkgver=2.6.28.5
-_kernver=2.6.28
-pkgrel=0
-pkgdesc="The vanilla Linux kernel sources"
-license=GPL-2
-options="!strip"
-url=http://kernel.org
-source="ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-$_kernver.tar.bz2
- ftp://ftp.kernel.org/pub/linux/kernel/v2.6/patch-$pkgver.bz2
- "
-
-build() {
- cd $srcdir/linux-$_kernver
- if [ "$_kernver" != "$pkgver" ]; then
- bunzip2 -c < ../patch-$pkgver.bz2 | patch -p1 || return 1
- fi
-
- mkdir -p "$pkgdir/usr/src"
- cd "$srcdir"
- mv "linux-$_kernver" "$pkgdir/usr/src/linux-$pkgver"
-}
-
-md5sums="d351e44709c9810b85e29b877f50968a linux-2.6.28.tar.bz2
-7a062fcdec46cec78c3fedbf558e334b patch-2.6.28.5.bz2"
diff --git a/core/lvm2/APKBUILD b/core/lvm2/APKBUILD
index 59384f487..d113a383c 100644
--- a/core/lvm2/APKBUILD
+++ b/core/lvm2/APKBUILD
@@ -1,6 +1,6 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=lvm2
-pkgver=2.02.47
+pkgver=2.02.48
pkgrel=0
pkgdesc="Logical Volume Manager 2 utilities"
url="http://sourceware.org/lvm2/"
@@ -31,5 +31,5 @@ build () {
install -d "$pkgdir"/etc/lvm/archive "$pkgdir"/etc/lvm/backup
install -Dm755 "$srcdir"/lvm.initd "$pkgdir"/etc/init.d/lvm
}
-md5sums="669d57ff97d171fd4e077c61da1f9a34 LVM2.2.02.47.tgz
+md5sums="0d24c2709f439eeca36261e5cea68330 LVM2.2.02.48.tgz
e60d88f78eedb9c1252deb5b9b9b978b lvm.initd"
diff --git a/core/mkinitfs/APKBUILD b/core/mkinitfs/APKBUILD
index 9851b70a5..d4b72297d 100644
--- a/core/mkinitfs/APKBUILD
+++ b/core/mkinitfs/APKBUILD
@@ -1,6 +1,6 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=mkinitfs
-pkgver=1.6.1
+pkgver=1.6.2
pkgrel=0
pkgdesc="Tool to generate initramfs images for Alpine"
url=http://git.alpinelinux.org/cgit/mkinitfs
@@ -10,8 +10,7 @@ license="GPL-2"
build() {
cd "$srcdir"/$pkgname-$pkgver
- patch -p1 < ../init.patch
make
make install DESTDIR="$pkgdir" || return 1
}
-md5sums="6f0cfaf7bc49d8d0236759124187305e mkinitfs-1.6.1.tar.bz2"
+md5sums="83afd0810ae7d71baa9d5f5c39e61842 mkinitfs-1.6.2.tar.bz2"
diff --git a/core/openntpd/APKBUILD b/core/openntpd/APKBUILD
index 118fe528a..38c11ca51 100644
--- a/core/openntpd/APKBUILD
+++ b/core/openntpd/APKBUILD
@@ -2,19 +2,18 @@
pkgname=openntpd
pkgver=3.9_p1
_myver=3.9p1
-pkgrel=3
+pkgrel=4
pkgdesc="Lightweight NTP server ported from OpenBSD"
url=http://www.openntpd.org/
install=openntpd.pre-install
subpackages="openntpd-doc"
-depends="uclibc openssl"
+depends=
makedepends="openssl-dev"
license=BSD
source="
ftp://ftp.openbsd.org/pub/OpenBSD/OpenNTPD/openntpd-$_myver.tar.gz
openntpd-3.9p1_reconnect_on_sendto_EINVAL.diff
- openntpd-3.9p1-ifaddr.patch
openntpd.conf.d
openntpd.rc
$install
@@ -22,7 +21,6 @@ source="
_prepare() {
cd "$srcdir/$pkgname-$_myver"
- patch -p1 < ../openntpd-3.9p1-ifaddr.patch
patch -p1 < ../openntpd-3.9p1_reconnect_on_sendto_EINVAL.diff
sed -i '/NTPD_USER/s:_ntp:ntp:' ntpd.h || return 1
}
@@ -36,9 +34,8 @@ _compile() {
_install() {
cd "$srcdir/$pkgname-$_myver"
make install DESTDIR="$pkgdir"
- mkdir -p "$pkgdir/etc/init.d" "$pkgdir/etc/conf.d"
- cp ../openntpd.rc "$pkgdir/etc/init.d/ntpd"
- cp ../openntpd.conf.d "$pkgdir/etc/conf.d/ntpd"
+ install -Dm755 ../openntpd.rc "$pkgdir/etc/init.d/ntpd"
+ install -Dm644 ../openntpd.conf.d "$pkgdir/etc/conf.d/ntpd"
}
@@ -47,7 +44,6 @@ build() {
}
md5sums="afc34175f38d08867c1403d9008600b3 openntpd-3.9p1.tar.gz
ae2f708b860975b64126bb316aeb6641 openntpd-3.9p1_reconnect_on_sendto_EINVAL.diff
-a1640ec40ac228338e60bd4fda42f84d openntpd-3.9p1-ifaddr.patch
e3eee9eb2ea092dfdf9d887cd6df5795 openntpd.conf.d
5000453927b7ae9943d51194c1042355 openntpd.rc
05349f95db78fb482798b2c6d1f9c61e openntpd.pre-install"
diff --git a/core/openntpd/openntpd-3.9p1-ifaddr.patch b/core/openntpd/openntpd-3.9p1-ifaddr.patch
deleted file mode 100644
index 4539fa123..000000000
--- a/core/openntpd/openntpd-3.9p1-ifaddr.patch
+++ /dev/null
@@ -1,12 +0,0 @@
---- openntpd-3.9p1.orig/server.c Thu Nov 6 10:11:16 2008
-+++ openntpd-3.9p1/server.c Thu Nov 6 10:11:36 2008
-@@ -23,9 +23,6 @@
- #include <sys/socket.h>
- #include <errno.h>
- #include <netinet/in.h>
--#ifdef HAVE_IFADDRS_H
--# include <ifaddrs.h>
--#endif
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
diff --git a/core/openrc/APKBUILD b/core/openrc/APKBUILD
index 6ba416ced..415f24a58 100644
--- a/core/openrc/APKBUILD
+++ b/core/openrc/APKBUILD
@@ -1,7 +1,7 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=openrc
pkgver=0.5.0
-pkgrel=5
+pkgrel=6
pkgdesc="OpenRC manages the services, startup and shutdown of a host"
url="http://roy.marples.name/openrc"
license='BSD-2'
@@ -52,5 +52,5 @@ b1e64885f301166df30be3e3cf5338ff hwdrivers.initd
098a1f16812f56fcb56eb6b6f0fa31f6 modules.initd
c77cb4a67aa7ef40dfb12dd1ff5bf5e2 modloop.initd
747168eee535e845179eaef5a3fcb334 networking.initd
-6e834194b246563fc5acd77e91e038c4 openrc.post-install
+71d823acc9935a8ac82649a94b5bc0b9 openrc.post-install
393ff61bc0bf2c07f9af81795554c584 openrc.post-upgrade"
diff --git a/core/openrc/openrc.post-install b/core/openrc/openrc.post-install
index de119c7d9..1d0201d3a 100644
--- a/core/openrc/openrc.post-install
+++ b/core/openrc/openrc.post-install
@@ -1,26 +1,35 @@
#!/bin/sh
+rc_update() {
+ local svc="$1"
+ local level="$2"
+ mkdir -p /etc/runlevels/$level
+ ln -sf /etc/init.d/$svc /etc/runlevels/$level
+}
+
if [ ! -d etc/rcS.d ] && [ ! -d etc/rcL.d ]; then
exit 0
fi
for i in etc/rc[SL].d/*; do
[ -L "$i" ] || continue
- svc=${i##*/S[0-9][0-9]}
+ oldsvc=${i##*/S[0-9][0-9]}
# some services are renamed
- case "$svc" in
+ case "$oldsvc" in
modutils) svc=modules;;
procps) svc=sysctl;;
bootmisc.sh) svc=bootmisc;;
keymap) svc=keymaps;;
+ *) svc=$oldsvc;;
esac
# add the service to correct "runlevel"
case "$svc" in
hwclock|modules|sysctl|hostname|keymaps|syslog|bootmisc)
- rc-update add $svc boot;;
- *) rc-update add $svc default;;
+ rc_update $svc boot;;
+ *) rc_update $svc default;;
esac
rm $i
done
+
diff --git a/core/openssl/APKBUILD b/core/openssl/APKBUILD
index 0ba7e4f1e..46d1e064b 100644
--- a/core/openssl/APKBUILD
+++ b/core/openssl/APKBUILD
@@ -1,19 +1,20 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=openssl
pkgver=0.9.8k
-pkgrel=0
+pkgrel=3
pkgdesc="Toolkit for SSL v2/v3 and TLS v1"
url=http://openssl.org
depends=
makedepends="perl"
license="openssl"
-subpackages="$pkgname-dev $pkgname-doc"
+subpackages="$pkgname-dev $pkgname-doc libcrypto"
source="http://www.openssl.org/source/${pkgname}-${pkgver}.tar.gz
http://www.linuxfromscratch.org/patches/downloads/openssl/openssl-0.9.8g-fix_manpages-1.patch
openssl-bb-basename.patch
openssl-0.9.8k-quote-cc.patch
+ openssl-0.9.8k-padlock-sha.patch
"
build() {
@@ -29,7 +30,18 @@ build() {
make -j1 INSTALL_PREFIX="$pkgdir" MANDIR=/usr/share/man install
}
+libcrypto() {
+ pkgdesc="Crypto library from openssl"
+ mkdir -p "$subpkgdir"/lib "$subpkgdir"/usr/lib
+ for i in "$pkgdir"/usr/lib/libcrypto*; do
+ mv $i "$subpkgdir"/lib/
+ ln -s ../../lib/${i##*/} "$subpkgdir"/usr/lib/${i##*/}
+ done
+ mv "$pkgdir"/usr/lib/engines "$subpkgdir"/usr/lib/
+}
+
md5sums="e555c6d58d276aec7fdc53363e338ab3 openssl-0.9.8k.tar.gz
04a6a88c2ee4badd4f8649792b73eaf3 openssl-0.9.8g-fix_manpages-1.patch
c6a9857a5dbd30cead0404aa7dd73977 openssl-bb-basename.patch
-c838eb8488896cfeb7de957a0cbe04ae openssl-0.9.8k-quote-cc.patch"
+c838eb8488896cfeb7de957a0cbe04ae openssl-0.9.8k-quote-cc.patch
+4c4f8c1482fb61aed5bd0fdec344d721 openssl-0.9.8k-padlock-sha.patch"
diff --git a/core/openssl/openssl-0.9.8k-padlock-sha.patch b/core/openssl/openssl-0.9.8k-padlock-sha.patch
new file mode 100644
index 000000000..63b27cea3
--- /dev/null
+++ b/core/openssl/openssl-0.9.8k-padlock-sha.patch
@@ -0,0 +1,897 @@
+#
+# OpenSSL patch to support VIA C7 hash engine
+# Written by: Timo Teras <timo.teras@iki.fi>
+# based on patch by: Michal Ludvig <michal@logix.cz>
+# http://www.logix.cz/michal/devel/padlock
+#
+Index: openssl-0.9.8k/crypto/engine/eng_padlock.c
+===================================================================
+--- openssl-0.9.8k.orig/crypto/engine/eng_padlock.c 2009-07-12 19:24:42.000000000 +0300
++++ openssl-0.9.8k/crypto/engine/eng_padlock.c 2009-07-13 13:07:26.000000000 +0300
+@@ -1,10 +1,13 @@
+-/*
++/*
+ * Support for VIA PadLock Advanced Cryptography Engine (ACE)
+ * Written by Michal Ludvig <michal@logix.cz>
+ * http://www.logix.cz/michal
+ *
+- * Big thanks to Andy Polyakov for a help with optimization,
+- * assembler fixes, port to MS Windows and a lot of other
++ * SHA support by Timo Teras <timo.teras@iki.fi> based on code
++ * originally by Michal Ludvig.
++ *
++ * Big thanks to Andy Polyakov for a help with optimization,
++ * assembler fixes, port to MS Windows and a lot of other
+ * valuable work on this engine!
+ */
+
+@@ -66,6 +69,13 @@
+ #include <stdio.h>
+ #include <string.h>
+
++#include <signal.h>
++#include <stdint.h>
++#include <unistd.h>
++#include <sys/mman.h>
++#include <sys/ucontext.h>
++#include <arpa/inet.h>
++
+ #include <openssl/opensslconf.h>
+ #include <openssl/crypto.h>
+ #include <openssl/dso.h>
+@@ -74,12 +84,23 @@
+ #ifndef OPENSSL_NO_AES
+ #include <openssl/aes.h>
+ #endif
++#ifndef OPENSSL_NO_SHA
++#include <openssl/sha.h>
++#endif
+ #include <openssl/rand.h>
+ #include <openssl/err.h>
+
+ #ifndef OPENSSL_NO_HW
+ #ifndef OPENSSL_NO_HW_PADLOCK
+
++/* PadLock RNG is disabled by default */
++#define PADLOCK_NO_RNG 1
++
++/* No ASM routines for SHA in MSC yet */
++#ifdef _MSC_VER
++#define OPENSSL_NO_SHA
++#endif
++
+ /* Attempt to have a single source for both 0.9.7 and 0.9.8 :-) */
+ #if (OPENSSL_VERSION_NUMBER >= 0x00908000L)
+ # ifndef OPENSSL_NO_DYNAMIC_ENGINE
+@@ -96,7 +117,7 @@
+ /* VIA PadLock AES is available *ONLY* on some x86 CPUs.
+ Not only that it doesn't exist elsewhere, but it
+ even can't be compiled on other platforms!
+-
++
+ In addition, because of the heavy use of inline assembler,
+ compiler choice is limited to GCC and Microsoft C. */
+ #undef COMPILE_HW_PADLOCK
+@@ -138,20 +159,42 @@
+ static int padlock_init(ENGINE *e);
+
+ /* RNG Stuff */
++#ifndef PADLOCK_NO_RNG
+ static RAND_METHOD padlock_rand;
++#endif
+
+ /* Cipher Stuff */
+ #ifndef OPENSSL_NO_AES
+ static int padlock_ciphers(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid);
+ #endif
+
++/* Digest Stuff */
++#ifndef OPENSSL_NO_SHA
++static int padlock_digests(ENGINE *e, const EVP_MD **digest, const int **nids, int nid);
++static volatile void *padlock_cached_sha_buffer = NULL;
++#endif
++
+ /* Engine names */
+ static const char *padlock_id = "padlock";
+ static char padlock_name[100];
+
+ /* Available features */
+-static int padlock_use_ace = 0; /* Advanced Cryptography Engine */
+-static int padlock_use_rng = 0; /* Random Number Generator */
++enum padlock_flags {
++ PADLOCK_RNG = 0x01,
++ PADLOCK_ACE = 0x02,
++ PADLOCK_ACE2 = 0x04,
++ PADLOCK_PHE = 0x08,
++ PADLOCK_PMM = 0x10
++};
++enum padlock_flags padlock_flags;
++
++#define PADLOCK_HAVE_RNG (padlock_flags & PADLOCK_RNG)
++#define PADLOCK_HAVE_ACE (padlock_flags & (PADLOCK_ACE|PADLOCK_ACE2))
++#define PADLOCK_HAVE_ACE1 (padlock_flags & PADLOCK_ACE)
++#define PADLOCK_HAVE_ACE2 (padlock_flags & PADLOCK_ACE2)
++#define PADLOCK_HAVE_PHE (padlock_flags & PADLOCK_PHE)
++#define PADLOCK_HAVE_PMM (padlock_flags & PADLOCK_PMM)
++
+ #ifndef OPENSSL_NO_AES
+ static int padlock_aes_align_required = 1;
+ #endif
+@@ -165,25 +208,30 @@
+ /* Check available features */
+ padlock_available();
+
+-#if 1 /* disable RNG for now, see commentary in vicinity of RNG code */
+- padlock_use_rng=0;
+-#endif
+-
+ /* Generate a nice engine name with available features */
+ BIO_snprintf(padlock_name, sizeof(padlock_name),
+- "VIA PadLock (%s, %s)",
+- padlock_use_rng ? "RNG" : "no-RNG",
+- padlock_use_ace ? "ACE" : "no-ACE");
++ "VIA PadLock: %s%s%s%s%s",
++ padlock_flags ? "" : "not supported",
++ PADLOCK_HAVE_RNG ? "RNG " : "",
++ PADLOCK_HAVE_ACE ? (PADLOCK_HAVE_ACE2 ? "ACE2 " : "ACE ") : "",
++ PADLOCK_HAVE_PHE ? "PHE " : "",
++ PADLOCK_HAVE_PMM ? "PMM " : "");
+
+- /* Register everything or return with an error */
++ /* Register everything or return with an error */
+ if (!ENGINE_set_id(e, padlock_id) ||
+ !ENGINE_set_name(e, padlock_name) ||
+
+- !ENGINE_set_init_function(e, padlock_init) ||
++ !ENGINE_set_init_function(e, padlock_init)
+ #ifndef OPENSSL_NO_AES
+- (padlock_use_ace && !ENGINE_set_ciphers (e, padlock_ciphers)) ||
++ || (PADLOCK_HAVE_ACE && !ENGINE_set_ciphers (e, padlock_ciphers))
++#endif
++#ifndef OPENSSL_NO_SHA
++ || (PADLOCK_HAVE_PHE && !ENGINE_set_digests (e, padlock_digests))
++#endif
++#ifndef PADLOCK_NO_RNG
++ || (PADLOCK_HAVE_RNG && !ENGINE_set_RAND (e, &padlock_rand))
+ #endif
+- (padlock_use_rng && !ENGINE_set_RAND (e, &padlock_rand))) {
++ ) {
+ return 0;
+ }
+
+@@ -213,7 +261,7 @@
+ static int
+ padlock_init(ENGINE *e)
+ {
+- return (padlock_use_rng || padlock_use_ace);
++ return (padlock_flags);
+ }
+
+ /* This stuff is needed if this ENGINE is being compiled into a self-contained
+@@ -247,7 +295,7 @@
+ #define AES_KEY_SIZE_192 24
+ #define AES_KEY_SIZE_256 32
+
+-/* Here we store the status information relevant to the
++/* Here we store the status information relevant to the
+ current context. */
+ /* BIG FAT WARNING:
+ * Inline assembler in PADLOCK_XCRYPT_ASM()
+@@ -306,7 +354,7 @@
+ {
+ int result = -1;
+
+- /* We're checking if the bit #21 of EFLAGS
++ /* We're checking if the bit #21 of EFLAGS
+ can be toggled. If yes = CPUID is available. */
+ asm volatile (
+ "pushf\n"
+@@ -322,7 +370,7 @@
+ "xorl %%eax, %%ecx\n"
+ "movl %%ecx, %0\n"
+ : "=r" (result) : : "eax", "ecx");
+-
++
+ return (result == 0);
+ }
+
+@@ -365,10 +413,22 @@
+ : "+a"(eax), "=d"(edx) : : "ecx");
+
+ /* Fill up some flags */
+- padlock_use_ace = ((edx & (0x3<<6)) == (0x3<<6));
+- padlock_use_rng = ((edx & (0x3<<2)) == (0x3<<2));
++ padlock_flags |= ((edx & (0x3<<3)) ? PADLOCK_RNG : 0);
++ padlock_flags |= ((edx & (0x3<<7)) ? PADLOCK_ACE : 0);
++ padlock_flags |= ((edx & (0x3<<9)) ? PADLOCK_ACE2 : 0);
++ padlock_flags |= ((edx & (0x3<<11)) ? PADLOCK_PHE : 0);
++ padlock_flags |= ((edx & (0x3<<13)) ? PADLOCK_PMM : 0);
++
++ return padlock_flags;
++}
+
+- return padlock_use_ace + padlock_use_rng;
++static inline void
++padlock_htonl_block(uint32_t *data, size_t count)
++{
++ while (count--) {
++ asm volatile ("bswapl %0" : "+r"(*data));
++ data++;
++ }
+ }
+
+ #ifndef OPENSSL_NO_AES
+@@ -377,17 +437,14 @@
+ padlock_bswapl(AES_KEY *ks)
+ {
+ size_t i = sizeof(ks->rd_key)/sizeof(ks->rd_key[0]);
+- unsigned int *key = ks->rd_key;
++ uint32_t *key = (uint32_t*) ks->rd_key;
+
+- while (i--) {
+- asm volatile ("bswapl %0" : "+r"(*key));
+- key++;
+- }
++ padlock_htonl_block(key, i);
+ }
+ #endif
+
+ /* Force key reload from memory to the CPU microcode.
+- Loading EFLAGS from the stack clears EFLAGS[30]
++ Loading EFLAGS from the stack clears EFLAGS[30]
+ which does the trick. */
+ static inline void
+ padlock_reload_key(void)
+@@ -423,7 +480,7 @@
+ }
+
+ /* Template for padlock_xcrypt_* modes */
+-/* BIG FAT WARNING:
++/* BIG FAT WARNING:
+ * The offsets used with 'leal' instructions
+ * describe items of the 'padlock_cipher_data'
+ * structure.
+@@ -475,7 +532,7 @@
+ * In case you wonder 'rep xcrypt*' instructions above are *not*
+ * affected by the Direction Flag and pointers advance toward
+ * larger addresses unconditionally.
+- */
++ */
+ static inline unsigned char *
+ padlock_memcpy(void *dst,const void *src,size_t n)
+ {
+@@ -501,7 +558,7 @@
+ _asm _emit 0x0f _asm _emit 0xa7 \
+ _asm _emit code
+
+-/* BIG FAT WARNING:
++/* BIG FAT WARNING:
+ * The offsets used with 'lea' instructions
+ * describe items of the 'padlock_cipher_data'
+ * structure.
+@@ -840,7 +897,7 @@
+ return 1;
+ }
+
+-/*
++/*
+ * Simplified version of padlock_aes_cipher() used when
+ * 1) both input and output buffers are at aligned addresses.
+ * or when
+@@ -895,7 +952,7 @@
+ # error "insane PADLOCK_CHUNK..."
+ #endif
+
+-/* Re-align the arguments to 16-Bytes boundaries and run the
++/* Re-align the arguments to 16-Bytes boundaries and run the
+ encryption function itself. This function is not AES-specific. */
+ static int
+ padlock_aes_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
+@@ -1157,6 +1214,470 @@
+
+ #endif /* OPENSSL_NO_AES */
+
++#ifndef OPENSSL_NO_SHA
++
++struct padlock_digest_data {
++ unsigned char output[128+16];
++ uint64_t total;
++
++ unsigned char *buffer;
++ size_t used;
++ size_t size;
++
++ void (*hash)(struct padlock_digest_data *data,
++ const void *buf, size_t len);
++ int (*update)(EVP_MD_CTX *ctx,
++ const void *buffer, size_t len);
++ int (*final)(EVP_MD_CTX *ctx, unsigned char *buffer);
++};
++
++#define DIGEST_DATA(ctx) ((struct padlock_digest_data *)(ctx->md_data))
++#define DIGEST_DATA_OUTPUT(dd) (uint32_t*)(((uintptr_t)(dd->output) + 15) & ~15)
++#define PADLOCK_BUFFER_PAGES 14
++
++static inline void *
++padlock_atomic_xchg(volatile void **mem, void *fixed)
++{
++ /* No lock prefix due the xchg asserts it anyway, and the
++ * funny unsigned long* cast is required to workaround some gcc
++ * problems if compiling in PIC mode */
++ asm volatile (
++ "xchg %0, %1"
++ : "=r"(fixed)
++ : "m"(*(unsigned long*)mem), "0"(fixed)
++ : "memory");
++ return fixed;
++}
++
++static void
++padlock_do_sha1(struct padlock_digest_data *data, const void *buf, size_t len)
++{
++ uint32_t *output = DIGEST_DATA_OUTPUT(data);
++ asm volatile (
++ "xsha1"
++ : "+S"(buf), "+D"(output)
++ : "c"(len), "a"(0));
++}
++
++static void
++padlock_do_sha256(struct padlock_digest_data *data, const void *buf, size_t len)
++{
++ uint32_t *output = DIGEST_DATA_OUTPUT(data);
++ asm volatile (
++ "xsha256"
++ : "+S"(buf), "+D"(output)
++ : "c"(len), "a"(0));
++}
++
++static void
++handle_sigsegv(int sig, siginfo_t *info, void *uctxp)
++{
++ ucontext_t *uctx = uctxp;
++
++ uctx->uc_mcontext.gregs[14] += 4;
++}
++
++static void
++padlock_sha_nonfinalizing(struct padlock_digest_data *data)
++{
++ struct sigaction act, oldact;
++ size_t bofs = 0;
++
++ if (data->used != data->size) {
++ bofs = data->size - data->used;
++ memmove(&data->buffer[bofs], data->buffer, data->used);
++ }
++
++ memset(&act, 0, sizeof(act));
++ act.sa_sigaction = handle_sigsegv;
++ act.sa_flags = SA_SIGINFO;
++ sigaction(SIGSEGV, &act, &oldact);
++ data->hash(data, &data->buffer[bofs], data->used + 64);
++ sigaction(SIGSEGV, &oldact, NULL);
++}
++
++static void
++padlock_free_buffer(void *buf)
++{
++ buf = padlock_atomic_xchg(&padlock_cached_sha_buffer, buf);
++ if (buf != NULL)
++ munmap(buf, (PADLOCK_BUFFER_PAGES + 1) * getpagesize());
++}
++
++static void *
++padlock_allocate_buffer(size_t *maxsize)
++{
++ void *buf;
++ size_t size, page;
++
++ page = getpagesize();
++ buf = padlock_atomic_xchg(&padlock_cached_sha_buffer, NULL);
++ if (buf != NULL)
++ goto ret;
++
++ size = (PADLOCK_BUFFER_PAGES + 1) * page;
++ buf = mmap(0, size, PROT_READ | PROT_WRITE,
++ MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
++ if (buf == NULL)
++ return NULL;
++
++ /* Try locking the pages to avoid swapping, but don't fail if
++ * we are over quota. */
++ mlock(buf, size);
++
++ if (mprotect(buf + PADLOCK_BUFFER_PAGES * page, page, PROT_NONE) < 0) {
++ munmap(buf, size);
++ return NULL;
++ }
++
++ret:
++ *maxsize = PADLOCK_BUFFER_PAGES * page - 64;
++
++ return buf;
++}
++
++static int
++padlock_multi_update(EVP_MD_CTX *ctx, const void *data, size_t len)
++{
++ struct padlock_digest_data *ddata = DIGEST_DATA(ctx);
++ size_t chunk_size;
++
++ if (ddata->buffer == NULL) {
++ ddata->buffer = padlock_allocate_buffer(&ddata->size);
++ }
++
++ while (len) {
++ if (ddata->used + len < ddata->size) {
++ memcpy(&ddata->buffer[ddata->used], data, len);
++ ddata->used += len;
++ ddata->total += len;
++ return 1;
++ }
++
++ chunk_size = ddata->size - ddata->used;
++ memcpy(&ddata->buffer[ddata->used], data, chunk_size);
++
++ data += chunk_size;
++ len -= chunk_size;
++ ddata->used = ddata->size;
++ ddata->total += chunk_size;
++ padlock_sha_nonfinalizing(ddata);
++ ddata->used = 0;
++ }
++
++ return 1;
++}
++
++static int
++padlock_oneshot_final(EVP_MD_CTX *ctx, unsigned char *md)
++{
++ struct padlock_digest_data *ddata = DIGEST_DATA(ctx);
++ size_t size = EVP_MD_CTX_size(ctx);
++ uint32_t *output = DIGEST_DATA_OUTPUT(ddata);
++
++ padlock_htonl_block(output, size / sizeof(uint32_t));
++ memcpy(md, output, size);
++
++ return 1;
++}
++
++static int
++padlock_multi_final(EVP_MD_CTX *ctx, unsigned char *md)
++{
++ static const char padding[64] = { 0x80, };
++ struct padlock_digest_data *ddata = DIGEST_DATA(ctx);
++
++ if (ddata->used == ddata->total) {
++ /* Sweet, everything fits in one buffer. */
++ ddata->hash(ddata, ddata->buffer, ddata->used);
++ } else {
++ /* Hardware already hashed some buffers.
++ * Do finalizing manually */
++ union {
++ uint64_t u64;
++ uint32_t u32[2];
++ } bits_le, bits;
++ size_t lastblocklen, padlen;
++
++ /* BigEndianise the length. */
++ bits_le.u64 = ddata->total * 8;
++ bits.u32[1] = htonl(bits_le.u32[0]);
++ bits.u32[0] = htonl(bits_le.u32[1]);
++
++ /* Append padding, leave space for length. */
++ lastblocklen = ddata->total & 63;
++ padlen = (lastblocklen < 56) ? (56 - lastblocklen) : ((64+56) - lastblocklen);
++ padlock_multi_update(ctx, padding, padlen);
++
++ /* Length in BigEndian64 */
++ padlock_multi_update(ctx, (const char *) &bits, sizeof(bits));
++
++ /* And finally calculate it */
++ padlock_sha_nonfinalizing(ddata);
++ }
++
++ return padlock_oneshot_final(ctx, md);
++}
++
++static int
++padlock_oneshot_update(EVP_MD_CTX *ctx, const void *data, size_t length)
++{
++ struct padlock_digest_data *ddata = DIGEST_DATA(ctx);
++
++ /* Oneshot update is only possible if context flags indicate so */
++ if (!(ctx->flags & EVP_MD_CTX_FLAG_ONESHOT)) {
++ ddata->update = padlock_multi_update;
++ ddata->final = padlock_multi_final;
++ return padlock_multi_update(ctx, data, length);
++ }
++
++ ddata->hash(ddata, data, length);
++ return 1;
++}
++
++static void
++padlock_sha_init(struct padlock_digest_data *ddata)
++{
++ ddata->total = 0;
++ ddata->buffer = NULL;
++ ddata->used = 0;
++ ddata->size = 0;
++ ddata->update = padlock_oneshot_update;
++ ddata->final = padlock_oneshot_final;
++}
++
++static int
++padlock_sha1_init(EVP_MD_CTX *ctx)
++{
++ struct padlock_digest_data *ddata = DIGEST_DATA(ctx);
++ uint32_t *output = DIGEST_DATA_OUTPUT(ddata);
++
++ output[0] = 0x67452301;
++ output[1] = 0xEFCDAB89;
++ output[2] = 0x98BADCFE;
++ output[3] = 0x10325476;
++ output[4] = 0xC3D2E1F0;
++
++ padlock_sha_init(ddata);
++ ddata->hash = padlock_do_sha1;
++
++ return 1;
++}
++
++static int
++padlock_sha224_init(EVP_MD_CTX *ctx)
++{
++ struct padlock_digest_data *ddata = DIGEST_DATA(ctx);
++ uint32_t *output = DIGEST_DATA_OUTPUT(ddata);
++
++ output[0] = 0xC1059ED8UL;
++ output[1] = 0x367CD507UL;
++ output[2] = 0x3070DD17UL;
++ output[3] = 0xF70E5939UL;
++ output[4] = 0xFFC00B31UL;
++ output[5] = 0x68581511UL;
++ output[6] = 0x64F98FA7UL;
++ output[7] = 0xBEFA4FA4UL;
++
++ padlock_sha_init(ddata);
++ ddata->hash = padlock_do_sha256;
++
++ return 1;
++}
++
++static int
++padlock_sha256_init(EVP_MD_CTX *ctx)
++{
++ struct padlock_digest_data *ddata = DIGEST_DATA(ctx);
++ uint32_t *output = DIGEST_DATA_OUTPUT(ddata);
++
++ output[0] = 0x6A09E667;
++ output[1] = 0xBB67AE85;
++ output[2] = 0x3C6EF372;
++ output[3] = 0xA54FF53A;
++ output[4] = 0x510E527F;
++ output[5] = 0x9B05688C;
++ output[6] = 0x1F83D9AB;
++ output[7] = 0x5BE0CD19;
++
++ padlock_sha_init(ddata);
++ ddata->hash = padlock_do_sha256;
++
++ return 1;
++}
++
++static int
++padlock_sha_update(EVP_MD_CTX *ctx, const void *data, size_t length)
++{
++ return DIGEST_DATA(ctx)->update(ctx, data, length);
++}
++
++static int
++padlock_sha_final(EVP_MD_CTX *ctx, unsigned char *md)
++{
++ return DIGEST_DATA(ctx)->final(ctx, md);
++}
++
++static int
++padlock_sha_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
++{
++ struct padlock_digest_data *dfrom = DIGEST_DATA(from);
++ struct padlock_digest_data *dto = DIGEST_DATA(to);
++
++ /* Copy the internal state */
++ memcpy(DIGEST_DATA_OUTPUT(dto), DIGEST_DATA_OUTPUT(dfrom), 128);
++ dto->total = dfrom->total - dfrom->used;
++ dto->hash = dfrom->hash;
++ dto->used = 0;
++
++ /* Try using oneshot update if possible */
++ if (dfrom->used == dfrom->total) {
++ dto->update = padlock_oneshot_update;
++ dto->final = padlock_oneshot_final;
++ } else {
++ dto->update = padlock_multi_update;
++ dto->final = padlock_multi_final;
++ }
++
++ /* Copy pending data - one oneshot destination, this means finalizing
++ * the contents if we are still on the first iteration. */
++ if (dfrom->buffer != NULL)
++ padlock_sha_update(to, dfrom->buffer, dfrom->used);
++
++ return 1;
++}
++
++static int
++padlock_sha_cleanup(EVP_MD_CTX *ctx)
++{
++ struct padlock_digest_data *ddata = DIGEST_DATA(ctx);
++
++ if (ddata->buffer != NULL)
++ padlock_free_buffer(ddata->buffer);
++ ddata->buffer = NULL;
++
++ return 1;
++}
++
++static const EVP_MD padlock_sha1_md = {
++ NID_sha1,
++ NID_sha1WithRSAEncryption,
++ SHA_DIGEST_LENGTH,
++ 0,
++ padlock_sha1_init,
++ padlock_sha_update,
++ padlock_sha_final,
++ padlock_sha_copy,
++ padlock_sha_cleanup,
++ EVP_PKEY_RSA_method,
++ SHA_CBLOCK,
++ sizeof(struct padlock_digest_data),
++};
++
++static const EVP_MD padlock_dss1_md = {
++ NID_dsa,
++ NID_dsaWithSHA1,
++ SHA_DIGEST_LENGTH,
++ 0,
++ padlock_sha1_init,
++ padlock_sha_update,
++ padlock_sha_final,
++ padlock_sha_copy,
++ padlock_sha_cleanup,
++ EVP_PKEY_DSA_method,
++ SHA_CBLOCK,
++ sizeof(struct padlock_digest_data),
++};
++
++static const EVP_MD padlock_sha224_md = {
++ NID_sha224,
++ NID_sha224WithRSAEncryption,
++ SHA224_DIGEST_LENGTH,
++ 0,
++ padlock_sha224_init,
++ padlock_sha_update,
++ padlock_sha_final,
++ padlock_sha_copy,
++ padlock_sha_cleanup,
++ EVP_PKEY_RSA_method,
++ SHA_CBLOCK,
++ sizeof(struct padlock_digest_data),
++};
++
++static const EVP_MD padlock_sha256_md = {
++ NID_sha256,
++ NID_sha256WithRSAEncryption,
++ SHA256_DIGEST_LENGTH,
++ 0,
++ padlock_sha256_init,
++ padlock_sha_update,
++ padlock_sha_final,
++ padlock_sha_copy,
++ padlock_sha_cleanup,
++ EVP_PKEY_RSA_method,
++ SHA_CBLOCK,
++ sizeof(struct padlock_digest_data),
++};
++
++static int padlock_digest_nids[] = {
++#if !defined(OPENSSL_NO_SHA)
++ NID_sha1,
++ NID_dsa,
++#endif
++#if !defined(OPENSSL_NO_SHA256)
++#if !defined(OPENSSL_NO_SHA224)
++ NID_sha224,
++#endif
++ NID_sha256,
++#endif
++};
++
++static int padlock_digest_nids_num = sizeof(padlock_digest_nids)/sizeof(padlock_digest_nids[0]);
++
++static int
++padlock_digests (ENGINE *e, const EVP_MD **digest, const int **nids, int nid)
++{
++ /* No specific digest => return a list of supported nids ... */
++ if (!digest) {
++ *nids = padlock_digest_nids;
++ return padlock_digest_nids_num;
++ }
++
++ /* ... or the requested "digest" otherwise */
++ switch (nid) {
++#if !defined(OPENSSL_NO_SHA)
++ case NID_sha1:
++ *digest = &padlock_sha1_md;
++ break;
++ case NID_dsa:
++ *digest = &padlock_dss1_md;
++ break;
++#endif
++
++#if !defined(OPENSSL_NO_SHA256)
++#if !defined(OPENSSL_NO_SHA224)
++ case NID_sha224:
++ *digest = &padlock_sha224_md;
++ break;
++#endif /* OPENSSL_NO_SHA224 */
++
++ case NID_sha256:
++ *digest = &padlock_sha256_md;
++ break;
++#endif /* OPENSSL_NO_SHA256 */
++
++ default:
++ /* Sorry, we don't support this NID */
++ *digest = NULL;
++ return 0;
++ }
++
++ return 1;
++}
++
++#endif /* OPENSSL_NO_SHA */
++
++#ifndef PADLOCK_NO_RNG
+ /* ===== Random Number Generator ===== */
+ /*
+ * This code is not engaged. The reason is that it does not comply
+@@ -1164,7 +1685,7 @@
+ * (posted at http://www.via.com.tw/en/viac3/c3.jsp) nor does it
+ * provide meaningful error control...
+ */
+-/* Wrapper that provides an interface between the API and
++/* Wrapper that provides an interface between the API and
+ the raw PadLock RNG */
+ static int
+ padlock_rand_bytes(unsigned char *output, int count)
+@@ -1212,6 +1733,7 @@
+ padlock_rand_bytes, /* pseudorand */
+ padlock_rand_status, /* rand status */
+ };
++#endif /* PADLOCK_NO_RNG */
+
+ #endif /* COMPILE_HW_PADLOCK */
+
+Index: openssl-0.9.8k/crypto/evp/p_sign.c
+===================================================================
+--- openssl-0.9.8k.orig/crypto/evp/p_sign.c 2009-07-13 11:01:02.000000000 +0300
++++ openssl-0.9.8k/crypto/evp/p_sign.c 2009-07-13 11:01:45.000000000 +0300
+@@ -5,21 +5,21 @@
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+- *
++ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+- *
++ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+- *
++ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+@@ -34,10 +34,10 @@
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+- * 4. If you include any Windows specific code (or a derivative thereof) from
++ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+- *
++ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+@@ -49,7 +49,7 @@
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+- *
++ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+@@ -105,6 +105,7 @@
+ return(0);
+ }
+ EVP_MD_CTX_init(&tmp_ctx);
++ M_EVP_MD_CTX_set_flags(&tmp_ctx,EVP_MD_CTX_FLAG_ONESHOT);
+ EVP_MD_CTX_copy_ex(&tmp_ctx,ctx);
+ if (ctx->digest->flags & EVP_MD_FLAG_SVCTX)
+ {
+Index: openssl-0.9.8k/crypto/evp/p_verify.c
+===================================================================
+--- openssl-0.9.8k.orig/crypto/evp/p_verify.c 2009-07-13 11:01:06.000000000 +0300
++++ openssl-0.9.8k/crypto/evp/p_verify.c 2009-07-13 11:02:11.000000000 +0300
+@@ -5,21 +5,21 @@
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+- *
++ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+- *
++ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+- *
++ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+@@ -34,10 +34,10 @@
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+- * 4. If you include any Windows specific code (or a derivative thereof) from
++ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+- *
++ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+@@ -49,7 +49,7 @@
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+- *
++ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+@@ -92,7 +92,8 @@
+ }
+
+ EVP_MD_CTX_init(&tmp_ctx);
+- EVP_MD_CTX_copy_ex(&tmp_ctx,ctx);
++ M_EVP_MD_CTX_set_flags(&tmp_ctx,EVP_MD_CTX_FLAG_ONESHOT);
++ EVP_MD_CTX_copy_ex(&tmp_ctx,ctx);
+ if (ctx->digest->flags & EVP_MD_FLAG_SVCTX)
+ {
+ EVP_MD_SVCTX sctmp;
diff --git a/core/parted/APKBUILD b/core/parted/APKBUILD
index 6ee3f3f04..a606b7579 100644
--- a/core/parted/APKBUILD
+++ b/core/parted/APKBUILD
@@ -1,12 +1,12 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=parted
pkgver=1.8.8
-pkgrel=0
+pkgrel=1
pkgdesc="Utility to create, destroy, resize, check and copy partitions"
url="http://www.gnu.org/software/parted/parted.html"
license="GPL3"
subpackages="$pkgname-dev $pkgname-doc"
-depends="libuuid uclibc readline ncurses"
+depends=
makedepends="pkgconfig e2fsprogs-dev readline-dev ncurses-dev"
source="ftp://ftp.gnu.org/pub/gnu/$pkgname/$pkgname-$pkgver.tar.gz
nocxx.patch"
@@ -18,6 +18,7 @@ build ()
./configure --prefix=/usr \
--disable-debug \
+ --disable-nls \
--disable-Werror
make || return 1
make DESTDIR="$pkgdir" install
diff --git a/core/readline/APKBUILD b/core/readline/APKBUILD
index 48addac30..3c26ba127 100644
--- a/core/readline/APKBUILD
+++ b/core/readline/APKBUILD
@@ -1,33 +1,25 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=readline
-_myver=5.2
-pkgver=${_myver}_p13
+_myver=6.0
+_patchver=003
+pkgver=${_myver}.${_patchver}
pkgrel=0
pkgdesc="GNU readline library"
url="ftp://ftp.cwru.edu/pub/bash/"
license="GPL"
-depends="uclibc ncurses"
-makedepends=""
+depends=
+makedepends="ncurses-dev"
subpackages="$pkgname-dev $pkgname-doc"
-source="ftp://ftp.gnu.org/gnu/readline/readline-5.2.tar.gz
- ftp://ftp.gnu.org/gnu/readline/readline-5.2-patches/readline52-001
- ftp://ftp.gnu.org/gnu/readline/readline-5.2-patches/readline52-002
- ftp://ftp.gnu.org/gnu/readline/readline-5.2-patches/readline52-003
- ftp://ftp.gnu.org/gnu/readline/readline-5.2-patches/readline52-004
- ftp://ftp.gnu.org/gnu/readline/readline-5.2-patches/readline52-005
- ftp://ftp.gnu.org/gnu/readline/readline-5.2-patches/readline52-006
- ftp://ftp.gnu.org/gnu/readline/readline-5.2-patches/readline52-007
- ftp://ftp.gnu.org/gnu/readline/readline-5.2-patches/readline52-008
- ftp://ftp.gnu.org/gnu/readline/readline-5.2-patches/readline52-009
- ftp://ftp.gnu.org/gnu/readline/readline-5.2-patches/readline52-010
- ftp://ftp.gnu.org/gnu/readline/readline-5.2-patches/readline52-011
- ftp://ftp.gnu.org/gnu/readline/readline-5.2-patches/readline52-012
- ftp://ftp.gnu.org/gnu/readline/readline-5.2-patches/readline52-013
+source="ftp://ftp.gnu.org/gnu/readline/readline-6.0.tar.gz
+ ftp://ftp.gnu.org/gnu/readline/readline-6.0-patches/readline60-001
+ ftp://ftp.gnu.org/gnu/readline/readline-6.0-patches/readline60-002
+ ftp://ftp.gnu.org/gnu/readline/readline-6.0-patches/readline60-003
"
build ()
{
cd "$srcdir/$pkgname-$_myver"
- for i in "$srcdir"/readline52-???; do
+ for i in "$srcdir"/readline60-???; do
msg "Applying ${i##*/}"
patch -Np2 -i ${i} || return 1
done
@@ -41,17 +33,7 @@ build ()
make DESTDIR="$pkgdir" install || return 1
}
-md5sums="e39331f32ad14009b9ff49cc10c5e751 readline-5.2.tar.gz
-9d4d41622aa9b230c57f68548ce87d8f readline52-001
-f03e512d14206e37f7d6a748b56b9476 readline52-002
-252b42d8750f1a94b6bdf086612dceb2 readline52-003
-a32333c2e603a3ed250514e91050e552 readline52-004
-8106796c09b789523a3a78ab69c04b6d readline52-005
-512188e2bf0837f7eca19dbf71f182ae readline52-006
-ac17aca62eb6fb398c9f2fe9de540aff readline52-007
-2484c392db021905f112cf97a94dfd4c readline52-008
-fc6eb35d07914fae5c57d49c12483ff7 readline52-009
-7a2bf3dc7ac7680b1461a5701100e91b readline52-010
-ef6cef6822663470f6ac8c517c5a7ec6 readline52-011
-e3e9f441c8111589855bc363e5640f6c readline52-012
-3e2e5f543ed268a68fd1fa839faade1a readline52-013"
+md5sums="b7f65a48add447693be6e86f04a63019 readline-6.0.tar.gz
+85c01ea031ad38a179053c67186bafed readline60-001
+4fad2a4ce987e3101229d0c8dfb0cd80 readline60-002
+80967f663864983a889af2eb53aea177 readline60-003"
diff --git a/core/sudo/APKBUILD b/core/sudo/APKBUILD
index 6d4b46ab0..75fd70f3c 100644
--- a/core/sudo/APKBUILD
+++ b/core/sudo/APKBUILD
@@ -1,12 +1,11 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=sudo
-pkgver=1.7.1
+pkgver=1.7.2
pkgrel=0
pkgdesc="Give certain users the ability to run some commands as root"
url="http://www.sudo.ws/sudo/"
license='custom ISC'
-depends='uclibc'
-backup='etc/sudoers'
+depends=
source="ftp://ftp.sudo.ws/pub/sudo/$pkgname-$pkgver.tar.gz"
subpackages="$pkgname-doc"
@@ -23,4 +22,4 @@ build() {
make -j1 DESTDIR="$pkgdir" install || return 1
}
-md5sums="af672524b2c854a67612bf4c743f58b8 sudo-1.7.1.tar.gz"
+md5sums="9caba8719c3e0f163880a05f02a48249 sudo-1.7.2.tar.gz"
diff --git a/core/uclibc/APKBUILD b/core/uclibc/APKBUILD
index 2b71c25f3..22914f15a 100644
--- a/core/uclibc/APKBUILD
+++ b/core/uclibc/APKBUILD
@@ -1,7 +1,7 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=uclibc
pkgver=0.9.30.1
-pkgrel=9
+pkgrel=11
pkgdesc="C library for developing embedded Linux systems"
url=http://uclibc.org
license="LGPL-2"
@@ -17,7 +17,9 @@ source="http://uclibc.org/downloads/$_mynamever.tar.bz2
0001-linuxthreads-fixes-from-Will-Newton-will.newton-AT-g.patch
pthread-new-aliasing-fix.diff
uclibc-resolv-cname-fix.diff
+ uclibc-i386-floating-stacks.diff
ppoll.patch
+ uclibc-fork-hook.diff
uclibcconfig
"
@@ -35,6 +37,8 @@ _compile() {
cd "$srcdir/$_mynamever/"
cp ../uclibcconfig .config
make silentoldconfig
+ # this is a hack to get uclibc-i386-floating-stacks.diff working
+ touch libc/sysdeps/linux/i386/sysdep.h
make || return 1
}
@@ -55,5 +59,7 @@ cf80c0d44a41e02f389be427ee615d61 uclibc-0.9.30.1-pthread_getattr_np.patch
bcd1c4c9c87f092fb4631559e6ec13ba 0001-linuxthreads-fixes-from-Will-Newton-will.newton-AT-g.patch
969187e1da84d0a0a5957b392a3d5a2b pthread-new-aliasing-fix.diff
bbb8475963e791f596c34c81ef5583d7 uclibc-resolv-cname-fix.diff
+0b3966ab7774ac42ecf34a7b596c661b uclibc-i386-floating-stacks.diff
60738298e377295d359768a09adac0bb ppoll.patch
+55bb709f5efd937df323f0d39a202cfd uclibc-fork-hook.diff
0a87f57d3e5001027f43b7c959d96319 uclibcconfig"
diff --git a/core/uclibc/uclibc-fork-hook.diff b/core/uclibc/uclibc-fork-hook.diff
new file mode 100644
index 000000000..012691883
--- /dev/null
+++ b/core/uclibc/uclibc-fork-hook.diff
@@ -0,0 +1,36 @@
+diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/fork.c b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/fork.c
+index e15b99b..70c750d 100644
+--- a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/fork.c
++++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/fork.c
+@@ -20,6 +20,7 @@
+ #include <errno.h>
+ #include <fork.h>
+ #include <bits/libc-lock.h>
++#include <internals.h>
+
+ struct fork_block __fork_block =
+ {
+@@ -28,3 +29,12 @@ struct fork_block __fork_block =
+ .parent_list = { &__fork_block.parent_list, &__fork_block.parent_list },
+ .child_list = { &__fork_block.child_list, &__fork_block.child_list }
+ };
++
++pid_t
++__libc_fork (void)
++{
++ return __libc_maybe_call2 (pthread_fork, (&__fork_block), ARCH_FORK ());
++}
++weak_alias (__libc_fork, __fork)
++libc_hidden_def (__fork)
++weak_alias (__libc_fork, fork)
+diff --git a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/fork.h b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/fork.h
+index 85477eb..1e7379e 100644
+--- a/libpthread/linuxthreads/sysdeps/unix/sysv/linux/fork.h
++++ b/libpthread/linuxthreads/sysdeps/unix/sysv/linux/fork.h
+@@ -54,5 +54,5 @@ extern int __register_atfork (void (*__prepare) (void),
+ void *dso_handle);
+
+ #ifndef ARCH_FORK
+-# define ARCH_FORK() __libc_fork()
++# define ARCH_FORK() INLINE_SYSCALL (fork, 0)
+ #endif
diff --git a/core/uclibc/uclibc-i386-floating-stacks.diff b/core/uclibc/uclibc-i386-floating-stacks.diff
new file mode 100644
index 000000000..553195e69
--- /dev/null
+++ b/core/uclibc/uclibc-i386-floating-stacks.diff
@@ -0,0 +1,23 @@
+--- uClibc-0.9.30.1/libpthread/linuxthreads/sysdeps/i386/pt-machine.h Thu Sep 25 13:55:14 2008
++++ /root/uClibc-0.9.30.1-patched/libpthread/linuxthreads/sysdeps/i386/pt-machine.h Wed Jun 24 13:13:31 2009
+@@ -113,6 +113,8 @@
+ }
+ #endif /* __ASSEMBLER__ */
+
++#include "./useldt.h"
++
+ #endif /* pt-machine.h */
+
+ #endif
+--- uClibc-0.9.30.1/libpthread/linuxthreads/sysdeps/i386/useldt.h Tue May 15 00:35:00 2007
++++ /root/uClibc-0.9.30.1-patched/libpthread/linuxthreads/sysdeps/i386/useldt.h Wed Jun 24 13:22:38 2009
+@@ -23,7 +23,8 @@
+ #include <stddef.h> /* For offsetof. */
+ #include <stdlib.h> /* For abort(). */
+ #include <sysdep.h>
+-
++#include <sys/syscall.h>
++#include <kernel-features.h>
+
+ /* We don't want to include the kernel header. So duplicate the
+ information. */
diff --git a/core/xtables-addons-grsec/APKBUILD b/core/xtables-addons-grsec/APKBUILD
new file mode 100644
index 000000000..60f45d8fc
--- /dev/null
+++ b/core/xtables-addons-grsec/APKBUILD
@@ -0,0 +1,39 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+_flavor=${FLAVOR:-grsec}
+_realname=xtables-addons
+
+# source the kernel version
+if [ -f ../linux-$_flavor/APKBUILD ]; then
+ . ../linux-$_flavor/APKBUILD
+fi
+_abi_release=$pkgver-${_flavor}
+
+# get pkgver from xtables-addons package
+if [ -f ../$_realname/APKBUILD ]; then
+ . ../$_realname/APKBUILD
+fi
+
+pkgname=${_realname}-${_flavor}
+pkgver=${pkgver:-1.17}
+pkgrel=0
+pkgdesc="Iptables extensions kernel modules"
+url="http://xtables-addons.sourceforge.net/"
+license="GPL"
+depends=
+makedepends="linux-${_flavor}-dev iptables-dev pkgconfig"
+install=
+subpackages=
+source="http://downloads.sourceforge.net/$_realname/$_realname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+
+ ./configure --prefix=/usr \
+ --with-kbuild=/usr/src/linux-headers-${_abi_release}
+
+ cd extensions
+ make CC="${CC:-gcc}" modules || return 1
+ make DESTDIR="$pkgdir" modules_install
+}
+
+md5sums="eca2e3f4f4904814e3a301539876fae6 xtables-addons-1.17.tar.bz2"
diff --git a/core/xtables-addons/APKBUILD b/core/xtables-addons/APKBUILD
index 49b1fc742..febbcdd72 100644
--- a/core/xtables-addons/APKBUILD
+++ b/core/xtables-addons/APKBUILD
@@ -1,42 +1,28 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
-_kflavor=${FLAVOR:-grsec}
-_kernver=2.6.28.9
-
pkgname=xtables-addons
-pkgver=1.14
-pkgrel=1
-pkgdesc="Xtables-addons is the successor to patch-o-matic(-ng)"
-url="http://jengelh.medozas.de/projects/xtables/"
+pkgver=1.17
+pkgrel=0
+pkgdesc="Netfilter userspace extensions for iptables"
+url="http://xtables-addons.sourceforge.net/"
license="GPL"
-depends="linux-$_kflavor"
-makedepends="linux-${_kflavor}-dev linux-${_kflavor}-sources iptables-dev pkgconfig"
+depends="iptables"
+makedepends="iptables-dev pkgconfig bash"
install=
-subpackages="$pkgname-doc $pkgname-${_kflavor}:mod"
-source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.bz2
- $pkgname-1.12-readlink.patch"
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.bz2"
build() {
- local kout="$srcdir"/$_kflavor
- mkdir -p "$kout"
- cd "$kout"
- cp /boot/config-$_kflavor .config || return 1
- cp /boot/Module.symvers-$_kflavor Module.symvers || return 1
- make -C /usr/src/linux-$_kernver-$_kflavor O=$PWD silentoldconfig \
- || return 1
- make modules_prepare
-
cd "$srcdir/$pkgname-$pkgver"
- for i in ../*.patch; do
- msg "Applying $i..."
- patch -p1 < $i || return
- done
-
./configure --prefix=/usr \
- --with-kbuild="$kout"
+ --mandir=/usr/share/man \
+ --without-kbuild
+
+ # we dont want to build or install modules. We hack the makefile
+ sed -i -e '/^all:/s/modules//; /^install:/s/modules_install//' \
+ extensions/GNUmakefile
- make CC="$CC" || return 1
+ make CC="${CC-gcc}" || return 1
make DESTDIR="$pkgdir" install
}
-md5sums="a17b178d137480b870a7aeb54aea44f8 xtables-addons-1.14.tar.bz2
-22bb434696be0960a6c758de17420e18 xtables-addons-1.12-readlink.patch"
+md5sums="eca2e3f4f4904814e3a301539876fae6 xtables-addons-1.17.tar.bz2"
diff --git a/core/xtables-addons/xtables-addons-1.12-readlink.patch b/core/xtables-addons/xtables-addons-1.12-readlink.patch
deleted file mode 100644
index 6f597738a..000000000
--- a/core/xtables-addons/xtables-addons-1.12-readlink.patch
+++ /dev/null
@@ -1,13 +0,0 @@
---- xtables-addons-1.12.orig/extensions/ipset/GNUmakefile.in 2009-03-19 14:38:02.000000000 +0000
-+++ xtables-addons-1.12/extensions/ipset/GNUmakefile.in 2009-03-19 14:40:28.000000000 +0000
-@@ -3,8 +3,8 @@
- top_srcdir := @top_srcdir@
- srcdir := @srcdir@
- datarootdir := @datarootdir@
--abstop_srcdir := $(shell readlink -e ${top_srcdir})
--abssrcdir := $(shell readlink -e ${srcdir})
-+abstop_srcdir := $(shell readlink -f ${top_srcdir})
-+abssrcdir := $(shell readlink -f ${srcdir})
-
- ifeq (${abstop_srcdir},)
- $(error Path resolution of ${top_srcdir} failed)
diff --git a/extra/acf-alpine-baselayout/APKBUILD b/extra/acf-alpine-baselayout/APKBUILD
index c3e9574cf..1f29cfb0b 100644
--- a/extra/acf-alpine-baselayout/APKBUILD
+++ b/extra/acf-alpine-baselayout/APKBUILD
@@ -1,6 +1,6 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=acf-alpine-baselayout
-pkgver=0.5.0
+pkgver=0.5.1
pkgrel=0
pkgdesc="A web-based system administration interface for alpine-baselayout"
url="http://git.alpinelinux.org/cgit/acf-alpine-baselayout"
@@ -12,4 +12,4 @@ build() {
cd "$srcdir/$pkgname-$pkgver"
make DESTDIR="$pkgdir" install
}
-md5sums="5b5c503f3350c5ef9f4cf5be81719e4e acf-alpine-baselayout-0.5.0.tar.bz2"
+md5sums="385620401b12c68e7bea1138505a1376 acf-alpine-baselayout-0.5.1.tar.bz2"
diff --git a/extra/acf-alpine-conf/APKBUILD b/extra/acf-alpine-conf/APKBUILD
index 8467e6324..fdb808017 100644
--- a/extra/acf-alpine-conf/APKBUILD
+++ b/extra/acf-alpine-conf/APKBUILD
@@ -1,6 +1,6 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=acf-alpine-conf
-pkgver=0.3.12
+pkgver=0.3.14
pkgrel=0
pkgdesc="A web-based system administration interface for alpine-conf"
url="http://git.alpinelinux.org/cgit/acf-alpine-conf"
@@ -12,4 +12,4 @@ build() {
cd "$srcdir/$pkgname-$pkgver"
make DESTDIR="$pkgdir" install
}
-md5sums="b4c5d5dd614a3585f4c941e847798f71 acf-alpine-conf-0.3.12.tar.bz2"
+md5sums="7f1f61e3188c0eadeba80b9436b26ebb acf-alpine-conf-0.3.14.tar.bz2"
diff --git a/extra/acf-core/APKBUILD b/extra/acf-core/APKBUILD
index 1dc55275b..73212736b 100644
--- a/extra/acf-core/APKBUILD
+++ b/extra/acf-core/APKBUILD
@@ -1,6 +1,6 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=acf-core
-pkgver=0.6.0
+pkgver=0.7.0
pkgrel=0
pkgdesc="A web-based system administration interface framework"
url="http://git.alpinelinux.org/cgit/acf-core"
@@ -12,4 +12,4 @@ build() {
cd "$srcdir/$pkgname-$pkgver"
make DESTDIR="$pkgdir" install
}
-md5sums="2b92e14da6b20cb093626f861025f92f acf-core-0.6.0.tar.bz2"
+md5sums="dbddfe49acb7cffc9b2bc4dbd11bb675 acf-core-0.7.0.tar.bz2"
diff --git a/extra/acf-fetchmail/APKBUILD b/extra/acf-fetchmail/APKBUILD
index 3065d63a7..c4638e342 100644
--- a/extra/acf-fetchmail/APKBUILD
+++ b/extra/acf-fetchmail/APKBUILD
@@ -1,6 +1,6 @@
# Contributor: Michael Mason <ms13sp@gmail.com>
pkgname=acf-fetchmail
-pkgver=0.3.0
+pkgver=0.4.0
pkgrel=0
pkgdesc="A web-based system administration interface for fetchmail"
url="http://git.alpinelinux.org/cgit/acf-fetchmail"
@@ -18,4 +18,4 @@ build() {
}
-md5sums="1fa9a7a46382757bdbae99fed539e28d acf-fetchmail-0.3.0.tar.bz2"
+md5sums="71c9d1245d4fa700e452e7a728ab42a8 acf-fetchmail-0.4.0.tar.bz2"
diff --git a/extra/acf-postgresql/APKBUILD b/extra/acf-postgresql/APKBUILD
index a86446ca8..88e8d68c7 100644
--- a/extra/acf-postgresql/APKBUILD
+++ b/extra/acf-postgresql/APKBUILD
@@ -1,7 +1,7 @@
# Contributor: Mika Havela <mika.havela@gmail.com>
# Maintainer: Mika Havela <mika.havela@gmail.com>
pkgname=acf-postgresql
-pkgver=0.2.0
+pkgver=0.3.0
pkgrel=0
pkgdesc="ACF module for postgresql"
url="http://git.alpinelinux.org/cgit/$pkgname"
@@ -19,4 +19,4 @@ build() {
}
-md5sums="9cef31e42ee80fbf5487835c52cf44b9 acf-postgresql-0.2.0.tar.bz2"
+md5sums="e2d712f1522c9ce9bd8f4a2a5bbe3209 acf-postgresql-0.3.0.tar.bz2"
diff --git a/extra/acf-samba/APKBUILD b/extra/acf-samba/APKBUILD
index e238c1b21..af0754859 100644
--- a/extra/acf-samba/APKBUILD
+++ b/extra/acf-samba/APKBUILD
@@ -1,6 +1,6 @@
# Contributor: Michael Mason <ms13sp@gmail.com>
pkgname=acf-samba
-pkgver=0.2.0
+pkgver=0.2.1
pkgrel=0
pkgdesc="A web-based system administration interface for samba"
url="http://git.alpinelinux.org/cgit/acf-samba"
@@ -18,4 +18,4 @@ build() {
}
-md5sums="092b41c639e47936674900b0c28f695e acf-samba-0.2.0.tar.bz2"
+md5sums="927edc6bb2204369b44ee8cd6dbc18a0 acf-samba-0.2.1.tar.bz2"
diff --git a/extra/acf-weblog/APKBUILD b/extra/acf-weblog/APKBUILD
new file mode 100644
index 000000000..15847a3f4
--- /dev/null
+++ b/extra/acf-weblog/APKBUILD
@@ -0,0 +1,20 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-weblog
+pkgver=0.2.0
+pkgrel=1
+pkgdesc="ACF for web proxy (squid and dansguardian) logfiles"
+url="http://git.alpinelinux.org/cgit/acf-weblog"
+license="GPL-2"
+depends="acf-core lua luasql-postgres wget postgresql-client"
+makedepends=""
+install=
+subpackages=""
+source="http://git.alpinelinux.org/cgit/$pkgname/snapshot/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="c3981ef8eca4684480d3df9474fc338b acf-weblog-0.2.0.tar.bz2"
diff --git a/extra/apr-util/APKBUILD b/extra/apr-util/APKBUILD
index e41878c32..38ab8eadf 100644
--- a/extra/apr-util/APKBUILD
+++ b/extra/apr-util/APKBUILD
@@ -1,11 +1,11 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=apr-util
-pkgver=1.3.4
+pkgver=1.3.7
pkgrel=0
pkgdesc="The Apache Portable Runtime"
url="http://apr.apache.org/"
license="APACHE"
-depends="apr expat libuuid"
+depends=
subpackages="$pkgname-dev"
makedepends="apr-dev expat-dev e2fsprogs-dev"
source="http://www.apache.org/dist/apr/$pkgname-$pkgver.tar.bz2"
@@ -29,4 +29,4 @@ build() {
rm "$pkgdir"/usr/lib/*.exp
}
-md5sums="adfbe525cf3914cf769340e8f6a6d14b apr-util-1.3.4.tar.bz2"
+md5sums="2ed3ae6734290296faa193e1177d50e6 apr-util-1.3.7.tar.bz2"
diff --git a/extra/apr/APKBUILD b/extra/apr/APKBUILD
index 275d6680e..bee01f8dc 100644
--- a/extra/apr/APKBUILD
+++ b/extra/apr/APKBUILD
@@ -1,11 +1,11 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=apr
-pkgver=1.3.3
+pkgver=1.3.5
pkgrel=0
pkgdesc="The Apache Portable Runtime"
url="http://apr.apache.org/"
license="APACHE"
-depends="libuuid"
+depends=
makedepends="e2fsprogs-dev"
subpackages="$pkgname-dev"
source="http://www.apache.org/dist/$pkgname/$pkgname-$pkgver.tar.bz2"
@@ -32,4 +32,4 @@ dev() {
return 0
}
-md5sums="2090c21dee4f0eb1512604127dcd158f apr-1.3.3.tar.bz2"
+md5sums="9ac9a00eaa190937fdbbde7b4f03ac1e apr-1.3.5.tar.bz2"
diff --git a/extra/asterisk/APKBUILD b/extra/asterisk/APKBUILD
index cf2de2eb9..7e8bb1d18 100644
--- a/extra/asterisk/APKBUILD
+++ b/extra/asterisk/APKBUILD
@@ -1,12 +1,12 @@
# Contributor: Timo Teras <timo.teras@iki.fi>
# Maintainer: Timo Teras <timo.teras@iki.fi>
pkgname=asterisk
-pkgver=1.6.0.9
-pkgrel=4
+pkgver=1.6.0.10
+pkgrel=1
pkgdesc="Asterisk: A Module Open Source PBX System"
url="http://www.asterisk.org/"
license="GPL"
-depends="dahdi-linux"
+depends=
makedepends="autoconf automake libtool ncurses-dev popt-dev newt-dev zlib-dev
postgresql-dev unixodbc-dev dahdi-tools-dev libpri-dev tar
freetds-dev openssl-dev"
@@ -85,7 +85,7 @@ tds() {
_find_and_move '*_tds*'
}
-md5sums="9142461a5ae047a5493bcb610963bc42 asterisk-1.6.0.9.tar.gz
+md5sums="c5e3ceaea876e602b1057d751278b497 asterisk-1.6.0.10.tar.gz
b00c9d98ce2ad445501248a197c6e436 100-uclibc-daemon.patch
929f740db7043b4553544ebcc7315c91 101-caps-uclibc.patch
97b39fd9777a2521d4f9f095482b7ac2 102-gsm-pic.patch
diff --git a/extra/b43-fwcutter/APKBUILD b/extra/b43-fwcutter/APKBUILD
new file mode 100644
index 000000000..0a7f4cc6a
--- /dev/null
+++ b/extra/b43-fwcutter/APKBUILD
@@ -0,0 +1,24 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=b43-fwcutter
+pkgver=012
+pkgrel=0
+pkgdesc="Tool to extract firmware from Broadcom drivers"
+url="http://linuxwireless.org/en/users/Drivers/b43"
+license="GPL"
+depends=""
+makedepends=""
+install=
+subpackages="$pkgname-doc"
+source="http://bu3sch.de/b43/fwcutter/b43-fwcutter-012.tar.bz2"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ make || return 1
+ make PREFIX="$pkgdir"/usr install
+ mkdir -p "$pkgdir"/usr/share/
+ mv "$pkgdir"/usr/man "$pkgdir"/usr/share/
+}
+
+md5sums="69eadf67b459f313a8d6b37aaabef96c b43-fwcutter-012.tar.bz2"
diff --git a/extra/bc/APKBUILD b/extra/bc/APKBUILD
index af84e8df8..d5f1851f2 100644
--- a/extra/bc/APKBUILD
+++ b/extra/bc/APKBUILD
@@ -2,11 +2,11 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=bc
pkgver=1.06
-pkgrel=0
+pkgrel=1
pkgdesc="arbitrary precision numeric processing language (calculator)"
url="http://www.gnu.org/software/bc/bc.html"
license="GPL"
-depends="uclibc readline"
+depends=
makedepends="flex readline-dev"
install=
subpackages="$pkgname-doc"
diff --git a/extra/ca-certificates/APKBUILD b/extra/ca-certificates/APKBUILD
index f4d33e8db..e39567de1 100644
--- a/extra/ca-certificates/APKBUILD
+++ b/extra/ca-certificates/APKBUILD
@@ -1,14 +1,13 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=ca-certificates
-pkgver=20080809
-pkgrel=1
+pkgver=20090709
+pkgrel=0
pkgdesc="Common CA certificates PEM files"
url="http://packages.debian.org/sid/ca-certificates"
license="MPL GPL"
depends="run-parts openssl"
install=ca-certificates.post-install
source="http://ftp.no.debian.org/debian/pool/main/c/$pkgname/${pkgname}_${pkgver}_all.deb
- $pkgname-20080514-warn-on-bad-symlinks.patch
$install
"
@@ -16,8 +15,6 @@ build () {
cd "$srcdir"
ar x "$srcdir"/${pkgname}_${pkgver}_all.deb || return 1
tar -zxf ./data.tar.gz
- patch -p0 < "$srcdir"/$pkgname-20080514-warn-on-bad-symlinks.patch \
- || return 1
mkdir -p "$pkgdir"
cp -Ra usr etc "$pkgdir"/
@@ -29,6 +26,5 @@ build () {
find . -name '*.crt' | sort | cut -b3-
) > "$pkgdir"/etc/ca-certificates.conf
}
-md5sums="3c44f9c232c2335da26d969c716af44d ca-certificates_20080809_all.deb
-fda24bd37c6cd55b9dd2ea7ef7b59778 ca-certificates-20080514-warn-on-bad-symlinks.patch
+md5sums="72c284149d15b336a1758af819192d21 ca-certificates_20090709_all.deb
83a92f371137ac9f046c94452bf17058 ca-certificates.post-install"
diff --git a/extra/ca-certificates/ca-certificates-20080514-warn-on-bad-symlinks.patch b/extra/ca-certificates/ca-certificates-20080514-warn-on-bad-symlinks.patch
deleted file mode 100644
index f9462da65..000000000
--- a/extra/ca-certificates/ca-certificates-20080514-warn-on-bad-symlinks.patch
+++ /dev/null
@@ -1,20 +0,0 @@
-http://bugs.gentoo.org/234816
-http://bugs.debian.org/495224
-
-Do not redirect error output from c_rehash in update-ca-certificates, as
-some errors, especially broken symlinks, can cause trouble for some
-applications like current openldap.
-
-2008-08-15 Martin von Gagern <Martin.vGagern@gmx.net>
-
---- usr/sbin/update-ca-certificates
-+++ usr/sbin/update-ca-certificates
-@@ -83,7 +83,7 @@
- # only run if set of files has changed
-
- if [ "$verbose" = 0 ]; then
-- c_rehash . > /dev/null 2>&1
-+ c_rehash . > /dev/null
- else
- c_rehash .
- fi
diff --git a/extra/clamav/APKBUILD b/extra/clamav/APKBUILD
index 7972c549d..a4daebc2f 100644
--- a/extra/clamav/APKBUILD
+++ b/extra/clamav/APKBUILD
@@ -1,14 +1,14 @@
# Contributor: Carlo Landmeter <clandmeter at gmail>
# Maintainer: Carlo Landmeter <clandmeter at gmail>
pkgname=clamav
-pkgver=0.95.1
+pkgver=0.95.2
pkgrel=0
pkgdesc="An anti-virus toolkit for UNIX"
url="http://www.clamav.net/"
license="GPL"
-depends="zlib gmp"
-install="$pkgname.pre-install $pkgname.post-install"
-makedepends="gmp-dev zlib-dev"
+depends="logrotate"
+install="$pkgname.pre-install $pkgname.post-install $pkgname.pre-upgrade"
+makedepends="ncurses-dev zlib-dev"
subpackages="$pkgname-doc $pkgname-dev"
source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz
clamd.initd
@@ -16,6 +16,7 @@ source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz
freshclam.initd
freshclam.confd
clamav-0.95.1-nls.patch
+ clamav.logrotate
$install"
build() {
@@ -24,25 +25,48 @@ build() {
patch -p0 -i "$srcdir/clamav-0.95.1-nls.patch" || return 1
./configure --prefix=/usr \
- --sysconfdir=/etc \
+ --sysconfdir=/etc/clamav \
--mandir=/usr/share/man \
--infodir=/usr/share/info \
- --disable-clamav
+ --without-iconv
make || return 1
make DESTDIR="$pkgdir" install
+ # Change /etc/clamd.conf to be usable out of the box
+ sed -i -e "s:^\(Example\):\# \1:" \
+ -e "s:.*\(PidFile\) .*:\1 /var/run/clamav/clamd.pid:" \
+ -e "s:.*\(LocalSocket\) .*:\1 /var/run/clamav/clamd.sock:" \
+ -e "s:.*\(User\) .*:\1 clamav:" \
+ -e "s:^\#\(LogFile\) .*:\1 /var/log/clamav/clamd.log:" \
+ -e "s:^\#\(LogTime\).*:\1 yes:" \
+ -e "s:^\#\(AllowSupplementaryGroups\).*:\1 yes:" \
+ "$pkgdir"/etc/clamav/clamd.conf
+
+ # Do the same for /etc/freshclam.conf
+ sed -i -e "s:^\(Example\):\# \1:" \
+ -e "s:.*\(PidFile\) .*:\1 /var/run/clamav/freshclam.pid:" \
+ -e "s:.*\(DatabaseOwner\) .*:\1 clamav:" \
+ -e "s:^\#\(UpdateLogFile\) .*:\1 /var/log/clamav/freshclam.log:" \
+ -e "s:^\#\(NotifyClamd\).*:\1 /etc/clamav/clamd.conf:" \
+ -e "s:^\#\(ScriptedUpdates\).*:\1 yes:" \
+ -e "s:^\#\(AllowSupplementaryGroups\).*:\1 yes:" \
+ "$pkgdir"/etc/clamav/freshclam.conf
+
install -m755 -D "$srcdir"/clamd.initd "$pkgdir"/etc/init.d/clamd
install -m644 -D "$srcdir"/clamd.confd "$pkgdir"/etc/conf.d/clamd
install -m755 -D "$srcdir"/freshclam.initd "$pkgdir"/etc/init.d/freshclam
install -m644 -D "$srcdir"/freshclam.confd "$pkgdir"/etc/conf.d/freshclam
+ install -m644 -D "$srcdir"/clamav.logrotate "$pkgdir"/etc/logrotate.d/clamav
mkdir -p "$pkgdir"/var/run/clamav "$pkgdir"/var/log/clamav
}
-md5sums="c802d4b372e455849cfcb0d776fc72d8 clamav-0.95.1.tar.gz
-04f32738c037c96c3fd2c4fa7781fc7a clamd.initd
-e84205681f64c07af9ec5b6a3dd8bc38 clamd.confd
-fe3cfca9e1355183117936bea6fc6783 freshclam.initd
-e84205681f64c07af9ec5b6a3dd8bc38 freshclam.confd
+md5sums="930362397d30e01ba81b5f24c1046d48 clamav-0.95.2.tar.gz
+adbbfa835f9dea213289719d983f1600 clamd.initd
+567bc32b657dd7031b9b7beaa946203a clamd.confd
+f43b987a0c37e6576face04a830263ac freshclam.initd
+e48466ddfb56f66c623b83e58777b778 freshclam.confd
0d08fd29656bd4b018ecf8ce9706ac55 clamav-0.95.1-nls.patch
+dffa5af2e7a563fc00fcd52ec4c02347 clamav.logrotate
275e05587e2da782781829a1862d57b1 clamav.pre-install
-ec4d600097a15e64dfb714e7739a1804 clamav.post-install"
+ec4d600097a15e64dfb714e7739a1804 clamav.post-install
+c9e80578c6e82d6154bc91f18dfd23ea clamav.pre-upgrade"
diff --git a/extra/clamav/clamav.logrotate b/extra/clamav/clamav.logrotate
new file mode 100644
index 000000000..757442841
--- /dev/null
+++ b/extra/clamav/clamav.logrotate
@@ -0,0 +1,15 @@
+/var/log/clamav/clamd.log {
+ missingok
+ postrotate
+ /etc/init.d/clamd logfix
+ /bin/kill -HUP `cat /var/run/clamav/clamd.pid 2> /dev/null` 2>/dev/null || true
+ endscript
+}
+
+/var/log/clamav/freshclam.log {
+ missingok
+ postrotate
+ /etc/init.d/freshclam logfix
+ /bin/kill -HUP `cat /var/run/clamav/freshclam.pid 2> /dev/null` 2>/dev/null || true
+ endscript
+}
diff --git a/extra/clamav/clamav.pre-upgrade b/extra/clamav/clamav.pre-upgrade
new file mode 100644
index 000000000..9956f95d6
--- /dev/null
+++ b/extra/clamav/clamav.pre-upgrade
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+# make sure we don't lose our config
+mkdir -p /etc/clamav
+if [ -f /etc/clamav.conf ]; then
+ mv /etc/clamav.conf /etc/clamav/
+ ln -s clamav/clamav.conf /etc/clamav.conf
+fi
+
+if [ -f /etc/freshclam.conf ]; then
+ mv /etc/freshclam.conf /etc/clamav/
+ ln -s clamav/freshclam.conf /etc/freshclam.conf
+fi
+
+exit 0
+
diff --git a/extra/clamav/clamd.confd b/extra/clamav/clamd.confd
index 8d08b6868..bc8072aea 100644
--- a/extra/clamav/clamd.confd
+++ b/extra/clamav/clamd.confd
@@ -1,5 +1,6 @@
-#
-# Specify daemon $OPTS here.
-#
-OPTS=""
+CLAMD_NICELEVEL=0
+
+# make sure we also start freshclam
+# comment out if you dont want start freshclam
+rc_need="freshclam"
diff --git a/extra/clamav/clamd.initd b/extra/clamav/clamd.initd
index 8aad87fb6..d3b915557 100644
--- a/extra/clamav/clamd.initd
+++ b/extra/clamav/clamd.initd
@@ -1,25 +1,32 @@
#!/sbin/runscript
-# Sample init.d file for alpine linux.
-
+opts="logfix reload"
NAME=clamd
-DAEMON=/usr/sbin/$NAME
+CONF=/etc/clamav/clamd.conf
depend() {
need net
+ provide antivirus
}
start() {
+ local clamd_socket=$(awk '$1 == "LocalSocket" { print $2 }' $CONF)
+
+ logfix
+
+ if [ -S "${clamd_socket:=/tmp/clamd}" ]; then
+ rm -f ${clamd_socket}
+ fi
ebegin "Starting ${NAME}"
- start-stop-daemon --start --quiet --background \
- --exec ${DAEMON} -- ${OPTS}
- eend $?
+ start-stop-daemon --start --quiet \
+ --nicelevel ${CLAMD_NICELEVEL:-0} \
+ --exec /usr/sbin/clamd
+ eend $? "Failed to start ${NAME}"
}
stop() {
ebegin "Stopping ${NAME}"
- start-stop-daemon --stop --quiet \
- --exec ${DAEMON} --name $NAME \
+ start-stop-daemon --stop --quiet --exec /usr/sbin/clamd
eend $?
}
@@ -30,7 +37,20 @@ reload() {
return 1
fi
start-stop-daemon --stop --oknodo --signal HUP \
- --exec ${DAEMON} --name $NAME
+ --exec /usr/sbin/clamd
eend $?
}
+logfix() {
+ # fix clamd log permissions
+ # (might be clobbered by logrotate or something)
+ local logfile=`awk '$1 == "LogFile" { print $2 }' $CONF`
+ local clamav_user=`awk '$1 == "User" { print $2 }' $CONF`
+ if [ -n "${logfile}" ] && [ -n "${clamav_user}" ]; then
+ if [ ! -f "${logfile}" ]; then
+ touch ${logfile}
+ fi
+ chown ${clamav_user} ${logfile}
+ chmod 640 ${logfile}
+ fi
+}
diff --git a/extra/clamav/freshclam.confd b/extra/clamav/freshclam.confd
index 8d08b6868..17559037d 100644
--- a/extra/clamav/freshclam.confd
+++ b/extra/clamav/freshclam.confd
@@ -1,5 +1,3 @@
-#
-# Specify daemon $OPTS here.
-#
-OPTS=""
+FRESHCLAM_NICELEVEL=0
+
diff --git a/extra/clamav/freshclam.initd b/extra/clamav/freshclam.initd
index e4643bc60..7961c7f80 100644
--- a/extra/clamav/freshclam.initd
+++ b/extra/clamav/freshclam.initd
@@ -1,23 +1,32 @@
#!/sbin/runscript
+opts="logfix reload"
+
NAME=freshclam
DAEMON=/usr/bin/$NAME
+CONF=/etc/clamav/freshclam.conf
depend() {
need net
}
start() {
- ebegin "Starting ${NAME}"
- start-stop-daemon --start --quiet --background \
- --exec ${DAEMON} -- -d ${OPTS}
- eend $?
+ ebegin "Starting freshclam"
+ start-stop-daemon --start --quiet \
+ --nicelevel ${FRESHCLAM_NICELEVEL:-0} \
+ --exec /usr/bin/freshclam -- -d
+ retcode=$?
+ if [ ${retcode} = 1 ]; then
+ eend 0
+ einfo "Virus databases are already up to date."
+ else
+ eend ${retcode} "Failed to start freshclam"
+ fi
}
stop() {
ebegin "Stopping ${NAME}"
- start-stop-daemon --stop --quiet \
- --exec ${DAEMON} --name $NAME \
+ start-stop-daemon --stop --quiet --name ${NAME}
eend $?
}
@@ -32,3 +41,18 @@ reload() {
eend $?
}
+
+logfix() {
+ # fix freshclam log permissions
+ # (might be clobbered by logrotate or something)
+ logfile=$(awk '$1 == "UpdateLogFile" { print $2 }' $CONF)
+ local freshclam_user=$(awk '$1 == "DatabaseOwner" { print $2 }' $CONF)
+ if [ -n "${logfile}" -a -n "${clamav_user}" ]; then
+ if [ ! -f "${logfile}" ]; then
+ touch ${logfile}
+ fi
+ chown ${freshclam_user} ${logfile}
+ chmod 640 ${logfile}
+ fi
+}
+
diff --git a/extra/dahdi-linux-grsec/APKBUILD b/extra/dahdi-linux-grsec/APKBUILD
new file mode 100644
index 000000000..48327be73
--- /dev/null
+++ b/extra/dahdi-linux-grsec/APKBUILD
@@ -0,0 +1,57 @@
+# Contributor: Timo Teras <timo.teras@iki.fi>
+# Maintainer: Timo Teras <timo.teras@iki.fi>
+
+_flavor=grsec
+
+# source the kernel version
+if [ -f ../linux-${_flavor}/APKBUILD ]; then
+ . ../linux-${_flavor}/APKBUILD
+fi
+
+_abi_release=${pkgver:-2.6.29.5}-${_flavor}
+_realname=dahdi-linux
+
+pkgname=${_realname}-${_flavor}
+pkgver=2.2.0
+pkgrel=2
+pkgdesc="Digium Asterisk Hardware Device Interface drivers"
+url="http://www.asterisk.org"
+license="GPL"
+depends="dahdi-linux"
+# we need wget and tar because make install downloads firmware and uses fancy
+# options for tar and wget.
+makedepends="linux-${_flavor}-dev wget tar perl"
+install=
+subpackages=
+source="http://downloads.digium.com/pub/telephony/dahdi-linux/releases/${_realname}-$pkgver.tar.gz
+ dahdi-depmod.patch
+ dahdi-bri_dchan.patch
+ dahdi-zaphfc.patch
+ zaphfc-dahdi-flortz.diff
+ dahdi-linux-2.2.0-hfc-4s.patch
+ "
+
+build() {
+ cd "$srcdir/$_realname-$pkgver"
+ for i in ../*.patch ../*.diff; do
+ msg "Applying $i"
+ patch -p1 < $i || return 1;
+ done
+
+ make KVERS="${_abi_release}" DYNFS="yes" MODULES_EXTRA="zaphfc" \
+ || return 1
+ make KVERS="${_abi_release}" DYNFS="yes" MODULES_EXTRA="zaphfc" \
+ DESTDIR="$pkgdir" install
+}
+
+# since we sourced the APKBUILD above we got the dev() function there to
+# so we override it again.
+dev() {
+ default_dev
+}
+md5sums="a6b1a24a436e1c1fd08b99d27cfe3f38 dahdi-linux-2.2.0.tar.gz
+c78fb8d80f9efdffd950297c88ff9273 dahdi-depmod.patch
+4b41a82ff390ac64c08092c5a3eab6a8 dahdi-bri_dchan.patch
+a822c092f0548cd13f5e8d8cba053af6 dahdi-zaphfc.patch
+291c5c44c86ab02443a742415461ddca zaphfc-dahdi-flortz.diff
+68dfe17a49cca15ae439fd83f4ccfbc5 dahdi-linux-2.2.0-hfc-4s.patch"
diff --git a/extra/dahdi-linux/dahdi-bri_dchan.patch b/extra/dahdi-linux-grsec/dahdi-bri_dchan.patch
index 80a80256c..d7a3fe859 100644
--- a/extra/dahdi-linux/dahdi-bri_dchan.patch
+++ b/extra/dahdi-linux-grsec/dahdi-bri_dchan.patch
@@ -37,8 +37,8 @@
struct dahdi_span {
spinlock_t lock;
---- a/drivers/dahdi/dahdi_config.h
-+++ b/drivers/dahdi/dahdi_config.h
+--- a/include/dahdi/dahdi_config.h
++++ b/include/dahdi/dahdi_config.h
@@ -174,4 +174,10 @@
*/
/* #define OPTIMIZE_CHANMUTE */
diff --git a/extra/dahdi-linux/dahdi-depmod.patch b/extra/dahdi-linux-grsec/dahdi-depmod.patch
index 289aad403..289aad403 100644
--- a/extra/dahdi-linux/dahdi-depmod.patch
+++ b/extra/dahdi-linux-grsec/dahdi-depmod.patch
diff --git a/extra/dahdi-linux/dahdi-linux-2.1.0.4-hfc-4s.patch b/extra/dahdi-linux-grsec/dahdi-linux-2.2.0-hfc-4s.patch
index e6011a403..67857e2f7 100644
--- a/extra/dahdi-linux/dahdi-linux-2.1.0.4-hfc-4s.patch
+++ b/extra/dahdi-linux-grsec/dahdi-linux-2.2.0-hfc-4s.patch
@@ -1,6 +1,5 @@
-diff -rupN /drivers/dahdi/wcb4xxp/base.c /usr/src/dahdi-linux-2.1.0.4/drivers/dahdi/wcb4xxp/base.c
---- a/drivers/dahdi/wcb4xxp/base.c 2008-12-17 15:57:56.000000000 +0000
-+++ b/drivers/dahdi/wcb4xxp/base.c 2009-03-10 00:47:02.000000000 +0000
+--- a/drivers/dahdi/wcb4xxp/base.c 2009-06-24 13:17:03.000000000 +0000
++++ b/drivers/dahdi/wcb4xxp/base.c 2009-06-24 13:40:15.000000000 +0000
@@ -75,7 +75,7 @@
#define DBG_SPANFILTER ((1 << bspan->port) & spanfilter)
@@ -10,31 +9,30 @@ diff -rupN /drivers/dahdi/wcb4xxp/base.c /usr/src/dahdi-linux-2.1.0.4/drivers/da
#ifdef LOOPBACK_SUPPORTED
static int loopback = 0;
#endif
-@@ -110,10 +110,21 @@ static struct proc_dir_entry *myproc;
+@@ -114,9 +114,21 @@
struct devtype {
char *desc;
unsigned int flags;
-+ int ports; /* Number of ports the card has */
-+ int has_ec; /* Does the card have an Echo Canceller */
-+ enum cards_ids card_type; /* Card type - Digium B410P, ... */
++ int ports; /* Number of ports the card has */
++ int has_ec; /* Does the card have an Echo Canceller */
++ enum cards_ids card_type; /* Card type - Digium B410P, ... */
};
-static struct devtype wcb4xxp = { "Wildcard B410P", 0 };
--
+static struct devtype wcb4xxp = { "Wildcard B410P", .ports = 4, .has_ec = 1, .card_type = B410P };
-+static struct devtype hfc2s = { "HFC-2S Junghanns.NET duoBRI PCI", .ports = 2, .has_ec = 0, .card_type = DUOBRI };
-+static struct devtype hfc4s = { "HFC-4S Junghanns.NET quadBRI PCI", .ports = 4, .has_ec = 0, .card_type = QUADBRI };
-+static struct devtype hfc8s = { "HFC-4S Junghanns.NET octoBRI PCI", .ports = 8, .has_ec = 0, .card_type = OCTOBRI };
++static struct devtype hfc2s = { "HFC-2S Junghanns.NET duoBRI PCI", .ports = 2, .has_ec = 0, .card_type = DUOBRI };
++static struct devtype hfc4s = { "HFC-4S Junghanns.NET quadBRI PCI", .ports = 4, .has_ec = 0, .card_type = QUADBRI };
++static struct devtype hfc8s = { "HFC-4S Junghanns.NET octoBRI PCI", .ports = 8, .has_ec = 0, .card_type = OCTOBRI };
+static struct devtype hfc2s_OV ={ "OpenVox B200P", .ports = 2, .has_ec = 0, .card_type = B200P_OV };
+static struct devtype hfc4s_OV ={ "OpenVox B400P", .ports = 4, .has_ec = 0, .card_type = B400P_OV };
+static struct devtype hfc8s_OV ={ "OpenVox B800P", .ports = 8, .has_ec = 0, .card_type = B800P_OV };
+static struct devtype hfc2s_BN ={ "BeroNet BN2S0", .ports = 2, .has_ec = 0, .card_type = BN2S0 };
+static struct devtype hfc4s_BN ={ "BeroNet BN4S0", .ports = 4, .has_ec = 0, .card_type = BN4S0 };
-+static struct devtype hfc8s_BN ={ "BeroNet BN8S0", .ports = 8, .has_ec = 0, .card_type = BN8S0 };
++static struct devtype hfc8s_BN ={ "BeroNet BN8S0", .ports = 8, .has_ec = 0, .card_type = BN8S0 };
- #if 0
- static const char *wcb4xxp_rcsdata = "$RCSfile: base.c,v $ $Revision: 5576 $";
-@@ -385,7 +396,14 @@ static void hfc_gpio_init(struct b4xxp *
+ static int echocan_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
+ struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec);
+@@ -403,7 +415,14 @@
mb();
@@ -50,7 +48,7 @@ diff -rupN /drivers/dahdi/wcb4xxp/base.c /usr/src/dahdi-linux-2.1.0.4/drivers/da
mb();
-@@ -600,13 +618,16 @@ static void ec_init(struct b4xxp *b4)
+@@ -618,13 +637,16 @@
unsigned char b;
unsigned int i, j, mask;
@@ -68,7 +66,7 @@ diff -rupN /drivers/dahdi/wcb4xxp/base.c /usr/src/dahdi-linux-2.1.0.4/drivers/da
ec_write(b4, i, 0x1a8 + j, 0x00); /* GPIO out */
ec_write(b4, i, 0x1ac + j, 0x00); /* GPIO dir */
ec_write(b4, i, 0x1b0 + j, 0x00); /* GPIO sel */
-@@ -990,7 +1011,15 @@ static void hfc_assign_dchan_fifo(struct
+@@ -1008,7 +1030,15 @@
int fifo, hfc_chan;
unsigned long irq_flags;
@@ -85,7 +83,7 @@ diff -rupN /drivers/dahdi/wcb4xxp/base.c /usr/src/dahdi-linux-2.1.0.4/drivers/da
hfc_chan = (port * 4) + 2;
/* record the host's FIFO # in the span fifo array */
-@@ -1192,7 +1221,7 @@ static void hfc_update_st_timers(struct
+@@ -1210,7 +1240,7 @@
int i, j;
struct b4xxp_span *s;
@@ -94,7 +92,7 @@ diff -rupN /drivers/dahdi/wcb4xxp/base.c /usr/src/dahdi-linux-2.1.0.4/drivers/da
s = &b4->spans[i];
for (j=HFC_T1; j <= HFC_T3; j++) {
-@@ -1394,12 +1423,21 @@ static void hfc_init_all_st(struct b4xxp
+@@ -1413,12 +1443,21 @@
gpio = b4xxp_getreg8(b4, R_GPI_IN3);
@@ -118,7 +116,7 @@ diff -rupN /drivers/dahdi/wcb4xxp/base.c /usr/src/dahdi-linux-2.1.0.4/drivers/da
s->te_mode = !nt;
dev_info(b4->dev, "Port %d: %s mode\n", i + 1, (nt ? "NT" : "TE"));
-@@ -1755,9 +1793,15 @@ static void b4xxp_init_stage1(struct b4x
+@@ -1774,9 +1813,15 @@
/*
* set up the clock controller
@@ -136,7 +134,7 @@ diff -rupN /drivers/dahdi/wcb4xxp/base.c /usr/src/dahdi-linux-2.1.0.4/drivers/da
flush_pci();
udelay(100); /* wait a bit for clock to settle */
-@@ -1788,7 +1832,7 @@ static void b4xxp_init_stage2(struct b4x
+@@ -1807,7 +1852,7 @@
/*
* set up the flow controller.
@@ -145,7 +143,7 @@ diff -rupN /drivers/dahdi/wcb4xxp/base.c /usr/src/dahdi-linux-2.1.0.4/drivers/da
* FIFO 0 connects Port 1 B0 using HFC channel 16 and PCM timeslots 0/1.
* FIFO 1 connects Port 1 B1 using HFC channel 17 and PCM timeslots 4/5.
* FIFO 2 connects Port 2 B0 using HFC channel 20 and PCM timeslots 8/9.
-@@ -1803,14 +1847,35 @@ static void b4xxp_init_stage2(struct b4x
+@@ -1822,14 +1867,35 @@
*
* D channels are handled by FIFOs 8-11.
* FIFO 8 connects Port 1 D using HFC channel 3
@@ -155,8 +153,8 @@ diff -rupN /drivers/dahdi/wcb4xxp/base.c /usr/src/dahdi-linux-2.1.0.4/drivers/da
+ * FIFO 9 connects Port 2 D using HFC channel 7
+ * FIFO 10 connects Port 3 D using HFC channel 11
+ * FIFO 11 connects Port 4 D using HFC channel 15
- *
- * D channel FIFOs are operated in HDLC mode and interrupt on end of frame.
++ *
++ * D channel FIFOs are operated in HDLC mode and interrupt on end of frame.
+ *
+ * B channel map: (8 ports cards without Hardware Echo Cancel)
+ * FIFO 0 connects Port 1 B0 using HFC channel 0
@@ -169,7 +167,7 @@ diff -rupN /drivers/dahdi/wcb4xxp/base.c /usr/src/dahdi-linux-2.1.0.4/drivers/da
+ *
+ * All B channel FIFOs have their HDLC controller in transparent mode,
+ * and only the FIFO for B0 on each port has its interrupt operational.
-+ *
+ *
+ * D channels are handled by FIFOs 16-23.
+ * FIFO 16 connects Port 1 D using HFC channel 3
+ * FIFO 17 connects Port 2 D using HFC channel 7
@@ -177,7 +175,7 @@ diff -rupN /drivers/dahdi/wcb4xxp/base.c /usr/src/dahdi-linux-2.1.0.4/drivers/da
+ * FIFO 19 connects Port 4 D using HFC channel 15
+ * ................
+ * FIFO 23 connects Port 8 D using HFC channel 31
-+ * D channel FIFOs are operated in HDLC mode and interrupt on end of frame.
+ * D channel FIFOs are operated in HDLC mode and interrupt on end of frame.
*/
for (span=0; span < b4->numspans; span++) {
- if (vpmsupport) {
@@ -185,7 +183,7 @@ diff -rupN /drivers/dahdi/wcb4xxp/base.c /usr/src/dahdi-linux-2.1.0.4/drivers/da
hfc_assign_bchan_fifo_ec(b4, span, 0);
hfc_assign_bchan_fifo_ec(b4, span, 1);
} else {
-@@ -1835,6 +1900,145 @@ static void b4xxp_setleds(struct b4xxp *
+@@ -1854,6 +1920,145 @@
ec_write(b4, 0, 0x1a8 + 3, val);
}
@@ -331,7 +329,7 @@ diff -rupN /drivers/dahdi/wcb4xxp/base.c /usr/src/dahdi-linux-2.1.0.4/drivers/da
static void b4xxp_set_span_led(struct b4xxp *b4, int span, unsigned char val)
{
int shift, spanmask;
-@@ -1852,6 +2056,18 @@ static void b4xxp_update_leds(struct b4x
+@@ -1871,6 +2076,18 @@
int i;
struct b4xxp_span *bspan;
@@ -350,16 +348,16 @@ diff -rupN /drivers/dahdi/wcb4xxp/base.c /usr/src/dahdi-linux-2.1.0.4/drivers/da
b4->blinktimer++;
for (i=0; i < b4->numspans; i++) {
bspan = &b4->spans[i];
-@@ -2138,7 +2354,7 @@ static void init_spans(struct b4xxp *b4)
+@@ -2174,7 +2391,7 @@
bspan->span.close = b4xxp_close;
bspan->span.ioctl = b4xxp_ioctl;
bspan->span.hdlc_hard_xmit = b4xxp_hdlc_hard_xmit;
- if (vpmsupport)
+ if (vpmsupport && b4->has_ec)
- bspan->span.echocan = b4xxp_echocan;
+ bspan->span.echocan_create = echocan_create;
/* HDLC stuff */
-@@ -2245,13 +2461,24 @@ DAHDI_IRQ_HANDLER(b4xxp_interrupt)
+@@ -2281,13 +2498,24 @@
static void b4xxp_bottom_half(unsigned long data)
{
struct b4xxp *b4 = (struct b4xxp *)data;
@@ -385,7 +383,7 @@ diff -rupN /drivers/dahdi/wcb4xxp/base.c /usr/src/dahdi-linux-2.1.0.4/drivers/da
for (i=0; i < 8; i++) {
b = b2 = b4->fifo_irqstatus[i];
-@@ -2260,7 +2487,7 @@ static void b4xxp_bottom_half(unsigned l
+@@ -2296,7 +2524,7 @@
fifo = i*4 + j;
if (b & V_IRQ_FIFOx_TX) {
@@ -394,7 +392,7 @@ diff -rupN /drivers/dahdi/wcb4xxp/base.c /usr/src/dahdi-linux-2.1.0.4/drivers/da
/*
* WOW I don't like this.
* It's bad enough that I have to send a fake frame to get an HDLC TX FIFO interrupt,
-@@ -2269,7 +2496,7 @@ static void b4xxp_bottom_half(unsigned l
+@@ -2305,7 +2533,7 @@
* Yuck. It works well, but yuck.
*/
do {
@@ -403,7 +401,7 @@ diff -rupN /drivers/dahdi/wcb4xxp/base.c /usr/src/dahdi-linux-2.1.0.4/drivers/da
} while (k);
} else {
if (printk_ratelimit())
-@@ -2278,7 +2505,7 @@ static void b4xxp_bottom_half(unsigned l
+@@ -2314,7 +2542,7 @@
}
if (b & V_IRQ_FIFOx_RX) {
@@ -412,7 +410,7 @@ diff -rupN /drivers/dahdi/wcb4xxp/base.c /usr/src/dahdi-linux-2.1.0.4/drivers/da
/*
* I have to loop here until hdlc_rx_frame says there are no more frames waiting.
* for whatever reason, the HFC will not generate another interrupt if there are
-@@ -2286,7 +2513,7 @@ static void b4xxp_bottom_half(unsigned l
+@@ -2322,7 +2550,7 @@
* i.e. I get an int when F1 changes, not when F1 != F2.
*/
do {
@@ -421,7 +419,7 @@ diff -rupN /drivers/dahdi/wcb4xxp/base.c /usr/src/dahdi-linux-2.1.0.4/drivers/da
} while (k);
} else {
if (printk_ratelimit())
-@@ -2368,8 +2595,8 @@ static int b4xxp_proc_read_one(char *buf
+@@ -2404,8 +2632,8 @@
sprintf(sBuf, "Card %d, PCI identifier %s, IRQ %d\n", b4->cardno + 1, b4->dev->bus_id, b4->irq);
strcat(sBuf,"Tx:\n");
@@ -432,7 +430,7 @@ diff -rupN /drivers/dahdi/wcb4xxp/base.c /usr/src/dahdi-linux-2.1.0.4/drivers/da
chan = b4->spans[i/3].chans[i%3];
sprintf(str, "%02x ", chan->writechunk[j]);
strcat(sBuf, str);
-@@ -2379,8 +2606,8 @@ static int b4xxp_proc_read_one(char *buf
+@@ -2415,8 +2643,8 @@
}
strcat(sBuf, "\nRx:\n");
@@ -443,7 +441,7 @@ diff -rupN /drivers/dahdi/wcb4xxp/base.c /usr/src/dahdi-linux-2.1.0.4/drivers/da
chan = b4->spans[i / 3].chans[i % 3];
sprintf(str, "%02x%c", chan->readchunk[j], (i == 11) ? '\n' : ' ');
strcat(sBuf, str);
-@@ -2388,7 +2615,7 @@ static int b4xxp_proc_read_one(char *buf
+@@ -2424,7 +2652,7 @@
}
strcat(sBuf, "\nPort states:\n");
@@ -452,7 +450,7 @@ diff -rupN /drivers/dahdi/wcb4xxp/base.c /usr/src/dahdi-linux-2.1.0.4/drivers/da
int state;
char *x;
struct b4xxp_span *s = &b4->spans[i];
-@@ -2483,7 +2710,8 @@ static int __devinit b4xx_probe(struct p
+@@ -2519,7 +2747,8 @@
/* card found, enabled and main struct allocated. Fill it out. */
b4->magic = WCB4XXP_MAGIC;
b4->variety = dt->desc;
@@ -462,7 +460,7 @@ diff -rupN /drivers/dahdi/wcb4xxp/base.c /usr/src/dahdi-linux-2.1.0.4/drivers/da
b4->pdev = pdev;
b4->dev = &pdev->dev;
pci_set_drvdata(pdev, b4);
-@@ -2497,7 +2725,7 @@ static int __devinit b4xx_probe(struct p
+@@ -2533,7 +2762,7 @@
spin_lock_init(&b4->fifolock);
x = b4xxp_getreg8(b4, R_CHIP_ID);
@@ -471,7 +469,7 @@ diff -rupN /drivers/dahdi/wcb4xxp/base.c /usr/src/dahdi-linux-2.1.0.4/drivers/da
dev_err(&pdev->dev, "Unknown/unsupported controller detected (R_CHIP_ID = 0x%02x)\n", x);
goto err_out_free_mem;
}
-@@ -2512,7 +2740,7 @@ static int __devinit b4xx_probe(struct p
+@@ -2548,7 +2777,7 @@
*/
/* TODO: determine whether this is a 2, 4 or 8 port card */
@@ -480,7 +478,7 @@ diff -rupN /drivers/dahdi/wcb4xxp/base.c /usr/src/dahdi-linux-2.1.0.4/drivers/da
b4->syncspan = -1; /* sync span is unknown */
if (b4->numspans > MAX_SPANS_PER_CARD) {
dev_err(b4->dev, "Driver does not know how to handle a %d span card!\n", b4->numspans);
-@@ -2660,7 +2888,17 @@ static void __devexit b4xxp_remove(struc
+@@ -2696,7 +2925,17 @@
static struct pci_device_id b4xx_ids[] __devinitdata =
{
{ 0xd161, 0xb410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wcb4xxp },
@@ -499,7 +497,7 @@ diff -rupN /drivers/dahdi/wcb4xxp/base.c /usr/src/dahdi-linux-2.1.0.4/drivers/da
};
static struct pci_driver b4xx_driver = {
-@@ -2719,7 +2957,7 @@ MODULE_PARM_DESC(timer_1_ms, "NT: msec t
+@@ -2756,7 +2995,7 @@
MODULE_PARM_DESC(timer_3_ms, "TE: msec to wait for link activation, NT: unused.");
MODULE_AUTHOR("Digium Incorporated <support@digium.com>");
@@ -508,9 +506,8 @@ diff -rupN /drivers/dahdi/wcb4xxp/base.c /usr/src/dahdi-linux-2.1.0.4/drivers/da
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, b4xx_ids);
-diff -rupN /usr/src/originales/dahdi-linux-2.1.0.4/drivers/dahdi/wcb4xxp/wcb4xxp.h /usr/src/dahdi-linux-2.1.0.4/drivers/dahdi/wcb4xxp/wcb4xxp.h
---- a/drivers/dahdi/wcb4xxp/wcb4xxp.h 2008-11-24 04:14:37.000000000 +0000
-+++ b/drivers/dahdi/wcb4xxp/wcb4xxp.h 2009-03-09 23:50:18.000000000 +0000
+--- a/drivers/dahdi/wcb4xxp/wcb4xxp.h 2009-06-24 13:17:03.000000000 +0000
++++ b/drivers/dahdi/wcb4xxp/wcb4xxp.h 2009-06-24 13:18:07.000000000 +0000
@@ -378,7 +378,7 @@
#define HFC_T3 2
@@ -520,7 +517,7 @@ diff -rupN /usr/src/originales/dahdi-linux-2.1.0.4/drivers/dahdi/wcb4xxp/wcb4xxp
#define WCB4XXP_CHANNELS_PER_SPAN 3 /* 2 B-channels and 1 D-Channel for each BRI span */
#define WCB4XXP_HDLC_BUF_LEN 32 /* arbitrary, just the max # of byts we will send to DAHDI per call */
-@@ -414,6 +414,19 @@ struct b4xxp_span {
+@@ -415,6 +415,19 @@
struct dahdi_chan _chans[WCB4XXP_CHANNELS_PER_SPAN]; /* Backing memory */
};
@@ -540,7 +537,7 @@ diff -rupN /usr/src/originales/dahdi-linux-2.1.0.4/drivers/dahdi/wcb4xxp/wcb4xxp
/* This structure exists one per card */
struct b4xxp {
unsigned magic; /* magic value to make sure we're looking at our struct */
-@@ -448,10 +461,12 @@ struct b4xxp {
+@@ -449,10 +462,12 @@
int globalconfig; /* Whether global setup has been done */
int syncspan; /* span that HFC uses for sync on this card */
int running; /* interrupts are enabled */
diff --git a/extra/dahdi-linux/dahdi-zaphfc.patch b/extra/dahdi-linux-grsec/dahdi-zaphfc.patch
index b711c07ff..b711c07ff 100644
--- a/extra/dahdi-linux/dahdi-zaphfc.patch
+++ b/extra/dahdi-linux-grsec/dahdi-zaphfc.patch
diff --git a/extra/dahdi-linux/zaphfc-dahdi-flortz.diff b/extra/dahdi-linux-grsec/zaphfc-dahdi-flortz.diff
index 719accdc6..719accdc6 100644
--- a/extra/dahdi-linux/zaphfc-dahdi-flortz.diff
+++ b/extra/dahdi-linux-grsec/zaphfc-dahdi-flortz.diff
diff --git a/extra/dahdi-linux/APKBUILD b/extra/dahdi-linux/APKBUILD
index 80121e1b0..b0f6edf78 100644
--- a/extra/dahdi-linux/APKBUILD
+++ b/extra/dahdi-linux/APKBUILD
@@ -1,56 +1,35 @@
# Contributor: Timo Teras <timo.teras@iki.fi>
# Maintainer: Timo Teras <timo.teras@iki.fi>
+
pkgname=dahdi-linux
-_kernflavor=grsec
-_kernver=2.6.28.9
-pkgver=2.1.0.4
-pkgrel=7
-pkgdesc="Digium Asterisk Hardware Device Interface drivers"
+pkgver=2.2.0
+pkgrel=1
+pkgdesc="Firmware for Digium Asterisk Hardware Device Interface drivers"
url="http://www.asterisk.org"
license="GPL"
-depends="linux-grsec"
+depends=
# we need wget and tar because make install downloads firmware and uses fancy
# options for tar and wget.
-makedepends="linux-grsec-dev linux-grsec-sources wget tar perl"
+makedepends="wget tar"
install=
-subpackages="$pkgname-dev $pkgname-grsec:mod"
-source="http://downloads.digium.com/pub/telephony/dahdi-linux/releases/$pkgname-$pkgver.tar.gz
- dahdi-depmod.patch
- dahdi-bri_dchan.patch
- dahdi-zaphfc.patch
- zaphfc-dahdi-flortz.diff
- $pkgname-2.1.0.4-hfc-4s.patch
- "
+subpackages="$pkgname-dev"
+source="http://downloads.digium.com/pub/telephony/dahdi-linux/releases/$pkgname-$pkgver.tar.gz"
-build() {
- local kout="$srcdir"/grsec
- local ksrc="/usr/src/linux-$_kernver-$_kernflavor"
- mkdir -p "$kout"
- cd "$kout"
- cp /boot/config-grsec .config
- cp /boot/Module.symvers-grsec Module.symvers
- make -C $ksrc O=$PWD silentoldconfig || return 1
- make modules_prepare
+# We onlin install the firwares in this package since those are common for all
+# kernel flavors. We also install the headers for the -dev package.
+#
+# The kernel drivers themselves are built from separate build recipe.
- cd "$srcdir/$pkgname-$pkgver"
- for i in ../*.patch; do
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+ for i in ../*.patch ../*.diff; do
+ [ -f "$i" ] || continue
msg "Applying $i"
patch -p1 < $i || return 1;
done
- make \
- KVERS="$_kernver-$_kernflavor" KSRC="$kout" \
- KCONFIG="$kout/.config" DYNFS="yes" MODULES_EXTRA="zaphfc" \
- || return 1
- make DESTDIR="$pkgdir" \
- KVERS="$_kernver-$_kernflavor" KSRC="$kout" \
- KCONFIG="$kout/.config" DYNFS="yes" MODULES_EXTRA="zaphfc" \
- install
+ make DESTDIR="$pkgdir" HOTPLUG_FIRMWARE=yes \
+ install-include install-firmware
}
-md5sums="ef2d34c394e8b600ad392560efc56920 dahdi-linux-2.1.0.4.tar.gz
-c78fb8d80f9efdffd950297c88ff9273 dahdi-depmod.patch
-1c9c44497fc883c6a5381abc93e5e6cf dahdi-bri_dchan.patch
-a822c092f0548cd13f5e8d8cba053af6 dahdi-zaphfc.patch
-291c5c44c86ab02443a742415461ddca zaphfc-dahdi-flortz.diff
-b01c57444be3a87f6f71dd71c4451ec7 dahdi-linux-2.1.0.4-hfc-4s.patch"
+md5sums="a6b1a24a436e1c1fd08b99d27cfe3f38 dahdi-linux-2.2.0.tar.gz"
diff --git a/extra/dahdi-tools/APKBUILD b/extra/dahdi-tools/APKBUILD
index 278483422..9a1538fab 100644
--- a/extra/dahdi-tools/APKBUILD
+++ b/extra/dahdi-tools/APKBUILD
@@ -1,12 +1,12 @@
# Contributor: Timo Teras <timo.teras@iki.fi>
# Maintainer: Timo Teras <timo.teras@iki.fi>
pkgname=dahdi-tools
-pkgver=2.1.0.2
-pkgrel=1
+pkgver=2.2.0
+pkgrel=0
pkgdesc="Digium Asterisk Hardware Device Interface management utilities"
url="http://www.asterisk.org"
license="GPL"
-depends="dahdi-linux newt"
+depends="dahdi-linux"
depends_dev="dahdi-linux-dev newt-dev"
makedepends="dahdi-linux-dev perl newt-dev"
install=
@@ -23,10 +23,10 @@ build() {
--infodir=/usr/share/info
sed -i -e 's/$(CC) $(LDFLAGS) -o $@ $^/$(CC) $^ $(LDFLAGS) -o $@/' Makefile
make || return 1
- make DESTDIR="$pkgdir" install
+ make -j1 DESTDIR="$pkgdir" install
install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/dahdi
}
-md5sums="2e0c2866112932e54aacf3dc62f548ca dahdi-tools-2.1.0.2.tar.gz
-78095255f5bf640e8dde374b28897524 dahdi-tools.initd"
+md5sums="a018f452f3851a312ff51705ac44de37 dahdi-tools-2.2.0.tar.gz
+d9702271dba6ff250f4d9a252f4dbf4c dahdi-tools.initd"
diff --git a/extra/dahdi-tools/dahdi-tools.initd b/extra/dahdi-tools/dahdi-tools.initd
index ccdace428..5e99122a5 100644
--- a/extra/dahdi-tools/dahdi-tools.initd
+++ b/extra/dahdi-tools/dahdi-tools.initd
@@ -2,6 +2,12 @@
conf=/etc/dahdi/system.conf
+depend() {
+ before asterisk
+ after hwdrivers modules
+ keyword novserver
+}
+
start() {
ebegin "Starting dahdi"
/usr/sbin/dahdi_cfg
diff --git a/extra/dhcpcd/APKBUILD b/extra/dhcpcd/APKBUILD
index 81fe0190b..110f2c4c0 100644
--- a/extra/dhcpcd/APKBUILD
+++ b/extra/dhcpcd/APKBUILD
@@ -1,12 +1,12 @@
# Contributor: Michael Mason <ms13sp@gmail.com>
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=dhcpcd
-pkgver=5.0.4
+pkgver=5.0.6
pkgrel=0
pkgdesc="RFC2131 compliant DHCP client"
url="http://roy.marples.name/projects/dhcpcd/"
license="BSD-2"
-depends="uclibc"
+depends=
makedepends=""
install=
subpackages="$pkgname-doc"
@@ -23,4 +23,4 @@ build() {
}
-md5sums="0b920a8094ee3a8c16c973794561feef dhcpcd-5.0.4.tar.bz2"
+md5sums="600716ddbfa2525a7ef7ae0968a8158a dhcpcd-5.0.6.tar.bz2"
diff --git a/extra/dovecot/APKBUILD b/extra/dovecot/APKBUILD
index ae9101db5..67d1c8707 100644
--- a/extra/dovecot/APKBUILD
+++ b/extra/dovecot/APKBUILD
@@ -1,7 +1,7 @@
# Contributor: Michael Mason <ms13sp@gmail.com>
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=dovecot
-pkgver=1.1.16
+pkgver=1.2.1
pkgrel=0
pkgdesc="IMAP and POP3 server"
url="http://www.dovecot.org/"
@@ -10,7 +10,7 @@ depends=
makedepends="libcap-dev zlib-dev openssl-dev bzip2-dev"
install="dovecot.pre-install"
subpackages="$pkgname-doc $pkgname-dev"
-source="http://www.dovecot.org/releases/1.1/$pkgname-$pkgver.tar.gz
+source="http://www.dovecot.org/releases/1.2/$pkgname-$pkgver.tar.gz
dovecot.initd
$install
"
@@ -22,8 +22,6 @@ build() {
--sysconfdir=/etc/dovecot \
--mandir=/usr/share/man \
--infodir=/usr/share/info \
- --enable-ipv6 \
- --with-pop3d \
--with-ssl=openssl || return 1
make || return 1
@@ -32,6 +30,6 @@ build() {
install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
}
-md5sums="2e20c761416b16aa0fe9cac260ca0d2d dovecot-1.1.16.tar.gz
+md5sums="c269cfe38fc40061e232dd28e5fe3721 dovecot-1.2.1.tar.gz
573e14589a6f8424d55753a2794ab99a dovecot.initd
f0f8893411f5e482e14f40a81a177b19 dovecot.pre-install"
diff --git a/extra/freetds/APKBUILD b/extra/freetds/APKBUILD
index 84a95aaf9..5e58429d9 100644
--- a/extra/freetds/APKBUILD
+++ b/extra/freetds/APKBUILD
@@ -2,11 +2,11 @@
# Maintainer: Michael Mason <ms13sp@gmail.com>
pkgname=freetds
pkgver=0.82
-pkgrel=0
+pkgrel=1
pkgdesc="Tabular Datastream Library"
url="http://www.freetds.org/"
license="GPL"
-depends="uclibc unixodbc readline"
+depends=
makedepends="unixodbc-dev readline-dev"
install=
subpackages="$pkgname-doc $pkgname-dev"
@@ -21,9 +21,6 @@ build() {
--infodir=/usr/share/info
make || return 1
make DESTDIR="$pkgdir" install
-
- # install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
- # install -m644 -D "$srcdir"/$pkgname.confd "$pkgdir"/etc/conf.d/$pkgname
}
md5sums="3df6b2e83fd420e90f1becbd1162990a freetds-0.82.tar.gz"
diff --git a/extra/gd/APKBUILD b/extra/gd/APKBUILD
index b7e58fe8e..75cd56cc4 100644
--- a/extra/gd/APKBUILD
+++ b/extra/gd/APKBUILD
@@ -2,17 +2,18 @@
# Maintainer: Carlo Landmeter <clandmeter at gmail>
pkgname=gd
pkgver=2.0.35
-pkgrel=1
+pkgrel=2
pkgdesc="Library for the dynamic creation of images by programmers"
url="http://www.libgd.org/"
license="custom"
-depends="libpng libjpeg freetype zlib"
-makedepends="libpng-dev libjpeg-dev freetype-dev zlib-dev"
+depends=
+makedepends="libpng-dev jpeg-dev freetype-dev zlib-dev"
subpackages="$pkgname-dev $pkgname-doc"
source="http://www.libgd.org/releases/${pkgname}-${pkgver}.tar.bz2"
build() {
cd "$srcdir/$pkgname-$pkgver"
+ find -name configure | xargs touch
./configure --prefix=/usr \
--sysconfdir=/etc \
diff --git a/extra/gdb/APKBUILD b/extra/gdb/APKBUILD
index b6905cd27..a851da314 100644
--- a/extra/gdb/APKBUILD
+++ b/extra/gdb/APKBUILD
@@ -1,12 +1,12 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=gdb
pkgver=6.8
-pkgrel=2
+pkgrel=3
pkgdesc="The GNU Debugger"
url="http://sources.redhat.com/gdb/"
license="GPL3"
-depends="ncurses expat readline"
-makedepends="ncurses-dev expat-dev readline-dev"
+depends=
+makedepends="ncurses-dev expat-dev"
subpackages="$pkgname-doc"
source="http://ftp.gnu.org/gnu/$pkgname/$pkgname-$pkgver.tar.bz2
50_all_gdb-pie-1.patch
@@ -23,8 +23,8 @@ build () {
done
./configure --prefix=/usr \
- --with-system-readline \
--disable-nls \
+ --without-system-readline \
--disable-werror \
--mandir=/usr/share/man \
--infodir=/usr/share/info
diff --git a/extra/glib/APKBUILD b/extra/glib/APKBUILD
index f67d78014..81c189dc8 100644
--- a/extra/glib/APKBUILD
+++ b/extra/glib/APKBUILD
@@ -1,7 +1,7 @@
# Maintainer: Carlo Landmeter <clandmeter at gmail.com>
pkgname=glib
-pkgver=2.20.3
-pkgrel=0
+pkgver=2.20.4
+pkgrel=1
pkgdesc="Common C routines used by Gtk+ and other libs"
url="http://www.gtk.org"
license='GPL'
@@ -10,11 +10,14 @@ makedepends="gettext-dev libiconv-dev pkgconfig"
source="http://ftp.gnome.org/pub/gnome/sources/glib/${pkgver%.*}/glib-$pkgver.tar.bz2"
subpackages="$pkgname-doc $pkgname-dev"
-depends_dev="perl gettext libiconv"
+depends_dev="perl gettext-dev libiconv-dev"
build() {
cd "$srcdir/$pkgname-$pkgver"
+ # busybox env does not handle the -w after perl. we remove it for now
+ sed -i -e '1,1s/ -w//' gobject/glib-mkenums.in
+
./configure --prefix=/usr \
--mandir=/usr/share/man
make || return 1
@@ -27,4 +30,4 @@ dev() {
mv "$pkgdir"/usr/bin "$subpkgdir"/usr/
}
-md5sums="1173688c58b4b62809c83bb07a2cf71a glib-2.20.3.tar.bz2"
+md5sums="346916673c0eab72191cf44b4afe535f glib-2.20.4.tar.bz2"
diff --git a/extra/gross/APKBUILD b/extra/gross/APKBUILD
index 986c0eb91..fd6e018e9 100644
--- a/extra/gross/APKBUILD
+++ b/extra/gross/APKBUILD
@@ -2,11 +2,11 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=gross
pkgver=1.0.1
-pkgrel=0
+pkgrel=1
pkgdesc="Greylisting of suspicious sources"
url="http://code.google.com/p/gross/"
license="BSD"
-depends="uclibc c-ares"
+depends=
makedepends="c-ares-dev autoconf automake libtool sed"
install="$pkgname.pre-install $pkgname.post-install"
subpackages="$pkgname-doc $pkgname-dev"
@@ -45,10 +45,10 @@ build() {
}
md5sums="f8f81b36850dcda30cb81799b9cee3b6 gross-1.0.1.tar.gz
-37b83bd0d94f66c733d5562c0327b70f gross.initd
+b0d8635b64c4a90d72c49e868f4c4c32 gross.initd
5ca1c6e51c3243236e6564480b20279b gross.confd
bb75b119ac96b8f99831ce6df810003f gross-1.0.1-configure.ac.patch
7c504b653c71dcf7b192bc487b3516fd gross-1.0.1-default-conf.patch
16e184d59d520db565388f010cc75e83 gross-1.0.1-user.patch
-4b55d1c5534167946cc11376d1b05c34 gross.post-install
-8f6e45b98888dbb9971f7681bf431f6f gross.pre-install"
+8f6e45b98888dbb9971f7681bf431f6f gross.pre-install
+4b55d1c5534167946cc11376d1b05c34 gross.post-install"
diff --git a/extra/gross/gross.initd b/extra/gross/gross.initd
index c67293e17..3d1c43d70 100644
--- a/extra/gross/gross.initd
+++ b/extra/gross/gross.initd
@@ -2,8 +2,8 @@
NAME="grossd"
DAEMON="/usr/sbin/$NAME"
-USER="gross"
-GROUP="gross"
+DAEMON_USER="gross"
+DAEMON_GROUP="gross"
depend() {
need net
@@ -12,18 +12,18 @@ depend() {
check_config() {
if [ ! -f /var/db/gross/state ] ; then
einfo "Generating Gross database..."
- install -dD -o${USER} -g${GROUP} /var/db/gross
- ${DAEMON} -Cu ${USER} > /dev/null
+ install -dD -o${DAEMON_USER} -g${DAEMON_GROUP} /var/db/gross
+ ${DAEMON} -Cu ${DAEMON_USER} > /dev/null
fi
}
start() {
check_config || return 1
ebegin "Starting ${NAME}"
- start-stop-daemon --start --quiet --background \
+ start-stop-daemon --start --quiet \
--exec ${DAEMON} -- \
-p /var/run/gross/grossd.pid \
- -u ${USER} ${OPTS}
+ -u ${DAEMON_USER} ${OPTS}
eend $?
}
diff --git a/extra/gzip/APKBUILD b/extra/gzip/APKBUILD
index 9b4de5801..eb06884d6 100644
--- a/extra/gzip/APKBUILD
+++ b/extra/gzip/APKBUILD
@@ -2,14 +2,13 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=gzip
pkgver=1.3.12
-pkgrel=1
+pkgrel=2
pkgdesc="A popular data compression program"
subpackages="$pkgname-doc"
-arch=""
url="http://www.gnu.org/software/gzip/"
license="GPL2"
-depends="uclibc"
-makedepends=""
+depends=
+makedepends=
install="$pkgname.post-deinstall"
source="http://ftp.gnu.org/gnu/gzip/gzip-1.3.12.tar.gz
$install"
@@ -17,11 +16,19 @@ source="http://ftp.gnu.org/gnu/gzip/gzip-1.3.12.tar.gz
build() {
cd "$srcdir/$pkgname-$pkgver"
+ # avoid text relocation
+ export DEFS="NO_ASM"
./configure --prefix=/usr \
--mandir=/usr/share/man \
+ --disable-nls \
--infodir=/usr/share/info
make || return 1
make DESTDIR=$pkgdir install
+
+ mkdir -p "$pkgdir"/bin
+ mv "$pkgdir"/usr/bin/gzip "$pkgdir"/usr/bin/gunzip "$pkgdir"/bin/
+ ln -s /bin/gzip "$pkgdir"/usr/bin/gzip
+ ln -s /bin/gunzip "$pkgdir"/usr/bin/gunzip
}
md5sums="b5bac2d21840ae077e0217bc5e4845b1 gzip-1.3.12.tar.gz
b84506d253e04db3c5af9016fead45a3 gzip.post-deinstall"
diff --git a/extra/heimdal/APKBUILD b/extra/heimdal/APKBUILD
index 6b1ccc1ef..a494e201a 100644
--- a/extra/heimdal/APKBUILD
+++ b/extra/heimdal/APKBUILD
@@ -2,7 +2,7 @@
# Contributor: Natanael Copa <ncopa@alpinelinux.org>
pkgname=heimdal
pkgver=1.2.1
-pkgrel=2
+pkgrel=3
pkgdesc="An implementation of Kerberos 5"
url="http://www.h5l.org/"
license="BSD"
diff --git a/testing/hylafax/APKBUILD b/extra/hylafax/APKBUILD
index 42450d467..42450d467 100644
--- a/testing/hylafax/APKBUILD
+++ b/extra/hylafax/APKBUILD
diff --git a/testing/hylafax/hylafax.post-install b/extra/hylafax/hylafax.post-install
index 839f96f54..839f96f54 100644
--- a/testing/hylafax/hylafax.post-install
+++ b/extra/hylafax/hylafax.post-install
diff --git a/extra/iaxmodem/iaxmodem.confd b/extra/iaxmodem/iaxmodem.confd
new file mode 100644
index 000000000..082a920e0
--- /dev/null
+++ b/extra/iaxmodem/iaxmodem.confd
@@ -0,0 +1,7 @@
+# Configfile for /etc/init.d/iaxmodem
+
+# Set the priority of the iaxmodem process
+# Value: (highest) -20..19 (lowest)
+#
+#IAXMODEM_NICE="-5"
+
diff --git a/extra/iaxmodem/iaxmodem.initd b/extra/iaxmodem/iaxmodem.initd
new file mode 100644
index 000000000..d6f2c947a
--- /dev/null
+++ b/extra/iaxmodem/iaxmodem.initd
@@ -0,0 +1,43 @@
+#!/sbin/runscript
+# Copyright 1999-2008 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/www/viewcvs.gentoo.org/raw_cvs/gentoo-x86/net-misc/iaxmodem/files/iaxmodem.initd,v 1.1 2008/10/14 23:53:39 sbriesen Exp $
+
+description="IAXmodem"
+description_reload="Reread configuration file and make the appropriate changes"
+extra_started_commands="reload"
+command="/usr/sbin/iaxmodem"
+pidfile="/var/run/iaxmodem.pid"
+name="iaxmodem"
+
+depend() {
+ use asterisk
+ need net
+}
+
+start() {
+ ebegin "Starting ${description}"
+ start-stop-daemon --start --quiet --pidfile "${pidfile}" \
+ --env TMPDIR="/tmp" --nice ${IAXMODEM_NICE:-0} --exec "${command}"
+ eend ${?}
+}
+
+stop() {
+ local childs=""
+ ebegin "Stopping ${description}"
+ # start-stop-daemon doesn't kill childs reliable, so we
+ # use a combination of pgrep + start-stop-daemon + kill
+ [ -s "${pidfile}" ] && childs=$(pgrep -P $(cat "${pidfile}"))
+ start-stop-daemon --stop --quiet --pidfile "${pidfile}" --retry TERM/10/KILL/5
+ if eend ${?}; then
+ # if there're still childs running, kill them!
+ [ -n "${childs}" ] && kill -KILL ${childs} 2>/dev/null
+ return 0
+ fi
+}
+
+reload() {
+ ebegin "Reloading ${description} configuration"
+ start-stop-daemon --stop --signal HUP --pidfile "${pidfile}"
+ eend ${?}
+}
diff --git a/extra/icu/APKBUILD b/extra/icu/APKBUILD
index 8bbacde8d..c2150b3ec 100644
--- a/extra/icu/APKBUILD
+++ b/extra/icu/APKBUILD
@@ -1,7 +1,7 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=icu
-pkgver=4.2.0.1
-_ver=4_2_0_1
+pkgver=4.2.1
+_ver=4_2_1
pkgrel=0
pkgdesc="International Components for Unicode library"
url="http://www.icu-project.org/"
@@ -24,4 +24,4 @@ build ()
install -Dm644 "$srcdir"/icu/license.html \
"$pkgdir"/usr/share/licenses/icu/license.html
}
-md5sums="fd80d21ea863e47ee57b95d466752701 icu4c-4_2_0_1-src.tgz"
+md5sums="e3738abd0d3ce1870dc1fd1f22bba5b1 icu4c-4_2_1-src.tgz"
diff --git a/extra/imagemagick/APKBUILD b/extra/imagemagick/APKBUILD
index ba660d19f..183b1e82c 100644
--- a/extra/imagemagick/APKBUILD
+++ b/extra/imagemagick/APKBUILD
@@ -1,14 +1,14 @@
# Contributor: Carlo Landmeter <clandmeter@gmail.com>
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=imagemagick
-pkgver=6.5.3.2
-_pkgver=6.5.3-2
+pkgver=6.5.3.10
+_pkgver=6.5.3-10
pkgrel=0
pkgdesc="A collection of tools and libraries for many image formats"
url="http://www.imagemagick.org/"
license="GPL"
depends=
-makedepends="zlib-dev libpng-dev libjpeg-dev freetype-dev"
+makedepends="zlib-dev libpng-dev jpeg-dev freetype-dev perl-dev"
subpackages="$pkgname-doc $pkgname-dev"
source="ftp://ftp.imagemagick.org/pub/ImageMagick/ImageMagick-$_pkgver.tar.gz"
@@ -28,8 +28,8 @@ build() {
--without-x \
--with-modules
make || return 1
- make DESTDIR="$pkgdir" install
+ make -j1 DESTDIR="$pkgdir" install
}
-md5sums="51547d4deafdba1d74ea4225805e63e9 ImageMagick-6.5.3-2.tar.gz"
+md5sums="d33621ea195792aeeec79900e7d1e395 ImageMagick-6.5.3-10.tar.gz"
diff --git a/extra/jpeg/APKBUILD b/extra/jpeg/APKBUILD
new file mode 100644
index 000000000..c795091a4
--- /dev/null
+++ b/extra/jpeg/APKBUILD
@@ -0,0 +1,35 @@
+# Contributor: Carlo Landmeter <clandmeter at gmail>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=jpeg
+pkgver=7
+pkgrel=0
+pkgdesc="JPEG image tools"
+url="http://www.ijg.org/"
+license="AS-IS"
+depends=
+makedepends=
+install=
+subpackages="$pkgname-doc $pkgname-dev libjpeg"
+source="http://www.ijg.org/files/jpegsrc.v${pkgver}.tar.gz"
+
+build() {
+ cd "$srcdir"/$pkgname-$pkgver
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --enable-shared
+ make || return 1
+ make -j1 install DESTDIR="$pkgdir"
+ install -Dm644 jpegint.h "$pkgdir"/usr/include/jpegint.h
+}
+
+libjpeg() {
+ pkgdesc="JPEG image library"
+ install -d "$subpkgdir"/usr/lib
+ mv "$pkgdir"/usr/lib/libjpeg* "$subpkgdir"/usr/lib/
+}
+
+
+md5sums="382ef33b339c299b56baf1296cda9785 jpegsrc.v7.tar.gz"
diff --git a/extra/lftp/APKBUILD b/extra/lftp/APKBUILD
index ec6571060..239573c12 100644
--- a/extra/lftp/APKBUILD
+++ b/extra/lftp/APKBUILD
@@ -2,11 +2,11 @@
# Maintainer: Carlo Landmeter <clandmeter@gmail.com>
pkgname=lftp
pkgver=3.7.14
-pkgrel=0
+pkgrel=1
pkgdesc="LFTP is sophisticated ftp/http client"
url="http://lftp.yar.ru/"
license="GPL"
-depends="uclibc ncurses libgcc openssl readline uclibc++"
+depends=
makedepends="openssl-dev uclibc++-dev readline-dev ncurses-dev gettext-dev"
subpackages="$pkgname-doc"
source="http://ftp.yars.free.net/pub/source/lftp/lftp-${pkgver}.tar.bz2"
diff --git a/extra/libgcrypt/APKBUILD b/extra/libgcrypt/APKBUILD
index c858e6884..efe95c1ab 100644
--- a/extra/libgcrypt/APKBUILD
+++ b/extra/libgcrypt/APKBUILD
@@ -1,29 +1,27 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=libgcrypt
pkgver=1.4.4
-pkgrel=0
+pkgrel=1
pkgdesc="general purpose crypto library based on the code used in GnuPG"
url="http://www.gnupg.org"
license="LGPL"
-depends="libgpg-error"
+depends=
makedepends="libgpg-error-dev texinfo"
subpackages="$pkgname-dev $pkgname-doc"
-source="ftp://ftp.franken.de/pub/crypt/mirror/ftp.gnupg.org/gcrypt/$pkgname/$pkgname-$pkgver.tar.bz2
- nocxx.patch"
+source="ftp://ftp.franken.de/pub/crypt/mirror/ftp.gnupg.org/gcrypt/$pkgname/$pkgname-$pkgver.tar.bz2"
+
+depends_dev="libgpg-error-dev"
build () {
cd "$srcdir"/$pkgname-$pkgver
- msg "Punting useless cpp checks..."
- patch configure < "$srcdir"/nocxx.patch || return 1
-
- ./configure --prefix=/usr \
- --disable-padlock-support \
+ ./configure --build=${CHOST:-i486-alpine-linux-uclibc} \
+ --prefix=/usr \
+ --enable-padlock-support \
--disable-static
make || return 1
make -j1 DESTDIR="$pkgdir" install || return 1
rm -f ${pkgdir}/usr/share/info/dir
}
-md5sums="34105aa927e23c217741966496b97e67 libgcrypt-1.4.4.tar.bz2
-28513788ba4d556ccd538867dc6205ab nocxx.patch"
+md5sums="34105aa927e23c217741966496b97e67 libgcrypt-1.4.4.tar.bz2"
diff --git a/extra/libidn/APKBUILD b/extra/libidn/APKBUILD
index 5b19b784e..afcb59c78 100644
--- a/extra/libidn/APKBUILD
+++ b/extra/libidn/APKBUILD
@@ -1,12 +1,12 @@
# Contributor: Michael Mason <ms13sp@gmail.com>
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=libidn
-pkgver=1.14
+pkgver=1.15
pkgrel=0
pkgdesc="An encode and decode library for internationalized domain names"
url="http://www.gnu.org/software/libidn/"
license="GPL"
-depends="uclibc"
+depends=
makedepends=""
install=
subpackages="$pkgname-doc $pkgname-dev"
@@ -26,4 +26,4 @@ build() {
}
-md5sums="2ac3913b2d6c42bf445e7c55db3e2a99 libidn-1.14.tar.gz"
+md5sums="482a25b7b223e52f967fafd284a1a992 libidn-1.15.tar.gz"
diff --git a/extra/libjpeg/APKBUILD b/extra/libjpeg/APKBUILD
deleted file mode 100644
index 54545ff04..000000000
--- a/extra/libjpeg/APKBUILD
+++ /dev/null
@@ -1,35 +0,0 @@
-# Contributor: Carlo Landmeter <clandmeter at gmail>
-# Maintainer: Carlo Landmeter <clandmeter at gmail>
-pkgname=libjpeg
-pkgver=6b
-pkgrel=1
-pkgdesc="Library of JPEG support functions"
-url="http://www.ijg.org/"
-license="custom"
-depends=""
-makedepends="libtool"
-install=
-subpackages="$pkgname-doc $pkgname-dev"
-source="ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v${pkgver}.tar.gz"
-
-build() {
- cd "$srcdir/jpeg-$pkgver"
-
- cp /usr/share/libtool/config/config.guess ./
- cp /usr/share/libtool/config/config.sub ./
- sed -i "s|./libtool|libtool|" configure
- ./configure --prefix=/usr \
- --sysconfdir=/etc \
- --mandir=/usr/share/man \
- --infodir=/usr/share/info \
- --enable-shared \
- --enable-static
- make || return 1
- for i in bin lib include share/man/man1; do
- mkdir -p "$pkgdir"/usr/"$i"
- done
- make prefix="$pkgdir"/usr mandir="$pkgdir"/usr/share/man/man1 install
- install -Dm644 jpegint.h "$pkgdir"/usr/include/jpegint.h
-}
-
-md5sums="dbd5f3b47ed13132f04c685d608a7547 jpegsrc.v6b.tar.gz"
diff --git a/extra/libtheora/APKBUILD b/extra/libtheora/APKBUILD
index 584a5335b..e3b3999a3 100644
--- a/extra/libtheora/APKBUILD
+++ b/extra/libtheora/APKBUILD
@@ -1,15 +1,16 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=libtheora
pkgver=1.0
-pkgrel=0
+pkgrel=1
pkgdesc="An open video codec developed by the Xiph.org"
url="http://www.xiph.org"
license="custom"
subpackages="$pkgname-dev $pkgname-doc"
-depends="libogg uclibc"
-makedepends="libvorbis-dev libogg-dev g++"
+depends=
+makedepends="libvorbis-dev libogg-dev"
source="http://downloads.xiph.org/releases/theora/$pkgname-$pkgver.tar.bz2"
+depends_dev="libogg-dev"
build ()
{
cd "$srcdir"/libtheora-$pkgver
diff --git a/extra/lighttpd/APKBUILD b/extra/lighttpd/APKBUILD
index 94b536069..0abe6dea7 100644
--- a/extra/lighttpd/APKBUILD
+++ b/extra/lighttpd/APKBUILD
@@ -1,12 +1,12 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=lighttpd
-pkgver=1.4.22
+pkgver=1.4.23
pkgrel=0
pkgdesc="a secure, fast, compliant and very flexible web-server"
url="http://www.lighttpd.net/"
license="custom"
install="$pkgname.pre-install $pkgname.post-install"
-depends="pcre openssl zlib lua"
+depends=
makedepends="flex pcre-dev openssl-dev zlib-dev bzip2-dev lua-dev pkgconfig"
source="http://www.$pkgname.net/download/$pkgname-$pkgver.tar.bz2
$pkgname.initd
@@ -67,7 +67,7 @@ build() {
install -m644 "$srcdir"/$i "$pkgdir"/etc/lighttpd/$i
done
}
-md5sums="ed4ca3897eadf419c893b03fee53c982 lighttpd-1.4.22.tar.bz2
+md5sums="0ab6bb7b17bf0f515ce7dce68e5e215a lighttpd-1.4.23.tar.bz2
6910842e8ba496e8aa984ab30a46eb72 lighttpd.initd
0dede109282bfe685bdec6b35f0e4b6b lighttpd.confd
e250fe505d07733e920348bea0909c29 lighttpd.pre-install
diff --git a/extra/lm_sensors/APKBUILD b/extra/lm_sensors/APKBUILD
index 8bd7e3b66..0327dc775 100644
--- a/extra/lm_sensors/APKBUILD
+++ b/extra/lm_sensors/APKBUILD
@@ -1,11 +1,11 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=lm_sensors
-pkgver=3.1.0
+pkgver=3.1.1
pkgrel=0
pkgdesc="Collection of user space tools for general SMBus access and hardware monitoring."
url="http://www.lm-sensors.org/"
license="GPL"
-depends="uclibc sysfsutils rrdtool"
+depends="sysfsutils rrdtool"
makedepends="perl rrdtool-dev bison flex"
subpackages="$pkgname-dev $pkgname-doc $pkgname-detect"
#install=sensors.install
@@ -55,7 +55,7 @@ detect() {
mv usr/sbin/sensors-detect "$subpkgdir"/usr/bin/
}
-md5sums="e23130eaa46c66b861729835e08bdccf lm_sensors-3.1.0.tar.bz2
+md5sums="613d7cfa23b70c0abae3fabb0a72ff5f lm_sensors-3.1.1.tar.bz2
b6e7de1a1768f7a6ea2e00c226331877 lm_sensors-3.1.0-sensors-detect-alpine.patch
58f4c9193a903711ace7fa0754693bd2 fancontrol.initd
2c7e97203da2c39bc9fbfc2a4849cfd4 lm_sensors.initd
diff --git a/extra/lua/APKBUILD b/extra/lua/APKBUILD
index c42d1c9d2..5e41bc03a 100644
--- a/extra/lua/APKBUILD
+++ b/extra/lua/APKBUILD
@@ -1,11 +1,11 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=lua
pkgver=5.1.4
-pkgrel=1
+pkgrel=2
pkgdesc="A powerful light-weight programming language designed for extending applications."
url="http://www.lua.org/"
license="MIT"
-depends="readline"
+depends=
makedepends="readline-dev libtool"
subpackages="$pkgname-dev $pkgname-doc"
source="http://www.$pkgname.org/ftp/$pkgname-$pkgver.tar.gz
diff --git a/testing/luasql-postgres/APKBUILD b/extra/luasql-postgres/APKBUILD
index 36756ca65..36756ca65 100644
--- a/testing/luasql-postgres/APKBUILD
+++ b/extra/luasql-postgres/APKBUILD
diff --git a/testing/luasql-postgres/config.new b/extra/luasql-postgres/config.new
index a8650c551..a8650c551 100644
--- a/testing/luasql-postgres/config.new
+++ b/extra/luasql-postgres/config.new
diff --git a/extra/mini_httpd/APKBUILD b/extra/mini_httpd/APKBUILD
index 275197976..4f7167e70 100644
--- a/extra/mini_httpd/APKBUILD
+++ b/extra/mini_httpd/APKBUILD
@@ -1,15 +1,14 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=mini_httpd
pkgver=1.19
-pkgrel=0
+pkgrel=1
pkgdesc="Small forking webserver with ssl and ipv6 support"
url="http://www.acme.com/software/mini_httpd/"
license="BSD"
-depends="uclibc openssl"
+depends=
makedepends="openssl-dev"
subpackages="$pkgname-doc"
source="http://www.acme.com/software/mini_httpd/$pkgname-$pkgver.tar.gz
- $pkgname.confd
$pkgname.conf.sample
$pkgname.initd
"
@@ -36,10 +35,8 @@ build() {
install -D -m644 ../mini_httpd.conf.sample \
"$pkgdir"/etc/mini_httpd.conf
install -D -m755 ../mini_httpd.initd "$pkgdir"/etc/init.d/mini_httpd
- install -D -m644 ../mini_httpd.confd "$pkgdir"/etc/conf.d/mini_httpd
}
md5sums="7c68293ad265ecfe2edea917912f6f1f mini_httpd-1.19.tar.gz
-8ec70211497d79a26d33006b0ce19aa0 mini_httpd.confd
-fd62c1809f658400acf2082eacd08bb8 mini_httpd.conf.sample
-ec52d2db1ce52f1b088d474aeefe9da8 mini_httpd.initd"
+ec656aadd4751a3f4f6e8c788a5237f2 mini_httpd.conf.sample
+804e5cba1537bddac195e64b5b50d609 mini_httpd.initd"
diff --git a/extra/mini_httpd/mini_httpd.conf.sample b/extra/mini_httpd/mini_httpd.conf.sample
index f215652fe..397a331ad 100644
--- a/extra/mini_httpd/mini_httpd.conf.sample
+++ b/extra/mini_httpd/mini_httpd.conf.sample
@@ -13,6 +13,9 @@ port=80
#port=443
user=nobody
##
+## The DOCROOT
+dir=/var/www/localhost/htdocs
+##
## CGI:
## ? match a single char
## * matches any string excluding "/"
@@ -25,7 +28,6 @@ chroot
#nochroot
##
logfile=/var/log/mini_httpd.log
-pidfile=/var/run/mini_httpd.pid
##
#charset=iso-8859-1
##
diff --git a/extra/mini_httpd/mini_httpd.confd b/extra/mini_httpd/mini_httpd.confd
deleted file mode 100644
index b5e9a8f23..000000000
--- a/extra/mini_httpd/mini_httpd.confd
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright 1999-2004 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-# $Header: /var/cvsroot/gentoo-x86/www-servers/mini_httpd/files/mini_httpd.confd-1.19,v 1.2 2007/08/26 21:20:21 bangert Exp $
-
-## Config file for /etc/init.d/mini_httpd
-
-## the startup-dir of mini_httpd is the docroot, so we specify it here
-## and the init-script does a "cd" prior to startup:
-MINI_HTTPD_DOCROOT="/var/www/localhost/htdocs"
-
-## There are 2 ways to configure mini_httpd:
-## 1) specify all params on the cmd-line
-## 2) use a config-file (and start with "-C <conf-file>")
-## Note: 1) and 2) can be mixed.
-##
-## We choose 1) here -- if you have a more complicated setup read
-## mini_httpd(8) for details on 2).
-
-# MINI_HTTPD_OPTS="-p 8080 -u nobody -r -i /var/run/mini_httpd.pid -l /var/log/mini_httpd.log -d ${MINI_HTTPD_DOCROOT}"
-
-## to add cgi-support you should switch over to a config-file, a sample can
-## be found in your DOCDESTTREE (/usr/share/doc/mini_httpd-xxxx) named
-## mini_httpd.conf.sample.gz
-## copy the sample to /etc/mini_httpd.conf and replace the MINI_HTTPD_OPTS-line
-## above by:
-MINI_HTTPD_OPTS="-C /etc/mini_httpd.conf"
diff --git a/extra/mini_httpd/mini_httpd.initd b/extra/mini_httpd/mini_httpd.initd
index ccaf53d31..4460a539e 100644
--- a/extra/mini_httpd/mini_httpd.initd
+++ b/extra/mini_httpd/mini_httpd.initd
@@ -3,27 +3,23 @@
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/www-servers/mini_httpd/files/mini_httpd.init,v 1.2 2007/08/26 21:20:21 bangert Exp $
+pidfile=/var/run/${SVCNAME}.pid
+
depend() {
need net
}
start() {
- ebegin "Starting mini_httpd"
- if [ ! -d "$MINI_HTTPD_DOCROOT" ]; then
- eend 1 "MINI_HTTPD_DOCROOT not set correctly in /etc/conf.d/mini_httpd"
- exit 1
- fi
- start-stop-daemon --quiet --start --startas /usr/sbin/mini_httpd \
- --pidfile /var/run/mini_httpd.pid -- ${MINI_HTTPD_OPTS}
+ ebegin "Starting $SVCNAME"
+ start-stop-daemon --quiet --start --exec /usr/sbin/mini_httpd \
+ --pidfile $pidfile -- -i $pidfile \
+ ${MINI_HTTPD_OPTS:--C /etc/${SVCNAME}.conf}
eend $?
}
stop() {
- local rc
-
- ebegin "Stopping mini_httpd"
- start-stop-daemon --quiet --stop --pidfile /var/run/mini_httpd.pid
- rc=$?
- rm -f /var/run/mini_httpd.pid
- eend $rc
+ ebegin "Stopping $SVCNAME"
+ start-stop-daemon --quiet --stop --pidfile $pidfile
+ eend $?
}
+
diff --git a/extra/mpg123/APKBUILD b/extra/mpg123/APKBUILD
index 51d252c53..4a13dea81 100644
--- a/extra/mpg123/APKBUILD
+++ b/extra/mpg123/APKBUILD
@@ -1,12 +1,12 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=mpg123
-pkgver=1.7.3
+pkgver=1.8.1
pkgrel=0
pkgdesc="A console based real time MPEG Audio Player for Layer 1, 2 and 3"
url="http://sourceforge.net/projects/mpg123"
license="GPL2 LGPL2"
subpackages="$pkgname-dev $pkgname-doc"
-depends="uclibc alsa-lib libltdl"
+depends=
makedepends="pkgconfig libtool alsa-lib-dev"
source="http://downloads.sourceforge.net/sourceforge/$pkgname/$pkgname-$pkgver.tar.bz2"
@@ -22,4 +22,4 @@ build() {
make || return 1
make DESTDIR="$pkgdir" install || return 1
}
-md5sums="2123db16c22a1fe3c5517c1551aa9d8b mpg123-1.7.3.tar.bz2"
+md5sums="856893f14b29b1cddf4aba32469860b4 mpg123-1.8.1.tar.bz2"
diff --git a/extra/mysql/APKBUILD b/extra/mysql/APKBUILD
index fbe666b0f..de03c127d 100644
--- a/extra/mysql/APKBUILD
+++ b/extra/mysql/APKBUILD
@@ -1,12 +1,12 @@
# Contributor: Carlo Landmeter <clandmeter@gmail.com>
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=mysql
-pkgver=5.0.77
-pkgrel=1
+pkgver=5.0.83
+pkgrel=0
pkgdesc="A fast SQL database server"
url="http://www.mysql.com/"
license='GPL'
-depends="readline openssl uclibc++ zlib"
+depends=
makedepends="libtool uclibc++-dev readline-dev openssl-dev ncurses-dev zlib-dev"
source="http://sunsite.informatik.rwth-aachen.de/mysql/Downloads/MySQL-5.0/${pkgname}-${pkgver}.tar.gz
$pkgname.initd
@@ -32,14 +32,10 @@ build() {
install -Dm 644 "$startdir"/$pkgname.mycnf $pkgdir/etc/mysql/my.cnf
install -dDo mysql $pkgdir/var/log/mysql
install -dDo mysql $pkgdir/var/run/mysqld
-
- # we dont want this be pulled in in the make depends resolving but we
- # want it in the binary package dependency so we add it late.
- depends="$depends libmysqlclient"
}
libmysqlclient() {
- depends="uclibc openssl zlib"
+ pkgdesc="MySQL client library"
mkdir -p "$subpkgdir"/usr/lib/mysql
mv "$pkgdir"/usr/lib/mysql/libmysqlclient.so* "$subpkgdir"/usr/lib/mysql
# make symlinks
@@ -55,7 +51,7 @@ test() {
}
client() {
- depends="libmysqlclient ncurses zlib"
+ pkgdesc="client for the MySQL database"
install=""
local bins="myisam_ftdump mysql mysqlaccess mysqladmin mysqlbug mysqlcheck
mysql_client_test mysqldump mysqldumpslow mysql_explain_log mysql_find_rows
@@ -69,6 +65,6 @@ client() {
done
}
-md5sums="6c30a20c9059daf053a301e927eb1667 mysql-5.0.77.tar.gz
+md5sums="051392064a1e32cca5c23a593908b10e mysql-5.0.83.tar.gz
3ce9827b22d8fbbb29d83a91cbe98ffc mysql.initd
15a7e3ddd6a40bf5a1eb3a8c69d9c34c mysql.mycnf"
diff --git a/extra/ngircd/APKBUILD b/extra/ngircd/APKBUILD
new file mode 100644
index 000000000..2f618a077
--- /dev/null
+++ b/extra/ngircd/APKBUILD
@@ -0,0 +1,36 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=ngircd
+pkgver=14.1
+pkgrel=0
+pkgdesc="Next Generation IRC Daemon"
+url="http://ngircd.barton.de/"
+license="GPL"
+makedepends=""
+makedepends="openssl-dev zlib-dev"
+install="$pkgname.pre-install"
+source="ftp://ftp.berlios.de/pub/$pkgname/$pkgname-$pkgver.tar.gz
+ $pkgname.initd
+ $install"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ sed -i \
+ -e "s:/usr/local/etc/ngircd.motd:/etc/ngircd/ngircd.motd:" \
+ -e "s:;ServerUID = 65534:ServerUID = ngircd:" \
+ -e "s:;ServerGID = 65534:ServerGID = nogroup:" \
+ doc/sample-ngircd.conf
+
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc/ngircd \
+ --mandir=/usr/share/man \
+ --without-ident \
+ --with-openssl
+ make || return 1
+ make DESTDIR="$pkgdir" install || return 1
+ install -Dm755 ../$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
+}
+
+md5sums="eef90855414c35bfb6590d17e24ee06f ngircd-14.1.tar.gz
+1a91f517ef865b51d67b77ceb28e4261 ngircd.initd
+c8fbedf0690f35ba565e6a1937afd4fb ngircd.pre-install"
diff --git a/extra/ngircd/ngircd.initd b/extra/ngircd/ngircd.initd
new file mode 100644
index 000000000..807d844e8
--- /dev/null
+++ b/extra/ngircd/ngircd.initd
@@ -0,0 +1,21 @@
+#!/sbin/runscript
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-irc/ngircd/files/ngircd.init.d,v 1.3 2006/01/02 15:31:27 swegener Exp $
+
+depend() {
+ need net
+ provide ircd
+}
+
+start() {
+ ebegin "Starting ngIRCd"
+ start-stop-daemon --start --quiet --exec /usr/sbin/ngircd
+ eend $? "Failed to start ngIRCd"
+}
+
+stop() {
+ ebegin "Stopping ngIRCd"
+ start-stop-daemon --stop --quiet --exec /usr/sbin/ngircd
+ eend $? "Failed to stop ngIRCd"
+}
diff --git a/extra/ngircd/ngircd.pre-install b/extra/ngircd/ngircd.pre-install
new file mode 100644
index 000000000..062e37ae4
--- /dev/null
+++ b/extra/ngircd/ngircd.pre-install
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+adduser -H -h /etc/ngircd -s /bin/false -D ngircd 2>/dev/null
+exit 0
diff --git a/extra/pgcluster/APKBUILD b/extra/pgcluster/APKBUILD
index 155b3c415..9d92b9b65 100644
--- a/extra/pgcluster/APKBUILD
+++ b/extra/pgcluster/APKBUILD
@@ -2,7 +2,7 @@
pkgname=pgcluster
pkgver=1.9.0_rc5
_myver=1.9.0rc5
-pkgrel=0
+pkgrel=1
pkgdesc="PostgreSQL with multi-master cluster/replication patch"
url="http://pgfoundry.org/projects/pgcluster/"
license="BSD"
diff --git a/extra/php/APKBUILD b/extra/php/APKBUILD
index a07bba0cd..f1a36a24e 100644
--- a/extra/php/APKBUILD
+++ b/extra/php/APKBUILD
@@ -1,53 +1,92 @@
# Contributor: Carlo Landmeter <clandmeter at gmail>
-# Maintainer: Carlo Landmeter <clandmeter at gmail>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=php
-pkgver=5.2.9
+pkgver=5.2.10
pkgrel=0
pkgdesc="The PHP language runtime engine"
url="http://www.php.net/"
license="PHP-3"
-depends="uclibc pcre libxml2"
+depends=
makedepends="pcre-dev libxml2-dev libiconv-dev openssl-dev zlib-dev bzip2-dev
-curl-dev libpng-dev libjpeg-dev freetype-dev libmcrypt-dev mysql-dev sqlite-dev
-libtool libltdl postgresql-dev"
+ curl-dev libpng-dev jpeg-dev freetype-dev libmcrypt-dev mysql-dev
+ sqlite-dev libtool libltdl postgresql-dev"
subpackages="$pkgname-doc $pkgname-dev $pkgname-bcmath $pkgname-bz2
-$pkgname-calendar $pkgname-curl $pkgname-exif $pkgname-ftp $pkgname-gd
-$pkgname-iconv $pkgname-json $pkgname-mcrypt $pkgname-mime_magic
-$pkgname-mysql $pkgname-mysqli $pkgname-openssl $pkgname-pdo
-$pkgname-pdo_mysql $pkgname-pdo_sqlite $pkgname-posix $pkgname-session
-$pkgname-shmop $pkgname-soap $pkgname-sockets $pkgname-sqlite $pkgname-sysvmsg
-$pkgname-sysvsem $pkgname-sysvshm $pkgname-xmlrpc $pkgname-zip $pkgname-zlib
-$pkgname-postgresql $pkgname-pdo_pgsql"
+ $pkgname-calendar $pkgname-curl $pkgname-exif $pkgname-ftp $pkgname-gd
+ $pkgname-iconv $pkgname-json $pkgname-mcrypt $pkgname-mime_magic
+ $pkgname-mysql $pkgname-mysqli $pkgname-openssl $pkgname-pdo
+ $pkgname-pdo_mysql $pkgname-pdo_sqlite $pkgname-posix $pkgname-session
+ $pkgname-shmop $pkgname-soap $pkgname-sockets $pkgname-sqlite
+ $pkgname-sysvmsg $pkgname-sysvsem $pkgname-sysvshm $pkgname-xmlrpc
+ $pkgname-zip $pkgname-zlib $pkgname-postgresql $pkgname-pdo_pgsql"
source="http://www.php.net/distributions/${pkgname}-${pkgver}.tar.bz2"
build() {
cd "$srcdir/$pkgname-$pkgver"
- ./configure \
- --prefix=/usr --sysconfdir=/etc/php --with-layout=GNU \
- --with-config-file-path=/etc/php \
- --with-config-file-scan-dir=/etc/php/conf.d \
- --enable-inline-optimization --disable-debug --disable-rpath \
- --disable-static --enable-shared --mandir=/usr/share/man \
- --with-openssl=shared --with-zlib=shared --enable-bcmath=shared \
- --with-bz2=shared --enable-calendar=shared --with-curl=shared \
- --enable-exif=shared --enable-ftp=shared --with-gd=shared \
- --with-jpeg-dir=shared,/usr --with-png-dir=shared,/usr \
- --enable-gd-native-ttf --enable-mbstring=shared --with-mcrypt=shared \
- --with-mysql=shared --with-mysql-sock=/tmp/mysql.sock \
- --with-mysql=shared --with-mysqli=shared --with-pear=/usr/share/pear \
- --enable-pdo=shared --with-pdo-mysql=shared \
- --with-pdo-sqlite=shared,/usr --enable-fastcgi \
- --with-sqlite=shared --enable-sqlite-utf8 --enable-shmop=shared \
- --enable-soap=shared --enable-sysvmsg=shared --enable-sysvsem=shared \
- --enable-sysvshm=shared --enable-zip=shared --enable-posix=shared \
- --enable-sockets=shared --enable-xml --with-ttf=shared \
- --enable-session=shared --with-regex=php --with-pcre-regex=/usr \
- --enable-mbstring=all --enable-mbregex --enable-json=shared \
- --with-iconv=shared --with-xmlrpc=shared --enable-cgi \
- --with-freetype-dir=shared,/usr --with-mime-magic=shared \
- --enable-discard-path --enable-force-cgi-redirect --disable-cli \
- --with-pgsql=shared --with-pdo-pgsql=shared --with-pic
+ ./configure --build=${CHOST:-i486-alpine-linux-uclibc} \
+ --prefix=/usr \
+ --sysconfdir=/etc/php \
+ --with-layout=GNU \
+ --with-config-file-path=/etc/php \
+ --with-config-file-scan-dir=/etc/php/conf.d \
+ --enable-inline-optimization \
+ --disable-debug \
+ --disable-rpath \
+ --disable-static \
+ --enable-shared \
+ --mandir=/usr/share/man \
+ --with-openssl=shared \
+ --with-zlib=shared \
+ --enable-bcmath=shared \
+ --with-bz2=shared \
+ --enable-calendar=shared \
+ --with-curl=shared \
+ --enable-exif=shared \
+ --enable-ftp=shared \
+ --with-gd=shared \
+ --with-jpeg-dir=shared,/usr \
+ --with-png-dir=shared,/usr \
+ --enable-gd-native-ttf \
+ --enable-mbstring=shared \
+ --with-mcrypt=shared \
+ --with-mysql=shared \
+ --with-mysql-sock=/tmp/mysql.sock \
+ --with-mysql=shared \
+ --with-mysqli=shared \
+ --with-pear=/usr/share/pear \
+ --enable-pdo=shared \
+ --with-pdo-mysql=shared \
+ --with-pdo-sqlite=shared,/usr \
+ --enable-fastcgi \
+ --with-sqlite=shared \
+ --enable-sqlite-utf8 \
+ --enable-shmop=shared \
+ --enable-soap=shared \
+ --enable-sysvmsg=shared \
+ --enable-sysvsem=shared \
+ --enable-sysvshm=shared \
+ --enable-zip=shared \
+ --enable-posix=shared \
+ --enable-sockets=shared \
+ --enable-xml \
+ --with-ttf=shared \
+ --enable-session=shared \
+ --with-regex=php \
+ --with-pcre-regex=/usr \
+ --enable-mbstring=all \
+ --enable-mbregex \
+ --enable-json=shared \
+ --with-iconv=shared \
+ --with-xmlrpc=shared \
+ --enable-cgi \
+ --with-freetype-dir=shared,/usr \
+ --with-mime-magic=shared \
+ --enable-discard-path \
+ --enable-force-cgi-redirect \
+ --disable-cli \
+ --with-pgsql=shared \
+ --with-pdo-pgsql=shared \
+ --with-pic
make || return 1
make -j1 INSTALL_ROOT="$pkgdir" install || return 1
@@ -62,163 +101,38 @@ _mv_mod() {
rmdir "$pkgdir/$d" 2>/dev/null
return 0
}
-
-
-bcmath() {
- depends="uclibc $pkgname"
- _mv_mod bcmath
-}
-
-bz2() {
- depends="uclibc $pkgname"
- _mv_mod bz2
-}
-
-calendar() {
- depends="uclibc $pkgname"
- _mv_mod calendar
-}
-
-curl() {
- depends="uclibc $pkgname curl"
- _mv_mod curl
-}
-
-exif() {
- depends="uclibc $pkgname"
- _mv_mod exif
-}
-
-ftp() {
- depends="uclibc $pkgname openssl"
- _mv_mod ftp
-}
-
-gd() {
- depends="uclibc $pkgname freetype libpng libjpeg zlib"
- _mv_mod gd
-}
-
-iconv() {
- depends="uclibc $pkgname libiconv"
- _mv_mod iconv
-}
-json() {
- depends="uclibc $pkgname"
- _mv_mod json
-}
-
-mcrypt() {
- depends="uclibc $pkgname libmcrypt"
- _mv_mod mcrypt
-}
-
-mime_magic() {
- depends="uclibc $pkgname"
- _mv_mod mime_magic
-}
-
-
-mysql() {
- depends="uclibc $pkgname libmysqlclient"
- _mv_mod mysql
-}
-
-mysqli() {
- depends="uclibc $pkgname libmysqlclient zlib openssl"
- _mv_mod mysqli
-}
-
-openssl() {
- depends="uclibc $pkgname openssl"
- _mv_mod openssl
-}
-
-pdo() {
- depends="uclibc $pkgname"
- _mv_mod pdo
-}
-
-pdo_mysql() {
- depends="uclibc $pkgname libmysqlclient zlib openssl"
- _mv_mod pdo_mysql
-}
-
-pdo_sqlite() {
- depends="uclibc $pkgname sqlite"
- _mv_mod pdo_sqlite
-}
-
-posix() {
- depends="uclibc $pkgname"
- _mv_mod posix
-}
-
-session() {
- depends="uclibc $pkgname"
- _mv_mod session
-}
-
-shmop() {
- depends="uclibc $pkgname"
- _mv_mod shmop
-}
-
-soap() {
- depends="uclibc $pkgname libxml2 zlib"
- _mv_mod soap
-}
-
-sockets() {
- depends="uclibc $pkgname"
- _mv_mod sockets
-}
-
-sqlite() {
- depends="uclibc $pkgname"
- _mv_mod sqlite
-}
-
-sysvmsg() {
- depends="uclibc $pkgname"
- _mv_mod sysvmsg
-}
-
-sysvsem() {
- depends="uclibc $pkgname"
- _mv_mod sysvsem
-}
-
-sysvshm() {
- depends="uclibc $pkgname"
- _mv_mod sysvshm
-}
-
-xmlrpc() {
- depends="uclibc $pkgname libiconv libxml2 zlib"
- _mv_mod xmlrpc
-}
-
-zip() {
- depends="uclibc $pkgname zlib"
- _mv_mod zip
-}
-
-zlib() {
- depends="uclibc $pkgname zlib"
- _mv_mod zlib
-}
-
-postgresql() {
- depends="uclibc $pkgname postgresql"
- _mv_mod pgsql
-}
-
-pdo_pgsql() {
- depends="uclibc $pkgname postgresql"
- _mv_mod pdo_pgsql
-}
+bcmath() { _mv_mod bcmath; }
+bz2() { _mv_mod bz2; }
+calendar() { _mv_mod calendar; }
+curl() { _mv_mod curl; }
+exif() { _mv_mod exif; }
+ftp() { _mv_mod ftp; }
+gd() { _mv_mod gd; }
+iconv() { _mv_mod iconv; }
+json() { _mv_mod json; }
+mcrypt() { _mv_mod mcrypt; }
+mime_magic() { _mv_mod mime_magic; }
+mysql() { _mv_mod mysql; }
+mysqli() { _mv_mod mysqli; }
+openssl() { _mv_mod openssl; }
+pdo() { _mv_mod pdo; }
+pdo_mysql() { _mv_mod pdo_mysql; }
+pdo_sqlite() { _mv_mod pdo_sqlite; }
+posix() { _mv_mod posix; }
+session() { _mv_mod session; }
+shmop() { _mv_mod shmop; }
+soap() { _mv_mod soap; }
+sockets() { _mv_mod sockets; }
+sqlite() { _mv_mod sqlite; }
+sysvmsg() { _mv_mod sysvmsg; }
+sysvsem() { _mv_mod sysvsem; }
+sysvshm() { _mv_mod sysvshm; }
+xmlrpc() { _mv_mod xmlrpc; }
+zip() { _mv_mod zip; }
+zlib() { _mv_mod zlib; }
+postgresql() { _mv_mod pgsql; }
+pdo_pgsql() { _mv_mod pdo_pgsql; }
# devleoper package
dev() {
@@ -227,4 +141,4 @@ dev() {
mv "$pkgdir"/usr/lib/php/build "$subpkgdir"/usr/lib/php/
}
-md5sums="280d6cda7f72a4fc6de42fda21ac2db7 php-5.2.9.tar.bz2"
+md5sums="15c7b5a87f57332d6fc683528e28247b php-5.2.10.tar.bz2"
diff --git a/extra/postgresql/APKBUILD b/extra/postgresql/APKBUILD
index 8ab952810..7d6cb61bd 100644
--- a/extra/postgresql/APKBUILD
+++ b/extra/postgresql/APKBUILD
@@ -1,11 +1,11 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=postgresql
pkgver=8.3.7
-pkgrel=1
+pkgrel=2
pkgdesc="A sophisticated object-relational DBMS"
url="http://www.postgresql.org/"
license="BSD"
-depends="uclibc openssl libpq bbsuid zlib"
+depends="bbsuid"
makedepends="readline-dev openssl-dev zlib-dev"
subpackages="$pkgname-dev $pkgname-doc libpq $pkgname-client"
source="ftp://ftp.$pkgname.org/pub/source/v$pkgver/$pkgname-$pkgver.tar.bz2
@@ -31,14 +31,14 @@ build() {
}
libpq() {
- depends="uclibc openssl"
+ depends=
pkgdesc="PostgreSQL libraries"
mkdir -p "$subpkgdir"/usr/lib
mv "$pkgdir"/usr/lib/libpq.so* "$subpkgdir"/usr/lib/
}
client() {
- depends="uclibc openssl libpq readline"
+ depends=
pkgdesc="PostgreSQL client"
mkdir -p "$subpkgdir"/usr/bin
mv "$pkgdir"/usr/bin/psql "$subpkgdir"/usr/bin/
diff --git a/extra/quagga/APKBUILD b/extra/quagga/APKBUILD
index d69803cb4..aaa3fc64d 100644
--- a/extra/quagga/APKBUILD
+++ b/extra/quagga/APKBUILD
@@ -1,18 +1,17 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=quagga
-pkgver=0.99.12
+pkgver=0.99.13
pkgrel=0
pkgdesc="A free routing daemon replacing Zebra supporting RIP, OSPF and BGP."
url="http://quagga.net/"
license="GPL-2"
depends="iproute2"
-makedepends="readline-dev ncurses-dev
+makedepends="readline-dev ncurses-dev gawk
autoconf automake libtool"
install="$pkgname.pre-install $pkgname.post-install"
subpackages="$pkgname-dev $pkgname-doc"
source="http://www.quagga.net/download/$pkgname-$pkgver.tar.gz
$pkgname-0.99.11-link-libcap.patch
- $pkgname-0.99.11-ipv6.patch
$pkgname-0.99.11-ipv6-only.patch
$pkgname-0.99.11-del-routes.patch
$pkgname-0.99.11-zombie.patch
@@ -63,9 +62,8 @@ build() {
done
install -Dm644 "$srcdir/zebra.confd" "$pkgdir"/etc/conf.d/zebra
}
-md5sums="d2bb513f4ac113dbb300c15a0bd0a241 quagga-0.99.12.tar.gz
+md5sums="55a7d2dcf016580a7c7412b3518cd942 quagga-0.99.13.tar.gz
8f99d41a8ed79e51704e8f655d255f29 quagga-0.99.11-link-libcap.patch
-d73000d128eaf20a17ffb15b5ca1805a quagga-0.99.11-ipv6.patch
44c517e988273e0e5076d24f3959a125 quagga-0.99.11-ipv6-only.patch
1cbcf60a637b2577dee4d6df711e1247 quagga-0.99.11-del-routes.patch
ce345725f2e7240cebe0fd5ac2b2fc48 quagga-0.99.11-zombie.patch
diff --git a/extra/quagga/quagga-0.99.11-ipv6.patch b/extra/quagga/quagga-0.99.11-ipv6.patch
deleted file mode 100644
index b7b0b3d25..000000000
--- a/extra/quagga/quagga-0.99.11-ipv6.patch
+++ /dev/null
@@ -1,19 +0,0 @@
-diff -Nru quagga-0.99.11.orig/lib/sockopt.c quagga-0.99.11/lib/sockopt.c
---- quagga-0.99.11.orig/lib/sockopt.c 2008-09-05 14:27:26.000000000 +0000
-+++ quagga-0.99.11/lib/sockopt.c 2008-10-13 21:46:13.000000000 +0000
-@@ -530,6 +530,7 @@
- return -1;
- };
-
-+#ifdef HAVE_IPV6
- /* If this does not work, then all users of this sockopt will need to
- * differentiate between IPv4 and IPv6, and keep seperate sockets for
- * each.
-@@ -546,6 +547,7 @@
- su2->sin6.sin6_addr.s6_addr32[2] = htonl(0xffff);
- memcpy (&su2->sin6.sin6_addr.s6_addr32[3], &su->sin.sin_addr, 4);
- }
-+#endif /* HAVE_IPV6 */
- }
-
- memset (&md5sig, 0, sizeof (md5sig));
diff --git a/extra/ruby/APKBUILD b/extra/ruby/APKBUILD
index cb01f4be5..ffeb78150 100644
--- a/extra/ruby/APKBUILD
+++ b/extra/ruby/APKBUILD
@@ -1,13 +1,13 @@
# Contributor: Carlo Landmeter <clandmeter@gmail.com>
# Maintainer: Carlo Landmeter <clandmeter@gmail.com>
pkgname=ruby
-pkgver=1.8.7_p160
-_pkgver=1.8.7-p160
-pkgrel=2
+pkgver=1.8.7_p174
+_pkgver=1.8.7-p174
+pkgrel=1
pkgdesc="An object-oriented language for quick and easy programming"
url="http://www.ruby-lang.org/en/"
license="Ruby"
-depends="zlib openssl libiconv gdbm db readline"
+depends=
makedepends="zlib-dev openssl-dev libiconv-dev gdbm-dev db-dev readline-dev"
subpackages="$pkgname-doc $pkgname-dev"
source="ftp://ftp.ruby-lang.org/pub/ruby/1.8/${pkgname}-${_pkgver}.tar.bz2"
@@ -22,15 +22,23 @@ build() {
# as it's risky with newer compilers to leave it as it is.
export CFLAGS="$CFLAGS -fno-omit-frame-pointer -fno-strict-aliasing"
- ./configure --prefix=/usr \
+ # turn off distcc/ccache
+ # http://bugs.alpinelinux.org/issues/show/1
+ export CC=cc
+
+ ./configure --build=${CHOST:-i486-alpine-linux-uclibc} \
+ --prefix=/usr \
--sysconfdir=/etc \
--mandir=/usr/share/man \
--infodir=/usr/share/info \
+ --with-sitedir='/usr/local/lib/site_ruby' \
+ --with-extra-site-search-path='/usr/lib/site_ruby/$(ruby_ver)/i686-linux' \
--enable-shared
make || return 1
make DESTDIR="$pkgdir" install
+
install -Dm644 COPYING "${pkgdir}/usr/share/licenses/${pkgname}"/COPYING || return 1
}
-md5sums="f8ddb886b8a81cf005f53e9a9541091d ruby-1.8.7-p160.tar.bz2"
+md5sums="88c45aaf627b4404e5e4273cb03ba2ee ruby-1.8.7-p174.tar.bz2"
diff --git a/extra/run-parts/APKBUILD b/extra/run-parts/APKBUILD
index ac7cd9f76..5854fa5d8 100644
--- a/extra/run-parts/APKBUILD
+++ b/extra/run-parts/APKBUILD
@@ -1,11 +1,11 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=run-parts
-pkgver=3.0.1
+pkgver=3.1.3
pkgrel=0
pkgdesc="run-parts from the debianutils package"
url="http://packages.qa.debian.org/d/debianutils.html"
license="GPL"
-depends="uclibc"
+depends=
subpackages="$pkgname-doc"
source="http://ftp.debian.org/debian/pool/main/d/debianutils/debianutils_$pkgver.tar.gz"
@@ -16,4 +16,4 @@ build () {
install -D -m755 run-parts $pkgdir/usr/bin/run-parts
install -D -m644 run-parts.8 $pkgdir/usr/share/man/man8/run-parts.8
}
-md5sums="bb476fd2bc76e6aa9106b6c922d0799a debianutils_3.0.1.tar.gz"
+md5sums="42c759ff41851313bb0b9c419598c04c debianutils_3.1.3.tar.gz"
diff --git a/extra/samba/APKBUILD b/extra/samba/APKBUILD
index c05a80f1b..c28a6e2de 100644
--- a/extra/samba/APKBUILD
+++ b/extra/samba/APKBUILD
@@ -1,7 +1,7 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=samba
-pkgver=3.3.5
-pkgrel=1
+pkgver=3.3.6
+pkgrel=0
pkgdesc="Tools to access a server's filespace and printers via SMB"
url="http://www.samba.org"
license="GPL3"
@@ -94,6 +94,6 @@ tdb() {
usr/bin/tdb*
}
-md5sums="8fa0e3c5daaba4c2ce2fb871a5f3157a samba-3.3.5.tar.gz
-df66f9e44bff016c76c41935e959557c samba.initd
+md5sums="858cb6c640358be0e81297c5de615a3c samba-3.3.6.tar.gz
+1b701fdb22c52c63b3af0e4a286a9329 samba.initd
c150433426e18261e6e3eed3930e1a76 samba.confd"
diff --git a/extra/samba/samba.initd b/extra/samba/samba.initd
index 67f65a339..d2d395a98 100644
--- a/extra/samba/samba.initd
+++ b/extra/samba/samba.initd
@@ -30,12 +30,12 @@ stop_nmbd() {
}
start_winbindd() {
- start-stop-daemon --start --quiet --exec /usr/sbin/winbindd \
- -- $winbindd_options
+ start-stop-daemon --start --quiet --exec /usr/sbin/winbindd -- \
+ $winbindd_options
}
stop_winbindd() {
- start-stop-daemon --stop --quiet --oknodo --exec /usr/sbin/winbindd
+ start-stop-daemon --stop --quiet --pidfile /var/run/samba/winbindd.pid
}
start() {
diff --git a/extra/sed/APKBUILD b/extra/sed/APKBUILD
index 653790c02..99ba1e6f8 100644
--- a/extra/sed/APKBUILD
+++ b/extra/sed/APKBUILD
@@ -1,12 +1,12 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=sed
-pkgver=4.2
+pkgver=4.2.1
pkgrel=0
subpackages="$pkgname-doc"
pkgdesc="GNU stream editor"
url="http://www.gnu.org/software/sed"
license="GPL"
-depends="uclibc"
+depends=
makedepends=""
install="$pkgname.post-deinstall"
source="ftp://ftp.gnu.org/pub/gnu/$pkgname/$pkgname-$pkgver.tar.gz
@@ -23,5 +23,5 @@ build() {
make DESTDIR="$pkgdir" install
}
-md5sums="31580bee0c109c0fc8f31c4cf204757e sed-4.2.tar.gz
+md5sums="f0fd4d7da574d4707e442285fd2d3b86 sed-4.2.1.tar.gz
b84506d253e04db3c5af9016fead45a3 sed.post-deinstall"
diff --git a/extra/shorewall-common/APKBUILD b/extra/shorewall-common/APKBUILD
index 267c778ba..1c0a51d8a 100644
--- a/extra/shorewall-common/APKBUILD
+++ b/extra/shorewall-common/APKBUILD
@@ -1,6 +1,6 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=shorewall-common
-pkgver=4.2.9
+pkgver=4.2.10
pkgrel=0
pkgdesc="Shoreline Firewall is an iptables-based firewall for Linux."
url="http://www.shorewall.net/"
@@ -17,5 +17,5 @@ build() {
PREFIX="${pkgdir}" ./install.sh || return 1
install -Dm755 "$srcdir"/shorewall.initd "$pkgdir"/etc/init.d/shorewall
}
-md5sums="6cdb50e7d3caadfc1046acb050ae1deb shorewall-common-4.2.9.tar.bz2
+md5sums="49bdbbae8dec65154c4e5538ed3c9865 shorewall-common-4.2.10.tar.bz2
71fb6da1f50f5c6e9dd35b60b3629531 shorewall.initd"
diff --git a/extra/shorewall-lite/APKBUILD b/extra/shorewall-lite/APKBUILD
index 1e0e89bf7..9c98a3bfd 100644
--- a/extra/shorewall-lite/APKBUILD
+++ b/extra/shorewall-lite/APKBUILD
@@ -1,6 +1,6 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=shorewall-lite
-pkgver=4.2.9
+pkgver=4.2.10
pkgrel=0
pkgdesc="An iptables-based firewall whose config is handled by a normal Shorewall"
url="http://www.shorewall.net/"
@@ -16,5 +16,5 @@ build() {
PREFIX="$pkgdir" ./install.sh || return 1
install -Dm755 "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
}
-md5sums="59ca1b403a8752bcaae5d245ae35210c shorewall-lite-4.2.9.tar.bz2
+md5sums="ef5958819ba18801bacfe20e67184f2a shorewall-lite-4.2.10.tar.bz2
17a37c934aeb601ce288f77000253e1e shorewall-lite.initd"
diff --git a/extra/shorewall-perl/APKBUILD b/extra/shorewall-perl/APKBUILD
index 9e84131c0..e601c96a5 100644
--- a/extra/shorewall-perl/APKBUILD
+++ b/extra/shorewall-perl/APKBUILD
@@ -1,7 +1,7 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=shorewall-perl
-pkgver=4.2.9
-_v=4.2.9
+pkgver=4.2.10.3
+_v=4.2.10
pkgrel=0
pkgdesc="Shoreline Firewall Perl-based compiler"
url="http://www.shorewall.net/"
@@ -13,4 +13,4 @@ build() {
cd "$srcdir"/$pkgname-$pkgver
PREFIX="$pkgdir" ./install.sh || return 1
}
-md5sums="d2df02807b023526f58cb41ece36f610 shorewall-perl-4.2.9.tar.bz2"
+md5sums="f19bed40fe28a905fd08482b9dc5f7ce shorewall-perl-4.2.10.3.tar.bz2"
diff --git a/extra/shorewall-shell/APKBUILD b/extra/shorewall-shell/APKBUILD
index ebcdba78c..643562f20 100644
--- a/extra/shorewall-shell/APKBUILD
+++ b/extra/shorewall-shell/APKBUILD
@@ -1,7 +1,7 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=shorewall-shell
-_v=4.2.9
-pkgver=4.2.9
+_v=4.2.10
+pkgver=4.2.10
pkgrel=0
pkgdesc="Shoreline Firewall shell-based compiler."
url="http://www.shorewall.net/"
@@ -14,4 +14,4 @@ build() {
cd "$srcdir"/$pkgname-$pkgver
PREFIX="$pkgdir" ./install.sh || return 1
}
-md5sums="caa96cf4c257a7156f1621a1ac41d69c shorewall-shell-4.2.9.tar.bz2"
+md5sums="d6f7cbc3c502c09921ede920547d5017 shorewall-shell-4.2.10.tar.bz2"
diff --git a/extra/shorewall/APKBUILD b/extra/shorewall/APKBUILD
index 98af51e52..735973cc2 100644
--- a/extra/shorewall/APKBUILD
+++ b/extra/shorewall/APKBUILD
@@ -1,7 +1,7 @@
# Contributor: Natanael Copa <ncopa@alpinelinux.org>
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=shorewall
-pkgver=4.2.9
+pkgver=4.2.10
pkgrel=0
pkgdesc="Meta package for shorewall"
url="http://www.shorewall.net/"
diff --git a/extra/squid/APKBUILD b/extra/squid/APKBUILD
index b19dd85dc..ac840cbbd 100644
--- a/extra/squid/APKBUILD
+++ b/extra/squid/APKBUILD
@@ -3,7 +3,7 @@
pkgname=squid
pkgver=2.7.6
_ver=2.7.STABLE6
-pkgrel=4
+pkgrel=5
pkgdesc="A full-featured Web proxy cache server."
url="http://www.squid-cache.org"
install="squid.post-install"
@@ -86,6 +86,7 @@ build() {
"$pkgdir"/etc/logrotate.d/squid
mkdir -p "$pkgdir"/var/cache/squid "$pkgdir"/var/log/squid
+ chmod +x "$pkgdir"/usr/lib/squid/*
}
diff --git a/extra/sysklogd/APKBUILD b/extra/sysklogd/APKBUILD
new file mode 100644
index 000000000..e3fe8badc
--- /dev/null
+++ b/extra/sysklogd/APKBUILD
@@ -0,0 +1,50 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=sysklogd
+pkgver=1.5
+pkgrel=0
+pkgdesc="System and kernel log daemons"
+url="http://www.infodrom.org/projects/sysklogd/"
+license="GPL BSD"
+subpackages="$pkgname-doc"
+depends="logrotate"
+makedepends=""
+source="http://www.infodrom.org/projects/$pkgname/download/$pkgname-$pkgver.tar.gz
+ sysklogd.logrotate
+ sysklogd.initd
+ sysklogd.confd
+ sysklogd-1.4.2-caen-owl-klogd-drop-root.diff
+ sysklogd-1.4.2-caen-owl-syslogd-bind.diff
+ sysklogd-1.4.2-caen-owl-syslogd-drop-root.diff
+ sysklogd-1.5-build.patch
+ LICENSE"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+
+ for i in ../*.patch ../*.diff; do
+ msg "Applying $i..."
+ patch -p1 < $i || return 1
+ done
+
+ export CFLAGS="$CFLAGS -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE"
+ make || return 1
+ install -d "$pkgdir"/usr/sbin
+ install -d "$pkgdir"/usr/share/man/man5
+ install -d "$pkgdir"/usr/share/man/man8
+ make INSTALL=install prefix="$pkgdir" install
+ install -D -m644 ../sysklogd.logrotate \
+ "$pkgdir"/etc/logrotate.d/sysklogd
+ install -D -m755 ../sysklogd.initd "$pkgdir"/etc/init.d/sysklogd
+ install -D -m644 ../sysklogd.confd "$pkgdir"/etc/conf.d/sysklogd
+ install -D -m644 ../LICENSE "$pkgdir"/usr/share/licenses/$pkgname/LICENSE
+}
+md5sums="e053094e8103165f98ddafe828f6ae4b sysklogd-1.5.tar.gz
+40304e92b2f6a92e252de24c5e3ca88e sysklogd.logrotate
+9332657663a9f4286e5c61d22c46378f sysklogd.initd
+e25d7b583b7e4bd8be503b89e1771e90 sysklogd.confd
+3b7ba3aa6519f96f11165a7d5900a8b1 sysklogd-1.4.2-caen-owl-klogd-drop-root.diff
+4715e1dd2deb7a9ac137e004210e3154 sysklogd-1.4.2-caen-owl-syslogd-bind.diff
+6c0a416e40a678cf99c454b0e98185c9 sysklogd-1.4.2-caen-owl-syslogd-drop-root.diff
+c71826d1a4f3f7e8ffa57adbfc24f1ce sysklogd-1.5-build.patch
+7930f7ff5038e1318511624e348581cc LICENSE"
diff --git a/extra/sysklogd/LICENSE b/extra/sysklogd/LICENSE
new file mode 100644
index 000000000..7e9b5d59c
--- /dev/null
+++ b/extra/sysklogd/LICENSE
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 1983, 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
diff --git a/extra/sysklogd/sysklogd-1.4.2-caen-owl-klogd-drop-root.diff b/extra/sysklogd/sysklogd-1.4.2-caen-owl-klogd-drop-root.diff
new file mode 100644
index 000000000..40b8817d4
--- /dev/null
+++ b/extra/sysklogd/sysklogd-1.4.2-caen-owl-klogd-drop-root.diff
@@ -0,0 +1,162 @@
+http://cvsweb.openwall.com/cgi/cvsweb.cgi/~checkout~/Owl/packages/sysklogd/sysklogd-1.4.2-caen-owl-klogd-drop-root.diff?rev=1.2;content-type=text%2Fplain
+diff -upk.orig sysklogd-1.4.2.orig/klogd.8 sysklogd-1.4.2/klogd.8
+--- sysklogd-1.4.2.orig/klogd.8 2005-03-11 16:12:09 +0000
++++ sysklogd-1.4.2/klogd.8 2005-08-18 14:37:47 +0000
+@@ -18,6 +19,12 @@ klogd \- Kernel Log Daemon
+ .RB [ " \-f "
+ .I fname
+ ]
++.RB [ " \-u "
++.I username
++]
++.RB [ " \-j "
++.I chroot_dir
++]
+ .RB [ " \-iI " ]
+ .RB [ " \-n " ]
+ .RB [ " \-o " ]
+@@ -53,6 +60,20 @@ stderr.
+ .BI "\-f " file
+ Log messages to the specified filename rather than to the syslog facility.
+ .TP
++.BI "\-u " username
++Tells klogd to become the specified user and drop root privileges before
++starting logging.
++.TP
++.BI "\-j " chroot_dir
++Tells klogd to
++.BR chroot (2)
++into this directory after initializing.
++This option is only valid if the \-u option is also used to run klogd
++without root privileges.
++Note that the use of this option will prevent \-i and \-I from working
++unless you set up the chroot directory in such a way that klogd can still
++read the kernel module symbols.
++.TP
+ .BI "\-i \-I"
+ Signal the currently executing klogd daemon. Both of these switches control
+ the loading/reloading of symbol information. The \-i switch signals the
+diff -upk.orig sysklogd-1.4.2.orig/klogd.c sysklogd-1.4.2/klogd.c
+--- sysklogd-1.4.2.orig/klogd.c 2005-08-18 12:29:52 +0000
++++ sysklogd-1.4.2/klogd.c 2005-08-18 14:37:47 +0000
+@@ -261,6 +261,8 @@
+ #include <stdarg.h>
+ #include <paths.h>
+ #include <stdlib.h>
++#include <pwd.h>
++#include <grp.h>
+ #include "klogd.h"
+ #include "ksyms.h"
+ #ifndef TESTING
+@@ -315,6 +317,9 @@ static enum LOGSRC {none, proc, kernel}
+ int debugging = 0;
+ int symbols_twice = 0;
+
++char *server_user = NULL;
++char *chroot_dir = NULL;
++int log_flags = 0;
+
+ /* Function prototypes. */
+ extern int ksyslog(int type, char *buf, int len);
+@@ -535,8 +540,9 @@ static enum LOGSRC GetKernelLogSrc(void)
+ * First do a stat to determine whether or not the proc based
+ * file system is available to get kernel messages from.
+ */
+- if ( use_syscall ||
+- ((stat(_PATH_KLOG, &sb) < 0) && (errno == ENOENT)) )
++ if (!server_user &&
++ (use_syscall ||
++ ((stat(_PATH_KLOG, &sb) < 0) && (errno == ENOENT))))
+ {
+ /* Initialize kernel logging. */
+ ksyslog(1, NULL, 0);
+@@ -983,6 +989,27 @@ static void LogProcLine(void)
+ }
+
+
++static int drop_root(void)
++{
++ struct passwd *pw;
++
++ if (!(pw = getpwnam(server_user))) return -1;
++
++ if (!pw->pw_uid) return -1;
++
++ if (chroot_dir) {
++ if (chdir(chroot_dir)) return -1;
++ if (chroot(".")) return -1;
++ }
++
++ if (setgroups(0, NULL)) return -1;
++ if (setgid(pw->pw_gid)) return -1;
++ if (setuid(pw->pw_uid)) return -1;
++
++ return 0;
++}
++
++
+ int main(argc, argv)
+
+ int argc;
+@@ -1000,7 +1027,7 @@ int main(argc, argv)
+ chdir ("/");
+ #endif
+ /* Parse the command-line. */
+- while ((ch = getopt(argc, argv, "c:df:iIk:nopsvx2")) != EOF)
++ while ((ch = getopt(argc, argv, "c:df:u:j:iIk:nopsvx2")) != EOF)
+ switch((char)ch)
+ {
+ case '2': /* Print lines with symbols twice. */
+@@ -1022,6 +1049,10 @@ int main(argc, argv)
+ case 'I':
+ SignalDaemon(SIGUSR2);
+ return(0);
++ case 'j': /* chroot 'j'ail */
++ chroot_dir = optarg;
++ log_flags |= LOG_NDELAY;
++ break;
+ case 'k': /* Kernel symbol file. */
+ symfile = optarg;
+ break;
+@@ -1037,6 +1068,9 @@ int main(argc, argv)
+ case 's': /* Use syscall interface. */
+ use_syscall = 1;
+ break;
++ case 'u': /* Run as this user */
++ server_user = optarg;
++ break;
+ case 'v':
+ printf("klogd %s.%s\n", VERSION, PATCHLEVEL);
+ exit (1);
+@@ -1045,6 +1079,10 @@ int main(argc, argv)
+ break;
+ }
+
++ if (chroot_dir && !server_user) {
++ fputs("'-j' is only valid with '-u'\n", stderr);
++ exit(1);
++ }
+
+ /* Set console logging level. */
+ if ( log_level != (char *) 0 )
+@@ -1158,7 +1196,7 @@ int main(argc, argv)
+ }
+ }
+ else
+- openlog("kernel", 0, LOG_KERN);
++ openlog("kernel", log_flags, LOG_KERN);
+
+
+ /* Handle one-shot logging. */
+@@ -1191,6 +1229,11 @@ int main(argc, argv)
+ }
+ }
+
++ if (server_user && drop_root()) {
++ syslog(LOG_ALERT, "klogd: failed to drop root");
++ Terminate();
++ }
++
+ /* The main loop. */
+ while (1)
+ {
diff --git a/extra/sysklogd/sysklogd-1.4.2-caen-owl-syslogd-bind.diff b/extra/sysklogd/sysklogd-1.4.2-caen-owl-syslogd-bind.diff
new file mode 100644
index 000000000..ad311a512
--- /dev/null
+++ b/extra/sysklogd/sysklogd-1.4.2-caen-owl-syslogd-bind.diff
@@ -0,0 +1,103 @@
+http://cvsweb.openwall.com/cgi/cvsweb.cgi/~checkout~/Owl/packages/sysklogd/sysklogd-1.4.2-caen-owl-syslogd-bind.diff?rev=1.1;content-type=text%2Fplain
+diff -upk.orig sysklogd-1.4.2.orig/sysklogd.8 sysklogd-1.4.2/sysklogd.8
+--- sysklogd-1.4.2.orig/sysklogd.8 2004-07-09 17:33:32 +0000
++++ sysklogd-1.4.2/sysklogd.8 2005-08-18 14:40:25 +0000
+@@ -15,6 +15,9 @@ sysklogd \- Linux system logging utiliti
+ .I config file
+ ]
+ .RB [ " \-h " ]
++.RB [ " \-i "
++.I IP address
++]
+ .RB [ " \-l "
+ .I hostlist
+ ]
+@@ -104,6 +107,13 @@ Specifying this switch on the command li
+ This can cause syslog loops that fill up hard disks quite fast and
+ thus needs to be used with caution.
+ .TP
++.BI "\-i " "IP address"
++If
++.B syslogd
++is configured to accept log input from a UDP port, specify an IP address
++to bind to, rather than the default of INADDR_ANY. The address must be in
++dotted quad notation, DNS host names are not allowed.
++.TP
+ .BI "\-l " "hostlist"
+ Specify a hostname that should be logged only with its simple hostname
+ and not the fqdn. Multiple hosts may be specified using the colon
+diff -upk.orig sysklogd-1.4.2.orig/syslogd.c sysklogd-1.4.2/syslogd.c
+--- sysklogd-1.4.2.orig/syslogd.c 2005-08-18 14:33:22 +0000
++++ sysklogd-1.4.2/syslogd.c 2005-08-18 14:40:25 +0000
+@@ -774,6 +774,8 @@ char **LocalHosts = NULL; /* these hosts
+ int NoHops = 1; /* Can we bounce syslog messages through an
+ intermediate host. */
+
++char *bind_addr = NULL; /* bind UDP port to this interface only */
++
+ extern int errno;
+
+ /* Function prototypes. */
+@@ -878,7 +880,7 @@ int main(argc, argv)
+ funix[i] = -1;
+ }
+
+- while ((ch = getopt(argc, argv, "a:dhf:l:m:np:rs:v")) != EOF)
++ while ((ch = getopt(argc, argv, "a:dhf:i:l:m:np:rs:v")) != EOF)
+ switch((char)ch) {
+ case 'a':
+ if (nfunix < MAXFUNIX)
+@@ -895,9 +897,17 @@ int main(argc, argv)
+ case 'h':
+ NoHops = 0;
+ break;
++ case 'i':
++ if (bind_addr) {
++ fprintf(stderr, "Only one -i argument allowed, "
++ "the first one is taken.\n");
++ break;
++ }
++ bind_addr = optarg;
++ break;
+ case 'l':
+ if (LocalHosts) {
+- fprintf (stderr, "Only one -l argument allowed," \
++ fprintf(stderr, "Only one -l argument allowed, "
+ "the first one is taken.\n");
+ break;
+ }
+@@ -1244,7 +1254,7 @@ int main(argc, argv)
+ int usage()
+ {
+ fprintf(stderr, "usage: syslogd [-drvh] [-l hostlist] [-m markinterval] [-n] [-p path]\n" \
+- " [-s domainlist] [-f conffile]\n");
++ " [-s domainlist] [-f conffile] [-i IP address]\n");
+ exit(1);
+ }
+
+@@ -1286,15 +1296,22 @@ static int create_inet_socket()
+ int fd, on = 1;
+ struct sockaddr_in sin;
+
++ memset(&sin, 0, sizeof(sin));
++ sin.sin_family = AF_INET;
++ sin.sin_port = LogPort;
++ if (bind_addr) {
++ if (!inet_aton(bind_addr, &sin.sin_addr)) {
++ logerror("syslog: not a valid IP address to bind to.");
++ return -1;
++ }
++ }
++
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (fd < 0) {
+ logerror("syslog: Unknown protocol, suspending inet service.");
+ return fd;
+ }
+
+- memset(&sin, 0, sizeof(sin));
+- sin.sin_family = AF_INET;
+- sin.sin_port = LogPort;
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, \
+ (char *) &on, sizeof(on)) < 0 ) {
+ logerror("setsockopt(REUSEADDR), suspending inet");
diff --git a/extra/sysklogd/sysklogd-1.4.2-caen-owl-syslogd-drop-root.diff b/extra/sysklogd/sysklogd-1.4.2-caen-owl-syslogd-drop-root.diff
new file mode 100644
index 000000000..8c3f571f3
--- /dev/null
+++ b/extra/sysklogd/sysklogd-1.4.2-caen-owl-syslogd-drop-root.diff
@@ -0,0 +1,118 @@
+http://cvsweb.openwall.com/cgi/cvsweb.cgi/~checkout~/Owl/packages/sysklogd/sysklogd-1.4.2-caen-owl-syslogd-drop-root.diff?rev=1.1;content-type=text%2Fplain
+diff -upk.orig sysklogd-1.4.2.orig/sysklogd.8 sysklogd-1.4.2/sysklogd.8
+--- sysklogd-1.4.2.orig/sysklogd.8 2005-08-18 14:40:25 +0000
++++ sysklogd-1.4.2/sysklogd.8 2005-08-18 14:41:26 +0000
+@@ -32,6 +32,9 @@ sysklogd \- Linux system logging utiliti
+ .RB [ " \-s "
+ .I domainlist
+ ]
++.RB [ " \-u"
++.IB username
++]
+ .RB [ " \-v " ]
+ .LP
+ .SH DESCRIPTION
+@@ -161,6 +164,19 @@ is specified and the host logging resolv
+ no domain would be cut, you will have to specify two domains like:
+ .BR "\-s north.de:infodrom.north.de" .
+ .TP
++.BI "\-u " "username"
++This causes the
++.B syslogd
++daemon to become the named user before starting up logging.
++
++Note that when this option is in use,
++.B syslogd
++will open all log files as root when the daemon is first started;
++however, after a
++.B SIGHUP
++the files will be reopened as the non-privileged user. You should
++take this into account when deciding the ownership of the log files.
++.TP
+ .B "\-v"
+ Print version and exit.
+ .LP
+diff -upk.orig sysklogd-1.4.2.orig/syslogd.c sysklogd-1.4.2/syslogd.c
+--- sysklogd-1.4.2.orig/syslogd.c 2005-08-18 14:40:25 +0000
++++ sysklogd-1.4.2/syslogd.c 2005-08-18 14:41:26 +0000
+@@ -524,6 +524,10 @@ static char sccsid[] = "@(#)syslogd.c 5.
+ #include <arpa/nameser.h>
+ #include <arpa/inet.h>
+ #include <resolv.h>
++
++#include <pwd.h>
++#include <grp.h>
++
+ #ifndef TESTING
+ #include "pidfile.h"
+ #endif
+@@ -775,6 +779,7 @@ int NoHops = 1; /* Can we bounce syslog
+ intermediate host. */
+
+ char *bind_addr = NULL; /* bind UDP port to this interface only */
++char *server_user = NULL; /* user name to run server as */
+
+ extern int errno;
+
+@@ -827,6 +832,21 @@ static int set_nonblock_flag(int desc)
+ return fcntl(desc, F_SETFL, flags | O_NONBLOCK);
+ }
+
++static int drop_root(void)
++{
++ struct passwd *pw;
++
++ if (!(pw = getpwnam(server_user))) return -1;
++
++ if (!pw->pw_uid) return -1;
++
++ if (initgroups(server_user, pw->pw_gid)) return -1;
++ if (setgid(pw->pw_gid)) return -1;
++ if (setuid(pw->pw_uid)) return -1;
++
++ return 0;
++}
++
+ int main(argc, argv)
+ int argc;
+ char **argv;
+@@ -880,7 +900,7 @@ int main(argc, argv)
+ funix[i] = -1;
+ }
+
+- while ((ch = getopt(argc, argv, "a:dhf:i:l:m:np:rs:v")) != EOF)
++ while ((ch = getopt(argc, argv, "a:dhf:i:l:m:np:rs:u:v")) != EOF)
+ switch((char)ch) {
+ case 'a':
+ if (nfunix < MAXFUNIX)
+@@ -933,6 +953,9 @@ int main(argc, argv)
+ }
+ StripDomains = crunch_list(optarg);
+ break;
++ case 'u':
++ server_user = optarg;
++ break;
+ case 'v':
+ printf("syslogd %s.%s\n", VERSION, PATCHLEVEL);
+ exit (0);
+@@ -1100,6 +1123,11 @@ int main(argc, argv)
+ kill (ppid, SIGTERM);
+ #endif
+
++ if (server_user && drop_root()) {
++ dprintf("syslogd: failed to drop root\n");
++ exit(1);
++ }
++
+ /* Main loop begins here. */
+ for (;;) {
+ int nfds;
+@@ -1254,7 +1282,7 @@ int main(argc, argv)
+ int usage()
+ {
+ fprintf(stderr, "usage: syslogd [-drvh] [-l hostlist] [-m markinterval] [-n] [-p path]\n" \
+- " [-s domainlist] [-f conffile] [-i IP address]\n");
++ " [-s domainlist] [-f conffile] [-i IP address] [-u username]\n");
+ exit(1);
+ }
+
diff --git a/extra/sysklogd/sysklogd-1.5-build.patch b/extra/sysklogd/sysklogd-1.5-build.patch
new file mode 100644
index 000000000..6175cdfe7
--- /dev/null
+++ b/extra/sysklogd/sysklogd-1.5-build.patch
@@ -0,0 +1,20 @@
+respect env CC/CFLAGS/CPPFLAGS/LDFLAGS
+
+--- a/Makefile
++++ b/Makefile
+@@ -17,14 +17,12 @@
+ # along with this program; if not, write to the Free Software
+ # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+-CC= gcc
+ #SKFLAGS= -g -DSYSV -Wall
+ #LDFLAGS= -g
+-SKFLAGS= $(RPM_OPT_FLAGS) -O3 -DSYSV -fomit-frame-pointer -Wall -fno-strength-reduce
++SKFLAGS= $(CFLAGS) $(CPPFLAGS) -DSYSV -Wall -fno-strength-reduce
+ # -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
+ # -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE
+ # $(shell getconf LFS_SKFLAGS)
+-LDFLAGS= -s
+
+ # Look where your install program is.
+ INSTALL = /usr/bin/install
diff --git a/extra/sysklogd/sysklogd.confd b/extra/sysklogd/sysklogd.confd
new file mode 100644
index 000000000..c97357391
--- /dev/null
+++ b/extra/sysklogd/sysklogd.confd
@@ -0,0 +1,6 @@
+# Config file for /etc/init.d/sysklogd
+
+SYSLOGD="-m 0"
+# send warnings and above to the console
+KLOGD="-c 3 -2"
+
diff --git a/extra/sysklogd/sysklogd.initd b/extra/sysklogd/sysklogd.initd
new file mode 100644
index 000000000..59db00fc9
--- /dev/null
+++ b/extra/sysklogd/sysklogd.initd
@@ -0,0 +1,79 @@
+#!/sbin/runscript
+# Copyright 1999-2005 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License, v2 or later
+# $Header: /var/cvsroot/gentoo-x86/app-admin/sysklogd/files/sysklogd.rc6,v 1.12 2007/05/01 12:49:04 uberlord Exp $
+
+opts="reload"
+
+depend() {
+ need clock hostname cron
+ provide logger
+}
+
+start_daemon() {
+ local retval=0
+ local daemon="$1"
+ local options="$2"
+
+ [ -z "${daemon}" ] && return 1
+
+ ebegin "sysklogd -> start: ${daemon}"
+ start-stop-daemon --start --exec /usr/sbin/"${daemon}" \
+ --pidfile /var/run/"${daemon}".pid -- ${options}
+ retval=$?
+ eend ${retval} "Failed to start ${daemon}"
+
+ return ${retval}
+}
+
+stop_daemon() {
+ local retval=0
+ local daemon="$1"
+
+ [ -z "${daemon}" ] && return 1
+
+ ebegin "sysklogd -> stop: ${daemon}"
+ # syslogd can be stubborn some times (--retry 15)...
+ start-stop-daemon --stop --retry 15 --quiet --pidfile /var/run/"${daemon}".pid
+ retval=$?
+ eend ${retval} "Failed to stop ${daemon}"
+
+ return ${retval}
+}
+
+start() {
+ start_daemon "syslogd" "${SYSLOGD}" || return 1
+
+ # vservers should not start klogd
+ [ "$RC_SYS" = "VSERVER" ] && return 0
+ # klogd do not always start proper if started too early
+ sleep 1
+
+ if ! start_daemon "klogd" "${KLOGD}" ; then
+ stop_daemon "syslogd"
+ return 1
+ fi
+
+ return 0
+}
+
+stop() {
+ if [ "$RC_SYS" != "VSERVER" ]; then
+ stop_daemon "klogd" || return 1
+ fi
+ stop_daemon "syslogd" || return 1
+ return 0
+}
+
+reload() {
+ local ret=0
+
+ ebegin "Reloading configuration"
+
+ start-stop-daemon --stop --oknodo --signal HUP --pidfile /var/run/syslogd.pid
+ ret=$((${ret} + $?))
+ start-stop-daemon --stop --oknodo --signal USR1 --pidfile /var/run/klogd.pid
+ ret=$((${ret} + $?))
+
+ eend ${ret}
+}
diff --git a/extra/sysklogd/sysklogd.logrotate b/extra/sysklogd/sysklogd.logrotate
new file mode 100644
index 000000000..29afd15bd
--- /dev/null
+++ b/extra/sysklogd/sysklogd.logrotate
@@ -0,0 +1,6 @@
+/var/log/messages /var/log/auth /var/log/mail /var/log/errors /var/log/kernel {
+ sharedscripts
+ postrotate
+ /etc/init.d/sysklogd --quiet reload
+ endscript
+}
diff --git a/extra/sysstat/APKBUILD b/extra/sysstat/APKBUILD
index 4fb6a0f12..f9a1408b7 100644
--- a/extra/sysstat/APKBUILD
+++ b/extra/sysstat/APKBUILD
@@ -1,14 +1,15 @@
# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=sysstat
-pkgver=9.0.2
+pkgver=9.0.3
pkgrel=0
pkgdesc="Performance monitoring tools for Linux"
url="http://pagesperso-orange.fr/sebastien.godard/"
license="GPL"
-depends="uclibc"
+depends=
makedepends=""
subpackages="$pkgname-doc"
-source="http://pagesperso-orange.fr/sebastien.godard/sysstat-9.0.2.tar.gz"
+source="http://pagesperso-orange.fr/sebastien.godard/sysstat-$pkgver.tar.gz"
build() {
cd "$srcdir/$pkgname-$pkgver"
@@ -23,4 +24,4 @@ build() {
}
-md5sums="80d255c64eb60e58d7e373ac070f8941 sysstat-9.0.2.tar.gz"
+md5sums="0b464951596db934418259737cf50a31 sysstat-9.0.3.tar.gz"
diff --git a/extra/tmux/APKBUILD b/extra/tmux/APKBUILD
new file mode 100644
index 000000000..7edc93226
--- /dev/null
+++ b/extra/tmux/APKBUILD
@@ -0,0 +1,27 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=tmux
+pkgver=0.9
+pkgrel=0
+pkgdesc="Tool to control multiple terminals from a single terminal"
+url="http://tmux.sourceforge.net/"
+license="BSD"
+depends=""
+makedepends="ncurses-dev"
+install=
+subpackages="$pkgname-doc"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz
+ build.patch"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+ patch -p1 < ../build.patch || return 1
+
+ ./configure
+ make || return 1
+ make DESTDIR="$pkgdir" PREFIX=/usr install
+
+}
+
+md5sums="2d1df646a6977bb7d9b20e53770d5593 tmux-0.9.tar.gz
+373cabbc35601c3ee71fde0877f5fe83 build.patch"
diff --git a/extra/tmux/build.patch b/extra/tmux/build.patch
new file mode 100644
index 000000000..b16c4f4ca
--- /dev/null
+++ b/extra/tmux/build.patch
@@ -0,0 +1,23 @@
+diff -ru tmux-0.9.orig/GNUmakefile tmux-0.9/GNUmakefile
+--- tmux-0.9.orig/GNUmakefile 2009-07-09 08:11:37.000000000 +0000
++++ tmux-0.9/GNUmakefile 2009-07-09 08:12:09.000000000 +0000
+@@ -53,5 +53,5 @@
+ install: all
+ $(INSTALLDIR) $(DESTDIR)$(PREFIX)/bin
+ $(INSTALLBIN) tmux $(DESTDIR)$(PREFIX)/bin/tmux
+- $(INSTALLDIR) $(DESTDIR)$(PREFIX)/man/man1
+- $(INSTALLMAN) tmux.1 $(DESTDIR)$(PREFIX)/man/man1/tmux.1
++ $(INSTALLDIR) $(DESTDIR)$(PREFIX)/share/man/man1
++ $(INSTALLMAN) tmux.1 $(DESTDIR)$(PREFIX)/share/man/man1/tmux.1
+diff -ru tmux-0.9.orig/configure tmux-0.9/configure
+--- tmux-0.9.orig/configure 2009-07-09 08:11:37.000000000 +0000
++++ tmux-0.9/configure 2009-07-09 08:12:20.000000000 +0000
+@@ -82,7 +82,7 @@
+ compat/strtonum.c \
+ compat/getopt.c \
+ compat/vis.c
+-CFLAGS+= -D_GNU_SOURCE -D_POSIX_SOURCE
++CFLAGS+= -D_GNU_SOURCE -D_POSIX_SOURCE -std=c99
+ LIBS+= -lcrypt -lutil
+ EOF
+ ;;
diff --git a/extra/unrar/APKBUILD b/extra/unrar/APKBUILD
index 3bb9ad5dd..67f33fac0 100644
--- a/extra/unrar/APKBUILD
+++ b/extra/unrar/APKBUILD
@@ -1,11 +1,12 @@
# Contributor: Carlo Landmeter <clandmeter@gmail.com>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=unrar
-pkgver=3.9.3
+pkgver=3.9.4
pkgrel=0
pkgdesc="The RAR uncompression program"
url="http://www.rarlab.com"
license="GPL"
-depends="uclibc uclibc++ libgcc"
+depends=
makedepends="uclibc++-dev"
subpackages="$pkgname-doc"
source="http://www.rarlab.com/rar/unrarsrc-$pkgver.tar.gz"
@@ -22,4 +23,4 @@ build() {
}
-md5sums="94963c803ea2398146d309b3d398c490 unrarsrc-3.9.3.tar.gz"
+md5sums="1800a2242911fc118f6a2b084d0c22c1 unrarsrc-3.9.4.tar.gz"
diff --git a/extra/xvidcore/APKBUILD b/extra/xvidcore/APKBUILD
index f5dc16697..64858bf8d 100644
--- a/extra/xvidcore/APKBUILD
+++ b/extra/xvidcore/APKBUILD
@@ -1,7 +1,7 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=xvidcore
pkgver=1.2.1
-pkgrel=0
+pkgrel=1
pkgdesc="XviD is an open source MPEG-4 video codec"
url="http://www.xvid.org/"
license="GPL"
@@ -13,7 +13,8 @@ source="http://downloads.xvid.org/downloads/$pkgname-$pkgver.tar.bz2"
build ()
{
cd "$srcdir"/$pkgname/build/generic
- ./configure --prefix=/usr
+ ./configure --prefix=/usr \
+ --disable-assembly
make || return 1
make DESTDIR="$pkgdir" install
cd "$pkgdir"/usr/lib
diff --git a/non-free/b43-firmware/APKBUILD b/non-free/b43-firmware/APKBUILD
new file mode 100644
index 000000000..7cfef4f2c
--- /dev/null
+++ b/non-free/b43-firmware/APKBUILD
@@ -0,0 +1,21 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=b43-firmware
+pkgver=4.150.10.5
+pkgrel=0
+pkgdesc="Firmware for b43 driver"
+url="http://linuxwireless.org/en/users/Drivers/b43#firmware_installation"
+license="propietary"
+depends=""
+makedepends="b43-fwcutter"
+install=
+subpackages=
+source="http://mirror2.openwrt.org/sources/broadcom-wl-$pkgver.tar.bz2"
+
+build() {
+ install -d "$pkgdir"/lib/firmware
+ b43-fwcutter -w "$pkgdir"/lib/firmware \
+ "$srcdir"/broadcom-wl-$pkgver/driver/wl_apsta_mimo.o
+}
+
+md5sums="0c6ba9687114c6b598e8019e262d9a60 broadcom-wl-4.150.10.5.tar.bz2"
diff --git a/testing/acf-fetch-crl/APKBUILD b/testing/acf-fetch-crl/APKBUILD
index 5ec99cc91..3728292fd 100644
--- a/testing/acf-fetch-crl/APKBUILD
+++ b/testing/acf-fetch-crl/APKBUILD
@@ -1,15 +1,15 @@
# Contributor: Michael Mason <ms13sp@gmail.com>
pkgname=acf-fetch-crl
-pkgver=0.1.1
+pkgver=0.2.0
pkgrel=0
pkgdesc="A web-based system administration interface for fetch-crl"
-url="http://dev.alpinelinux.org/alpine/acf"
+url="http://git.alpinelinux.org/cgit/$pkgname"
license="GPL-2"
depends="acf-core lua fetch-crl"
makedepends=""
install=
subpackages=""
-source="http://dev.alpinelinux.org/alpine/acf/${pkgname:4}/$pkgname-$pkgver.tar.bz2"
+source="http://git.alpinelinux.org/cgit/$pkgname/snapshot/$pkgname-$pkgver.tar.bz2"
build() {
cd "$srcdir/$pkgname-$pkgver"
@@ -18,4 +18,4 @@ build() {
}
-md5sums="7032943de411a4a048ad07a502671cf4 acf-fetch-crl-0.1.1.tar.bz2"
+md5sums="d8789ef066ac41abd0db69a8ec470540 acf-fetch-crl-0.2.0.tar.bz2"
diff --git a/testing/acf-lvm2/APKBUILD b/testing/acf-lvm2/APKBUILD
new file mode 100644
index 000000000..26aece861
--- /dev/null
+++ b/testing/acf-lvm2/APKBUILD
@@ -0,0 +1,22 @@
+# Contributor: Ted Trask <ttrask01@yahoo.com>
+# Maintainer: Ted Trask <ttrask01@yahoo.com>
+pkgname=acf-lvm2
+pkgver=0.2.0
+pkgrel=0
+pkgdesc="ACF module for lvm2"
+url="http://git.alpinelinux.org/cgit/$pkgname"
+license="GPL-2"
+depends="acf-core lua lvm2"
+makedepends=""
+install=
+subpackages=""
+source="http://git.alpinelinux.org/cgit/$pkgname/snapshot/$pkgname-$pkgver.tar.bz2"
+
+build() {
+ cd "$srcdir/$pkgname-$pkgver"
+
+ make DESTDIR="$pkgdir" install
+
+}
+
+md5sums="daef1d0449814f496b0c4c46538b7e22 acf-lvm2-0.2.0.tar.bz2"
diff --git a/testing/apcupsd/APKBUILD b/testing/apcupsd/APKBUILD
index 03c280f8a..19f4e88d9 100644
--- a/testing/apcupsd/APKBUILD
+++ b/testing/apcupsd/APKBUILD
@@ -1,5 +1,5 @@
pkgname=apcupsd
-pkgver=3.14.5
+pkgver=3.14.6
pkgrel=0
pkgdesc="A Daemon to control APC UPSes"
subpackages="$pkgname-doc"
@@ -22,5 +22,5 @@ build() {
install -D -m755 "$srcdir"/apcupsd.initd "$pkgdir"/etc/init.d/apcupsd
}
-md5sums="4ac73ec91d8ab56f3fac894e172567c4 apcupsd-3.14.5.tar.gz
+md5sums="7df2dbe325a6b1822763cbf6a9fa8263 apcupsd-3.14.6.tar.gz
d276b567fd8dfb9e2a74e533b25de031 apcupsd.initd"
diff --git a/testing/asterisk/APKBUILD b/testing/asterisk/APKBUILD
index ced7f2119..209a93d0d 100644
--- a/testing/asterisk/APKBUILD
+++ b/testing/asterisk/APKBUILD
@@ -1,43 +1,47 @@
# Contributor: Timo Teras <timo.teras@iki.fi>
# Maintainer: Timo Teras <timo.teras@iki.fi>
pkgname=asterisk
-pkgver=1.6.2.0_beta1
-_myver=1.6.2.0-beta1
-pkgrel=4
+pkgver=1.6.3.0_pre20090623
+_basever=1.6.2.0-beta3
+pkgrel=1
pkgdesc="Asterisk: A Module Open Source PBX System"
url="http://www.asterisk.org/"
license="GPL"
-depends="ncurses popt zlib newt dahdi-linux dahdi-tools libltdl libpri freetds"
+depends="dahdi-linux"
makedepends="autoconf automake libtool ncurses-dev popt-dev newt-dev zlib-dev
- postgresql-dev unixodbc-dev dahdi-tools-dev libpri-dev g++ tar
- freetds-dev"
+ postgresql-dev unixodbc-dev dahdi-tools-dev libpri-dev tar
+ freetds-dev openssl-dev lua-dev"
install="$pkgname.pre-install $pkgname.post-install"
subpackages="$pkgname-dev $pkgname-doc $pkgname-pgsql $pkgname-odbc
$pkgname-tds"
-source="http://downloads.digium.com/pub/asterisk/releases/$pkgname-$_myver.tar.gz
+source="http://downloads.digium.com/pub/asterisk/releases/$pkgname-$_basever.tar.gz
asterisk-01-1.6.0-gsm-pic.patch
- asterisk-03-1.6.2.0-beta1-to-r186562.patch
+ asterisk-02-uclibc-daemon.patch
+ asterisk-03-1.6.2.0-beta3-to-svn-r202568.patch
asterisk-04-1.6.0-beta7.1-caps-uclibc.patch
asterisk-05-1.6.1-glob-uclibc.patch
asterisk-06-overlapped-enum.patch
asterisk-07-issue14068.patch
- 200-uclibc-daemon.patch
asterisk.pre-install
asterisk.post-install
asterisk.initd
asterisk.confd"
build() {
- cd "$srcdir/$pkgname-$_myver"
+ cd "$srcdir/$pkgname-$_basever"
for i in ../*.patch; do
msg "Apply $i"
patch -p1 < $i || return 1
done
+ # fix lua includes location
+ sed -i -e 's:lua5.1/::' pbx/pbx_lua.c
+
sed -i -e 's/PBX_ICONV=1/PBX_ICONV=0/g' configure.ac
./bootstrap.sh
- ./configure --prefix=/usr \
+ ./configure --host=${CHOST:-i486-alpine-linux-uclibc} \
+ --prefix=/usr \
--sysconfdir=/etc \
--mandir=/usr/share/man \
--infodir=/usr/share/info \
@@ -47,6 +51,7 @@ build() {
--without-iconv --with-popt --with-z --with-newt \
--with-odbc --with-postgres --with-tds \
--with-dahdi --with-pri --with-tonezone \
+ --without-x11 \
|| return 1
# and figure out which modules to build
@@ -70,31 +75,31 @@ _find_and_move() {
}
pgsql() {
- depends="uclibc asterisk libpq zlib"
+ depends=""
install=
_find_and_move '*_pgsql*'
}
odbc() {
- depends="uclibc asterisk unixodbc"
+ depends=""
install=
_find_and_move '*odbc*'
}
tds() {
- depends="uclibc asterisk freetds"
+ depends=""
install=
_find_and_move '*_tds*'
}
-md5sums="1a44f295fc9e72d19da7f42d095e6c60 asterisk-1.6.2.0-beta1.tar.gz
+md5sums="53989aba01b046a67c6f7754d7a3abcd asterisk-1.6.2.0-beta3.tar.gz
97b39fd9777a2521d4f9f095482b7ac2 asterisk-01-1.6.0-gsm-pic.patch
-9f5d2412feea58ed49e2dff5cfd1fb8f asterisk-03-1.6.2.0-beta1-to-r186562.patch
+b00c9d98ce2ad445501248a197c6e436 asterisk-02-uclibc-daemon.patch
+39f12a80ee2ba70689d7ff244a2b20aa asterisk-03-1.6.2.0-beta3-to-svn-r202568.patch
929f740db7043b4553544ebcc7315c91 asterisk-04-1.6.0-beta7.1-caps-uclibc.patch
c37928e95ebef36aad097accfdbbfcb8 asterisk-05-1.6.1-glob-uclibc.patch
1b49f980e56dc7ce493a046eadff3545 asterisk-06-overlapped-enum.patch
-95bdc48553cc18c9d3807ac96956fc8a asterisk-07-issue14068.patch
-b00c9d98ce2ad445501248a197c6e436 200-uclibc-daemon.patch
+cc6a11b73f3ba7e98a621540c8e71542 asterisk-07-issue14068.patch
b4a97cb1ec3cc3f71a10ce8c067ab430 asterisk.pre-install
62ecffc90b6714b85f377d1fac73c58b asterisk.post-install
bbcd152417bb7c838b25cb6007db91da asterisk.initd
diff --git a/testing/asterisk/200-uclibc-daemon.patch b/testing/asterisk/asterisk-02-uclibc-daemon.patch
index 4956791d4..4956791d4 100644
--- a/testing/asterisk/200-uclibc-daemon.patch
+++ b/testing/asterisk/asterisk-02-uclibc-daemon.patch
diff --git a/testing/asterisk/asterisk-03-1.6.2.0-beta1-to-r186562.patch b/testing/asterisk/asterisk-03-1.6.2.0-beta1-to-r186562.patch
deleted file mode 100644
index 21ff8236e..000000000
--- a/testing/asterisk/asterisk-03-1.6.2.0-beta1-to-r186562.patch
+++ /dev/null
@@ -1,41697 +0,0 @@
-Index: .version
-===================================================================
---- a/.version (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/.version (.../trunk) (revision 186562)
-@@ -1 +1 @@
--1.6.2.0-beta1
-+1.6.2.0-beta1-r186562
-Index: build_tools/strip_nonapi
-===================================================================
---- a/build_tools/strip_nonapi (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/build_tools/strip_nonapi (.../trunk) (revision 186562)
-@@ -1,38 +0,0 @@
--#!/bin/sh -e
--
--# This script is designed to remove all non-API global symbols from an object
--# file. The only global symbols that should be retained are those that belong
--# to the official namespace. Unfortunately doing this is platform-specific, as
--# the object file manipulation tools are not consistent across platforms.
--#
--# On platforms where this script does not know what to do, the object file
--# will retain non-API global symbols, and this may have unpleasant side effects.
--#
--# Prefixes that belong to the official namespace are:
--# ast_
--# _ast_
--# __ast_
--# astman_
--# pbx_
--# resample_
--
--FILTER="${GREP} -v -e ^ast_ -e ^_ast_ -e ^__ast_ -e ^astman_ -e ^pbx_ -e ^resample_"
--
--case "${PROC}" in
-- powerpc64)
-- TEXTSYM=" D "
-- ;;
-- *)
-- TEXTSYM=" T "
-- ;;
--esac
--
--case "${OSARCH}" in
-- linux-gnu|FreeBSD)
-- nm ${1} | ${GREP} -e "$TEXTSYM" | cut -d" " -f3 | ${FILTER} > striplist
-- sed -e "s/^/-N /" striplist | xargs -n 40 ${STRIP} ${1}
-- rm -f striplist
-- ;;
-- *)
-- ;;
--esac
-Index: bridges/bridge_softmix.c
-===================================================================
---- a/bridges/bridge_softmix.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/bridges/bridge_softmix.c (.../trunk) (revision 186562)
-@@ -85,17 +85,25 @@
- /*! \brief Function called when a bridge is created */
- static int softmix_bridge_create(struct ast_bridge *bridge)
- {
-- int timingfd;
-+ struct ast_timer *timer;
-
-- if ((timingfd = ast_timer_open()) < 0) {
-+ if (!(timer = ast_timer_open())) {
- return -1;
- }
-
-- ast_timer_close(timingfd);
-+ bridge->bridge_pvt = timer;
-
- return 0;
- }
-
-+/*! \brief Function called when a bridge is destroyed */
-+static int softmix_bridge_destroy(struct ast_bridge *bridge)
-+{
-+ ast_timer_close((struct ast_timer *) bridge->bridge_pvt);
-+
-+ return 0;
-+}
-+
- /*! \brief Function called when a channel is joined into the bridge */
- static int softmix_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
- {
-@@ -199,14 +207,11 @@
- /*! \brief Function which acts as the mixing thread */
- static int softmix_bridge_thread(struct ast_bridge *bridge)
- {
-- int timingfd;
-+ struct ast_timer *timer = (struct ast_timer *) bridge->bridge_pvt;
-+ int timingfd = ast_timer_fd(timer);
-
-- if ((timingfd = ast_timer_open()) < 0) {
-- return -1;
-- }
-+ ast_timer_set_rate(timer, (1000 / SOFTMIX_INTERVAL));
-
-- ast_timer_set_rate(timingfd, (1000 / SOFTMIX_INTERVAL));
--
- while (!bridge->stop && !bridge->refresh && bridge->array_num) {
- struct ast_bridge_channel *bridge_channel = NULL;
- short buf[SOFTMIX_DATALEN] = {0, };
-@@ -262,14 +267,11 @@
- /* Wait for the timing source to tell us to wake up and get things done */
- ast_waitfor_n_fd(&timingfd, 1, &timeout, NULL);
-
-- ast_timer_ack(timingfd, 1);
-+ ast_timer_ack(timer, 1);
-
- ao2_lock(bridge);
- }
-
-- ast_timer_set_rate(timingfd, 0);
-- ast_timer_close(timingfd);
--
- return 0;
- }
-
-@@ -283,6 +285,7 @@
- .formats = AST_FORMAT_SLINEAR,
- #endif
- .create = softmix_bridge_create,
-+ .destroy = softmix_bridge_destroy,
- .join = softmix_bridge_join,
- .leave = softmix_bridge_leave,
- .write = softmix_bridge_write,
-Index: configure
-===================================================================
---- a/configure (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/configure (.../trunk) (revision 186562)
-@@ -1,5 +1,5 @@
- #! /bin/sh
--# From configure.ac Revision: 182355 .
-+# From configure.ac Revision: 182847 .
- # Guess values for system-dependent variables and create Makefiles.
- # Generated by GNU Autoconf 2.61 for asterisk 1.6.
- #
-@@ -992,7 +992,6 @@
- AST_FORTIFY_SOURCE
- AST_NO_STRICT_OVERFLOW
- AST_SHADOW_WARNINGS
--PBX_RTLD_NOLOAD
- PBX_IP_MTU_DISCOVER
- PBX_DAHDI_HALF_FULL
- GSM_INTERNAL
-@@ -1631,7 +1630,7 @@
- --with-crypto=PATH use OpenSSL Cryptography support files in PATH
- --with-dahdi=PATH use DAHDI files in PATH
- --with-avcodec=PATH use Ffmpeg and avcodec library files in PATH
-- --with-gsm=PATH use External GSM library files in PATH , use
-+ --with-gsm=PATH use External GSM library files in PATH, use
- 'internal' GSM otherwise
- --with-gtk=PATH use gtk libraries files in PATH
- --with-gtk2=PATH use gtk2 libraries files in PATH
-@@ -19141,83 +19140,6 @@
- conftest$ac_exeext conftest.$ac_ext
-
-
-- if test "x${PBX_RTLD_NOLOAD}" != "x1"; then
-- { echo "$as_me:$LINENO: checking for RTLD_NOLOAD in dlfcn.h" >&5
--echo $ECHO_N "checking for RTLD_NOLOAD in dlfcn.h... $ECHO_C" >&6; }
-- saved_cppflags="${CPPFLAGS}"
-- if test "x${RTLD_NOLOAD_DIR}" != "x"; then
-- RTLD_NOLOAD_INCLUDE="-I${RTLD_NOLOAD_DIR}/include"
-- fi
-- CPPFLAGS="${CPPFLAGS} ${RTLD_NOLOAD_INCLUDE}"
--
-- cat >conftest.$ac_ext <<_ACEOF
-- /* confdefs.h. */
--_ACEOF
--cat confdefs.h >>conftest.$ac_ext
--cat >>conftest.$ac_ext <<_ACEOF
--/* end confdefs.h. */
--#include <dlfcn.h>
--int
--main ()
--{
--#if defined(RTLD_NOLOAD)
-- int foo = 0;
-- #else
-- int foo = bar;
-- #endif
-- 0
--
-- ;
-- return 0;
--}
--_ACEOF
--rm -f conftest.$ac_objext
--if { (ac_try="$ac_compile"
--case "(($ac_try" in
-- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-- *) ac_try_echo=$ac_try;;
--esac
--eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-- (eval "$ac_compile") 2>conftest.er1
-- ac_status=$?
-- grep -v '^ *+' conftest.er1 >conftest.err
-- rm -f conftest.er1
-- cat conftest.err >&5
-- echo "$as_me:$LINENO: \$? = $ac_status" >&5
-- (exit $ac_status); } && {
-- test -z "$ac_c_werror_flag" ||
-- test ! -s conftest.err
-- } && test -s conftest.$ac_objext; then
-- { echo "$as_me:$LINENO: result: yes" >&5
--echo "${ECHO_T}yes" >&6; }
-- PBX_RTLD_NOLOAD=1
--
--cat >>confdefs.h <<\_ACEOF
--#define HAVE_RTLD_NOLOAD 1
--_ACEOF
--
--
--cat >>confdefs.h <<\_ACEOF
--#define HAVE_RTLD_NOLOAD_VERSION
--_ACEOF
--
--
--else
-- echo "$as_me: failed program was:" >&5
--sed 's/^/| /' conftest.$ac_ext >&5
--
-- { echo "$as_me:$LINENO: result: no" >&5
--echo "${ECHO_T}no" >&6; }
--
--fi
--
--rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-- CPPFLAGS="${saved_cppflags}"
-- fi
--
--
--
--
- if test "x${PBX_IP_MTU_DISCOVER}" != "x1"; then
- { echo "$as_me:$LINENO: checking for IP_MTU_DISCOVER in netinet/in.h" >&5
- echo $ECHO_N "checking for IP_MTU_DISCOVER in netinet/in.h... $ECHO_C" >&6; }
-@@ -54451,7 +54373,6 @@
- AST_FORTIFY_SOURCE!$AST_FORTIFY_SOURCE$ac_delim
- AST_NO_STRICT_OVERFLOW!$AST_NO_STRICT_OVERFLOW$ac_delim
- AST_SHADOW_WARNINGS!$AST_SHADOW_WARNINGS$ac_delim
--PBX_RTLD_NOLOAD!$PBX_RTLD_NOLOAD$ac_delim
- PBX_IP_MTU_DISCOVER!$PBX_IP_MTU_DISCOVER$ac_delim
- PBX_DAHDI_HALF_FULL!$PBX_DAHDI_HALF_FULL$ac_delim
- GSM_INTERNAL!$GSM_INTERNAL$ac_delim
-@@ -54466,6 +54387,7 @@
- PWLIB_LIBDIR!$PWLIB_LIBDIR$ac_delim
- PWLIB_PLATFORM!$PWLIB_PLATFORM$ac_delim
- OPENH323DIR!$OPENH323DIR$ac_delim
-+OPENH323_INCDIR!$OPENH323_INCDIR$ac_delim
- _ACEOF
-
- if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then
-@@ -54507,7 +54429,6 @@
- ac_delim='%!_!# '
- for ac_last_try in false false false false false :; do
- cat >conf$$subs.sed <<_ACEOF
--OPENH323_INCDIR!$OPENH323_INCDIR$ac_delim
- OPENH323_LIBDIR!$OPENH323_LIBDIR$ac_delim
- OPENH323_SUFFIX!$OPENH323_SUFFIX$ac_delim
- OPENH323_BUILD!$OPENH323_BUILD$ac_delim
-@@ -54528,7 +54449,7 @@
- LTLIBOBJS!$LTLIBOBJS$ac_delim
- _ACEOF
-
-- if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 19; then
-+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 18; then
- break
- elif $ac_last_try; then
- { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
-Index: default.exports
-===================================================================
---- a/default.exports (.../tags/1.6.2.0-beta1) (revision 0)
-+++ b/default.exports (.../trunk) (revision 186562)
-@@ -0,0 +1,4 @@
-+{
-+ local:
-+ *;
-+};
-
-Property changes on: default.exports
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + Author Date Id Revision
-
-Index: pbx/pbx_dundi.c
-===================================================================
---- a/pbx/pbx_dundi.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/pbx/pbx_dundi.c (.../trunk) (revision 186562)
-@@ -4614,7 +4614,7 @@
- ast_log(LOG_WARNING, "Unable to get host name!\n");
- AST_LIST_LOCK(&peers);
-
-- memcpy(&global_eid, &g_eid, sizeof(global_eid));
-+ memcpy(&global_eid, &ast_eid_default, sizeof(global_eid));
-
- global_storehistory = 0;
- ast_copy_string(secretpath, "dundi", sizeof(secretpath));
-Index: channels/h323/Makefile.in
-===================================================================
---- a/channels/h323/Makefile.in (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/channels/h323/Makefile.in (.../trunk) (revision 186562)
-@@ -24,7 +24,9 @@
- OPENH323DIR=@OPENH323DIR@
- endif
-
-+ifneq ($(wildcard $(OPENH323DIR)/openh323u.mak),)
- include $(OPENH323DIR)/openh323u.mak
-+endif
-
- notrace::
- $(MAKE) NOTRACE=1 opt
-Index: channels/misdn_config.c
-===================================================================
---- a/channels/misdn_config.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/channels/misdn_config.c (.../trunk) (revision 186562)
-@@ -1,6 +1,6 @@
- /*
- * Asterisk -- An open source telephony toolkit.
-- *
-+ *
- * Copyright (C) 2005, Christian Richter
- *
- * Christian Richter <crich@beronet.com>
-@@ -132,69 +132,79 @@
- { "musicclass", MISDN_CFG_MUSICCLASS, MISDN_CTYPE_STR, "default", NONE,
- "Sets the musiconhold class." },
- { "callerid", MISDN_CFG_CALLERID, MISDN_CTYPE_STR, "", NONE,
-- "Sets the caller ID." },
-+ "Set the outgoing caller id to the value." },
- { "method", MISDN_CFG_METHOD, MISDN_CTYPE_STR, "standard", NONE,
-- "Sets the method to use for channel selection:\n"
-- "\t standard - always choose the first free channel with the lowest number\n"
-- "\t round_robin - use the round robin algorithm to select a channel. use this\n"
-- "\t if you want to balance your load." },
-+ "Set the method to use for channel selection:\n"
-+ "\t standard - Use the first free channel starting from the lowest number.\n"
-+ "\t standard_dec - Use the first free channel starting from the highest number.\n"
-+ "\t round_robin - Use the round robin algorithm to select a channel. Use this\n"
-+ "\t if you want to balance your load." },
- { "dialplan", MISDN_CFG_DIALPLAN, MISDN_CTYPE_INT, "0", NONE,
-- "Dialplan means Type Of Number in ISDN Terms (for outgoing calls)\n"
-- "\n"
-+ "Dialplan means Type Of Number in ISDN Terms\n"
- "\tThere are different types of the dialplan:\n"
- "\n"
-- "\tdialplan -> outgoing Number\n"
-- "\tlocaldialplan -> callerid\n"
-- "\tcpndialplan -> connected party number\n"
-+ "\tdialplan -> for outgoing call's dialed number\n"
-+ "\tlocaldialplan -> for outgoing call's callerid\n"
-+ "\t (if -1 is set use the value from the asterisk channel)\n"
-+ "\tcpndialplan -> for incoming call's connected party number sent to caller\n"
-+ "\t (if -1 is set use the value from the asterisk channel)\n"
- "\n"
- "\tdialplan options:\n"
- "\n"
- "\t0 - unknown\n"
- "\t1 - International\n"
- "\t2 - National\n"
-- "\t4 - Subscriber\n"
-- "\n"
-- "\tThis setting is used for outgoing calls." },
-+ "\t4 - Subscriber" },
- { "localdialplan", MISDN_CFG_LOCALDIALPLAN, MISDN_CTYPE_INT, "0", NONE,
-- "Dialplan means Type Of Number in ISDN Terms (for outgoing calls)\n"
-- "\n"
-+ "Dialplan means Type Of Number in ISDN Terms\n"
- "\tThere are different types of the dialplan:\n"
- "\n"
-- "\tdialplan -> outgoing Number\n"
-- "\tlocaldialplan -> callerid\n"
-- "\tcpndialplan -> connected party number\n"
-+ "\tdialplan -> for outgoing call's dialed number\n"
-+ "\tlocaldialplan -> for outgoing call's callerid\n"
-+ "\t (if -1 is set use the value from the asterisk channel)\n"
-+ "\tcpndialplan -> for incoming call's connected party number sent to caller\n"
-+ "\t (if -1 is set use the value from the asterisk channel)\n"
- "\n"
- "\tdialplan options:\n"
- "\n"
- "\t0 - unknown\n"
- "\t1 - International\n"
- "\t2 - National\n"
-- "\t4 - Subscriber\n"
-- "\n"
-- "\tThis setting is used for outgoing calls." },
-+ "\t4 - Subscriber" },
- { "cpndialplan", MISDN_CFG_CPNDIALPLAN, MISDN_CTYPE_INT, "0", NONE,
-- "Dialplan means Type Of Number in ISDN Terms (for outgoing calls)\n"
-- "\n"
-+ "Dialplan means Type Of Number in ISDN Terms\n"
- "\tThere are different types of the dialplan:\n"
- "\n"
-- "\tdialplan -> outgoing Number\n"
-- "\tlocaldialplan -> callerid\n"
-- "\tcpndialplan -> connected party number\n"
-+ "\tdialplan -> for outgoing call's dialed number\n"
-+ "\tlocaldialplan -> for outgoing call's callerid\n"
-+ "\t (if -1 is set use the value from the asterisk channel)\n"
-+ "\tcpndialplan -> for incoming call's connected party number sent to caller\n"
-+ "\t (if -1 is set use the value from the asterisk channel)\n"
- "\n"
- "\tdialplan options:\n"
- "\n"
- "\t0 - unknown\n"
- "\t1 - International\n"
- "\t2 - National\n"
-- "\t4 - Subscriber\n"
-- "\n"
-- "\tThis setting is used for outgoing calls." },
-- { "nationalprefix", MISDN_CFG_NATPREFIX, MISDN_CTYPE_STR, "0", NONE,
-- "Prefix for national, this is put before the\n"
-- "\toad if an according dialplan is set by the other end." },
-- { "internationalprefix", MISDN_CFG_INTERNATPREFIX, MISDN_CTYPE_STR, "00", NONE,
-- "Prefix for international, this is put before the\n"
-- "\toad if an according dialplan is set by the other end." },
-+ "\t4 - Subscriber" },
-+ { "unknownprefix", MISDN_CFG_TON_PREFIX_UNKNOWN, MISDN_CTYPE_STR, "", NONE,
-+ "Prefix for unknown numbers, this is put before an incoming number\n"
-+ "\tif its type-of-number is unknown." },
-+ { "internationalprefix", MISDN_CFG_TON_PREFIX_INTERNATIONAL, MISDN_CTYPE_STR, "00", NONE,
-+ "Prefix for international numbers, this is put before an incoming number\n"
-+ "\tif its type-of-number is international." },
-+ { "nationalprefix", MISDN_CFG_TON_PREFIX_NATIONAL, MISDN_CTYPE_STR, "0", NONE,
-+ "Prefix for national numbers, this is put before an incoming number\n"
-+ "\tif its type-of-number is national." },
-+ { "netspecificprefix", MISDN_CFG_TON_PREFIX_NETWORK_SPECIFIC, MISDN_CTYPE_STR, "", NONE,
-+ "Prefix for network-specific numbers, this is put before an incoming number\n"
-+ "\tif its type-of-number is network-specific." },
-+ { "subscriberprefix", MISDN_CFG_TON_PREFIX_SUBSCRIBER, MISDN_CTYPE_STR, "", NONE,
-+ "Prefix for subscriber numbers, this is put before an incoming number\n"
-+ "\tif its type-of-number is subscriber." },
-+ { "abbreviatedprefix", MISDN_CFG_TON_PREFIX_ABBREVIATED, MISDN_CTYPE_STR, "", NONE,
-+ "Prefix for abbreviated numbers, this is put before an incoming number\n"
-+ "\tif its type-of-number is abbreviated." },
- { "presentation", MISDN_CFG_PRES, MISDN_CTYPE_INT, "-1", NONE,
- "These (presentation and screen) are the exact isdn screening and presentation\n"
- "\tindicators.\n"
-@@ -211,6 +221,22 @@
- "\n"
- "\tscreen=0, presentation=0 -> callerid presented\n"
- "\tscreen=1, presentation=1 -> callerid restricted (the remote end doesn't see it!)" },
-+ { "display_connected", MISDN_CFG_DISPLAY_CONNECTED, MISDN_CTYPE_INT, "0", NONE,
-+ "Put a display ie in the CONNECT message containing the following\n"
-+ "\tinformation if it is available (nt port only):\n"
-+ "\n"
-+ "\t0 - Do not put the connected line information in the display ie.\n"
-+ "\t1 - Put the available connected line name in the display ie.\n"
-+ "\t2 - Put the available connected line number in the display ie.\n"
-+ "\t3 - Put the available connected line name and number in the display ie." },
-+ { "display_setup", MISDN_CFG_DISPLAY_SETUP, MISDN_CTYPE_INT, "0", NONE,
-+ "Put a display ie in the SETUP message containing the following\n"
-+ "\tinformation if it is available (nt port only):\n"
-+ "\n"
-+ "\t0 - Do not put the caller information in the display ie.\n"
-+ "\t1 - Put the available caller name in the display ie.\n"
-+ "\t2 - Put the available caller number in the display ie.\n"
-+ "\t3 - Put the available caller name and number in the display ie." },
- { "always_immediate", MISDN_CFG_ALWAYS_IMMEDIATE, MISDN_CTYPE_BOOL, "no", NONE,
- "Enable this to get into the s dialplan-extension.\n"
- "\tThere you can use DigitTimeout if you can't or don't want to use\n"
-@@ -219,7 +245,7 @@
- { "nodialtone", MISDN_CFG_NODIALTONE, MISDN_CTYPE_BOOL, "no", NONE,
- "Enable this to prevent chan_misdn to generate the dialtone\n"
- "\tThis makes only sense together with the always_immediate=yes option\n"
-- "\tto generate your own dialtone with Playtones or so."},
-+ "\tto generate your own dialtone with Playtones or so." },
- { "immediate", MISDN_CFG_IMMEDIATE, MISDN_CTYPE_BOOL, "no", NONE,
- "Enable this if you want callers which called exactly the base\n"
- "\tnumber (so no extension is set) to jump into the s extension.\n"
-@@ -256,17 +282,17 @@
- #endif
- #ifdef WITH_BEROEC
- { "bnechocancel", MISDN_CFG_BNECHOCANCEL, MISDN_CTYPE_BOOLINT, "yes", 64,
-- "echotail in ms (1-200)\n"},
-+ "echotail in ms (1-200)" },
- { "bnec_antihowl", MISDN_CFG_BNEC_ANTIHOWL, MISDN_CTYPE_INT, "0", NONE,
-- "Use antihowl\n"},
-+ "Use antihowl" },
- { "bnec_nlp", MISDN_CFG_BNEC_NLP, MISDN_CTYPE_BOOL, "yes", NONE,
-- "Nonlinear Processing (much faster adaption)"},
-+ "Nonlinear Processing (much faster adaption)" },
- { "bnec_zerocoeff", MISDN_CFG_BNEC_ZEROCOEFF, MISDN_CTYPE_BOOL, "no", NONE,
-- "ZeroCoeffeciens\n"},
-+ "ZeroCoeffeciens" },
- { "bnec_tonedisabler", MISDN_CFG_BNEC_TD, MISDN_CTYPE_BOOL, "no", NONE,
-- "Disable Tone\n"},
-+ "Disable Tone" },
- { "bnec_adaption", MISDN_CFG_BNEC_ADAPT, MISDN_CTYPE_INT, "1", NONE,
-- "Adaption mode (0=no,1=full,2=fast)\n"},
-+ "Adaption mode (0=no,1=full,2=fast)" },
- #endif
- { "need_more_infos", MISDN_CFG_NEED_MORE_INFOS, MISDN_CTYPE_BOOL, "0", NONE,
- "Send Setup_Acknowledge on incoming calls anyway (instead of PROCEEDING),\n"
-@@ -310,13 +336,13 @@
- { "faxdetect_context", MISDN_CFG_FAXDETECT_CONTEXT, MISDN_CTYPE_STR, NO_DEFAULT, NONE,
- "Context to jump into if we detect a fax. Don't set this if you want to stay in the current context." },
- { "l1watcher_timeout", MISDN_CFG_L1_TIMEOUT, MISDN_CTYPE_BOOLINT, "0", 4,
-- "Watches the layer 1. If the layer 1 is down, it tries to\n"
-- "\tget it up. The timeout is given in seconds. with 0 as value it\n"
-- "\tdoes not watch the l1 at all\n"
-+ "Monitors L1 of the port. If L1 is down it tries\n"
-+ "\tto bring it up. The polling timeout is given in seconds.\n"
-+ "\tSetting the value to 0 disables monitoring L1 of the port.\n"
- "\n"
-- "\tThis option is only read at loading time of chan_misdn, which\n"
-- "\tmeans you need to unload and load chan_misdn to change the value,\n"
-- "\tan Asterisk restart should do the trick." },
-+ "\tThis option is only read at chan_misdn loading time.\n"
-+ "\tYou need to unload and load chan_misdn to change the\n"
-+ "\tvalue. An asterisk restart will also do the trick." },
- { "overlapdial", MISDN_CFG_OVERLAP_DIAL, MISDN_CTYPE_BOOLINT, "0", 4,
- "Enables overlap dial for the given amount of seconds.\n"
- "\tPossible values are positive integers or:\n"
-@@ -364,8 +390,8 @@
- { "crypt_keys", MISDN_GEN_CRYPT_KEYS, MISDN_CTYPE_STR, NO_DEFAULT, NONE,
- "Keys for cryption, you reference them in the dialplan\n"
- "\tLater also in dynamic encr." },
-- { "ntkeepcalls", MISDN_GEN_NTKEEPCALLS, MISDN_CTYPE_BOOL, "no", NONE,
-- "avoid dropping calls if the L2 goes down. some Nortel pbx\n"
-+ { "ntkeepcalls", MISDN_GEN_NTKEEPCALLS, MISDN_CTYPE_BOOL, "no", NONE,
-+ "avoid dropping calls if the L2 goes down. some Nortel pbx\n"
- "do put down the L2/L1 for some milliseconds even if there\n"
- "are running calls. with this option you can avoid dropping them" },
- { "ntdebugflags", MISDN_GEN_NTDEBUGFLAGS, MISDN_CTYPE_INT, "0", NONE,
-@@ -386,7 +412,7 @@
- /* maps enum config elements to array positions */
- static int *map;
-
--static ast_mutex_t config_mutex;
-+static ast_mutex_t config_mutex;
-
- #define CLI_ERROR(name, value, section) ({ \
- ast_log(LOG_WARNING, "misdn.conf: \"%s=%s\" (section: %s) invalid or out of range. " \
-@@ -475,7 +501,7 @@
- int i, j;
- int gn = map[MISDN_CFG_GROUPNAME];
- union misdn_cfg_pt* free_list[max_ports + 2];
--
-+
- memset(free_list, 0, sizeof(free_list));
- free_list[0] = port_cfg[0];
- for (i = 1; i <= max_ports; ++i) {
-@@ -507,7 +533,7 @@
- {
- int i;
-
-- for (i = 0; i < NUM_GEN_ELEMENTS; i++)
-+ for (i = 0; i < NUM_GEN_ELEMENTS; i++)
- if (general_cfg[i].any)
- ast_free(general_cfg[i].any);
- }
-@@ -579,11 +605,11 @@
- pos = get_cfg_position(name, PORT_CFG);
- if (pos >= 0)
- return port_spec[pos].elem;
--
-+
- pos = get_cfg_position(name, GEN_CFG);
- if (pos >= 0)
- return gen_spec[pos].elem;
--
-+
- return MISDN_CFG_FIRST;
- }
-
-@@ -597,7 +623,7 @@
- memset(buf, 0, 1);
- return;
- }
--
-+
- /* here comes a hack to replace the (not existing) "name" element with the "ports" element */
- if (elem == MISDN_CFG_GROUPNAME) {
- if (!snprintf(buf, bufsize, "ports"))
-@@ -630,7 +656,7 @@
- spec = (struct misdn_cfg_spec *)port_spec;
- else if ((elem > MISDN_GEN_FIRST) && (elem < MISDN_GEN_LAST))
- spec = (struct misdn_cfg_spec *)gen_spec;
--
-+
- if (!spec || !spec[place].desc)
- memset(buf, 0, 1);
- else {
-@@ -659,7 +685,7 @@
- iter = port_cfg[port][map[MISDN_CFG_MSNS]].ml;
- else
- iter = port_cfg[0][map[MISDN_CFG_MSNS]].ml;
-- for (; iter; iter = iter->next)
-+ for (; iter; iter = iter->next)
- if (*(iter->msn) == '*' || ast_extension_match(iter->msn, msn)) {
- re = 1;
- break;
-@@ -688,7 +714,7 @@
- for (i = 1; i <= max_ports; i++) {
- if (port_cfg[i] && port_cfg[i][map[MISDN_CFG_GROUPNAME]].str) {
- if (!strcasecmp(port_cfg[i][map[MISDN_CFG_GROUPNAME]].str, group))
-- method = (port_cfg[i][map[MISDN_CFG_METHOD]].str ?
-+ method = (port_cfg[i][map[MISDN_CFG_METHOD]].str ?
- port_cfg[i][map[MISDN_CFG_METHOD]].str : port_cfg[0][map[MISDN_CFG_METHOD]].str);
- }
- }
-@@ -708,7 +734,7 @@
- return re;
- }
-
--/*!
-+/*!
- * \brief Generate a comma separated list of all active ports
- */
- void misdn_cfg_get_ports_string (char *ports)
-@@ -776,10 +802,10 @@
- break;
- case MISDN_CTYPE_ASTGROUP:
- if (port_cfg[port][place].grp)
-- snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name,
-+ snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name,
- ast_print_group(tempbuf, sizeof(tempbuf), *port_cfg[port][place].grp));
- else if (port_cfg[0][place].grp)
-- snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name,
-+ snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name,
- ast_print_group(tempbuf, sizeof(tempbuf), *port_cfg[0][place].grp));
- else
- snprintf(buf, bufsize, " -> %s:", port_spec[place].name);
-@@ -844,7 +870,7 @@
- {
- int p = -1;
- int gn = map[MISDN_CFG_GROUPNAME];
--
-+
- misdn_cfg_lock();
- for (port++; port <= max_ports; port++) {
- if (port_cfg[port][gn].str) {
-@@ -936,7 +962,7 @@
- for (; v; v = v->next) {
- if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
- continue;
-- if (((pos = get_cfg_position(v->name, GEN_CFG)) < 0) ||
-+ if (((pos = get_cfg_position(v->name, GEN_CFG)) < 0) ||
- (_parse(&general_cfg[pos], v->value, gen_spec[pos].type, gen_spec[pos].boolint_def) < 0))
- CLI_ERROR(v->name, v->value, "general");
- }
-@@ -958,7 +984,7 @@
- cfg_for_ports[0] = 1;
- }
-
-- if (((pos = get_cfg_position("name", PORT_CFG)) < 0) ||
-+ if (((pos = get_cfg_position("name", PORT_CFG)) < 0) ||
- (_parse(&cfg_tmp[pos], cat, port_spec[pos].type, port_spec[pos].boolint_def) < 0)) {
- CLI_ERROR(v->name, v->value, cat);
- return;
-@@ -969,7 +995,7 @@
- char *token, *tmp = ast_strdupa(v->value);
- char ptpbuf[BUFFERSIZE] = "";
- int start, end;
-- for (token = strsep(&tmp, ","); token; token = strsep(&tmp, ","), *ptpbuf = 0) {
-+ for (token = strsep(&tmp, ","); token; token = strsep(&tmp, ","), *ptpbuf = 0) {
- if (!*token)
- continue;
- if (sscanf(token, "%d-%d%s", &start, &end, ptpbuf) >= 2) {
-@@ -992,7 +1018,7 @@
- }
- }
- } else {
-- if (((pos = get_cfg_position(v->name, PORT_CFG)) < 0) ||
-+ if (((pos = get_cfg_position(v->name, PORT_CFG)) < 0) ||
- (_parse(&cfg_tmp[pos], v->value, port_spec[pos].type, port_spec[pos].boolint_def) < 0))
- CLI_ERROR(v->name, v->value, cat);
- }
-Index: channels/chan_jingle.c
-===================================================================
---- a/channels/chan_jingle.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/channels/chan_jingle.c (.../trunk) (revision 186562)
-@@ -53,7 +53,7 @@
- #include "asterisk/pbx.h"
- #include "asterisk/sched.h"
- #include "asterisk/io.h"
--#include "asterisk/rtp.h"
-+#include "asterisk/rtp_engine.h"
- #include "asterisk/acl.h"
- #include "asterisk/callerid.h"
- #include "asterisk/file.h"
-@@ -112,9 +112,9 @@
- char exten[80]; /*!< Called extension */
- struct ast_channel *owner; /*!< Master Channel */
- char audio_content_name[100]; /*!< name attribute of content tag */
-- struct ast_rtp *rtp; /*!< RTP audio session */
-+ struct ast_rtp_instance *rtp; /*!< RTP audio session */
- char video_content_name[100]; /*!< name attribute of content tag */
-- struct ast_rtp *vrtp; /*!< RTP video session */
-+ struct ast_rtp_instance *vrtp; /*!< RTP video session */
- int jointcapability; /*!< Supported capability at both ends (codecs ) */
- int peercapability;
- struct jingle_pvt *next; /* Next entity */
-@@ -183,11 +183,6 @@
- static struct jingle_pvt *jingle_alloc(struct jingle *client, const char *from, const char *sid);
- static char *jingle_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
- static char *jingle_do_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
--/*----- RTP interface functions */
--static int jingle_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp,
-- struct ast_rtp *vrtp, struct ast_rtp *tpeer, int codecs, int nat_active);
--static enum ast_rtp_get_result jingle_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp);
--static int jingle_get_codec(struct ast_channel *chan);
-
- /*! \brief PBX interface structure for channel registration */
- static const struct ast_channel_tech jingle_tech = {
-@@ -197,7 +192,7 @@
- .requester = jingle_request,
- .send_digit_begin = jingle_digit_begin,
- .send_digit_end = jingle_digit_end,
-- .bridge = ast_rtp_bridge,
-+ .bridge = ast_rtp_instance_bridge,
- .call = jingle_call,
- .hangup = jingle_hangup,
- .answer = jingle_answer,
-@@ -216,15 +211,6 @@
- static struct io_context *io; /*!< The IO context */
- static struct in_addr __ourip;
-
--
--/*! \brief RTP driver interface */
--static struct ast_rtp_protocol jingle_rtp = {
-- type: "Jingle",
-- get_rtp_info: jingle_get_rtp_peer,
-- set_rtp_peer: jingle_set_rtp_peer,
-- get_codec: jingle_get_codec,
--};
--
- static struct ast_cli_entry jingle_cli[] = {
- AST_CLI_DEFINE(jingle_do_reload, "Reload Jingle configuration"),
- AST_CLI_DEFINE(jingle_show_channels, "Show Jingle channels"),
-@@ -304,7 +290,6 @@
- iks_insert_attrib(payload_g723, "name", "G723");
- iks_insert_node(dcodecs, payload_g723);
- }
-- ast_rtp_lookup_code(p->rtp, 1, codec);
- }
-
- static int jingle_accept_call(struct jingle *client, struct jingle_pvt *p)
-@@ -398,18 +383,19 @@
- return res;
- }
-
--static enum ast_rtp_get_result jingle_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
-+static enum ast_rtp_glue_result jingle_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
- {
- struct jingle_pvt *p = chan->tech_pvt;
-- enum ast_rtp_get_result res = AST_RTP_GET_FAILED;
-+ enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_FORBID;
-
- if (!p)
- return res;
-
- ast_mutex_lock(&p->lock);
- if (p->rtp) {
-- *rtp = p->rtp;
-- res = AST_RTP_TRY_PARTIAL;
-+ ao2_ref(p->rtp, +1);
-+ *instance = p->rtp;
-+ res = AST_RTP_GLUE_RESULT_LOCAL;
- }
- ast_mutex_unlock(&p->lock);
-
-@@ -422,7 +408,7 @@
- return p->peercapability;
- }
-
--static int jingle_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *tpeer, int codecs, int nat_active)
-+static int jingle_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *tpeer, int codecs, int nat_active)
- {
- struct jingle_pvt *p;
-
-@@ -442,6 +428,13 @@
- return 0;
- }
-
-+static struct ast_rtp_glue jingle_rtp_glue = {
-+ .type = "Jingle",
-+ .get_rtp_info = jingle_get_rtp_peer,
-+ .get_codec = jingle_get_codec,
-+ .update_peer = jingle_set_rtp_peer,
-+};
-+
- static int jingle_response(struct jingle *client, ikspak *pak, const char *reasonstr, const char *reasonstr2)
- {
- iks *response = NULL, *error = NULL, *reason = NULL;
-@@ -621,7 +614,7 @@
- goto safeout;
- }
-
-- ast_rtp_get_us(p->rtp, &sin);
-+ ast_rtp_instance_get_local_address(p->rtp, &sin);
- ast_find_ourip(&us, bindaddr);
-
- /* Setup our first jingle candidate */
-@@ -779,7 +772,7 @@
- ast_copy_string(tmp->them, idroster, sizeof(tmp->them));
- tmp->initiator = 1;
- }
-- tmp->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
-+ tmp->rtp = ast_rtp_instance_new(NULL, sched, &bindaddr, NULL);
- tmp->parent = client;
- if (!tmp->rtp) {
- ast_log(LOG_WARNING, "Out of RTP sessions?\n");
-@@ -825,18 +818,18 @@
-
- /* Set Frame packetization */
- if (i->rtp)
-- ast_rtp_codec_setpref(i->rtp, &i->prefs);
-+ ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(i->rtp), i->rtp, &i->prefs);
-
- tmp->nativeformats = ast_codec_choose(&i->prefs, what, 1) | (i->jointcapability & AST_FORMAT_VIDEO_MASK);
- fmt = ast_best_codec(tmp->nativeformats);
-
- if (i->rtp) {
-- ast_channel_set_fd(tmp, 0, ast_rtp_fd(i->rtp));
-- ast_channel_set_fd(tmp, 1, ast_rtcp_fd(i->rtp));
-+ ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(i->rtp, 0));
-+ ast_channel_set_fd(tmp, 1, ast_rtp_instance_fd(i->rtp, 1));
- }
- if (i->vrtp) {
-- ast_channel_set_fd(tmp, 2, ast_rtp_fd(i->vrtp));
-- ast_channel_set_fd(tmp, 3, ast_rtcp_fd(i->vrtp));
-+ ast_channel_set_fd(tmp, 2, ast_rtp_instance_fd(i->vrtp, 0));
-+ ast_channel_set_fd(tmp, 3, ast_rtp_instance_fd(i->vrtp, 1));
- }
- if (state == AST_STATE_RING)
- tmp->rings = 1;
-@@ -942,9 +935,9 @@
- if (p->owner)
- ast_log(LOG_WARNING, "Uh oh, there's an owner, this is going to be messy.\n");
- if (p->rtp)
-- ast_rtp_destroy(p->rtp);
-+ ast_rtp_instance_destroy(p->rtp);
- if (p->vrtp)
-- ast_rtp_destroy(p->vrtp);
-+ ast_rtp_instance_destroy(p->vrtp);
- jingle_free_candidates(p->theircandidates);
- ast_free(p);
- }
-@@ -1009,8 +1002,8 @@
- ast_copy_string(p->audio_content_name, iks_find_attrib(content, "name"), sizeof(p->audio_content_name));
-
- while (codec) {
-- ast_rtp_set_m_type(p->rtp, atoi(iks_find_attrib(codec, "id")));
-- ast_rtp_set_rtpmap_type(p->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0);
-+ ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id")));
-+ ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0);
- codec = iks_next(codec);
- }
- }
-@@ -1025,8 +1018,8 @@
- ast_copy_string(p->video_content_name, iks_find_attrib(content, "name"), sizeof(p->video_content_name));
-
- while (codec) {
-- ast_rtp_set_m_type(p->rtp, atoi(iks_find_attrib(codec, "id")));
-- ast_rtp_set_rtpmap_type(p->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0);
-+ ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id")));
-+ ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0);
- codec = iks_next(codec);
- }
- }
-@@ -1079,7 +1072,7 @@
- sin.sin_port = htons(tmp->port);
- snprintf(username, sizeof(username), "%s:%s", tmp->ufrag, p->ourcandidates->ufrag);
-
-- ast_rtp_stun_request(p->rtp, &sin, username);
-+ ast_rtp_instance_stun_request(p->rtp, &sin, username);
- tmp = tmp->next;
- }
- return 1;
-@@ -1169,7 +1162,7 @@
-
- if (!p->rtp)
- return &ast_null_frame;
-- f = ast_rtp_read(p->rtp);
-+ f = ast_rtp_instance_read(p->rtp, 0);
- jingle_update_stun(p->parent, p);
- if (p->owner) {
- /* We already hold the channel lock */
-@@ -1220,7 +1213,7 @@
- if (p) {
- ast_mutex_lock(&p->lock);
- if (p->rtp) {
-- res = ast_rtp_write(p->rtp, frame);
-+ res = ast_rtp_instance_write(p->rtp, frame);
- }
- ast_mutex_unlock(&p->lock);
- }
-@@ -1229,7 +1222,7 @@
- if (p) {
- ast_mutex_lock(&p->lock);
- if (p->vrtp) {
-- res = ast_rtp_write(p->vrtp, frame);
-+ res = ast_rtp_instance_write(p->vrtp, frame);
- }
- ast_mutex_unlock(&p->lock);
- }
-@@ -1879,7 +1872,7 @@
- return 0;
- }
-
-- ast_rtp_proto_register(&jingle_rtp);
-+ ast_rtp_glue_register(&jingle_rtp_glue);
- ast_cli_register_multiple(jingle_cli, ARRAY_LEN(jingle_cli));
- /* Make sure we can register our channel type */
- if (ast_channel_register(&jingle_tech)) {
-@@ -1902,7 +1895,7 @@
- ast_cli_unregister_multiple(jingle_cli, ARRAY_LEN(jingle_cli));
- /* First, take us out of the channel loop */
- ast_channel_unregister(&jingle_tech);
-- ast_rtp_proto_unregister(&jingle_rtp);
-+ ast_rtp_glue_unregister(&jingle_rtp_glue);
-
- if (!ast_mutex_lock(&jinglelock)) {
- /* Hangup all interfaces if they have an owner */
-Index: channels/chan_dahdi.c
-===================================================================
---- a/channels/chan_dahdi.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/channels/chan_dahdi.c (.../trunk) (revision 186562)
-@@ -153,9 +153,6 @@
- <description>
- <para>This application will Accept the R2 call either with charge or no charge.</para>
- </description>
-- <description>
-- <para>This application will Accept the R2 call either with charge or no charge.</para>
-- </description>
- </application>
- ***/
-
-@@ -2535,9 +2532,6 @@
- /* Don't delete if we don't think it's conferenced at all (implied) */
- ) return 0;
- memset(&zi, 0, sizeof(zi));
-- zi.chan = 0;
-- zi.confno = 0;
-- zi.confmode = 0;
- if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
- ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
- return -1;
-@@ -2593,11 +2587,12 @@
-
- static int reset_conf(struct dahdi_pvt *p)
- {
-- struct dahdi_confinfo zi;
-- memset(&zi, 0, sizeof(zi));
- p->confno = -1;
- memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
- if (p->subs[SUB_REAL].dfd > -1) {
-+ struct dahdi_confinfo zi;
-+
-+ memset(&zi, 0, sizeof(zi));
- if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
- ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
- }
-@@ -2911,8 +2906,7 @@
- p->saveconf.confmode = 0;
- return -1;
- }
-- c.chan = 0;
-- c.confno = 0;
-+ memset(&c, 0, sizeof(c));
- c.confmode = DAHDI_CONF_NORMAL;
- res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
- if (res) {
-@@ -2962,10 +2956,7 @@
- return;
- }
-
-- ast_event_queue_and_cache(event,
-- AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR,
-- AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR,
-- AST_EVENT_IE_END);
-+ ast_event_queue_and_cache(event);
-
- if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
- snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
-@@ -3019,7 +3010,6 @@
- event = ast_event_get_cached(AST_EVENT_MWI,
- AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
- AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
-- AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
- AST_EVENT_IE_END);
-
- if (event) {
-@@ -3166,7 +3156,7 @@
- }
- p->callwaitcas = 0;
- if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
-- p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
-+ p->cidlen = ast_callerid_generate(p->cidspill, ast->connected.id.name, ast->connected.id.number, AST_LAW(p));
- p->cidpos = 0;
- send_callerid(p);
- }
-@@ -3207,12 +3197,12 @@
- } else {
- /* Call waiting call */
- p->callwaitrings = 0;
-- if (ast->cid.cid_num)
-- ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
-+ if (ast->connected.id.number)
-+ ast_copy_string(p->callwait_num, ast->connected.id.number, sizeof(p->callwait_num));
- else
- p->callwait_num[0] = '\0';
-- if (ast->cid.cid_name)
-- ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
-+ if (ast->connected.id.name)
-+ ast_copy_string(p->callwait_name, ast->connected.id.name, sizeof(p->callwait_name));
- else
- p->callwait_name[0] = '\0';
- /* Call waiting tone instead */
-@@ -3224,8 +3214,8 @@
- if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
- ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
- }
-- n = ast->cid.cid_name;
-- l = ast->cid.cid_num;
-+ n = ast->connected.id.name;
-+ l = ast->connected.id.number;
- if (l)
- ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
- else
-@@ -3291,14 +3281,14 @@
-
- switch (mysig) {
- case SIG_FEATD:
-- l = ast->cid.cid_num;
-+ l = ast->connected.id.number;
- if (l)
- snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
- else
- snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
- break;
- case SIG_FEATDMF:
-- l = ast->cid.cid_num;
-+ l = ast->connected.id.number;
- if (l)
- snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
- else
-@@ -3394,6 +3384,7 @@
- case SIG_MFCR2:
- /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
- p->dialdest[0] = '\0';
-+ p->dialing = 1;
- break;
- default:
- ast_debug(1, "not yet implemented\n");
-@@ -3432,7 +3423,7 @@
- }
-
- if (!p->hidecallerid) {
-- l = ast->cid.cid_num;
-+ l = ast->connected.id.number;
- } else {
- l = NULL;
- }
-@@ -3481,10 +3472,10 @@
- }
- }
- isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
-- p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
-- p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED );
-+ p->use_callingpres ? cid_pres2ss7pres(ast->connected.id.number_presentation) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
-+ p->use_callingpres ? cid_pres2ss7screen(ast->connected.id.number_presentation) : SS7_SCREENING_USER_PROVIDED );
-
-- isup_set_oli(p->ss7call, ast->cid.cid_ani2);
-+ isup_set_oli(p->ss7call, ast->connected.ani2);
- isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
-
- ast_channel_lock(ast);
-@@ -3596,9 +3587,9 @@
- l = NULL;
- n = NULL;
- if (!p->hidecallerid) {
-- l = ast->cid.cid_num;
-+ l = ast->connected.id.number;
- if (!p->hidecalleridname) {
-- n = ast->cid.cid_name;
-+ n = ast->connected.id.name;
- }
- }
-
-@@ -3812,7 +3803,7 @@
- }
- }
- pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
-- p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
-+ p->use_callingpres ? ast->connected.id.number_presentation : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
- if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
- if (!strcasecmp(rr_str, "UNKNOWN"))
- redirect_reason = 0;
-@@ -4468,6 +4459,7 @@
- p->onhooktime = time(NULL);
- #if defined(HAVE_PRI) || defined(HAVE_SS7)
- p->proceeding = 0;
-+ p->dialing = 0;
- p->progress = 0;
- p->alerting = 0;
- p->setup_ack = 0;
-@@ -4604,6 +4596,7 @@
- case SIG_FXOGS:
- case SIG_FXOLS:
- case SIG_FXOKS:
-+ memset(&par, 0, sizeof(par));
- res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
- if (!res) {
- #if 0
-@@ -4769,6 +4762,7 @@
- /* Send a pri acknowledge */
- if (!pri_grab(p, p->pri)) {
- p->proceeding = 1;
-+ p->dialing = 0;
- res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
- pri_rel(p->pri);
- } else {
-@@ -5580,6 +5574,7 @@
- }
-
- /* No alarms on the span. Check for channel alarms. */
-+ memset(&params, 0, sizeof(params));
- if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
- return params.chan_alarms;
-
-@@ -6206,6 +6201,7 @@
- {
- struct dahdi_params par;
-
-+ memset(&par, 0, sizeof(par));
- if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
- {
- if (!par.rxisoffhook)
-@@ -6698,6 +6694,7 @@
- {
- struct dahdi_params ps;
-
-+ memset(&ps, 0, sizeof(ps));
- ps.channo = p->channel;
- if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
- ast_mutex_unlock(&p->lock);
-@@ -7209,6 +7206,7 @@
- ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
- }
- p->proceeding = 1;
-+ p->dialing = 0;
- }
- #endif
- #ifdef HAVE_SS7
-@@ -7390,6 +7388,7 @@
- if (!tmp)
- return NULL;
- tmp->tech = &dahdi_tech;
-+ memset(&ps, 0, sizeof(ps));
- ps.channo = i->channel;
- res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
- if (res) {
-@@ -7407,7 +7406,7 @@
- deflaw = AST_FORMAT_ULAW;
- }
- ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
-- tmp->nativeformats = AST_FORMAT_SLINEAR | deflaw;
-+ tmp->nativeformats = deflaw;
- /* Start out assuming ulaw since it's smaller :) */
- tmp->rawreadformat = deflaw;
- tmp->readformat = deflaw;
-@@ -9017,8 +9016,8 @@
- #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
- if (pvt->mwisend_fsk) {
- #endif
-- pvt->cidlen = vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
-- AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
-+ pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
-+ AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
- pvt->cidpos = 0;
- #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
- }
-@@ -10219,9 +10218,10 @@
- #endif
- } else {
- chan_sig = tmp->sig;
-- memset(&p, 0, sizeof(p));
-- if (tmp->subs[SUB_REAL].dfd > -1)
-+ if (tmp->subs[SUB_REAL].dfd > -1) {
-+ memset(&p, 0, sizeof(p));
- res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
-+ }
- }
- /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
- switch (chan_sig) {
-@@ -10602,9 +10602,10 @@
- if (!p->sig || (p->sig == SIG_FXSLS))
- return 1;
- /* Check hook state */
-- if (p->subs[SUB_REAL].dfd > -1)
-+ if (p->subs[SUB_REAL].dfd > -1) {
-+ memset(&par, 0, sizeof(par));
- res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
-- else {
-+ } else {
- /* Assume not off hook on CVRS */
- res = 0;
- par.rxisoffhook = 0;
-@@ -11940,6 +11941,7 @@
-
- if (!explicit) {
- spanfd = pri_active_dchan_fd(pri);
-+ memset(&param, 0, sizeof(param));
- if (ioctl(spanfd, DAHDI_GET_PARAMS, &param))
- return -1;
- span = pris[param.spanno - 1].prilogicalspan;
-@@ -12991,8 +12993,12 @@
- ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
- pri->pvts[chanpos]->dsp_features = 0;
- }
-+ /* Bring voice path up */
-+ f.subclass = AST_CONTROL_PROGRESS;
-+ dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
- }
- pri->pvts[chanpos]->progress = 1;
-+ pri->pvts[chanpos]->dialing = 0;
- ast_mutex_unlock(&pri->pvts[chanpos]->lock);
- }
- }
-@@ -13024,6 +13030,7 @@
- dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
- }
- pri->pvts[chanpos]->proceeding = 1;
-+ pri->pvts[chanpos]->dialing = 0;
- ast_mutex_unlock(&pri->pvts[chanpos]->lock);
- }
- }
-@@ -13400,6 +13407,7 @@
- ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
- return -1;
- }
-+ memset(&p, 0, sizeof(p));
- res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
- if (res) {
- dahdi_close_pri_fd(pri, i);
-@@ -13421,6 +13429,7 @@
- pri->dchanavail[i] |= DCHAN_NOTINALARM;
- else
- pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
-+ memset(&bi, 0, sizeof(bi));
- bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
- bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
- bi.numbufs = 32;
-@@ -14632,12 +14641,14 @@
- memset(&ci, 0, sizeof(ci));
- ps.channo = tmp->channel;
- if (tmp->subs[SUB_REAL].dfd > -1) {
-+ memset(&ci, 0, sizeof(ci));
- if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
- ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
- }
- if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
- ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
- }
-+ memset(&ps, 0, sizeof(ps));
- if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
- ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
- } else {
-@@ -15017,7 +15028,7 @@
- AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
- AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
- AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
-- AST_CLI_DEFINE(dahdi_set_dnd, "Set software gain on a channel"),
-+ AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
- };
-
- #define TRANSFER 0
-@@ -15297,6 +15308,7 @@
- ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan, strerror(errno));
- return -1;
- }
-+ memset(&p, 0, sizeof(p));
- res = ioctl(link->fds[curfd], DAHDI_GET_PARAMS, &p);
- if (res) {
- dahdi_close_ss7_fd(link, curfd);
-@@ -15309,6 +15321,7 @@
- return -1;
- }
-
-+ memset(&bi, 0, sizeof(bi));
- bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
- bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
- bi.numbufs = 32;
-Index: channels/chan_phone.c
-===================================================================
---- a/channels/chan_phone.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/channels/chan_phone.c (.../trunk) (revision 186562)
-@@ -303,13 +303,13 @@
- snprintf(cid.min, sizeof(cid.min), "%02d", tm.tm_min);
- }
- /* the standard format of ast->callerid is: "name" <number>, but not always complete */
-- if (ast_strlen_zero(ast->cid.cid_name))
-+ if (ast_strlen_zero(ast->connected.id.name))
- strcpy(cid.name, DEFAULT_CALLER_ID);
- else
-- ast_copy_string(cid.name, ast->cid.cid_name, sizeof(cid.name));
-+ ast_copy_string(cid.name, ast->connected.id.name, sizeof(cid.name));
-
-- if (ast->cid.cid_num)
-- ast_copy_string(cid.number, ast->cid.cid_num, sizeof(cid.number));
-+ if (ast->connected.id.number)
-+ ast_copy_string(cid.number, ast->connected.id.number, sizeof(cid.number));
-
- p = ast->tech_pvt;
-
-Index: channels/chan_h323.c
-===================================================================
---- a/channels/chan_h323.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/channels/chan_h323.c (.../trunk) (revision 186562)
-@@ -76,7 +76,7 @@
- #include "asterisk/utils.h"
- #include "asterisk/sched.h"
- #include "asterisk/io.h"
--#include "asterisk/rtp.h"
-+#include "asterisk/rtp_engine.h"
- #include "asterisk/acl.h"
- #include "asterisk/callerid.h"
- #include "asterisk/cli.h"
-@@ -161,7 +161,7 @@
- char accountcode[256]; /*!< Account code */
- char rdnis[80]; /*!< Referring DNIS, if available */
- int amaflags; /*!< AMA Flags */
-- struct ast_rtp *rtp; /*!< RTP Session */
-+ struct ast_rtp_instance *rtp; /*!< RTP Session */
- struct ast_dsp *vad; /*!< Used for in-band DTMF detection */
- int nativeformats; /*!< Codec formats supported by a channel */
- int needhangup; /*!< Send hangup when Asterisk is ready */
-@@ -254,7 +254,7 @@
- .write = oh323_write,
- .indicate = oh323_indicate,
- .fixup = oh323_fixup,
-- .bridge = ast_rtp_bridge,
-+ .bridge = ast_rtp_instance_bridge,
- };
-
- static const char* redirectingreason2str(int redirectingreason)
-@@ -381,8 +381,8 @@
- if (pvt->update_rtp_info > 0) {
- if (pvt->rtp) {
- ast_jb_configure(c, &global_jbconf);
-- ast_channel_set_fd(c, 0, ast_rtp_fd(pvt->rtp));
-- ast_channel_set_fd(c, 1, ast_rtcp_fd(pvt->rtp));
-+ ast_channel_set_fd(c, 0, ast_rtp_instance_fd(pvt->rtp, 0));
-+ ast_channel_set_fd(c, 1, ast_rtp_instance_fd(pvt->rtp, 1));
- ast_queue_frame(pvt->owner, &ast_null_frame); /* Tell Asterisk to apply changes */
- }
- pvt->update_rtp_info = -1;
-@@ -444,7 +444,7 @@
- AST_SCHED_DEL(sched, pvt->DTMFsched);
-
- if (pvt->rtp) {
-- ast_rtp_destroy(pvt->rtp);
-+ ast_rtp_instance_destroy(pvt->rtp);
- }
-
- /* Free dsp used for in-band DTMF detection */
-@@ -510,7 +510,7 @@
- if (h323debug) {
- ast_log(LOG_DTMF, "Begin sending out-of-band digit %c on %s\n", digit, c->name);
- }
-- ast_rtp_senddigit_begin(pvt->rtp, digit);
-+ ast_rtp_instance_dtmf_begin(pvt->rtp, digit);
- ast_mutex_unlock(&pvt->lock);
- } else if (pvt->txDtmfDigit != digit) {
- /* in-band DTMF */
-@@ -549,7 +549,7 @@
- if (h323debug) {
- ast_log(LOG_DTMF, "End sending out-of-band digit %c on %s, duration %d\n", digit, c->name, duration);
- }
-- ast_rtp_senddigit_end(pvt->rtp, digit);
-+ ast_rtp_instance_dtmf_end(pvt->rtp, digit);
- ast_mutex_unlock(&pvt->lock);
- } else {
- /* in-band DTMF */
-@@ -606,18 +606,18 @@
- /* make sure null terminated */
- called_addr[sizeof(called_addr) - 1] = '\0';
-
-- if (c->cid.cid_num)
-- ast_copy_string(pvt->options.cid_num, c->cid.cid_num, sizeof(pvt->options.cid_num));
-+ if (c->connected.id.number)
-+ ast_copy_string(pvt->options.cid_num, c->connected.id.number, sizeof(pvt->options.cid_num));
-
-- if (c->cid.cid_name)
-- ast_copy_string(pvt->options.cid_name, c->cid.cid_name, sizeof(pvt->options.cid_name));
-+ if (c->connected.id.name)
-+ ast_copy_string(pvt->options.cid_name, c->connected.id.name, sizeof(pvt->options.cid_name));
-
- if (c->cid.cid_rdnis) {
- ast_copy_string(pvt->options.cid_rdnis, c->cid.cid_rdnis, sizeof(pvt->options.cid_rdnis));
- }
-
-- pvt->options.presentation = c->cid.cid_pres;
-- pvt->options.type_of_number = c->cid.cid_ton;
-+ pvt->options.presentation = c->connected.id.number_presentation;
-+ pvt->options.type_of_number = c->connected.id.number_type;
-
- if ((addr = pbx_builtin_getvar_helper(c, "PRIREDIRECTREASON"))) {
- if (!strcasecmp(addr, "UNKNOWN"))
-@@ -747,11 +747,11 @@
-
- /* Only apply it for the first packet, we just need the correct ip/port */
- if (pvt->options.nat) {
-- ast_rtp_setnat(pvt->rtp, pvt->options.nat);
-+ ast_rtp_instance_set_prop(pvt->rtp, AST_RTP_PROPERTY_NAT, pvt->options.nat);
- pvt->options.nat = 0;
- }
-
-- f = ast_rtp_read(pvt->rtp);
-+ f = ast_rtp_instance_read(pvt->rtp, 0);
- /* Don't send RFC2833 if we're not supposed to */
- if (f && (f->frametype == AST_FRAME_DTMF) && !(pvt->options.dtmfmode & (H323_DTMF_RFC2833 | H323_DTMF_CISCO))) {
- return &ast_null_frame;
-@@ -808,7 +808,7 @@
- break;
- case 1:
- if (pvt->rtp)
-- fr = ast_rtcp_read(pvt->rtp);
-+ fr = ast_rtp_instance_read(pvt->rtp, 1);
- else
- fr = &ast_null_frame;
- break;
-@@ -842,7 +842,7 @@
- if (pvt) {
- ast_mutex_lock(&pvt->lock);
- if (pvt->rtp && !pvt->recvonly)
-- res = ast_rtp_write(pvt->rtp, frame);
-+ res = ast_rtp_instance_write(pvt->rtp, frame);
- __oh323_update_info(c, pvt);
- ast_mutex_unlock(&pvt->lock);
- }
-@@ -910,7 +910,7 @@
- res = 0;
- break;
- case AST_CONTROL_SRCUPDATE:
-- ast_rtp_new_source(pvt->rtp);
-+ ast_rtp_instance_new_source(pvt->rtp);
- res = 0;
- break;
- case AST_CONTROL_PROCEEDING:
-@@ -946,17 +946,17 @@
-
- static int __oh323_rtp_create(struct oh323_pvt *pvt)
- {
-- struct in_addr our_addr;
-+ struct sockaddr_in our_addr;
-
- if (pvt->rtp)
- return 0;
-
-- if (ast_find_ourip(&our_addr, bindaddr)) {
-+ if (ast_find_ourip(&our_addr.sin_addr, bindaddr)) {
- ast_mutex_unlock(&pvt->lock);
- ast_log(LOG_ERROR, "Unable to locate local IP address for RTP stream\n");
- return -1;
- }
-- pvt->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, our_addr);
-+ pvt->rtp = ast_rtp_instance_new(NULL, sched, &our_addr, NULL);
- if (!pvt->rtp) {
- ast_mutex_unlock(&pvt->lock);
- ast_log(LOG_WARNING, "Unable to create RTP session: %s\n", strerror(errno));
-@@ -965,24 +965,24 @@
- if (h323debug)
- ast_debug(1, "Created RTP channel\n");
-
-- ast_rtp_setqos(pvt->rtp, tos, cos, "H323 RTP");
-+ ast_rtp_instance_set_qos(pvt->rtp, tos, cos, "H323 RTP");
-
- if (h323debug)
- ast_debug(1, "Setting NAT on RTP to %d\n", pvt->options.nat);
-- ast_rtp_setnat(pvt->rtp, pvt->options.nat);
-+ ast_rtp_instance_set_prop(pvt->rtp, AST_RTP_PROPERTY_NAT, pvt->options.nat);
-
- if (pvt->dtmf_pt[0] > 0)
-- ast_rtp_set_rtpmap_type(pvt->rtp, pvt->dtmf_pt[0], "audio", "telephone-event", 0);
-+ ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, pvt->dtmf_pt[0], "audio", "telephone-event", 0);
- if (pvt->dtmf_pt[1] > 0)
-- ast_rtp_set_rtpmap_type(pvt->rtp, pvt->dtmf_pt[1], "audio", "cisco-telephone-event", 0);
-+ ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, pvt->dtmf_pt[1], "audio", "cisco-telephone-event", 0);
-
- if (pvt->peercapability)
-- ast_rtp_codec_setpref(pvt->rtp, &pvt->peer_prefs);
-+ ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, &pvt->peer_prefs);
-
- if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
- ast_jb_configure(pvt->owner, &global_jbconf);
-- ast_channel_set_fd(pvt->owner, 0, ast_rtp_fd(pvt->rtp));
-- ast_channel_set_fd(pvt->owner, 1, ast_rtcp_fd(pvt->rtp));
-+ ast_channel_set_fd(pvt->owner, 0, ast_rtp_instance_fd(pvt->rtp, 0));
-+ ast_channel_set_fd(pvt->owner, 1, ast_rtp_instance_fd(pvt->rtp, 1));
- ast_queue_frame(pvt->owner, &ast_null_frame); /* Tell Asterisk to apply changes */
- ast_channel_unlock(pvt->owner);
- } else
-@@ -1028,13 +1028,13 @@
- if (!pvt->rtp)
- __oh323_rtp_create(pvt);
- #if 0
-- ast_channel_set_fd(ch, 0, ast_rtp_fd(pvt->rtp));
-- ast_channel_set_fd(ch, 1, ast_rtcp_fd(pvt->rtp));
-+ ast_channel_set_fd(ch, 0, ast_rtp_instance_fd(pvt->rtp, 0));
-+ ast_channel_set_fd(ch, 1, ast_rtp_instance_fd(pvt->rtp, 1));
- #endif
- #ifdef VIDEO_SUPPORT
- if (pvt->vrtp) {
-- ast_channel_set_fd(ch, 2, ast_rtp_fd(pvt->vrtp));
-- ast_channel_set_fd(ch, 3, ast_rtcp_fd(pvt->vrtp));
-+ ast_channel_set_fd(ch, 2, ast_rtp_instance_fd(pvt->vrtp, 0));
-+ ast_channel_set_fd(ch, 3, ast_rtp_instance_fd(pvt->vrtp, 1));
- }
- #endif
- #ifdef T38_SUPPORT
-@@ -1112,7 +1112,7 @@
- }
- if (!pvt->cd.call_token) {
- ast_log(LOG_ERROR, "Not enough memory to alocate call token\n");
-- ast_rtp_destroy(pvt->rtp);
-+ ast_rtp_instance_destroy(pvt->rtp);
- ast_free(pvt);
- return NULL;
- }
-@@ -1912,7 +1912,7 @@
- return NULL;
- }
- /* figure out our local RTP port and tell the H.323 stack about it */
-- ast_rtp_get_us(pvt->rtp, &us);
-+ ast_rtp_instance_get_local_address(pvt->rtp, &us);
- ast_mutex_unlock(&pvt->lock);
-
- ast_copy_string(info->addr, ast_inet_ntoa(us.sin_addr), sizeof(info->addr));
-@@ -1931,7 +1931,6 @@
- {
- struct oh323_pvt *pvt;
- struct sockaddr_in them;
-- struct rtpPayloadType rtptype;
- int nativeformats_changed;
- enum { NEED_NONE, NEED_HOLD, NEED_UNHOLD } rtp_change = NEED_NONE;
-
-@@ -1953,7 +1952,7 @@
- __oh323_rtp_create(pvt);
-
- if ((pt == 2) && (pvt->jointcapability & AST_FORMAT_G726_AAL2)) {
-- ast_rtp_set_rtpmap_type(pvt->rtp, pt, "audio", "G726-32", AST_RTP_OPT_G726_NONSTANDARD);
-+ ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, pt, "audio", "G726-32", AST_RTP_OPT_G726_NONSTANDARD);
- }
-
- them.sin_family = AF_INET;
-@@ -1962,13 +1961,13 @@
- them.sin_port = htons(remotePort);
-
- if (them.sin_addr.s_addr) {
-- ast_rtp_set_peer(pvt->rtp, &them);
-+ ast_rtp_instance_set_remote_address(pvt->rtp, &them);
- if (pvt->recvonly) {
- pvt->recvonly = 0;
- rtp_change = NEED_UNHOLD;
- }
- } else {
-- ast_rtp_stop(pvt->rtp);
-+ ast_rtp_instance_stop(pvt->rtp);
- if (!pvt->recvonly) {
- pvt->recvonly = 1;
- rtp_change = NEED_HOLD;
-@@ -1978,7 +1977,7 @@
- /* Change native format to reflect information taken from OLC/OLCAck */
- nativeformats_changed = 0;
- if (pt != 128 && pvt->rtp) { /* Payload type is invalid, so try to use previously decided */
-- rtptype = ast_rtp_lookup_pt(pvt->rtp, pt);
-+ struct ast_rtp_payload_type rtptype = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(pvt->rtp), pt);
- if (h323debug)
- ast_debug(1, "Native format is set to %d from %d by RTP payload type %d\n", rtptype.code, pvt->nativeformats, pt);
- if (pvt->nativeformats != rtptype.code) {
-@@ -2359,7 +2358,7 @@
- }
- if (pvt->rtp) {
- /* Immediately stop RTP */
-- ast_rtp_destroy(pvt->rtp);
-+ ast_rtp_instance_destroy(pvt->rtp);
- pvt->rtp = NULL;
- }
- /* Free dsp used for in-band DTMF detection */
-@@ -2421,7 +2420,7 @@
- return;
- }
- if (pvt->rtp) {
-- ast_rtp_set_rtpmap_type(pvt->rtp, payload, "audio", (is_cisco ? "cisco-telephone-event" : "telephone-event"), 0);
-+ ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, payload, "audio", (is_cisco ? "cisco-telephone-event" : "telephone-event"), 0);
- }
- pvt->dtmf_pt[is_cisco ? 1 : 0] = payload;
- ast_mutex_unlock(&pvt->lock);
-@@ -2452,7 +2451,7 @@
- }
- }
- if (pvt->rtp)
-- ast_rtp_codec_setpref(pvt->rtp, &pvt->peer_prefs);
-+ ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, &pvt->peer_prefs);
- }
- ast_mutex_unlock(&pvt->lock);
- }
-@@ -3113,19 +3112,19 @@
- static struct ast_cli_entry cli_h323_reload =
- AST_CLI_DEFINE(handle_cli_h323_reload, "Reload H.323 configuration");
-
--static enum ast_rtp_get_result oh323_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
-+static enum ast_rtp_glue_result oh323_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
- {
- struct oh323_pvt *pvt;
-- enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL;
-+ enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_LOCAL;
-
- if (!(pvt = (struct oh323_pvt *)chan->tech_pvt))
-- return AST_RTP_GET_FAILED;
-+ return AST_RTP_GLUE_RESULT_FORBID;
-
- ast_mutex_lock(&pvt->lock);
-- *rtp = pvt->rtp;
-+ *instance = pvt->rtp ? ao2_ref(pvt->rtp, +1), pvt->rtp : NULL;
- #if 0
- if (pvt->options.bridge) {
-- res = AST_RTP_TRY_NATIVE;
-+ res = AST_RTP_GLUE_RESULT_REMOTE;
- }
- #endif
- ast_mutex_unlock(&pvt->lock);
-@@ -3133,11 +3132,6 @@
- return res;
- }
-
--static enum ast_rtp_get_result oh323_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
--{
-- return AST_RTP_GET_FAILED;
--}
--
- static char *convertcap(int cap)
- {
- switch (cap) {
-@@ -3165,7 +3159,7 @@
- }
- }
-
--static int oh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active)
-+static int oh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, int codecs, int nat_active)
- {
- /* XXX Deal with Video */
- struct oh323_pvt *pvt;
-@@ -3183,19 +3177,18 @@
- ast_log(LOG_ERROR, "No Private Structure, this is bad\n");
- return -1;
- }
-- ast_rtp_get_peer(rtp, &them);
-- ast_rtp_get_us(rtp, &us);
-+ ast_rtp_instance_get_remote_address(rtp, &them);
-+ ast_rtp_instance_get_local_address(rtp, &us);
- #if 0 /* Native bridge still isn't ready */
- h323_native_bridge(pvt->cd.call_token, ast_inet_ntoa(them.sin_addr), mode);
- #endif
- return 0;
- }
-
--static struct ast_rtp_protocol oh323_rtp = {
-+static struct ast_rtp_glue oh323_rtp_glue = {
- .type = "H323",
- .get_rtp_info = oh323_get_rtp_peer,
-- .get_vrtp_info = oh323_get_vrtp_peer,
-- .set_rtp_peer = oh323_set_rtp_peer,
-+ .update_peer = oh323_set_rtp_peer,
- };
-
- static enum ast_module_load_result load_module(void)
-@@ -3250,7 +3243,7 @@
- }
- ast_cli_register_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
-
-- ast_rtp_proto_register(&oh323_rtp);
-+ ast_rtp_glue_register(&oh323_rtp_glue);
-
- /* Register our callback functions */
- h323_callback_register(setup_incoming_call,
-@@ -3271,7 +3264,7 @@
- /* start the h.323 listener */
- if (h323_start_listener(h323_signalling_port, bindaddr)) {
- ast_log(LOG_ERROR, "Unable to create H323 listener.\n");
-- ast_rtp_proto_unregister(&oh323_rtp);
-+ ast_rtp_glue_unregister(&oh323_rtp_glue);
- ast_cli_unregister_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
- ast_cli_unregister(&cli_h323_reload);
- h323_end_process();
-@@ -3310,7 +3303,7 @@
- ast_cli_unregister(&cli_h323_reload);
-
- ast_channel_unregister(&oh323_tech);
-- ast_rtp_proto_unregister(&oh323_rtp);
-+ ast_rtp_glue_unregister(&oh323_rtp_glue);
-
- if (!ast_mutex_lock(&iflock)) {
- /* hangup all interfaces if they have an owner */
-Index: channels/chan_sip.c
-===================================================================
---- a/channels/chan_sip.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/channels/chan_sip.c (.../trunk) (revision 186562)
-@@ -229,7 +229,7 @@
- #include "asterisk/pbx.h"
- #include "asterisk/sched.h"
- #include "asterisk/io.h"
--#include "asterisk/rtp.h"
-+#include "asterisk/rtp_engine.h"
- #include "asterisk/udptl.h"
- #include "asterisk/acl.h"
- #include "asterisk/manager.h"
-@@ -271,6 +271,7 @@
- #include "asterisk/ast_version.h"
- #include "asterisk/event.h"
- #include "asterisk/tcptls.h"
-+#include "asterisk/stun.h"
-
- /*** DOCUMENTATION
- <application name="SIPDtmfMode" language="en_US">
-@@ -691,6 +692,7 @@
- AUTH_PEER_NOT_DYNAMIC = -6,
- AUTH_ACL_FAILED = -7,
- AUTH_BAD_TRANSPORT = -8,
-+ AUTH_RTP_FAILED = 9,
- };
-
- /*! \brief States for outbound registrations (with register= lines in sip.conf */
-@@ -940,7 +942,55 @@
- { SIP_OPT_TARGET_DIALOG,NOT_SUPPORTED, "tdialog" },
- };
-
-+/*! \brief Diversion header reasons
-+ *
-+ * The core defines a bunch of constants used to define
-+ * redirecting reasons. This provides a translation table
-+ * between those and the strings which may be present in
-+ * a SIP Diversion header
-+ */
-+static const struct sip_reasons {
-+ enum AST_REDIRECTING_REASON code;
-+ char * const text;
-+} sip_reason_table[] = {
-+ { AST_REDIRECTING_REASON_UNKNOWN, "unknown" },
-+ { AST_REDIRECTING_REASON_USER_BUSY, "user-busy" },
-+ { AST_REDIRECTING_REASON_NO_ANSWER, "no-answer" },
-+ { AST_REDIRECTING_REASON_UNAVAILABLE, "unavailable" },
-+ { AST_REDIRECTING_REASON_UNCONDITIONAL, "unconditional" },
-+ { AST_REDIRECTING_REASON_TIME_OF_DAY, "time-of-day" },
-+ { AST_REDIRECTING_REASON_DO_NOT_DISTURB, "do-not-disturb" },
-+ { AST_REDIRECTING_REASON_DEFLECTION, "deflection" },
-+ { AST_REDIRECTING_REASON_FOLLOW_ME, "follow-me" },
-+ { AST_REDIRECTING_REASON_OUT_OF_ORDER, "out-of-service" },
-+ { AST_REDIRECTING_REASON_AWAY, "away" },
-+ { AST_REDIRECTING_REASON_CALL_FWD_DTE, "unknown"}
-+};
-
-+static enum AST_REDIRECTING_REASON sip_reason_str_to_code(const char *text)
-+{
-+ enum AST_REDIRECTING_REASON ast = AST_REDIRECTING_REASON_UNKNOWN;
-+ int i;
-+
-+ for (i = 0; i < ARRAY_LEN(sip_reason_table); ++i) {
-+ if (!strcasecmp(text, sip_reason_table[i].text)) {
-+ ast = sip_reason_table[i].code;
-+ break;
-+ }
-+ }
-+
-+ return ast;
-+}
-+
-+static const char *sip_reason_code_to_str(enum AST_REDIRECTING_REASON code)
-+{
-+ if (code >= 0 && code < ARRAY_LEN(sip_reason_table)) {
-+ return sip_reason_table[code].text;
-+ }
-+
-+ return "unknown";
-+}
-+
- /*! \brief SIP Methods we support
- \todo This string should be set dynamically. We only support REFER and SUBSCRIBE if we have
- allowsubscribe and allowrefer on in sip.conf.
-@@ -1011,6 +1061,7 @@
- #define DEFAULT_USERAGENT "Asterisk PBX" /*!< Default Useragent: header unless re-defined in sip.conf */
- #define DEFAULT_SDPSESSION "Asterisk PBX" /*!< Default SDP session name, (s=) header unless re-defined in sip.conf */
- #define DEFAULT_SDPOWNER "root" /*!< Default SDP username field in (o=) header unless re-defined in sip.conf */
-+#define DEFAULT_ENGINE "asterisk" /*!< Default RTP engine to use for sessions */
- #endif
- /*@}*/
-
-@@ -1029,6 +1080,7 @@
- static char default_mohsuggest[MAX_MUSICCLASS]; /*!< Global setting for moh class to suggest when putting
- * a bridged channel on hold */
- static char default_parkinglot[AST_MAX_CONTEXT]; /*!< Parkinglot */
-+static char default_engine[256]; /*!< Default RTP engine */
- static int default_maxcallbitrate; /*!< Maximum bitrate for call */
- static struct ast_codec_pref default_prefs; /*!< Default codec prefs */
- static unsigned int default_transports; /*!< Default Transports (enum sip_transport) that are acceptable */
-@@ -1350,7 +1402,10 @@
- #define SIP_PROG_INBAND_NO (1 << 25)
- #define SIP_PROG_INBAND_YES (2 << 25)
-
--#define SIP_SENDRPID (1 << 29) /*!< DP: Remote Party-ID Support */
-+#define SIP_SENDRPID (3 << 29) /*!< DP: Remote Party-ID Support */
-+#define SIP_SENDRPID_NO (0 << 29)
-+#define SIP_SENDRPID_PAI (1 << 29) /*!< Use "P-Asserted-Identity" for rpid */
-+#define SIP_SENDRPID_RPID (2 << 29) /*!< Use "Remote-Party-ID" for rpid */
- #define SIP_G726_NONSTANDARD (1 << 31) /*!< DP: Use non-standard packing for G726-32 data */
-
- /*! \brief Flags to copy from peer/user to dialog */
-@@ -1369,6 +1424,10 @@
- /* Space for addition of other realtime flags in the future */
- #define SIP_PAGE2_STATECHANGEQUEUE (1 << 9) /*!< D: Unsent state pending change exists */
-
-+#define SIP_PAGE2_CONNECTLINEUPDATE_PEND (1 << 10)
-+#define SIP_PAGE2_RPID_IMMEDIATE (1 << 11)
-+
-+#define SIP_PAGE2_PREFERRED_CODEC (1 << 13) /*!< GDP: Only respond with single most preferred joint codec */
- #define SIP_PAGE2_VIDEOSUPPORT (1 << 14) /*!< DP: Video supported if offered? */
- #define SIP_PAGE2_TEXTSUPPORT (1 << 15) /*!< GDP: Global text enable */
- #define SIP_PAGE2_ALLOWSUBSCRIBE (1 << 16) /*!< GP: Allow subscriptions from this peer? */
-@@ -1398,7 +1457,8 @@
- (SIP_PAGE2_ALLOWSUBSCRIBE | SIP_PAGE2_ALLOWOVERLAP | SIP_PAGE2_IGNORESDPVERSION | \
- SIP_PAGE2_VIDEOSUPPORT | SIP_PAGE2_T38SUPPORT | SIP_PAGE2_RFC2833_COMPENSATE | \
- SIP_PAGE2_BUGGY_MWI | SIP_PAGE2_TEXTSUPPORT | SIP_PAGE2_FAX_DETECT | \
-- SIP_PAGE2_UDPTL_DESTINATION | SIP_PAGE2_VIDEOSUPPORT_ALWAYS)
-+ SIP_PAGE2_UDPTL_DESTINATION | SIP_PAGE2_VIDEOSUPPORT_ALWAYS | SIP_PAGE2_PREFERRED_CODEC | \
-+ SIP_PAGE2_RPID_IMMEDIATE)
-
- /*@}*/
-
-@@ -1455,7 +1515,6 @@
- /*! \brief T38 States for a call */
- enum t38state {
- T38_DISABLED = 0, /*!< Not enabled */
-- T38_LOCAL_DIRECT, /*!< Offered from local */
- T38_LOCAL_REINVITE, /*!< Offered from local - REINVITE */
- T38_PEER_DIRECT, /*!< Offered from peer */
- T38_PEER_REINVITE, /*!< Offered from peer - REINVITE */
-@@ -1469,6 +1528,7 @@
- int peercapability; /*!< Peers T38 capability */
- int jointcapability; /*!< Supported T38 capability at both ends */
- enum t38state state; /*!< T.38 state */
-+ unsigned int direct:1; /*!< Whether the T38 came from the initial invite or not */
- };
-
- /*! \brief Parameters to know status of transfer */
-@@ -1606,10 +1666,9 @@
- AST_STRING_FIELD(fullcontact); /*!< The Contact: that the UA registers with us */
- /* we only store the part in <brackets> in this field. */
- AST_STRING_FIELD(our_contact); /*!< Our contact header */
-- AST_STRING_FIELD(rpid); /*!< Our RPID header */
-- AST_STRING_FIELD(rpid_from); /*!< Our RPID From header */
- AST_STRING_FIELD(url); /*!< URL to be sent with next message to peer */
- AST_STRING_FIELD(parkinglot); /*!< Parkinglot */
-+ AST_STRING_FIELD(engine); /*!< RTP engine to use */
- );
- char via[128]; /*!< Via: header */
- struct sip_socket socket; /*!< The socket used for this dialog */
-@@ -1669,17 +1728,19 @@
- struct ast_channel *owner; /*!< Who owns us (if we have an owner) */
- struct sip_route *route; /*!< Head of linked list of routing steps (fm Record-Route) */
- int route_persistant; /*!< Is this the "real" route? */
-- struct ast_variable *notify_headers; /*!< Custom notify type */
-+ struct ast_variable *notify_headers; /*!< Custom notify type */
- struct sip_auth *peerauth; /*!< Realm authentication */
- int noncecount; /*!< Nonce-count */
- char lastmsg[256]; /*!< Last Message sent/received */
- int amaflags; /*!< AMA Flags */
- int pendinginvite; /*!< Any pending INVITE or state NOTIFY (in subscribe pvt's) ? (seqno of this) */
-+ int glareinvite; /*!< A invite received while a pending invite is already present is stored here. Its seqno is the
-+ value. Since this glare invite's seqno is not the same as the pending invite's, it must be
-+ held in order to properly process acknowledgements for our 491 response. */
- struct sip_request initreq; /*!< Latest request that opened a new transaction
- within this dialog.
-- NOT the request that opened the dialog
-- */
--
-+ NOT the request that opened the dialog */
-+
- int initid; /*!< Auto-congest ID if appropriate (scheduler) */
- int waitid; /*!< Wait ID for scheduler after 491 or other delays */
- int autokillid; /*!< Auto-kill ID (scheduler) */
-@@ -1690,15 +1751,15 @@
- int stateid; /*!< SUBSCRIBE: ID for devicestate subscriptions */
- int laststate; /*!< SUBSCRIBE: Last known extension state */
- int dialogver; /*!< SUBSCRIBE: Version for subscription dialog-info */
--
-+
- struct ast_dsp *vad; /*!< Inband DTMF Detection dsp */
--
-+
- struct sip_peer *relatedpeer; /*!< If this dialog is related to a peer, which one
- Used in peerpoke, mwi subscriptions */
- struct sip_registry *registry; /*!< If this is a REGISTER dialog, to which registry */
-- struct ast_rtp *rtp; /*!< RTP Session */
-- struct ast_rtp *vrtp; /*!< Video RTP session */
-- struct ast_rtp *trtp; /*!< Text RTP session */
-+ struct ast_rtp_instance *rtp; /*!< RTP Session */
-+ struct ast_rtp_instance *vrtp; /*!< Video RTP session */
-+ struct ast_rtp_instance *trtp; /*!< Text RTP session */
- struct sip_pkt *packets; /*!< Packets scheduled for re-transmission */
- struct sip_history_head *history; /*!< History of this SIP dialog */
- size_t history_entries; /*!< Number of entires in the history */
-@@ -1841,6 +1902,7 @@
- AST_STRING_FIELD(mohsuggest); /*!< Music on Hold class */
- AST_STRING_FIELD(parkinglot); /*!< Parkinglot */
- AST_STRING_FIELD(useragent); /*!< User agent in SIP request (saved from registration) */
-+ AST_STRING_FIELD(engine); /*!< RTP Engine to use */
- );
- struct sip_socket socket; /*!< Socket used for this peer */
- unsigned int transports:3; /*!< Transports (enum sip_transport) that are acceptable for this peer */
-@@ -2228,11 +2290,11 @@
- static int transmit_response(struct sip_pvt *p, const char *msg, const struct sip_request *req);
- static int transmit_response_reliable(struct sip_pvt *p, const char *msg, const struct sip_request *req);
- static int transmit_response_with_date(struct sip_pvt *p, const char *msg, const struct sip_request *req);
--static int transmit_response_with_sdp(struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable, int oldsdp);
-+static int transmit_response_with_sdp(struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable, int oldsdp, int rpid);
- static int transmit_response_with_unsupported(struct sip_pvt *p, const char *msg, const struct sip_request *req, const char *unsupported);
- static int transmit_response_with_auth(struct sip_pvt *p, const char *msg, const struct sip_request *req, const char *rand, enum xmittype reliable, const char *header, int stale);
- static int transmit_response_with_allow(struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable);
--static void transmit_fake_auth_response(struct sip_pvt *p, struct sip_request *req, enum xmittype reliable);
-+static void transmit_fake_auth_response(struct sip_pvt *p, int sipmethod, struct sip_request *req, enum xmittype reliable);
- static int transmit_request(struct sip_pvt *p, int sipmethod, int inc, enum xmittype reliable, int newbranch);
- static int transmit_request_with_auth(struct sip_pvt *p, int sipmethod, int seqno, enum xmittype reliable, int newbranch);
- static int transmit_invite(struct sip_pvt *p, int sipmethod, int sdp, int init);
-@@ -2249,7 +2311,7 @@
- static int send_request(struct sip_pvt *p, struct sip_request *req, enum xmittype reliable, int seqno);
- static void copy_request(struct sip_request *dst, const struct sip_request *src);
- static void receive_message(struct sip_pvt *p, struct sip_request *req);
--static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req);
-+static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req, char **name, char **number, int set_call_forward);
- static int sip_send_mwi_to_peer(struct sip_peer *peer, const struct ast_event *event, int cache_only);
-
- /*--- Dialog management */
-@@ -2293,7 +2355,7 @@
- static void add_noncodec_to_sdp(const struct sip_pvt *p, int format,
- struct ast_str **m_buf, struct ast_str **a_buf,
- int debug);
--static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int oldsdp);
-+static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int oldsdp, int add_audio, int add_t38);
- static void do_setnat(struct sip_pvt *p, int natflags);
- static void stop_media_flows(struct sip_pvt *p);
-
-@@ -2497,11 +2559,14 @@
- static int set_address_from_contact(struct sip_pvt *pvt);
- static void check_via(struct sip_pvt *p, struct sip_request *req);
- static char *get_calleridname(const char *input, char *output, size_t outputsize);
--static int get_rpid_num(const char *input, char *output, int maxlen);
--static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq);
-+static int get_rpid(struct sip_pvt *p, struct sip_request *oreq);
-+static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq, char **name, char **number, int *reason);
- static int get_destination(struct sip_pvt *p, struct sip_request *oreq);
- static int get_msg_text(char *buf, int len, struct sip_request *req, int addnewline);
- static int transmit_state_notify(struct sip_pvt *p, int state, int full, int timeout);
-+static void update_connectedline(struct sip_pvt *p, const void *data, size_t datalen);
-+static void update_redirecting(struct sip_pvt *p, const void *data, size_t datalen);
-+static void change_redirecting_information(struct sip_pvt *p, struct sip_request *req, struct ast_party_redirecting *redirecting, int set_call_forward);
-
- /*-- TCP connection handling ---*/
- static void *_sip_tcp_helper_thread(struct sip_pvt *pvt, struct ast_tcptls_session_instance *tcptls_session);
-@@ -2528,6 +2593,7 @@
- static int add_line(struct sip_request *req, const char *line);
- static int add_text(struct sip_request *req, const char *text);
- static int add_digit(struct sip_request *req, char digit, unsigned int duration, int mode);
-+static int add_rpid(struct sip_request *req, struct sip_pvt *p);
- static int add_vidupdate(struct sip_request *req);
- static void add_route(struct sip_request *req, struct sip_route *route);
- static int copy_header(struct sip_request *req, const struct sip_request *orig, const char *field);
-@@ -2536,7 +2602,6 @@
- static void set_destination(struct sip_pvt *p, char *uri);
- static void append_date(struct sip_request *req);
- static void build_contact(struct sip_pvt *p);
--static void build_rpid(struct sip_pvt *p);
-
- /*------Request handling functions */
- static int handle_incoming(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, int *recount, int *nounlock);
-@@ -2561,14 +2626,6 @@
- static int handle_response_register(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno);
- static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno);
-
--/*----- RTP interface functions */
--static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active);
--static enum ast_rtp_get_result sip_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp);
--static enum ast_rtp_get_result sip_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp **rtp);
--static enum ast_rtp_get_result sip_get_trtp_peer(struct ast_channel *chan, struct ast_rtp **rtp);
--static int sip_get_codec(struct ast_channel *chan);
--static struct ast_frame *sip_rtp_read(struct ast_channel *ast, struct sip_pvt *p, int *faxdetect);
--
- /*------ T38 Support --------- */
- static int transmit_response_with_t38_sdp(struct sip_pvt *p, char *msg, struct sip_request *req, int retrans);
- static struct ast_udptl *sip_get_udptl_peer(struct ast_channel *chan);
-@@ -2589,6 +2646,9 @@
- static enum st_mode st_get_mode(struct sip_pvt *);
- static struct sip_st_dlg* sip_st_alloc(struct sip_pvt *const p);
-
-+/*------- RTP Glue functions -------- */
-+static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *instance, struct ast_rtp_instance *vinstance, struct ast_rtp_instance *tinstance, int codecs, int nat_active);
-+
- /*!--- SIP MWI Subscription support */
- static int sip_subscribe_mwi(const char *value, int lineno);
- static void sip_subscribe_mwi_destroy(struct sip_subscription_mwi *mwi);
-@@ -2617,8 +2677,8 @@
- .fixup = sip_fixup, /* called with chan locked */
- .send_digit_begin = sip_senddigit_begin, /* called with chan unlocked */
- .send_digit_end = sip_senddigit_end,
-- .bridge = ast_rtp_bridge, /* XXX chan unlocked ? */
-- .early_bridge = ast_rtp_early_bridge,
-+ .bridge = ast_rtp_instance_bridge, /* XXX chan unlocked ? */
-+ .early_bridge = ast_rtp_instance_early_bridge,
- .send_text = sip_sendtext, /* called with chan locked */
- .func_channel_read = acf_channel_read,
- .queryoption = sip_queryoption,
-@@ -2691,17 +2751,6 @@
- return errorvalue;
- }
-
--
--/*! \brief Interface structure with callbacks used to connect to RTP module */
--static struct ast_rtp_protocol sip_rtp = {
-- .type = "SIP",
-- .get_rtp_info = sip_get_rtp_peer,
-- .get_vrtp_info = sip_get_vrtp_peer,
-- .get_trtp_info = sip_get_trtp_peer,
-- .set_rtp_peer = sip_set_rtp_peer,
-- .get_codec = sip_get_codec,
--};
--
- /*!
- * duplicate a list of channel variables, \return the copy.
- */
-@@ -3896,7 +3945,6 @@
- /* Now if T38 support is enabled we need to look and see what the current state is to get what we want to report back */
- if (ast_test_flag(&p->t38.t38support, SIP_PAGE2_T38SUPPORT)) {
- switch (p->t38.state) {
-- case T38_LOCAL_DIRECT:
- case T38_LOCAL_REINVITE:
- case T38_PEER_DIRECT:
- case T38_PEER_REINVITE:
-@@ -4591,11 +4639,11 @@
-
- if (p->rtp) {
- ast_debug(1, "Setting NAT on RTP to %s\n", mode);
-- ast_rtp_setnat(p->rtp, natflags);
-+ ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_NAT, natflags);
- }
- if (p->vrtp) {
- ast_debug(1, "Setting NAT on VRTP to %s\n", mode);
-- ast_rtp_setnat(p->vrtp, natflags);
-+ ast_rtp_instance_set_prop(p->vrtp, AST_RTP_PROPERTY_NAT, natflags);
- }
- if (p->udptl) {
- ast_debug(1, "Setting NAT on UDPTL to %s\n", mode);
-@@ -4603,7 +4651,7 @@
- }
- if (p->trtp) {
- ast_debug(1, "Setting NAT on TRTP to %s\n", mode);
-- ast_rtp_setnat(p->trtp, natflags);
-+ ast_rtp_instance_set_prop(p->trtp, AST_RTP_PROPERTY_NAT, natflags);
- }
- }
-
-@@ -4618,6 +4666,10 @@
- if (old == state)
- return;
-
-+ if (state == T38_PEER_DIRECT) {
-+ p->t38.direct = 1;
-+ }
-+
- p->t38.state = state;
- ast_debug(2, "T38 state changed to %d on channel %s\n", p->t38.state, chan ? chan->name : "<none>");
-
-@@ -4691,6 +4743,51 @@
- *to_sock = *from_sock;
- }
-
-+/*! \brief Initialize RTP portion of a dialog
-+ * \returns -1 on failure, 0 on success
-+ */
-+static int dialog_initialize_rtp(struct sip_pvt *dialog)
-+{
-+ if (!sip_methods[dialog->method].need_rtp) {
-+ return 0;
-+ }
-+
-+ if (!(dialog->rtp = ast_rtp_instance_new(dialog->engine, sched, &bindaddr, NULL))) {
-+ return -1;
-+ }
-+
-+ if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT) && (dialog->capability & AST_FORMAT_VIDEO_MASK)) {
-+ if (!(dialog->vrtp = ast_rtp_instance_new(dialog->engine, sched, &bindaddr, NULL))) {
-+ return -1;
-+ }
-+ ast_rtp_instance_set_timeout(dialog->vrtp, global_rtptimeout);
-+ ast_rtp_instance_set_hold_timeout(dialog->vrtp, global_rtpholdtimeout);
-+
-+ ast_rtp_instance_set_prop(dialog->vrtp, AST_RTP_PROPERTY_RTCP, 1);
-+ }
-+
-+ if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_TEXTSUPPORT)) {
-+ if (!(dialog->trtp = ast_rtp_instance_new(dialog->engine, sched, &bindaddr, NULL))) {
-+ return -1;
-+ }
-+ ast_rtp_instance_set_timeout(dialog->trtp, global_rtptimeout);
-+ ast_rtp_instance_set_hold_timeout(dialog->trtp, global_rtpholdtimeout);
-+
-+ ast_rtp_instance_set_prop(dialog->trtp, AST_RTP_PROPERTY_RTCP, 1);
-+ }
-+
-+ ast_rtp_instance_set_timeout(dialog->rtp, global_rtptimeout);
-+ ast_rtp_instance_set_hold_timeout(dialog->rtp, global_rtpholdtimeout);
-+
-+ ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_RTCP, 1);
-+ ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF, ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
-+ ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_test_flag(&dialog->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
-+
-+ ast_rtp_instance_set_qos(dialog->rtp, global_tos_audio, 0, "SIP RTP");
-+
-+ return 0;
-+}
-+
- /*! \brief Create address structure from peer reference.
- * This function copies data from peer to the dialog, so we don't have to look up the peer
- * again from memory or database during the life time of the dialog.
-@@ -4718,17 +4815,6 @@
- ast_copy_flags(&dialog->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY);
- ast_copy_flags(&dialog->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY);
- dialog->capability = peer->capability;
-- if (!ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT_ALWAYS) &&
-- (!ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT) ||
-- !(dialog->capability & AST_FORMAT_VIDEO_MASK)) &&
-- dialog->vrtp) {
-- ast_rtp_destroy(dialog->vrtp);
-- dialog->vrtp = NULL;
-- }
-- if (!ast_test_flag(&dialog->flags[1], SIP_PAGE2_TEXTSUPPORT) && dialog->trtp) {
-- ast_rtp_destroy(dialog->trtp);
-- dialog->trtp = NULL;
-- }
- dialog->prefs = peer->prefs;
- if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_T38SUPPORT)) {
- if (!dialog->udptl) {
-@@ -4744,29 +4830,28 @@
- }
- do_setnat(dialog, ast_test_flag(&dialog->flags[0], SIP_NAT) & SIP_NAT_ROUTE);
-
-+ ast_string_field_set(dialog, engine, peer->engine);
-+
-+ if (dialog_initialize_rtp(dialog)) {
-+ return -1;
-+ }
-+
- if (dialog->rtp) { /* Audio */
-- ast_rtp_setdtmf(dialog->rtp, ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
-- ast_rtp_setdtmfcompensate(dialog->rtp, ast_test_flag(&dialog->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
-- ast_rtp_set_rtptimeout(dialog->rtp, peer->rtptimeout);
-- ast_rtp_set_rtpholdtimeout(dialog->rtp, peer->rtpholdtimeout);
-- ast_rtp_set_rtpkeepalive(dialog->rtp, peer->rtpkeepalive);
-+ ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF, ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
-+ ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_test_flag(&dialog->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
-+ ast_rtp_instance_set_timeout(dialog->rtp, peer->rtptimeout);
-+ ast_rtp_instance_set_hold_timeout(dialog->rtp, peer->rtpholdtimeout);
- /* Set Frame packetization */
-- ast_rtp_codec_setpref(dialog->rtp, &dialog->prefs);
-+ ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(dialog->rtp), dialog->rtp, &dialog->prefs);
- dialog->autoframing = peer->autoframing;
- }
- if (dialog->vrtp) { /* Video */
-- ast_rtp_setdtmf(dialog->vrtp, 0);
-- ast_rtp_setdtmfcompensate(dialog->vrtp, 0);
-- ast_rtp_set_rtptimeout(dialog->vrtp, peer->rtptimeout);
-- ast_rtp_set_rtpholdtimeout(dialog->vrtp, peer->rtpholdtimeout);
-- ast_rtp_set_rtpkeepalive(dialog->vrtp, peer->rtpkeepalive);
-+ ast_rtp_instance_set_timeout(dialog->vrtp, peer->rtptimeout);
-+ ast_rtp_instance_set_hold_timeout(dialog->vrtp, peer->rtpholdtimeout);
- }
- if (dialog->trtp) { /* Realtime text */
-- ast_rtp_setdtmf(dialog->trtp, 0);
-- ast_rtp_setdtmfcompensate(dialog->trtp, 0);
-- ast_rtp_set_rtptimeout(dialog->trtp, peer->rtptimeout);
-- ast_rtp_set_rtpholdtimeout(dialog->trtp, peer->rtpholdtimeout);
-- ast_rtp_set_rtpkeepalive(dialog->trtp, peer->rtpkeepalive);
-+ ast_rtp_instance_set_timeout(dialog->trtp, peer->rtptimeout);
-+ ast_rtp_instance_set_hold_timeout(dialog->trtp, peer->rtpholdtimeout);
- }
-
- ast_string_field_set(dialog, peername, peer->name);
-@@ -4779,7 +4864,10 @@
- ast_string_field_set(dialog, tohost, peer->tohost);
- ast_string_field_set(dialog, fullcontact, peer->fullcontact);
- ast_string_field_set(dialog, context, peer->context);
-+ ast_string_field_set(dialog, cid_num, peer->cid_num);
-+ ast_string_field_set(dialog, cid_name, peer->cid_name);
- ast_string_field_set(dialog, parkinglot, peer->parkinglot);
-+ ast_string_field_set(dialog, engine, peer->engine);
- ref_proxy(dialog, obproxy_get(dialog, peer));
- dialog->callgroup = peer->callgroup;
- dialog->pickupgroup = peer->pickupgroup;
-@@ -4875,6 +4963,12 @@
- return res;
- }
-
-+ if (dialog_initialize_rtp(dialog)) {
-+ return -1;
-+ }
-+
-+ do_setnat(dialog, ast_test_flag(&dialog->flags[0], SIP_NAT) & SIP_NAT_ROUTE);
-+
- ast_string_field_set(dialog, tohost, peername);
-
- /* Get the outbound proxy information */
-@@ -4995,9 +5089,6 @@
- } else if (!strcasecmp(ast_var_name(current), "SIPTRANSFER_REPLACES")) {
- /* We're replacing a call. */
- p->options->replaces = ast_var_value(current);
-- } else if (!strcasecmp(ast_var_name(current), "T38CALL")) {
-- p->t38.state = T38_LOCAL_DIRECT;
-- ast_debug(1, "T38State change to %d on channel %s\n", p->t38.state, ast->name);
- }
- }
-
-@@ -5039,11 +5130,13 @@
- p->t38.jointcapability = p->t38.capability;
- ast_debug(2, "Our T38 capability (%d), joint T38 capability (%d)\n", p->t38.capability, p->t38.jointcapability);
-
-+ sip_pvt_lock(p);
- xmitres = transmit_invite(p, SIP_INVITE, 1, 2);
-+ sip_pvt_unlock(p);
- if (xmitres == XMIT_ERROR)
- return -1;
- p->invitestate = INV_CALLING;
--
-+
- /* Initialize auto-congest time */
- AST_SCHED_REPLACE_UNREF(p->initid, sched, p->timer_b, auto_congest, p,
- dialog_unref(_data, "dialog ptr dec when SCHED_REPLACE del op succeeded"),
-@@ -5150,15 +5243,13 @@
- p->notify_headers = NULL;
- }
- if (p->rtp) {
-- ast_rtp_destroy(p->rtp);
-+ ast_rtp_instance_destroy(p->rtp);
- }
- if (p->vrtp) {
-- ast_rtp_destroy(p->vrtp);
-+ ast_rtp_instance_destroy(p->vrtp);
- }
- if (p->trtp) {
-- while (ast_rtp_get_bridged(p->trtp))
-- usleep(1);
-- ast_rtp_destroy(p->trtp);
-+ ast_rtp_instance_destroy(p->trtp);
- }
- if (p->udptl)
- ast_udptl_destroy(p->udptl);
-@@ -5677,42 +5768,50 @@
-
- if (!p->pendinginvite) {
- struct ast_channel *bridge = ast_bridged_channel(oldowner);
-- char *audioqos = "";
-- char *videoqos = "";
-- char *textqos = "";
-+ char quality_buf[AST_MAX_USER_FIELD], *quality;
-
-- if (p->rtp)
-- ast_rtp_set_vars(oldowner, p->rtp);
-+ if (p->rtp) {
-+ ast_rtp_instance_set_stats_vars(oldowner, p->rtp);
-+ }
-
- if (bridge) {
- struct sip_pvt *q = bridge->tech_pvt;
-
-- if (IS_SIP_TECH(bridge->tech) && q)
-- ast_rtp_set_vars(bridge, q->rtp);
-+ if (IS_SIP_TECH(bridge->tech) && q) {
-+ ast_rtp_instance_set_stats_vars(bridge, q->rtp);
-+ }
- }
-
-- if (p->vrtp)
-- videoqos = ast_rtp_get_quality(p->vrtp, NULL, RTPQOS_SUMMARY);
-- if (p->trtp)
-- textqos = ast_rtp_get_quality(p->trtp, NULL, RTPQOS_SUMMARY);
-+ if (p->do_history || oldowner) {
-+ if (p->rtp && (quality = ast_rtp_instance_get_quality(p->rtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, quality_buf, sizeof(quality_buf)))) {
-+ if (p->do_history) {
-+ append_history(p, "RTCPaudio", "Quality:%s", quality);
-+ }
-+ if (oldowner) {
-+ pbx_builtin_setvar_helper(oldowner, "RTPAUDIOQOS", quality);
-+ }
-+ }
-+ if (p->vrtp && (quality = ast_rtp_instance_get_quality(p->vrtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, quality_buf, sizeof(quality_buf)))) {
-+ if (p->do_history) {
-+ append_history(p, "RTCPvideo", "Quality:%s", quality);
-+ }
-+ if (oldowner) {
-+ pbx_builtin_setvar_helper(oldowner, "RTPVIDEOQOS", quality);
-+ }
-+ }
-+ if (p->trtp && (quality = ast_rtp_instance_get_quality(p->trtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, quality_buf, sizeof(quality_buf)))) {
-+ if (p->do_history) {
-+ append_history(p, "RTCPtext", "Quality:%s", quality);
-+ }
-+ if (oldowner) {
-+ pbx_builtin_setvar_helper(oldowner, "RTPTEXTQOS", quality);
-+ }
-+ }
-+ }
-+
- /* Send a hangup */
- transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, 1);
-
-- /* Get RTCP quality before end of call */
-- if (p->do_history) {
-- if (p->rtp)
-- append_history(p, "RTCPaudio", "Quality:%s", audioqos);
-- if (p->vrtp)
-- append_history(p, "RTCPvideo", "Quality:%s", videoqos);
-- if (p->trtp)
-- append_history(p, "RTCPtext", "Quality:%s", textqos);
-- }
-- if (p->rtp && oldowner)
-- pbx_builtin_setvar_helper(oldowner, "RTPAUDIOQOS", audioqos);
-- if (p->vrtp && oldowner)
-- pbx_builtin_setvar_helper(oldowner, "RTPVIDEOQOS", videoqos);
-- if (p->trtp && oldowner)
-- pbx_builtin_setvar_helper(oldowner, "RTPTEXTQOS", textqos);
- } else {
- /* Note we will need a BYE when this all settles out
- but we can't send one while we have "INVITE" outstanding. */
-@@ -5769,13 +5868,10 @@
- ast_debug(1, "SIP answering channel: %s\n", ast->name);
- if (p->t38.state == T38_PEER_DIRECT) {
- change_t38_state(p, T38_ENABLED);
-- res = transmit_response_with_t38_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL);
-- ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
-- } else {
-- ast_rtp_new_source(p->rtp);
-- res = transmit_response_with_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL, FALSE);
-- ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
- }
-+ ast_rtp_instance_new_source(p->rtp);
-+ res = transmit_response_with_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL, FALSE, TRUE);
-+ ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
- }
- sip_pvt_unlock(p);
- return res;
-@@ -5808,13 +5904,17 @@
- if ((ast->_state != AST_STATE_UP) &&
- !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) &&
- !ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
-- ast_rtp_new_source(p->rtp);
-+ ast_rtp_instance_new_source(p->rtp);
- p->invitestate = INV_EARLY_MEDIA;
-- transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE, FALSE);
-- ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
-+ transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE, FALSE, FALSE);
-+ ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
-+ } else if (p->t38.state == T38_ENABLED && !p->t38.direct) {
-+ change_t38_state(p, T38_DISABLED);
-+ transmit_reinvite_with_sdp(p, FALSE, FALSE);
-+ } else {
-+ p->lastrtptx = time(NULL);
-+ res = ast_rtp_instance_write(p->rtp, frame);
- }
-- p->lastrtptx = time(NULL);
-- res = ast_rtp_write(p->rtp, frame);
- }
- sip_pvt_unlock(p);
- }
-@@ -5828,11 +5928,11 @@
- !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) &&
- !ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
- p->invitestate = INV_EARLY_MEDIA;
-- transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE, FALSE);
-- ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
-+ transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE, FALSE, FALSE);
-+ ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
- }
- p->lastrtptx = time(NULL);
-- res = ast_rtp_write(p->vrtp, frame);
-+ res = ast_rtp_instance_write(p->vrtp, frame);
- }
- sip_pvt_unlock(p);
- }
-@@ -5841,7 +5941,7 @@
- if (p) {
- sip_pvt_lock(p);
- if (p->red) {
-- red_buffer_t140(p->trtp, frame);
-+ ast_rtp_red_buffer(p->trtp, frame);
- } else {
- if (p->trtp) {
- /* Activate text early media */
-@@ -5849,11 +5949,11 @@
- !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) &&
- !ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
- p->invitestate = INV_EARLY_MEDIA;
-- transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE, FALSE);
-- ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
-+ transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE, FALSE, FALSE);
-+ ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
- }
- p->lastrtptx = time(NULL);
-- res = ast_rtp_write(p->trtp, frame);
-+ res = ast_rtp_instance_write(p->trtp, frame);
- }
- }
- sip_pvt_unlock(p);
-@@ -5869,8 +5969,16 @@
- we simply forget the frames if we get modem frames before the bridge is up.
- Fax will re-transmit.
- */
-- if (p->udptl && ast->_state == AST_STATE_UP)
-- res = ast_udptl_write(p->udptl, frame);
-+ if (ast->_state == AST_STATE_UP) {
-+ if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) && p->t38.state == T38_DISABLED) {
-+ if (!p->pendinginvite) {
-+ change_t38_state(p, T38_LOCAL_REINVITE);
-+ transmit_reinvite_with_sdp(p, TRUE, FALSE);
-+ }
-+ } else if (p->udptl && p->t38.state == T38_ENABLED) {
-+ res = ast_udptl_write(p->udptl, frame);
-+ }
-+ }
- sip_pvt_unlock(p);
- }
- break;
-@@ -5933,11 +6041,15 @@
- sip_pvt_lock(p);
- switch (ast_test_flag(&p->flags[0], SIP_DTMF)) {
- case SIP_DTMF_INBAND:
-- res = -1; /* Tell Asterisk to generate inband indications */
-+ if (p->rtp && ast_rtp_instance_dtmf_mode_get(p->rtp) == AST_RTP_DTMF_MODE_INBAND) {
-+ ast_rtp_instance_dtmf_begin(p->rtp, digit);
-+ } else {
-+ res = -1; /* Tell Asterisk to generate inband indications */
-+ }
- break;
- case SIP_DTMF_RFC2833:
- if (p->rtp)
-- ast_rtp_senddigit_begin(p->rtp, digit);
-+ ast_rtp_instance_dtmf_begin(p->rtp, digit);
- break;
- default:
- break;
-@@ -5962,10 +6074,14 @@
- break;
- case SIP_DTMF_RFC2833:
- if (p->rtp)
-- ast_rtp_senddigit_end(p->rtp, digit);
-+ ast_rtp_instance_dtmf_end(p->rtp, digit);
- break;
- case SIP_DTMF_INBAND:
-- res = -1; /* Tell Asterisk to stop inband indications */
-+ if (p->rtp && ast_rtp_instance_dtmf_mode_get(p->rtp) == AST_RTP_DTMF_MODE_INBAND) {
-+ ast_rtp_instance_dtmf_end(p->rtp, digit);
-+ } else {
-+ res = -1; /* Tell Asterisk to stop inband indications */
-+ }
- break;
- }
- sip_pvt_unlock(p);
-@@ -6053,18 +6169,18 @@
- !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) &&
- !ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
- p->invitestate = INV_EARLY_MEDIA;
-- transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE, FALSE);
-- ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
-+ transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE, FALSE, FALSE);
-+ ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
- break;
- }
- res = -1;
- break;
- case AST_CONTROL_HOLD:
-- ast_rtp_new_source(p->rtp);
-+ ast_rtp_instance_new_source(p->rtp);
- ast_moh_start(ast, data, p->mohinterpret);
- break;
- case AST_CONTROL_UNHOLD:
-- ast_rtp_new_source(p->rtp);
-+ ast_rtp_instance_new_source(p->rtp);
- ast_moh_stop(ast);
- break;
- case AST_CONTROL_VIDUPDATE: /* Request a video frame update */
-@@ -6085,7 +6201,7 @@
- AST_SCHED_DEL_UNREF(sched, p->t38id, dialog_unref(p, "when you delete the t38id sched, you should dec the refcount for the stored dialog ptr"));
- change_t38_state(p, T38_ENABLED);
- transmit_response_with_t38_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL);
-- } else if (p->t38.state != T38_ENABLED) {
-+ } else if (ast_test_flag(&p->t38.t38support, SIP_PAGE2_T38SUPPORT) && p->t38.state != T38_ENABLED) {
- change_t38_state(p, T38_LOCAL_REINVITE);
- if (!p->pendinginvite) {
- transmit_reinvite_with_sdp(p, TRUE, FALSE);
-@@ -6110,8 +6226,14 @@
- }
- break;
- case AST_CONTROL_SRCUPDATE:
-- ast_rtp_new_source(p->rtp);
-+ ast_rtp_instance_new_source(p->rtp);
- break;
-+ case AST_CONTROL_CONNECTED_LINE:
-+ update_connectedline(p, data, datalen);
-+ break;
-+ case AST_CONTROL_REDIRECTING:
-+ update_redirecting(p, data, datalen);
-+ break;
- case -1:
- res = -1;
- break;
-@@ -6224,23 +6346,29 @@
- ast_debug(3, "This channel will not be able to handle video.\n");
-
- if ((ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) || (ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) {
-- i->vad = ast_dsp_new();
-- ast_dsp_set_features(i->vad, DSP_FEATURE_DIGIT_DETECT);
-- if (global_relaxdtmf)
-- ast_dsp_set_digitmode(i->vad, DSP_DIGITMODE_DTMF | DSP_DIGITMODE_RELAXDTMF);
-+ if (!i->rtp || ast_rtp_instance_dtmf_mode_set(i->rtp, AST_RTP_DTMF_MODE_INBAND)) {
-+ i->vad = ast_dsp_new();
-+ ast_dsp_set_features(i->vad, DSP_FEATURE_DIGIT_DETECT);
-+ if (global_relaxdtmf)
-+ ast_dsp_set_digitmode(i->vad, DSP_DIGITMODE_DTMF | DSP_DIGITMODE_RELAXDTMF);
-+ }
-+ } else if (ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) {
-+ if (i->rtp) {
-+ ast_rtp_instance_dtmf_mode_set(i->rtp, AST_RTP_DTMF_MODE_RFC2833);
-+ }
- }
-
- /* Set file descriptors for audio, video, realtime text and UDPTL as needed */
- if (i->rtp) {
-- ast_channel_set_fd(tmp, 0, ast_rtp_fd(i->rtp));
-- ast_channel_set_fd(tmp, 1, ast_rtcp_fd(i->rtp));
-+ ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(i->rtp, 0));
-+ ast_channel_set_fd(tmp, 1, ast_rtp_instance_fd(i->rtp, 1));
- }
- if (needvideo && i->vrtp) {
-- ast_channel_set_fd(tmp, 2, ast_rtp_fd(i->vrtp));
-- ast_channel_set_fd(tmp, 3, ast_rtcp_fd(i->vrtp));
-+ ast_channel_set_fd(tmp, 2, ast_rtp_instance_fd(i->vrtp, 0));
-+ ast_channel_set_fd(tmp, 3, ast_rtp_instance_fd(i->vrtp, 1));
- }
- if (needtext && i->trtp)
-- ast_channel_set_fd(tmp, 4, ast_rtp_fd(i->trtp));
-+ ast_channel_set_fd(tmp, 4, ast_rtp_instance_fd(i->trtp, 0));
- if (i->udptl)
- ast_channel_set_fd(tmp, 5, ast_udptl_fd(i->udptl));
-
-@@ -6292,10 +6420,6 @@
- if (i->rtp)
- ast_jb_configure(tmp, &global_jbconf);
-
-- /* If the INVITE contains T.38 SDP information set the proper channel variable so a created outgoing call will also have T.38 */
-- if (i->udptl && i->t38.state == T38_PEER_DIRECT)
-- pbx_builtin_setvar_helper(tmp, "_T38CALL", "1");
--
- /* Set channel variables for this call from configuration */
- for (v = i->chanvars ; v ; v = v->next) {
- char valuebuf[1024];
-@@ -6468,19 +6592,19 @@
-
- switch(ast->fdno) {
- case 0:
-- f = ast_rtp_read(p->rtp); /* RTP Audio */
-+ f = ast_rtp_instance_read(p->rtp, 0); /* RTP Audio */
- break;
- case 1:
-- f = ast_rtcp_read(p->rtp); /* RTCP Control Channel */
-+ f = ast_rtp_instance_read(p->rtp, 1); /* RTCP Control Channel */
- break;
- case 2:
-- f = ast_rtp_read(p->vrtp); /* RTP Video */
-+ f = ast_rtp_instance_read(p->vrtp, 0); /* RTP Video */
- break;
- case 3:
-- f = ast_rtcp_read(p->vrtp); /* RTCP Control Channel for video */
-+ f = ast_rtp_instance_read(p->vrtp, 1); /* RTCP Control Channel for video */
- break;
- case 4:
-- f = ast_rtp_read(p->trtp); /* RTP Text */
-+ f = ast_rtp_instance_read(p->trtp, 0); /* RTP Text */
- if (sipdebug_text) {
- int i;
- unsigned char* arr = f->data.ptr;
-@@ -6687,50 +6811,11 @@
- p->ocseq = INITIAL_CSEQ;
-
- if (sip_methods[intended_method].need_rtp) {
-- p->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
-- /* If the global videosupport flag is on, we always create a RTP interface for video */
-- if (ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT))
-- p->vrtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
-- if (ast_test_flag(&p->flags[1], SIP_PAGE2_TEXTSUPPORT))
-- p->trtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
-- if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT))
-- p->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, bindaddr.sin_addr);
-- if (!p->rtp|| (ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT) && !p->vrtp)
-- || (ast_test_flag(&p->flags[1], SIP_PAGE2_TEXTSUPPORT) && !p->trtp)) {
-- ast_log(LOG_WARNING, "Unable to create RTP audio %s%ssession: %s\n",
-- ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT) ? "and video " : "",
-- ast_test_flag(&p->flags[1], SIP_PAGE2_TEXTSUPPORT) ? "and text " : "", strerror(errno));
-- if (p->chanvars) {
-- ast_variables_destroy(p->chanvars);
-- p->chanvars = NULL;
-- }
-- ao2_t_ref(p, -1, "failed to create RTP audio session, drop p");
-- return NULL;
-+ if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) && (p->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, bindaddr.sin_addr))) {
-+ ast_udptl_setqos(p->udptl, global_tos_audio, global_cos_audio);
- }
-- ast_rtp_setqos(p->rtp, global_tos_audio, global_cos_audio, "SIP RTP");
-- ast_rtp_setdtmf(p->rtp, ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
-- ast_rtp_setdtmfcompensate(p->rtp, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
-- ast_rtp_set_rtptimeout(p->rtp, global_rtptimeout);
-- ast_rtp_set_rtpholdtimeout(p->rtp, global_rtpholdtimeout);
-- ast_rtp_set_rtpkeepalive(p->rtp, global_rtpkeepalive);
-- if (p->vrtp) {
-- ast_rtp_setqos(p->vrtp, global_tos_video, global_cos_video, "SIP VRTP");
-- ast_rtp_setdtmf(p->vrtp, 0);
-- ast_rtp_setdtmfcompensate(p->vrtp, 0);
-- ast_rtp_set_rtptimeout(p->vrtp, global_rtptimeout);
-- ast_rtp_set_rtpholdtimeout(p->vrtp, global_rtpholdtimeout);
-- ast_rtp_set_rtpkeepalive(p->vrtp, global_rtpkeepalive);
-- }
-- if (p->trtp) {
-- ast_rtp_setqos(p->trtp, global_tos_text, global_cos_text, "SIP TRTP");
-- ast_rtp_setdtmf(p->trtp, 0);
-- ast_rtp_setdtmfcompensate(p->trtp, 0);
-- }
-- if (p->udptl)
-- ast_udptl_setqos(p->udptl, global_tos_audio, global_cos_audio);
- p->maxcallbitrate = default_maxcallbitrate;
- p->autoframing = global_autoframing;
-- ast_rtp_codec_setpref(p->rtp, &p->prefs);
- }
-
- if (useglobal_nat && sin) {
-@@ -6762,6 +6847,7 @@
- }
- ast_string_field_set(p, context, sip_cfg.default_context);
- ast_string_field_set(p, parkinglot, default_parkinglot);
-+ ast_string_field_set(p, engine, default_engine);
-
- AST_LIST_HEAD_INIT_NOLOCK(&p->request_queue);
-
-@@ -7396,7 +7482,7 @@
- int iterator;
- int sendonly = -1;
- int numberofports;
-- struct ast_rtp *newaudiortp, *newvideortp, *newtextrtp; /* Buffers for codec handling */
-+ struct ast_rtp_codecs newaudiortp, newvideortp, newtextrtp;
- int newjointcapability; /* Negotiated capability */
- int newpeercapability;
- int newnoncodeccapability;
-@@ -7421,34 +7507,11 @@
- return -1;
- }
-
-- /* Initialize the temporary RTP structures we use to evaluate the offer from the peer */
--#ifdef LOW_MEMORY
-- newaudiortp = ast_threadstorage_get(&ts_audio_rtp, ast_rtp_alloc_size());
--#else
-- newaudiortp = alloca(ast_rtp_alloc_size());
--#endif
-- memset(newaudiortp, 0, ast_rtp_alloc_size());
-- ast_rtp_new_init(newaudiortp);
-- ast_rtp_pt_clear(newaudiortp);
-+ /* Make sure that the codec structures are all cleared out */
-+ ast_rtp_codecs_payloads_clear(&newaudiortp, NULL);
-+ ast_rtp_codecs_payloads_clear(&newvideortp, NULL);
-+ ast_rtp_codecs_payloads_clear(&newtextrtp, NULL);
-
--#ifdef LOW_MEMORY
-- newvideortp = ast_threadstorage_get(&ts_video_rtp, ast_rtp_alloc_size());
--#else
-- newvideortp = alloca(ast_rtp_alloc_size());
--#endif
-- memset(newvideortp, 0, ast_rtp_alloc_size());
-- ast_rtp_new_init(newvideortp);
-- ast_rtp_pt_clear(newvideortp);
--
--#ifdef LOW_MEMORY
-- newtextrtp = ast_threadstorage_get(&ts_text_rtp, ast_rtp_alloc_size());
--#else
-- newtextrtp = alloca(ast_rtp_alloc_size());
--#endif
-- memset(newtextrtp, 0, ast_rtp_alloc_size());
-- ast_rtp_new_init(newtextrtp);
-- ast_rtp_pt_clear(newtextrtp);
--
- /* Update our last rtprx when we receive an SDP, too */
- p->lastrtprx = p->lastrtptx = time(NULL); /* XXX why both ? */
-
-@@ -7529,12 +7592,14 @@
- p->novideo = TRUE;
- p->notext = TRUE;
-
-- if (p->vrtp)
-- ast_rtp_pt_clear(newvideortp); /* Must be cleared in case no m=video line exists */
--
-- if (p->trtp)
-- ast_rtp_pt_clear(newtextrtp); /* Must be cleared in case no m=text line exists */
-+ if (p->vrtp) {
-+ ast_rtp_codecs_payloads_clear(&newvideortp, NULL);
-+ }
-
-+ if (p->trtp) {
-+ ast_rtp_codecs_payloads_clear(&newtextrtp, NULL);
-+ }
-+
- /* Find media streams in this SDP offer */
- while ((m = get_sdp_iterate(&iterator, req, "m"))[0] != '\0') {
- int x;
-@@ -7558,7 +7623,8 @@
- }
- if (debug)
- ast_verbose("Found RTP audio format %d\n", codec);
-- ast_rtp_set_m_type(newaudiortp, codec);
-+
-+ ast_rtp_codecs_payloads_set_m_type(&newaudiortp, NULL, codec);
- }
- } else if ((sscanf(m, "video %d/%d RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
- (sscanf(m, "video %d RTP/AVP %n", &x, &len) == 1 && len >= 0)) {
-@@ -7574,7 +7640,7 @@
- }
- if (debug)
- ast_verbose("Found RTP video format %d\n", codec);
-- ast_rtp_set_m_type(newvideortp, codec);
-+ ast_rtp_codecs_payloads_set_m_type(&newvideortp, NULL, codec);
- }
- } else if ((sscanf(m, "text %d/%d RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
- (sscanf(m, "text %d RTP/AVP %n", &x, &len) == 1 && len > 0)) {
-@@ -7590,7 +7656,7 @@
- }
- if (debug)
- ast_verbose("Found RTP text format %d\n", codec);
-- ast_rtp_set_m_type(newtextrtp, codec);
-+ ast_rtp_codecs_payloads_set_m_type(&newtextrtp, NULL, codec);
- }
- } else if (p->udptl && ( (sscanf(m, "image %d udptl t38%n", &x, &len) == 1 && len > 0) ||
- (sscanf(m, "image %d UDPTL t38%n", &x, &len) == 1 && len > 0) )) {
-@@ -7655,10 +7721,10 @@
- if (udptlportno > 0) {
- sin.sin_port = htons(udptlportno);
- if (ast_test_flag(&p->flags[0], SIP_NAT) && ast_test_flag(&p->flags[1], SIP_PAGE2_UDPTL_DESTINATION)) {
-- struct sockaddr_in peer;
-- ast_rtp_get_peer(p->rtp, &peer);
-- if (peer.sin_addr.s_addr) {
-- memcpy(&sin.sin_addr, &peer.sin_addr, sizeof(sin.sin_addr));
-+ struct sockaddr_in remote_address;
-+ ast_rtp_instance_get_remote_address(p->rtp, &remote_address);
-+ if (remote_address.sin_addr.s_addr) {
-+ memcpy(&sin, &remote_address, sizeof(sin));
- if (debug) {
- ast_log(LOG_DEBUG, "Peer T.38 UDPTL is set behind NAT and with destination, destination address now %s\n", ast_inet_ntoa(sin.sin_addr));
- }
-@@ -7678,7 +7744,7 @@
- if (p->rtp) {
- if (portno > 0) {
- sin.sin_port = htons(portno);
-- ast_rtp_set_peer(p->rtp, &sin);
-+ ast_rtp_instance_set_remote_address(p->rtp, &sin);
- if (debug)
- ast_verbose("Peer audio RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
- } else {
-@@ -7686,7 +7752,7 @@
- if (debug)
- ast_verbose("Got T.38 Re-invite without audio. Keeping RTP active during T.38 session. Callid %s\n", p->callid);
- } else {
-- ast_rtp_stop(p->rtp);
-+ ast_rtp_instance_stop(p->rtp);
- if (debug)
- ast_verbose("Peer doesn't provide audio. Callid %s\n", p->callid);
- }
-@@ -7769,18 +7835,17 @@
- }
- }
- if (framing && p->autoframing) {
-- struct ast_codec_pref *pref = ast_rtp_codec_getpref(p->rtp);
-+ struct ast_codec_pref *pref = &ast_rtp_instance_get_codecs(p->rtp)->pref;
- int codec_n;
-- int format = 0;
-- for (codec_n = 0; codec_n < MAX_RTP_PT; codec_n++) {
-- format = ast_rtp_codec_getformat(codec_n);
-- if (!format) /* non-codec or not found */
-+ for (codec_n = 0; codec_n < AST_RTP_MAX_PT; codec_n++) {
-+ struct ast_rtp_payload_type format = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(p->rtp), codec_n);
-+ if (!format.asterisk_format || !format.code) /* non-codec or not found */
- continue;
- if (option_debug)
-- ast_log(LOG_DEBUG, "Setting framing for %d to %ld\n", format, framing);
-- ast_codec_pref_setsize(pref, format, framing);
-+ ast_log(LOG_DEBUG, "Setting framing for %d to %ld\n", format.code, framing);
-+ ast_codec_pref_setsize(pref, format.code, framing);
- }
-- ast_rtp_codec_setpref(p->rtp, pref);
-+ ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, pref);
- }
- continue;
- }
-@@ -7792,7 +7857,7 @@
-
- sscanf(red_cp, "%u", &red_data_pt[red_num_gen]);
- red_cp = strtok(red_cp, "/");
-- while (red_cp && red_num_gen++ < RED_MAX_GENERATION) {
-+ while (red_cp && red_num_gen++ < AST_RED_MAX_GENERATION) {
- sscanf(red_cp, "%u", &red_data_pt[red_num_gen]);
- red_cp = strtok(NULL, "/");
- }
-@@ -7801,15 +7866,15 @@
- }
-
- if (sscanf(a, "fmtp: %u %63s", &codec, fmtp_string) == 2) {
-- struct rtpPayloadType payload;
-+ struct ast_rtp_payload_type payload;
- unsigned int handled = 0;
-
-- payload = ast_rtp_lookup_pt(newaudiortp, codec);
-+ payload = ast_rtp_codecs_payload_lookup(&newaudiortp, codec);
- if (!payload.code) {
- /* it wasn't found, try the video rtp */
-- payload = ast_rtp_lookup_pt(newvideortp, codec);
-+ payload = ast_rtp_codecs_payload_lookup(&newvideortp, codec);
- }
-- if (payload.code && payload.isAstFormat) {
-+ if (payload.code && payload.asterisk_format) {
- unsigned int bit_rate;
-
- switch (payload.code) {
-@@ -7817,7 +7882,7 @@
- if (sscanf(fmtp_string, "bitrate=%u", &bit_rate) == 1) {
- if (bit_rate != 32000) {
- ast_log(LOG_WARNING, "Got Siren7 offer at %d bps, but only 32000 bps supported; ignoring.\n", bit_rate);
-- ast_rtp_unset_m_type(newaudiortp, codec);
-+ ast_rtp_codecs_payloads_unset(&newaudiortp, NULL, codec);
- } else {
- handled = 1;
- }
-@@ -7827,7 +7892,7 @@
- if (sscanf(fmtp_string, "bitrate=%u", &bit_rate) == 1) {
- if (bit_rate != 48000) {
- ast_log(LOG_WARNING, "Got Siren14 offer at %d bps, but only 48000 bps supported; ignoring.\n", bit_rate);
-- ast_rtp_unset_m_type(newaudiortp, codec);
-+ ast_rtp_codecs_payloads_unset(&newaudiortp, NULL, codec);
- } else {
- handled = 1;
- }
-@@ -7849,24 +7914,24 @@
- /* Note: should really look at the '#chans' params too */
- /* Note: This should all be done in the context of the m= above */
- if (!strncasecmp(mimeSubtype, "H26", 3) || !strncasecmp(mimeSubtype, "MP4", 3)) { /* Video */
-- if (ast_rtp_set_rtpmap_type_rate(newvideortp, codec, "video", mimeSubtype, 0, sample_rate) != -1) {
-+ if (ast_rtp_codecs_payloads_set_rtpmap_type_rate(&newvideortp, NULL, codec, "video", mimeSubtype, 0, sample_rate) != -1) {
- if (debug)
- ast_verbose("Found video description format %s for ID %d\n", mimeSubtype, codec);
- found_rtpmap_codecs[last_rtpmap_codec] = codec;
- last_rtpmap_codec++;
- } else {
-- ast_rtp_unset_m_type(newvideortp, codec);
-+ ast_rtp_codecs_payloads_unset(&newvideortp, NULL, codec);
- if (debug)
- ast_verbose("Found unknown media description format %s for ID %d\n", mimeSubtype, codec);
- }
- } else if (!strncasecmp(mimeSubtype, "T140", 4)) { /* Text */
- if (p->trtp) {
- /* ast_verbose("Adding t140 mimeSubtype to textrtp struct\n"); */
-- ast_rtp_set_rtpmap_type(newtextrtp, codec, "text", mimeSubtype, 0);
-+ ast_rtp_codecs_payloads_set_rtpmap_type_rate(&newtextrtp, NULL, codec, "text", mimeSubtype, 0, sample_rate);
- }
- } else if (!strncasecmp(mimeSubtype, "RED", 3)) { /* Text with Redudancy */
- if (p->trtp) {
-- ast_rtp_set_rtpmap_type(newtextrtp, codec, "text", mimeSubtype, 0);
-+ ast_rtp_codecs_payloads_set_rtpmap_type_rate(&newtextrtp, NULL, codec, "text", mimeSubtype, 0, sample_rate);
- red_pt = codec;
- sprintf(red_fmtp, "fmtp:%d ", red_pt);
-
-@@ -7874,15 +7939,14 @@
- ast_verbose("RED submimetype has payload type: %d\n", red_pt);
- }
- } else { /* Must be audio?? */
-- if (ast_rtp_set_rtpmap_type_rate(newaudiortp, codec, "audio", mimeSubtype,
-- ast_test_flag(&p->flags[0], SIP_G726_NONSTANDARD) ? AST_RTP_OPT_G726_NONSTANDARD : 0,
-- sample_rate) != -1) {
-+ if (ast_rtp_codecs_payloads_set_rtpmap_type_rate(&newaudiortp, NULL, codec, "audio", mimeSubtype,
-+ ast_test_flag(&p->flags[0], SIP_G726_NONSTANDARD) ? AST_RTP_OPT_G726_NONSTANDARD : 0, sample_rate) != -1) {
- if (debug)
- ast_verbose("Found audio description format %s for ID %d\n", mimeSubtype, codec);
- found_rtpmap_codecs[last_rtpmap_codec] = codec;
- last_rtpmap_codec++;
- } else {
-- ast_rtp_unset_m_type(newaudiortp, codec);
-+ ast_rtp_codecs_payloads_unset(&newaudiortp, NULL, codec);
- if (debug)
- ast_verbose("Found unknown media description format %s for ID %d\n", mimeSubtype, codec);
- }
-@@ -8007,7 +8071,7 @@
-
- /* Remote party offers T38, we need to update state */
- if (t38action == SDP_T38_ACCEPT) {
-- if (p->t38.state == T38_LOCAL_DIRECT || p->t38.state == T38_LOCAL_REINVITE)
-+ if (p->t38.state == T38_LOCAL_REINVITE)
- change_t38_state(p, T38_ENABLED);
- } else if (t38action == SDP_T38_INITIATE) {
- if (p->owner && p->lastinvite) {
-@@ -8021,15 +8085,14 @@
- }
-
- /* Now gather all of the codecs that we are asked for: */
-- ast_rtp_get_current_formats(newaudiortp, &peercapability, &peernoncodeccapability);
-- ast_rtp_get_current_formats(newvideortp, &vpeercapability, &vpeernoncodeccapability);
-- ast_rtp_get_current_formats(newtextrtp, &tpeercapability, &tpeernoncodeccapability);
-+ ast_rtp_codecs_payload_formats(&newaudiortp, &peercapability, &peernoncodeccapability);
-+ ast_rtp_codecs_payload_formats(&newvideortp, &vpeercapability, &vpeernoncodeccapability);
-+ ast_rtp_codecs_payload_formats(&newtextrtp, &tpeercapability, &tpeernoncodeccapability);
-
- newjointcapability = p->capability & (peercapability | vpeercapability | tpeercapability);
- newpeercapability = (peercapability | vpeercapability | tpeercapability);
- newnoncodeccapability = p->noncodeccapability & peernoncodeccapability;
--
--
-+
- if (debug) {
- /* shame on whoever coded this.... */
- char s1[SIPBUFSIZE], s2[SIPBUFSIZE], s3[SIPBUFSIZE], s4[SIPBUFSIZE], s5[SIPBUFSIZE];
-@@ -8040,11 +8103,17 @@
- ast_getformatname_multiple(s3, SIPBUFSIZE, vpeercapability),
- ast_getformatname_multiple(s4, SIPBUFSIZE, tpeercapability),
- ast_getformatname_multiple(s5, SIPBUFSIZE, newjointcapability));
-+ }
-
-+ if (debug) {
-+ struct ast_str *s1 = ast_str_alloca(SIPBUFSIZE);
-+ struct ast_str *s2 = ast_str_alloca(SIPBUFSIZE);
-+ struct ast_str *s3 = ast_str_alloca(SIPBUFSIZE);
-+
- ast_verbose("Non-codec capabilities (dtmf): us - %s, peer - %s, combined - %s\n",
-- ast_rtp_lookup_mime_multiple(s1, SIPBUFSIZE, p->noncodeccapability, 0, 0),
-- ast_rtp_lookup_mime_multiple(s2, SIPBUFSIZE, peernoncodeccapability, 0, 0),
-- ast_rtp_lookup_mime_multiple(s3, SIPBUFSIZE, newnoncodeccapability, 0, 0));
-+ ast_rtp_lookup_mime_multiple2(s1, p->noncodeccapability, 0, 0),
-+ ast_rtp_lookup_mime_multiple2(s2, peernoncodeccapability, 0, 0),
-+ ast_rtp_lookup_mime_multiple2(s3, newnoncodeccapability, 0, 0));
- }
- if (!newjointcapability) {
- /* If T.38 was not negotiated either, totally bail out... */
-@@ -8064,18 +8133,24 @@
- p->peercapability = newpeercapability; /* The other sides capability in latest offer */
- p->jointnoncodeccapability = newnoncodeccapability; /* DTMF capabilities */
-
-+ if (ast_test_flag(&p->flags[1], SIP_PAGE2_PREFERRED_CODEC)) { /* respond with single most preferred joint codec, limiting the other side's choice */
-+ p->jointcapability = ast_codec_choose(&p->prefs, p->jointcapability, 1);
-+ }
-+
- if (p->jointcapability & AST_FORMAT_T140RED) {
-- p->red = 1;
-- rtp_red_init(p->trtp, 300, red_data_pt, 2);
-+ p->red = 1;
-+ ast_rtp_red_init(p->trtp, 300, red_data_pt, 2);
- } else {
-- p->red = 0;
-+ p->red = 0;
- }
-
-- ast_rtp_pt_copy(p->rtp, newaudiortp);
-- if (p->vrtp)
-- ast_rtp_pt_copy(p->vrtp, newvideortp);
-- if (p->trtp)
-- ast_rtp_pt_copy(p->trtp, newtextrtp);
-+ ast_rtp_codecs_payloads_copy(&newaudiortp, ast_rtp_instance_get_codecs(p->rtp), p->rtp);
-+ if (p->vrtp) {
-+ ast_rtp_codecs_payloads_copy(&newvideortp, ast_rtp_instance_get_codecs(p->vrtp), p->vrtp);
-+ }
-+ if (p->trtp) {
-+ ast_rtp_codecs_payloads_copy(&newtextrtp, ast_rtp_instance_get_codecs(p->trtp), p->trtp);
-+ }
-
- if (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO) {
- ast_clear_flag(&p->flags[0], SIP_DTMF);
-@@ -8083,8 +8158,8 @@
- /* XXX Would it be reasonable to drop the DSP at this point? XXX */
- ast_set_flag(&p->flags[0], SIP_DTMF_RFC2833);
- /* Since RFC2833 is now negotiated we need to change some properties of the RTP stream */
-- ast_rtp_setdtmf(p->rtp, 1);
-- ast_rtp_setdtmfcompensate(p->rtp, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
-+ ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_DTMF, 1);
-+ ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
- } else {
- ast_set_flag(&p->flags[0], SIP_DTMF_INBAND);
- }
-@@ -8092,21 +8167,21 @@
-
- /* Setup audio port number */
- if (p->rtp && sin.sin_port) {
-- ast_rtp_set_peer(p->rtp, &sin);
-+ ast_rtp_instance_set_remote_address(p->rtp, &sin);
- if (debug)
- ast_verbose("Peer audio RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
- }
-
- /* Setup video port number */
- if (p->vrtp && vsin.sin_port) {
-- ast_rtp_set_peer(p->vrtp, &vsin);
-+ ast_rtp_instance_set_remote_address(p->vrtp, &vsin);
- if (debug)
- ast_verbose("Peer video RTP is at port %s:%d\n", ast_inet_ntoa(vsin.sin_addr), ntohs(vsin.sin_port));
- }
-
- /* Setup text port number */
- if (p->trtp && tsin.sin_port) {
-- ast_rtp_set_peer(p->trtp, &tsin);
-+ ast_rtp_instance_set_remote_address(p->trtp, &tsin);
- if (debug)
- ast_verbose("Peer text RTP is at port %s:%d\n", ast_inet_ntoa(tsin.sin_addr), ntohs(tsin.sin_port));
- }
-@@ -8153,7 +8228,7 @@
- S_OR(p->mohsuggest, NULL),
- !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
- if (sendonly)
-- ast_rtp_stop(p->rtp);
-+ ast_rtp_instance_stop(p->rtp);
- /* RTCP needs to go ahead, even if we're on hold!!! */
- /* Activate a re-invite */
- ast_queue_frame(p->owner, &ast_null_frame);
-@@ -8700,9 +8775,6 @@
- if (!ast_strlen_zero(global_useragent))
- add_header(req, "User-Agent", global_useragent);
-
-- if (!ast_strlen_zero(p->rpid))
-- add_header(req, "Remote-Party-ID", p->rpid);
--
- if (!ast_strlen_zero(p->url)) {
- add_header(req, "Access-URL", p->url);
- ast_string_field_set(p, url, NULL);
-@@ -8740,6 +8812,14 @@
- return -1;
- }
- respprep(&resp, p, msg, req);
-+
-+ if (ast_test_flag(&p->flags[0], SIP_SENDRPID)
-+ && ast_test_flag(&p->flags[1], SIP_PAGE2_CONNECTLINEUPDATE_PEND)
-+ && (!strncmp(msg, "180", 3) || !strncmp(msg, "183", 3))) {
-+ ast_clear_flag(&p->flags[1], SIP_PAGE2_CONNECTLINEUPDATE_PEND);
-+ add_rpid(&resp, p);
-+ }
-+
- add_header_contentLength(&resp, 0);
- /* If we are cancelling an incoming invite for some reason, add information
- about the reason why we are doing this in clear text */
-@@ -8959,6 +9039,89 @@
- return 0;
- }
-
-+/*!
-+ * \pre if p->owner exists, it must be locked
-+ * \brief Add Remote-Party-ID header to SIP message
-+ */
-+static int add_rpid(struct sip_request *req, struct sip_pvt *p)
-+{
-+ struct ast_str *tmp = ast_str_alloca(256);
-+ char *lid_num = NULL;
-+ char *lid_name = NULL;
-+ int lid_pres;
-+ const char *fromdomain;
-+ const char *privacy = NULL;
-+ const char *screen = NULL;
-+ const char *anonymous_string = "\"Anonymous\" <anonymous@anonymous.invalid>";
-+
-+ if (!ast_test_flag(&p->flags[0], SIP_SENDRPID)) {
-+ return 0;
-+ }
-+
-+ if (p->owner && p->owner->connected.id.number)
-+ lid_num = p->owner->connected.id.number;
-+ if (p->owner && p->owner->connected.id.name)
-+ lid_name = p->owner->connected.id.name;
-+ lid_pres = (p->owner) ? p->owner->connected.id.number_presentation : AST_PRES_NUMBER_NOT_AVAILABLE;
-+
-+ if (ast_strlen_zero(lid_num))
-+ return 0;
-+ if (ast_strlen_zero(lid_name))
-+ lid_name = lid_num;
-+ fromdomain = S_OR(p->fromdomain, ast_inet_ntoa(p->ourip.sin_addr));
-+
-+ if (ast_test_flag(&p->flags[0], SIP_SENDRPID_PAI)) {
-+ if ((lid_pres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED) {
-+ ast_str_set(&tmp, -1, "%s", anonymous_string);
-+ } else {
-+ ast_str_set(&tmp, -1, "\"%s\" <sip:%s@%s>", lid_name, lid_num, fromdomain);
-+ }
-+ add_header(req, "P-Asserted-Identity", ast_str_buffer(tmp));
-+ } else {
-+ ast_str_set(&tmp, -1, "\"%s\" <sip:%s@%s>;party=%s", lid_name, lid_num, fromdomain, ast_test_flag(&p->flags[0], SIP_OUTGOING) ? "calling" : "called");
-+
-+ switch (lid_pres) {
-+ case AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
-+ case AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
-+ privacy = "off";
-+ screen = "no";
-+ break;
-+ case AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
-+ case AST_PRES_ALLOWED_NETWORK_NUMBER:
-+ privacy = "off";
-+ screen = "yes";
-+ break;
-+ case AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
-+ case AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
-+ privacy = "full";
-+ screen = "no";
-+ break;
-+ case AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
-+ case AST_PRES_PROHIB_NETWORK_NUMBER:
-+ privacy = "full";
-+ screen = "yes";
-+ break;
-+ case AST_PRES_NUMBER_NOT_AVAILABLE:
-+ break;
-+ default:
-+ if ((lid_pres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED) {
-+ privacy = "full";
-+ }
-+ else
-+ privacy = "off";
-+ screen = "no";
-+ break;
-+ }
-+
-+ if (!ast_strlen_zero(privacy) && !ast_strlen_zero(screen)) {
-+ ast_str_append(&tmp, -1, ";privacy=%s;screen=%s", privacy, screen);
-+ }
-+
-+ add_header(req, "Remote-Party-ID", ast_str_buffer(tmp));
-+ }
-+ return 0;
-+}
-+
- /*! \brief add XML encoded media control with update
- \note XML: The only way to turn 0 bits of information into a few hundred. (markster) */
- static int add_vidupdate(struct sip_request *req)
-@@ -8990,19 +9153,19 @@
-
- if (debug)
- ast_verbose("Adding codec 0x%x (%s) to SDP\n", codec, ast_getformatname(codec));
-- if ((rtp_code = ast_rtp_lookup_code(p->rtp, 1, codec)) == -1)
-+ if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->rtp), 1, codec)) == -1)
- return;
-
- if (p->rtp) {
-- struct ast_codec_pref *pref = ast_rtp_codec_getpref(p->rtp);
-+ struct ast_codec_pref *pref = &ast_rtp_instance_get_codecs(p->rtp)->pref;
- fmt = ast_codec_pref_getsize(pref, codec);
- } else /* I dont see how you couldn't have p->rtp, but good to check for and error out if not there like earlier code */
- return;
- ast_str_append(m_buf, 0, " %d", rtp_code);
- ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code,
-- ast_rtp_lookup_mime_subtype(1, codec,
-+ ast_rtp_lookup_mime_subtype2(1, codec,
- ast_test_flag(&p->flags[0], SIP_G726_NONSTANDARD) ? AST_RTP_OPT_G726_NONSTANDARD : 0),
-- ast_rtp_lookup_sample_rate(1, codec));
-+ ast_rtp_lookup_sample_rate2(1, codec));
-
- switch (codec) {
- case AST_FORMAT_G729A:
-@@ -9049,13 +9212,13 @@
- if (debug)
- ast_verbose("Adding video codec 0x%x (%s) to SDP\n", codec, ast_getformatname(codec));
-
-- if ((rtp_code = ast_rtp_lookup_code(p->vrtp, 1, codec)) == -1)
-+ if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->vrtp), 1, codec)) == -1)
- return;
-
- ast_str_append(m_buf, 0, " %d", rtp_code);
- ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code,
-- ast_rtp_lookup_mime_subtype(1, codec, 0),
-- ast_rtp_lookup_sample_rate(1, codec));
-+ ast_rtp_lookup_mime_subtype2(1, codec, 0),
-+ ast_rtp_lookup_sample_rate2(1, codec));
- /* Add fmtp code here */
- }
-
-@@ -9072,20 +9235,21 @@
- if (debug)
- ast_verbose("Adding text codec 0x%x (%s) to SDP\n", codec, ast_getformatname(codec));
-
-- if ((rtp_code = ast_rtp_lookup_code(p->trtp, 1, codec)) == -1)
-+ if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->trtp), 1, codec)) == -1)
- return;
-
- ast_str_append(m_buf, 0, " %d", rtp_code);
- ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code,
-- ast_rtp_lookup_mime_subtype(1, codec, 0),
-- ast_rtp_lookup_sample_rate(1, codec));
-+ ast_rtp_lookup_mime_subtype2(1, codec, 0),
-+ ast_rtp_lookup_sample_rate2(1, codec));
- /* Add fmtp code here */
-
- if (codec == AST_FORMAT_T140RED) {
-- ast_str_append(a_buf, 0, "a=fmtp:%d %d/%d/%d\r\n", rtp_code,
-- ast_rtp_lookup_code(p->trtp, 1, AST_FORMAT_T140),
-- ast_rtp_lookup_code(p->trtp, 1, AST_FORMAT_T140),
-- ast_rtp_lookup_code(p->trtp, 1, AST_FORMAT_T140));
-+ int t140code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->trtp), 1, AST_FORMAT_T140);
-+ ast_str_append(a_buf, 0, "a=fmtp:%d %d/%d/%d\r\n", rtp_code,
-+ t140code,
-+ t140code,
-+ t140code);
-
- }
- }
-@@ -9120,92 +9284,6 @@
- }
- }
-
--/*! \brief Add T.38 Session Description Protocol message */
--static int add_t38_sdp(struct sip_request *resp, struct sip_pvt *p)
--{
-- int len = 0;
-- int x = 0;
-- struct sockaddr_in udptlsin;
-- struct ast_str *m_modem = ast_str_alloca(1024);
-- struct ast_str *a_modem = ast_str_alloca(1024);
-- struct sockaddr_in udptldest = { 0, };
-- int debug;
--
-- debug = sip_debug_test_pvt(p);
-- len = 0;
-- if (!p->udptl) {
-- ast_log(LOG_WARNING, "No way to add SDP without an UDPTL structure\n");
-- return -1;
-- }
--
-- if (!p->sessionid) {
-- p->sessionid = (int)ast_random();
-- p->sessionversion = p->sessionid;
-- } else
-- p->sessionversion++;
--
-- /* Our T.38 end is */
-- ast_udptl_get_us(p->udptl, &udptlsin);
--
-- /* Determine T.38 UDPTL destination */
-- if (p->udptlredirip.sin_addr.s_addr) {
-- udptldest.sin_port = p->udptlredirip.sin_port;
-- udptldest.sin_addr = p->udptlredirip.sin_addr;
-- } else {
-- udptldest.sin_addr = p->ourip.sin_addr;
-- udptldest.sin_port = udptlsin.sin_port;
-- }
--
-- if (debug)
-- ast_debug(1, "T.38 UDPTL is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(udptlsin.sin_port));
--
-- /* We break with the "recommendation" and send our IP, in order that our
-- peer doesn't have to ast_gethostbyname() us */
--
-- if (debug) {
-- ast_debug(1, "Our T38 capability (%d), peer T38 capability (%d), joint capability (%d)\n",
-- p->t38.capability,
-- p->t38.peercapability,
-- p->t38.jointcapability);
-- }
-- ast_str_append(&m_modem, 0, "v=0\r\n");
-- ast_str_append(&m_modem, 0, "o=%s %d %d IN IP4 %s\r\n", ast_strlen_zero(global_sdpowner) ? "-" : global_sdpowner , p->sessionid, p->sessionversion, ast_inet_ntoa(udptldest.sin_addr));
-- ast_str_append(&m_modem, 0, "s=%s\r\n", ast_strlen_zero(global_sdpsession) ? "-" : global_sdpsession);
-- ast_str_append(&m_modem, 0, "c=IN IP4 %s\r\n", ast_inet_ntoa(udptldest.sin_addr));
-- ast_str_append(&m_modem, 0, "t=0 0\r\n");
-- ast_str_append(&m_modem, 0, "m=image %d udptl t38\r\n", ntohs(udptldest.sin_port));
--
-- if ((p->t38.jointcapability & T38FAX_VERSION) == T38FAX_VERSION_0)
-- ast_str_append(&a_modem, 0, "a=T38FaxVersion:0\r\n");
-- if ((p->t38.jointcapability & T38FAX_VERSION) == T38FAX_VERSION_1)
-- ast_str_append(&a_modem, 0, "a=T38FaxVersion:1\r\n");
-- if ((x = t38_get_rate(p->t38.jointcapability)))
-- ast_str_append(&a_modem, 0, "a=T38MaxBitRate:%d\r\n", x);
-- if ((p->t38.jointcapability & T38FAX_FILL_BIT_REMOVAL) == T38FAX_FILL_BIT_REMOVAL)
-- ast_str_append(&a_modem, 0, "a=T38FaxFillBitRemoval\r\n");
-- if ((p->t38.jointcapability & T38FAX_TRANSCODING_MMR) == T38FAX_TRANSCODING_MMR)
-- ast_str_append(&a_modem, 0, "a=T38FaxTranscodingMMR\r\n");
-- if ((p->t38.jointcapability & T38FAX_TRANSCODING_JBIG) == T38FAX_TRANSCODING_JBIG)
-- ast_str_append(&a_modem, 0, "a=T38FaxTranscodingJBIG\r\n");
-- ast_str_append(&a_modem, 0, "a=T38FaxRateManagement:%s\r\n", (p->t38.jointcapability & T38FAX_RATE_MANAGEMENT_LOCAL_TCF) ? "localTCF" : "transferredTCF");
-- x = ast_udptl_get_local_max_datagram(p->udptl);
-- ast_str_append(&a_modem, 0, "a=T38FaxMaxBuffer:%d\r\n", x);
-- ast_str_append(&a_modem, 0, "a=T38FaxMaxDatagram:%d\r\n", x);
-- if (p->t38.jointcapability != T38FAX_UDP_EC_NONE)
-- ast_str_append(&a_modem, 0, "a=T38FaxUdpEC:%s\r\n", (p->t38.jointcapability & T38FAX_UDP_EC_REDUNDANCY) ? "t38UDPRedundancy" : "t38UDPFEC");
-- len = m_modem->used + a_modem->used;
-- add_header(resp, "Content-Type", "application/sdp");
-- add_header_contentLength(resp, len);
-- add_line(resp, m_modem->str);
-- add_line(resp, a_modem->str);
--
-- /* Update lastrtprx when we send our SDP */
-- p->lastrtprx = p->lastrtptx = time(NULL);
--
-- return 0;
--}
--
--
- /*! \brief Add RFC 2833 DTMF offer to SDP */
- static void add_noncodec_to_sdp(const struct sip_pvt *p, int format,
- struct ast_str **m_buf, struct ast_str **a_buf,
-@@ -9214,14 +9292,14 @@
- int rtp_code;
-
- if (debug)
-- ast_verbose("Adding non-codec 0x%x (%s) to SDP\n", format, ast_rtp_lookup_mime_subtype(0, format, 0));
-- if ((rtp_code = ast_rtp_lookup_code(p->rtp, 0, format)) == -1)
-+ ast_verbose("Adding non-codec 0x%x (%s) to SDP\n", format, ast_rtp_lookup_mime_subtype2(0, format, 0));
-+ if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->rtp), 0, format)) == -1)
- return;
-
- ast_str_append(m_buf, 0, " %d", rtp_code);
- ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code,
-- ast_rtp_lookup_mime_subtype(0, format, 0),
-- ast_rtp_lookup_sample_rate(0, format));
-+ ast_rtp_lookup_mime_subtype2(0, format, 0),
-+ ast_rtp_lookup_sample_rate2(0, format));
- if (format == AST_RTP_DTMF) /* Indicate we support DTMF and FLASH... */
- ast_str_append(a_buf, 0, "a=fmtp:%d 0-16\r\n", rtp_code);
- }
-@@ -9234,11 +9312,11 @@
- struct sockaddr_in *dest, struct sockaddr_in *vdest)
- {
- /* First, get our address */
-- ast_rtp_get_us(p->rtp, sin);
-+ ast_rtp_instance_get_local_address(p->rtp, sin);
- if (p->vrtp)
-- ast_rtp_get_us(p->vrtp, vsin);
-+ ast_rtp_instance_get_local_address(p->vrtp, vsin);
- if (p->trtp)
-- ast_rtp_get_us(p->trtp, tsin);
-+ ast_rtp_instance_get_local_address(p->trtp, tsin);
-
- /* Now, try to figure out where we want them to send data */
- /* Is this a re-invite to move the media out, then use the original offer from caller */
-@@ -9268,7 +9346,7 @@
- is used in Session-Timers where RE-INVITEs are used for refreshing SIP sessions
- without modifying the media session in any way.
- */
--static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int oldsdp)
-+static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int oldsdp, int add_audio, int add_t38)
- {
- int len = 0;
- int alreadysent = 0;
-@@ -9277,8 +9355,10 @@
- struct sockaddr_in vsin;
- struct sockaddr_in tsin;
- struct sockaddr_in dest;
-+ struct sockaddr_in udptlsin;
- struct sockaddr_in vdest = { 0, };
- struct sockaddr_in tdest = { 0, };
-+ struct sockaddr_in udptldest = { 0, };
-
- /* SDP fields */
- char *version = "v=0\r\n"; /* Protocol version */
-@@ -9287,16 +9367,18 @@
- char connection[256]; /* Connection data */
- char *session_time = "t=0 0\r\n"; /* Time the session is active */
- char bandwidth[256] = ""; /* Max bitrate */
-- char *hold;
-+ char *hold = "";
- struct ast_str *m_audio = ast_str_alloca(256); /* Media declaration line for audio */
- struct ast_str *m_video = ast_str_alloca(256); /* Media declaration line for video */
- struct ast_str *m_text = ast_str_alloca(256); /* Media declaration line for text */
-+ struct ast_str *m_modem = ast_str_alloca(256); /* Media declaration line for modem */
- struct ast_str *a_audio = ast_str_alloca(1024); /* Attributes for audio */
- struct ast_str *a_video = ast_str_alloca(1024); /* Attributes for video */
- struct ast_str *a_text = ast_str_alloca(1024); /* Attributes for text */
-+ struct ast_str *a_modem = ast_str_alloca(1024); /* Attributes for modem */
-
- int x;
-- int capability;
-+ int capability = 0;
- int needaudio = FALSE;
- int needvideo = FALSE;
- int needtext = FALSE;
-@@ -9327,184 +9409,235 @@
- p->sessionversion++;
- }
-
-- capability = p->jointcapability;
-+ get_our_media_address(p, needvideo, &sin, &vsin, &tsin, &dest, &vdest);
-
-- /* XXX note, Video and Text are negated - 'true' means 'no' */
-- ast_debug(1, "** Our capability: %s Video flag: %s Text flag: %s\n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), capability),
-- p->novideo ? "True" : "False", p->notext ? "True" : "False");
-- ast_debug(1, "** Our prefcodec: %s \n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), p->prefcodec));
-+ snprintf(owner, sizeof(owner), "o=%s %d %d IN IP4 %s\r\n", ast_strlen_zero(global_sdpowner) ? "-" : global_sdpowner, p->sessionid, p->sessionversion, ast_inet_ntoa(dest.sin_addr));
-+ snprintf(connection, sizeof(connection), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr));
-+
-+ if (add_audio) {
-+ capability = p->jointcapability;
-+
-+ /* XXX note, Video and Text are negated - 'true' means 'no' */
-+ ast_debug(1, "** Our capability: %s Video flag: %s Text flag: %s\n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), capability),
-+ p->novideo ? "True" : "False", p->notext ? "True" : "False");
-+ ast_debug(1, "** Our prefcodec: %s \n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), p->prefcodec));
-
- #ifdef WHEN_WE_HAVE_T38_FOR_OTHER_TRANSPORTS
-- if (ast_test_flag(&p->t38.t38support, SIP_PAGE2_T38SUPPORT_RTP)) {
-- ast_str_append(&m_audio, 0, " %d", 191);
-- ast_str_append(&a_audio, 0, "a=rtpmap:%d %s/%d\r\n", 191, "t38", 8000);
-- }
-+ if (ast_test_flag(&p->t38.t38support, SIP_PAGE2_T38SUPPORT_RTP)) {
-+ ast_str_append(&m_audio, 0, " %d", 191);
-+ ast_str_append(&a_audio, 0, "a=rtpmap:%d %s/%d\r\n", 191, "t38", 8000);
-+ }
- #endif
-
-- /* Check if we need audio */
-- if (capability & AST_FORMAT_AUDIO_MASK)
-- needaudio = TRUE;
-+ /* Check if we need audio */
-+ if (capability & AST_FORMAT_AUDIO_MASK)
-+ needaudio = TRUE;
-
-- /* Check if we need video in this call */
-- if ((capability & AST_FORMAT_VIDEO_MASK) && !p->novideo) {
-- if (p->vrtp) {
-- needvideo = TRUE;
-- ast_debug(2, "This call needs video offers!\n");
-- } else
-- ast_debug(2, "This call needs video offers, but there's no video support enabled!\n");
-- }
-+ /* Check if we need video in this call */
-+ if ((capability & AST_FORMAT_VIDEO_MASK) && !p->novideo) {
-+ if (p->vrtp) {
-+ needvideo = TRUE;
-+ ast_debug(2, "This call needs video offers!\n");
-+ } else
-+ ast_debug(2, "This call needs video offers, but there's no video support enabled!\n");
-+ }
-
-- /* Get our media addresses */
-- get_our_media_address(p, needvideo, &sin, &vsin, &tsin, &dest, &vdest);
--
-- if (debug)
-- ast_verbose("Audio is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(sin.sin_port));
-+ if (debug)
-+ ast_verbose("Audio is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(sin.sin_port));
-
-- /* Ok, we need video. Let's add what we need for video and set codecs.
-- Video is handled differently than audio since we can not transcode. */
-- if (needvideo) {
-- ast_str_append(&m_video, 0, "m=video %d RTP/AVP", ntohs(vdest.sin_port));
-+ /* Ok, we need video. Let's add what we need for video and set codecs.
-+ Video is handled differently than audio since we can not transcode. */
-+ if (needvideo) {
-+ ast_str_append(&m_video, 0, "m=video %d RTP/AVP", ntohs(vdest.sin_port));
-
-- /* Build max bitrate string */
-- if (p->maxcallbitrate)
-- snprintf(bandwidth, sizeof(bandwidth), "b=CT:%d\r\n", p->maxcallbitrate);
-- if (debug)
-- ast_verbose("Video is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(vsin.sin_port));
-- }
-+ /* Build max bitrate string */
-+ if (p->maxcallbitrate)
-+ snprintf(bandwidth, sizeof(bandwidth), "b=CT:%d\r\n", p->maxcallbitrate);
-+ if (debug)
-+ ast_verbose("Video is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(vsin.sin_port));
-+ }
-
-- /* Check if we need text in this call */
-- if((capability & AST_FORMAT_TEXT_MASK) && !p->notext) {
-- if (sipdebug_text)
-- ast_verbose("We think we can do text\n");
-- if (p->trtp) {
-+ /* Check if we need text in this call */
-+ if((capability & AST_FORMAT_TEXT_MASK) && !p->notext) {
- if (sipdebug_text)
-- ast_verbose("And we have a text rtp object\n");
-- needtext = TRUE;
-- ast_debug(2, "This call needs text offers! \n");
-- } else
-- ast_debug(2, "This call needs text offers, but there's no text support enabled ! \n");
-- }
-+ ast_verbose("We think we can do text\n");
-+ if (p->trtp) {
-+ if (sipdebug_text)
-+ ast_verbose("And we have a text rtp object\n");
-+ needtext = TRUE;
-+ ast_debug(2, "This call needs text offers! \n");
-+ } else
-+ ast_debug(2, "This call needs text offers, but there's no text support enabled ! \n");
-+ }
-
-- /* Ok, we need text. Let's add what we need for text and set codecs.
-- Text is handled differently than audio since we can not transcode. */
-- if (needtext) {
-- if (sipdebug_text)
-- ast_verbose("Lets set up the text sdp\n");
-- /* Determine text destination */
-- if (p->tredirip.sin_addr.s_addr) {
-- tdest.sin_addr = p->tredirip.sin_addr;
-- tdest.sin_port = p->tredirip.sin_port;
-- } else {
-- tdest.sin_addr = p->ourip.sin_addr;
-- tdest.sin_port = tsin.sin_port;
-+ /* Ok, we need text. Let's add what we need for text and set codecs.
-+ Text is handled differently than audio since we can not transcode. */
-+ if (needtext) {
-+ if (sipdebug_text)
-+ ast_verbose("Lets set up the text sdp\n");
-+ /* Determine text destination */
-+ if (p->tredirip.sin_addr.s_addr) {
-+ tdest.sin_addr = p->tredirip.sin_addr;
-+ tdest.sin_port = p->tredirip.sin_port;
-+ } else {
-+ tdest.sin_addr = p->ourip.sin_addr;
-+ tdest.sin_port = tsin.sin_port;
-+ }
-+ ast_str_append(&m_text, 0, "m=text %d RTP/AVP", ntohs(tdest.sin_port));
-+ if (debug) /* XXX should I use tdest below ? */
-+ ast_verbose("Text is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(tsin.sin_port));
-+
- }
-- ast_str_append(&m_text, 0, "m=text %d RTP/AVP", ntohs(tdest.sin_port));
-
-- if (debug) /* XXX should I use tdest below ? */
-- ast_verbose("Text is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(tsin.sin_port));
-+ /* Start building generic SDP headers */
-
-- }
-+ /* We break with the "recommendation" and send our IP, in order that our
-+ peer doesn't have to ast_gethostbyname() us */
-
-- /* Start building generic SDP headers */
-+ ast_str_append(&m_audio, 0, "m=audio %d RTP/AVP", ntohs(dest.sin_port));
-
-- /* We break with the "recommendation" and send our IP, in order that our
-- peer doesn't have to ast_gethostbyname() us */
-+ if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) == SIP_PAGE2_CALL_ONHOLD_ONEDIR)
-+ hold = "a=recvonly\r\n";
-+ else if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) == SIP_PAGE2_CALL_ONHOLD_INACTIVE)
-+ hold = "a=inactive\r\n";
-+ else
-+ hold = "a=sendrecv\r\n";
-
-- snprintf(owner, sizeof(owner), "o=%s %d %d IN IP4 %s\r\n", ast_strlen_zero(global_sdpowner) ? "-" : global_sdpowner, p->sessionid, p->sessionversion, ast_inet_ntoa(dest.sin_addr));
-- snprintf(connection, sizeof(connection), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr));
-- ast_str_append(&m_audio, 0, "m=audio %d RTP/AVP", ntohs(dest.sin_port));
-+ /* Now, start adding audio codecs. These are added in this order:
-+ - First what was requested by the calling channel
-+ - Then preferences in order from sip.conf device config for this peer/user
-+ - Then other codecs in capabilities, including video
-+ */
-
-- if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) == SIP_PAGE2_CALL_ONHOLD_ONEDIR)
-- hold = "a=recvonly\r\n";
-- else if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) == SIP_PAGE2_CALL_ONHOLD_INACTIVE)
-- hold = "a=inactive\r\n";
-- else
-- hold = "a=sendrecv\r\n";
-+ /* Prefer the audio codec we were requested to use, first, no matter what
-+ Note that p->prefcodec can include video codecs, so mask them out
-+ */
-+ if (capability & p->prefcodec) {
-+ int codec = p->prefcodec & AST_FORMAT_AUDIO_MASK;
-
-- /* Now, start adding audio codecs. These are added in this order:
-- - First what was requested by the calling channel
-- - Then preferences in order from sip.conf device config for this peer/user
-- - Then other codecs in capabilities, including video
-- */
-+ add_codec_to_sdp(p, codec, &m_audio, &a_audio, debug, &min_audio_packet_size);
-+ alreadysent |= codec;
-+ }
-
-- /* Prefer the audio codec we were requested to use, first, no matter what
-- Note that p->prefcodec can include video codecs, so mask them out
-- */
-- if (capability & p->prefcodec) {
-- int codec = p->prefcodec & AST_FORMAT_AUDIO_MASK;
-+ /* Start by sending our preferred audio/video codecs */
-+ for (x = 0; x < 32; x++) {
-+ int codec;
-
-- add_codec_to_sdp(p, codec, &m_audio, &a_audio, debug, &min_audio_packet_size);
-- alreadysent |= codec;
-- }
-+ if (!(codec = ast_codec_pref_index(&p->prefs, x)))
-+ break;
-
-- /* Start by sending our preferred audio/video codecs */
-- for (x = 0; x < 32; x++) {
-- int codec;
-+ if (!(capability & codec))
-+ continue;
-
-- if (!(codec = ast_codec_pref_index(&p->prefs, x)))
-- break;
-+ if (alreadysent & codec)
-+ continue;
-
-- if (!(capability & codec))
-- continue;
-+ add_codec_to_sdp(p, codec, &m_audio, &a_audio, debug, &min_audio_packet_size);
-+ alreadysent |= codec;
-+ }
-
-- if (alreadysent & codec)
-- continue;
-+ /* Now send any other common audio and video codecs, and non-codec formats: */
-+ for (x = 1; x <= (needtext ? AST_FORMAT_TEXT_MASK : (needvideo ? AST_FORMAT_VIDEO_MASK : AST_FORMAT_AUDIO_MASK)); x <<= 1) {
-+ if (!(capability & x)) /* Codec not requested */
-+ continue;
-
-- add_codec_to_sdp(p, codec, &m_audio, &a_audio, debug, &min_audio_packet_size);
-- alreadysent |= codec;
-- }
-+ if (alreadysent & x) /* Already added to SDP */
-+ continue;
-
-- /* Now send any other common audio and video codecs, and non-codec formats: */
-- for (x = 1; x <= (needtext ? AST_FORMAT_TEXT_MASK : (needvideo ? AST_FORMAT_VIDEO_MASK : AST_FORMAT_AUDIO_MASK)); x <<= 1) {
-- if (!(capability & x)) /* Codec not requested */
-- continue;
-+ if (x & AST_FORMAT_AUDIO_MASK)
-+ add_codec_to_sdp(p, x, &m_audio, &a_audio, debug, &min_audio_packet_size);
-+ else if (x & AST_FORMAT_VIDEO_MASK)
-+ add_vcodec_to_sdp(p, x, &m_video, &a_video, debug, &min_video_packet_size);
-+ else if (x & AST_FORMAT_TEXT_MASK)
-+ add_tcodec_to_sdp(p, x, &m_text, &a_text, debug, &min_text_packet_size);
-+ }
-
-- if (alreadysent & x) /* Already added to SDP */
-- continue;
-+ /* Now add DTMF RFC2833 telephony-event as a codec */
-+ for (x = 1; x <= AST_RTP_MAX; x <<= 1) {
-+ if (!(p->jointnoncodeccapability & x))
-+ continue;
-
-- if (x & AST_FORMAT_AUDIO_MASK)
-- add_codec_to_sdp(p, x, &m_audio, &a_audio, debug, &min_audio_packet_size);
-- else if (x & AST_FORMAT_VIDEO_MASK)
-- add_vcodec_to_sdp(p, x, &m_video, &a_video, debug, &min_video_packet_size);
-- else if (x & AST_FORMAT_TEXT_MASK)
-- add_tcodec_to_sdp(p, x, &m_text, &a_text, debug, &min_text_packet_size);
-- }
-+ add_noncodec_to_sdp(p, x, &m_audio, &a_audio, debug);
-+ }
-
-- /* Now add DTMF RFC2833 telephony-event as a codec */
-- for (x = 1; x <= AST_RTP_MAX; x <<= 1) {
-- if (!(p->jointnoncodeccapability & x))
-- continue;
-+ ast_debug(3, "-- Done with adding codecs to SDP\n");
-
-- add_noncodec_to_sdp(p, x, &m_audio, &a_audio, debug);
-+ if (!p->owner || !ast_internal_timing_enabled(p->owner))
-+ ast_str_append(&a_audio, 0, "a=silenceSupp:off - - - -\r\n");
-+
-+ if (min_audio_packet_size)
-+ ast_str_append(&a_audio, 0, "a=ptime:%d\r\n", min_audio_packet_size);
-+
-+ /* XXX don't think you can have ptime for video */
-+ if (min_video_packet_size)
-+ ast_str_append(&a_video, 0, "a=ptime:%d\r\n", min_video_packet_size);
-+
-+ /* XXX don't think you can have ptime for text */
-+ if (min_text_packet_size)
-+ ast_str_append(&a_text, 0, "a=ptime:%d\r\n", min_text_packet_size);
-+
-+ if (m_audio->len - m_audio->used < 2 || m_video->len - m_video->used < 2 ||
-+ m_text->len - m_text->used < 2 || a_text->len - a_text->used < 2 ||
-+ a_audio->len - a_audio->used < 2 || a_video->len - a_video->used < 2)
-+ ast_log(LOG_WARNING, "SIP SDP may be truncated due to undersized buffer!!\n");
- }
-
-- ast_debug(3, "-- Done with adding codecs to SDP\n");
-+ if (add_t38) {
-+ /* Our T.38 end is */
-+ ast_udptl_get_us(p->udptl, &udptlsin);
-
-- if (!p->owner || !ast_internal_timing_enabled(p->owner))
-- ast_str_append(&a_audio, 0, "a=silenceSupp:off - - - -\r\n");
-+ /* Determine T.38 UDPTL destination */
-+ if (p->udptlredirip.sin_addr.s_addr) {
-+ udptldest.sin_port = p->udptlredirip.sin_port;
-+ udptldest.sin_addr = p->udptlredirip.sin_addr;
-+ } else {
-+ udptldest.sin_addr = p->ourip.sin_addr;
-+ udptldest.sin_port = udptlsin.sin_port;
-+ }
-
-- if (min_audio_packet_size)
-- ast_str_append(&a_audio, 0, "a=ptime:%d\r\n", min_audio_packet_size);
-+ if (debug)
-+ ast_debug(1, "T.38 UDPTL is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(udptlsin.sin_port));
-
-- /* XXX don't think you can have ptime for video */
-- if (min_video_packet_size)
-- ast_str_append(&a_video, 0, "a=ptime:%d\r\n", min_video_packet_size);
-+ /* We break with the "recommendation" and send our IP, in order that our
-+ peer doesn't have to ast_gethostbyname() us */
-
-- /* XXX don't think you can have ptime for text */
-- if (min_text_packet_size)
-- ast_str_append(&a_text, 0, "a=ptime:%d\r\n", min_text_packet_size);
--
-- if (m_audio->len - m_audio->used < 2 || m_video->len - m_video->used < 2 ||
-- m_text->len - m_text->used < 2 || a_text->len - a_text->used < 2 ||
-- a_audio->len - a_audio->used < 2 || a_video->len - a_video->used < 2)
-- ast_log(LOG_WARNING, "SIP SDP may be truncated due to undersized buffer!!\n");
-+ if (debug) {
-+ ast_debug(1, "Our T38 capability (%d), peer T38 capability (%d), joint capability (%d)\n",
-+ p->t38.capability,
-+ p->t38.peercapability,
-+ p->t38.jointcapability);
-+ }
-
-+ ast_str_append(&m_modem, 0, "m=image %d udptl t38", ntohs(udptldest.sin_port));
-+
-+ if ((p->t38.jointcapability & T38FAX_VERSION) == T38FAX_VERSION_0)
-+ ast_str_append(&a_modem, 0, "a=T38FaxVersion:0\r\n");
-+ if ((p->t38.jointcapability & T38FAX_VERSION) == T38FAX_VERSION_1)
-+ ast_str_append(&a_modem, 0, "a=T38FaxVersion:1\r\n");
-+ if ((x = t38_get_rate(p->t38.jointcapability)))
-+ ast_str_append(&a_modem, 0, "a=T38MaxBitRate:%d\r\n", x);
-+ if ((p->t38.jointcapability & T38FAX_FILL_BIT_REMOVAL) == T38FAX_FILL_BIT_REMOVAL)
-+ ast_str_append(&a_modem, 0, "a=T38FaxFillBitRemoval\r\n");
-+ if ((p->t38.jointcapability & T38FAX_TRANSCODING_MMR) == T38FAX_TRANSCODING_MMR)
-+ ast_str_append(&a_modem, 0, "a=T38FaxTranscodingMMR\r\n");
-+ if ((p->t38.jointcapability & T38FAX_TRANSCODING_JBIG) == T38FAX_TRANSCODING_JBIG)
-+ ast_str_append(&a_modem, 0, "a=T38FaxTranscodingJBIG\r\n");
-+ ast_str_append(&a_modem, 0, "a=T38FaxRateManagement:%s\r\n", (p->t38.jointcapability & T38FAX_RATE_MANAGEMENT_LOCAL_TCF) ? "localTCF" : "transferredTCF");
-+ x = ast_udptl_get_local_max_datagram(p->udptl);
-+ ast_str_append(&a_modem, 0, "a=T38FaxMaxBuffer:%d\r\n", x);
-+ ast_str_append(&a_modem, 0, "a=T38FaxMaxDatagram:%d\r\n", x);
-+ if (p->t38.jointcapability != T38FAX_UDP_EC_NONE)
-+ ast_str_append(&a_modem, 0, "a=T38FaxUdpEC:%s\r\n", (p->t38.jointcapability & T38FAX_UDP_EC_REDUNDANCY) ? "t38UDPRedundancy" : "t38UDPFEC");
-+ }
-+
- if (needaudio)
- ast_str_append(&m_audio, 0, "\r\n");
- if (needvideo)
- ast_str_append(&m_video, 0, "\r\n");
- if (needtext)
- ast_str_append(&m_text, 0, "\r\n");
-+ if (add_t38)
-+ ast_str_append(&m_modem, 0, "\r\n");
-
- len = strlen(version) + strlen(subject) + strlen(owner) +
- strlen(connection) + strlen(session_time);
-@@ -9514,6 +9647,8 @@
- len += m_video->used + a_video->used + strlen(bandwidth) + strlen(hold);
- if (needtext) /* only if text response is appropriate */
- len += m_text->used + a_text->used + strlen(hold);
-+ if (add_t38)
-+ len += m_modem->used + a_modem->used;
-
- add_header(resp, "Content-Type", "application/sdp");
- add_header_contentLength(resp, len);
-@@ -9539,6 +9674,10 @@
- add_line(resp, a_text->str);
- add_line(resp, hold); /* Repeat hold for the text stream */
- }
-+ if (add_t38) {
-+ add_line(resp, m_modem->str);
-+ add_line(resp, a_modem->str);
-+ }
-
- /* Update lastrtprx when we send our SDP */
- p->lastrtprx = p->lastrtptx = time(NULL); /* XXX why both ? */
-@@ -9561,7 +9700,7 @@
- respprep(&resp, p, msg, req);
- if (p->udptl) {
- ast_udptl_offered_from_local(p->udptl, 0);
-- add_t38_sdp(&resp, p);
-+ add_sdp(&resp, p, 0, 0, 1);
- } else
- ast_log(LOG_ERROR, "Can't add SDP to response, since we have no UDPTL session allocated. Call-ID %s\n", p->callid);
- if (retrans && !p->pendinginvite)
-@@ -9596,7 +9735,7 @@
- /*! \brief Used for 200 OK and 183 early media
- \return Will return XMIT_ERROR for network errors.
- */
--static int transmit_response_with_sdp(struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable, int oldsdp)
-+static int transmit_response_with_sdp(struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable, int oldsdp, int rpid)
- {
- struct sip_request resp;
- int seqno;
-@@ -9605,13 +9744,20 @@
- return -1;
- }
- respprep(&resp, p, msg, req);
-+ if (rpid == TRUE) {
-+ add_rpid(&resp, p);
-+ }
- if (p->rtp) {
- if (!p->autoframing && !ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
- ast_debug(1, "Setting framing from config on incoming call\n");
-- ast_rtp_codec_setpref(p->rtp, &p->prefs);
-+ ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, &p->prefs);
- }
-- try_suggested_sip_codec(p);
-- add_sdp(&resp, p, oldsdp);
-+ try_suggested_sip_codec(p);
-+ if (p->t38.state == T38_PEER_DIRECT || p->t38.state == T38_ENABLED) {
-+ add_sdp(&resp, p, oldsdp, TRUE, TRUE);
-+ } else {
-+ add_sdp(&resp, p, oldsdp, TRUE, FALSE);
-+ }
- } else
- ast_log(LOG_ERROR, "Can't add SDP to response, since we have no RTP session allocated. Call-ID %s\n", p->callid);
- if (reliable && !p->pendinginvite)
-@@ -9693,9 +9839,9 @@
- if (p->do_history)
- append_history(p, "ReInv", "Re-invite sent");
- if (t38version)
-- add_t38_sdp(&req, p);
-+ add_sdp(&req, p, oldsdp, FALSE, TRUE);
- else
-- add_sdp(&req, p, oldsdp);
-+ add_sdp(&req, p, oldsdp, TRUE, FALSE);
-
- /* Use this as the basis */
- initialize_initreq(p, &req);
-@@ -9750,85 +9896,6 @@
- }
- }
-
--/*! \brief Build the Remote Party-ID & From using callingpres options */
--static void build_rpid(struct sip_pvt *p)
--{
-- int send_pres_tags = TRUE;
-- const char *privacy=NULL;
-- const char *screen=NULL;
-- char buf[256];
-- const char *clid = default_callerid;
-- const char *clin = NULL;
-- const char *fromdomain;
--
-- if (!ast_strlen_zero(p->rpid) || !ast_strlen_zero(p->rpid_from))
-- return;
--
-- if (p->owner && p->owner->cid.cid_num)
-- clid = p->owner->cid.cid_num;
-- if (p->owner && p->owner->cid.cid_name)
-- clin = p->owner->cid.cid_name;
-- if (ast_strlen_zero(clin))
-- clin = clid;
--
-- switch (p->callingpres) {
-- case AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
-- privacy = "off";
-- screen = "no";
-- break;
-- case AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
-- privacy = "off";
-- screen = "yes";
-- break;
-- case AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
-- privacy = "off";
-- screen = "no";
-- break;
-- case AST_PRES_ALLOWED_NETWORK_NUMBER:
-- privacy = "off";
-- screen = "yes";
-- break;
-- case AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
-- privacy = "full";
-- screen = "no";
-- break;
-- case AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
-- privacy = "full";
-- screen = "yes";
-- break;
-- case AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
-- privacy = "full";
-- screen = "no";
-- break;
-- case AST_PRES_PROHIB_NETWORK_NUMBER:
-- privacy = "full";
-- screen = "yes";
-- break;
-- case AST_PRES_NUMBER_NOT_AVAILABLE:
-- send_pres_tags = FALSE;
-- break;
-- default:
-- ast_log(LOG_WARNING, "Unsupported callingpres (%d)\n", p->callingpres);
-- if ((p->callingpres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED)
-- privacy = "full";
-- else
-- privacy = "off";
-- screen = "no";
-- break;
-- }
--
-- fromdomain = S_OR(p->fromdomain, ast_inet_ntoa(p->ourip.sin_addr));
--
-- snprintf(buf, sizeof(buf), "\"%s\" <sip:%s@%s>", clin, clid, fromdomain);
-- if (send_pres_tags)
-- snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ";privacy=%s;screen=%s", privacy, screen);
-- ast_string_field_set(p, rpid, buf);
--
-- ast_string_field_build(p, rpid_from, "\"%s\" <sip:%s@%s>;tag=%s", clin,
-- S_OR(p->fromuser, clid),
-- fromdomain, p->tag);
--}
--
- /*! \brief Initiate new SIP request to peer/user */
- static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmethod)
- {
-@@ -9864,16 +9931,10 @@
-
- snprintf(p->lastmsg, sizeof(p->lastmsg), "Init: %s", sip_methods[sipmethod].text);
-
-- if (p->owner) {
-- l = p->owner->cid.cid_num;
-- n = p->owner->cid.cid_name;
-+ if (p->owner && (p->owner->connected.id.number_presentation & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED) {
-+ l = p->owner->connected.id.number;
-+ n = p->owner->connected.id.name;
- }
-- /* if we are not sending RPID and user wants his callerid restricted */
-- if (!ast_test_flag(&p->flags[0], SIP_SENDRPID) &&
-- ((p->callingpres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED)) {
-- l = CALLERID_UNKNOWN;
-- n = l;
-- }
- if (ast_strlen_zero(l))
- l = default_callerid;
- if (ast_strlen_zero(n))
-@@ -9961,12 +10022,7 @@
- /* SLD: FIXME?: do Route: here too? I think not cos this is the first request.
- * OTOH, then we won't have anything in p->route anyway */
-
-- /* Build Remote Party-ID and From */
-- if (ast_test_flag(&p->flags[0], SIP_SENDRPID) && (sipmethod == SIP_INVITE)) {
-- build_rpid(p);
-- add_header(req, "From", p->rpid_from);
-- } else
-- add_header(req, "From", from);
-+ add_header(req, "From", from);
- add_header(req, "To", to);
- ast_string_field_set(p, exten, l);
- build_contact(p);
-@@ -9975,10 +10031,46 @@
- add_header(req, "CSeq", tmp_n);
- if (!ast_strlen_zero(global_useragent))
- add_header(req, "User-Agent", global_useragent);
-- if (!ast_strlen_zero(p->rpid))
-- add_header(req, "Remote-Party-ID", p->rpid);
- }
-
-+/*! \brief Add "Diversion" header to outgoing message
-+ *
-+ * We need to add a Diversion header if the owner channel of
-+ * this dialog has redirecting information associated with it.
-+ *
-+ * \param req The request/response to which we will add the header
-+ * \param pvt The sip_pvt which represents the call-leg
-+ * \param apr Redirecting data used to make the diversion header
-+ */
-+static void add_diversion_header(struct sip_request *req, struct sip_pvt *pvt)
-+{
-+ const char *diverting_number;
-+ const char *diverting_name;
-+ const char *reason;
-+ char header_text[256];
-+
-+ if (!pvt->owner) {
-+ return;
-+ }
-+
-+ diverting_number = pvt->owner->cid.cid_rdnis;
-+ diverting_name = pvt->owner->redirecting.from.name;
-+ reason = sip_reason_code_to_str(pvt->owner->redirecting.reason);
-+
-+ if (ast_strlen_zero(diverting_number)) {
-+ return;
-+ }
-+
-+ /* We at least have a number to place in the Diversion header, which is enough */
-+ if (ast_strlen_zero(diverting_name)) {
-+ snprintf(header_text, sizeof(header_text), "<sip:%s@%s>;reason=%s", diverting_number, ast_inet_ntoa(pvt->ourip.sin_addr), reason);
-+ } else {
-+ snprintf(header_text, sizeof(header_text), "\"%s\" <sip:%s@%s>;reason=%s", diverting_name, diverting_number, ast_inet_ntoa(pvt->ourip.sin_addr), reason);
-+ }
-+
-+ add_header(req, "Diversion", header_text);
-+}
-+
- /*! \brief Build REFER/INVITE/OPTIONS/SUBSCRIBE message and transmit it
- \param init 0 = Prepare request within dialog, 1= prepare request, new branch, 2= prepare new request and new dialog. do_proxy_auth calls this with init!=2
- \param p sip_pvt structure
-@@ -10097,13 +10189,18 @@
-
- ast_channel_unlock(chan);
- }
-+ if ((sipmethod == SIP_INVITE || sipmethod == SIP_UPDATE) && ast_test_flag(&p->flags[0], SIP_SENDRPID))
-+ add_rpid(&req, p);
-+ if (sipmethod == SIP_INVITE) {
-+ add_diversion_header(&req, p);
-+ }
- if (sdp) {
-- if (p->udptl && (p->t38.state == T38_LOCAL_DIRECT || p->t38.state == T38_LOCAL_REINVITE)) {
-+ if (p->udptl && p->t38.state == T38_LOCAL_REINVITE) {
- ast_udptl_offered_from_local(p->udptl, 1);
- ast_debug(1, "T38 is in state %d on channel %s\n", p->t38.state, p->owner ? p->owner->name : "<none>");
-- add_t38_sdp(&req, p);
-+ add_sdp(&req, p, FALSE, FALSE, TRUE);
- } else if (p->rtp)
-- add_sdp(&req, p, FALSE);
-+ add_sdp(&req, p, FALSE, TRUE, FALSE);
- } else {
- if (!p->notify_headers) {
- add_header_contentLength(&req, 0);
-@@ -10579,6 +10676,80 @@
- " *Variable: <name>=<value> At least one variable pair must be specified.\n"
- " ActionID: <id> Action ID for this transaction. Will be returned.\n";
-
-+/*! \brief Send a provisional response indicating that a call was redirected
-+ */
-+static void update_redirecting(struct sip_pvt *p, const void *data, size_t datalen)
-+{
-+ struct sip_request resp;
-+
-+ if (p->owner->_state == AST_STATE_UP || ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
-+ return;
-+ }
-+
-+ if (!ast_strlen_zero(p->owner->redirecting.to.number)) {
-+ ast_string_field_set(p, exten, p->owner->redirecting.to.number);
-+ build_contact(p);
-+ }
-+ respprep(&resp, p, "181 Call is being forwarded", &p->initreq);
-+ add_diversion_header(&resp, p);
-+ send_response(p, &resp, XMIT_UNRELIABLE, 0);
-+}
-+
-+/*! \brief Notify peer that the connected line has changed */
-+static void update_connectedline(struct sip_pvt *p, const void *data, size_t datalen)
-+{
-+
-+ if (!ast_test_flag(&p->flags[0], SIP_SENDRPID))
-+ return;
-+ if (ast_strlen_zero(p->owner->connected.id.number))
-+ return;
-+
-+ append_history(p, "ConnectedLine", "%s party is now %s <%s>", ast_test_flag(&p->flags[0], SIP_OUTGOING) ? "Calling" : "Called", p->owner->connected.id.name, p->owner->connected.id.number);
-+
-+ if (p->owner->_state == AST_STATE_UP || ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
-+ struct sip_request req;
-+
-+ if (p->invitestate == INV_CONFIRMED || p->invitestate == INV_TERMINATED) {
-+ reqprep(&req, p, ast_test_flag(&p->flags[0], SIP_REINVITE_UPDATE) ? SIP_UPDATE : SIP_INVITE, 0, 1);
-+
-+ add_header(&req, "Allow", ALLOWED_METHODS);
-+ add_header(&req, "Supported", SUPPORTED_EXTENSIONS);
-+ add_rpid(&req, p);
-+ add_sdp(&req, p, FALSE, TRUE, FALSE);
-+
-+ initialize_initreq(p, &req);
-+ p->lastinvite = p->ocseq;
-+ ast_set_flag(&p->flags[0], SIP_OUTGOING);
-+ send_request(p, &req, XMIT_CRITICAL, p->ocseq);
-+ } else {
-+ reqprep(&req, p, SIP_UPDATE, 0, 1);
-+ add_rpid(&req, p);
-+ add_header_contentLength(&req, 0);
-+ send_request(p, &req, XMIT_CRITICAL, p->ocseq);
-+ }
-+ } else {
-+ if (ast_test_flag(&p->flags[1], SIP_PAGE2_RPID_IMMEDIATE)) {
-+ struct sip_request resp;
-+
-+ if ((p->owner->_state == AST_STATE_RING) && !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT)) {
-+ respprep(&resp, p, "180 Ringing", &p->initreq);
-+ add_rpid(&resp, p);
-+ send_response(p, &resp, XMIT_UNRELIABLE, 0);
-+ ast_set_flag(&p->flags[0], SIP_RINGING);
-+ } else if (p->owner->_state == AST_STATE_RINGING) {
-+ respprep(&resp, p, "183 Session Progress", &p->initreq);
-+ add_rpid(&resp, p);
-+ send_response(p, &resp, XMIT_UNRELIABLE, 0);
-+ ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
-+ } else {
-+ ast_log(LOG_DEBUG, "Unable able to send update to '%s' in state '%s'\n", p->owner->name, ast_state2str(p->owner->_state));
-+ }
-+ } else {
-+ ast_set_flag(&p->flags[1], SIP_PAGE2_CONNECTLINEUPDATE_PEND);
-+ }
-+ }
-+}
-+
- static const struct _map_x_s regstatestrings[] = {
- { REG_STATE_FAILED, "Failed" },
- { REG_STATE_UNREGISTERED, "Unregistered"},
-@@ -10606,7 +10777,7 @@
- static int sip_reregister(const void *data)
- {
- /* if we are here, we know that we need to reregister. */
-- struct sip_registry *r= (struct sip_registry *) data;
-+ struct sip_registry *r = (struct sip_registry *) data;
-
- /* if we couldn't get a reference to the registry object, punt */
- if (!r)
-@@ -11916,10 +12087,96 @@
- /*! \brief Send a fake 401 Unauthorized response when the administrator
- wants to hide the names of local devices from fishers
- */
--static void transmit_fake_auth_response(struct sip_pvt *p, struct sip_request *req, enum xmittype reliable)
-+static void transmit_fake_auth_response(struct sip_pvt *p, int sipmethod, struct sip_request *req, enum xmittype reliable)
- {
-- ast_string_field_build(p, randdata, "%08lx", ast_random()); /* Create nonce for challenge */
-- transmit_response_with_auth(p, "401 Unauthorized", req, p->randdata, reliable, "WWW-Authenticate", 0);
-+ /* We have to emulate EXACTLY what we'd get with a good peer
-+ * and a bad password, or else we leak information. */
-+ const char *response = "407 Proxy Authentication Required";
-+ const char *reqheader = "Proxy-Authorization";
-+ const char *respheader = "Proxy-Authenticate";
-+ const char *authtoken;
-+ struct ast_str *buf;
-+ char *c;
-+
-+ /* table of recognised keywords, and their value in the digest */
-+ enum keys { K_NONCE, K_LAST };
-+ struct x {
-+ const char *key;
-+ const char *s;
-+ } *i, keys[] = {
-+ [K_NONCE] = { "nonce=", "" },
-+ [K_LAST] = { NULL, NULL}
-+ };
-+
-+ if (sipmethod == SIP_REGISTER || sipmethod == SIP_SUBSCRIBE) {
-+ response = "401 Unauthorized";
-+ reqheader = "Authorization";
-+ respheader = "WWW-Authenticate";
-+ }
-+ authtoken = get_header(req, reqheader);
-+ if (req->ignore && !ast_strlen_zero(p->randdata) && ast_strlen_zero(authtoken)) {
-+ /* This is a retransmitted invite/register/etc, don't reconstruct authentication
-+ * information */
-+ transmit_response_with_auth(p, response, req, p->randdata, 0, respheader, 0);
-+ /* Schedule auto destroy in 32 seconds (according to RFC 3261) */
-+ sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
-+ return;
-+ } else if (ast_strlen_zero(p->randdata) || ast_strlen_zero(authtoken)) {
-+ /* We have no auth, so issue challenge and request authentication */
-+ ast_string_field_build(p, randdata, "%08lx", ast_random()); /* Create nonce for challenge */
-+ transmit_response_with_auth(p, response, req, p->randdata, 0, respheader, 0);
-+ /* Schedule auto destroy in 32 seconds */
-+ sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
-+ return;
-+ }
-+
-+ if (!(buf = ast_str_thread_get(&check_auth_buf, CHECK_AUTH_BUF_INITLEN))) {
-+ transmit_response(p, "403 Forbidden (Bad auth)", &p->initreq);
-+ return;
-+ }
-+
-+ /* Make a copy of the response and parse it */
-+ if (ast_str_set(&buf, 0, "%s", authtoken) == AST_DYNSTR_BUILD_FAILED) {
-+ transmit_response(p, "403 Forbidden (Bad auth)", &p->initreq);
-+ return;
-+ }
-+
-+ c = buf->str;
-+
-+ while (c && *(c = ast_skip_blanks(c))) { /* lookup for keys */
-+ for (i = keys; i->key != NULL; i++) {
-+ const char *separator = ","; /* default */
-+
-+ if (strncasecmp(c, i->key, strlen(i->key)) != 0) {
-+ continue;
-+ }
-+ /* Found. Skip keyword, take text in quotes or up to the separator. */
-+ c += strlen(i->key);
-+ if (*c == '"') { /* in quotes. Skip first and look for last */
-+ c++;
-+ separator = "\"";
-+ }
-+ i->s = c;
-+ strsep(&c, separator);
-+ break;
-+ }
-+ if (i->key == NULL) { /* not found, jump after space or comma */
-+ strsep(&c, " ,");
-+ }
-+ }
-+
-+ /* Verify nonce from request matches our nonce. If not, send 401 with new nonce */
-+ if (strcasecmp(p->randdata, keys[K_NONCE].s)) {
-+ if (!req->ignore) {
-+ ast_string_field_build(p, randdata, "%08lx", ast_random());
-+ }
-+ transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, FALSE);
-+
-+ /* Schedule auto destroy in 32 seconds */
-+ sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
-+ } else {
-+ transmit_response(p, "403 Forbidden (Bad auth)", &p->initreq);
-+ }
- }
-
- /*!
-@@ -12011,12 +12268,6 @@
- }
-
- if (peer) {
-- /*! \todo OEJ Remove this - there's never RTP in a REGISTER dialog... */
-- /* Set Frame packetization */
-- if (p->rtp) {
-- ast_rtp_codec_setpref(p->rtp, &peer->prefs);
-- p->autoframing = peer->autoframing;
-- }
- if (!peer->host_dynamic) {
- ast_log(LOG_ERROR, "Peer '%s' is trying to register, but not configured as host=dynamic\n", peer->name);
- res = AUTH_PEER_NOT_DYNAMIC;
-@@ -12095,6 +12346,14 @@
- }
- }
- }
-+ if (!peer && sip_cfg.alwaysauthreject) {
-+ /* If we found a peer, we transmit a 100 Trying. Therefore, if we're
-+ * trying to avoid leaking information, we MUST also transmit the same
-+ * response when we DON'T find a peer. */
-+ transmit_response(p, "100 Trying", req);
-+ /* Insert a fake delay between the 100 and the subsequent failure. */
-+ sched_yield();
-+ }
- if (!res) {
- ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", peer->name);
- }
-@@ -12108,7 +12367,7 @@
- name, ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
- break;
- case AUTH_USERNAME_MISMATCH:
-- /* Username and digest username does not match.
-+ /* Username and digest username does not match.
- Asterisk uses the From: username for authentication. We need the
- devices to use the same authentication user name until we support
- proper authentication by digest auth name */
-@@ -12121,7 +12380,12 @@
- case AUTH_PEER_NOT_DYNAMIC:
- case AUTH_ACL_FAILED:
- if (sip_cfg.alwaysauthreject) {
-- transmit_fake_auth_response(p, &p->initreq, XMIT_UNRELIABLE);
-+ transmit_fake_auth_response(p, SIP_REGISTER, &p->initreq, XMIT_UNRELIABLE);
-+ if (global_authfailureevents) {
-+ manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Rejected\r\nCause: %s\r\nAddress: %s\r\nPort: %d\r\n",
-+ name, res == AUTH_PEER_NOT_DYNAMIC ? "AUTH_PEER_NOT_DYNAMIC" : "URI_NOT_FOUND",
-+ ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
-+ }
- } else {
- /* URI not found */
- if (res == AUTH_PEER_NOT_DYNAMIC) {
-@@ -12178,23 +12442,199 @@
- }
- }
-
-+/*! \brief Parse the parts of the P-Asserted-Identity header
-+ * on an incoming packet. Returns 1 if a valid header is found
-+ * and it is different from the current caller id.
-+ */
-+static int get_pai(struct sip_pvt *p, struct sip_request *req)
-+{
-+ char pai[256];
-+ char privacy[64];
-+ char *cid_num = "";
-+ char *cid_name = "";
-+ int callingpres = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
-+ char *start = NULL, *end = NULL;
-+
-+ ast_copy_string(pai, get_header(req, "P-Asserted-Identity"), sizeof(pai));
-+
-+ if (ast_strlen_zero(pai)) {
-+ return 0;
-+ }
-+
-+ start = pai;
-+ if (*start == '"') {
-+ *start++ = '\0';
-+ end = strchr(start, '"');
-+ if (!end)
-+ return 0;
-+ *end++ = '\0';
-+ cid_name = start;
-+ start = ast_skip_blanks(end);
-+ }
-+
-+ if (*start != '<')
-+ return 0;
-+ *start++ = '\0';
-+ end = strchr(start, '@');
-+ if (!end)
-+ return 0;
-+ *end++ = '\0';
-+ if (!strncasecmp(start, "anonymous@anonymous.invalid", 27)) {
-+ callingpres = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
-+ /*XXX Assume no change in cid_num. Perhaps it should be
-+ * blanked?
-+ */
-+ cid_num = (char *)p->cid_num;
-+ } else if (!strncasecmp(start, "sip:", 4)) {
-+ cid_num = start + 4;
-+ if (ast_is_shrinkable_phonenumber(cid_num))
-+ ast_shrink_phone_number(cid_num);
-+ start = end;
-+
-+ end = strchr(start, '>');
-+ if (!end)
-+ return 0;
-+ *end = '\0';
-+ } else {
-+ return 0;
-+ }
-+
-+ ast_copy_string(privacy, get_header(req, "Privacy"), sizeof(privacy));
-+ if (!ast_strlen_zero(privacy) && strncmp(privacy, "id", 2)) {
-+ callingpres = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
-+ }
-+
-+ /* Only return true if the supplied caller id is different */
-+ if (!strcasecmp(p->cid_num, cid_num) && !strcasecmp(p->cid_name, cid_name) && p->callingpres == callingpres)
-+ return 0;
-+
-+ ast_string_field_set(p, cid_num, cid_num);
-+ ast_string_field_set(p, cid_name, cid_name);
-+ p->callingpres = callingpres;
-+
-+ if (p->owner) {
-+ ast_set_callerid(p->owner, cid_num, cid_name, NULL);
-+ p->owner->cid.cid_pres = callingpres;
-+ }
-+
-+ return 1;
-+}
-+
-+/*! \brief Get name, number and presentation from remote party id header,
-+ * returns true if a valid header was found and it was different from the
-+ * current caller id.
-+ */
-+static int get_rpid(struct sip_pvt *p, struct sip_request *oreq)
-+{
-+ char tmp[256];
-+ struct sip_request *req;
-+ char *cid_num = "";
-+ char *cid_name = "";
-+ int callingpres = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
-+ char *privacy = "";
-+ char *screen = "";
-+ char *start, *end;
-+
-+ if (!ast_test_flag(&p->flags[0], SIP_TRUSTRPID))
-+ return 0;
-+ req = oreq;
-+ if (!req)
-+ req = &p->initreq;
-+ ast_copy_string(tmp, get_header(req, "Remote-Party-ID"), sizeof(tmp));
-+ if (ast_strlen_zero(tmp)) {
-+ return get_pai(p, req);
-+ }
-+
-+ start = tmp;
-+ if (*start == '"') {
-+ *start++ = '\0';
-+ end = strchr(start, '"');
-+ if (!end)
-+ return 0;
-+ *end++ = '\0';
-+ cid_name = start;
-+ start = ast_skip_blanks(end);
-+ }
-+
-+ if (*start != '<')
-+ return 0;
-+ *start++ = '\0';
-+ end = strchr(start, '@');
-+ if (!end)
-+ return 0;
-+ *end++ = '\0';
-+ if (strncasecmp(start, "sip:", 4))
-+ return 0;
-+ cid_num = start + 4;
-+ if (ast_is_shrinkable_phonenumber(cid_num))
-+ ast_shrink_phone_number(cid_num);
-+ start = end;
-+
-+ end = strchr(start, '>');
-+ if (!end)
-+ return 0;
-+ *end++ = '\0';
-+ if (*end) {
-+ start = end;
-+ if (*start != ';')
-+ return 0;
-+ *start++ = '\0';
-+ while (!ast_strlen_zero(start)) {
-+ end = strchr(start, ';');
-+ if (end)
-+ *end++ = '\0';
-+ if (!strncasecmp(start, "privacy=", 8))
-+ privacy = start + 8;
-+ else if (!strncasecmp(start, "screen=", 7))
-+ screen = start + 7;
-+ start = end;
-+ }
-+
-+ if (!strcasecmp(privacy, "full")) {
-+ if (!strcasecmp(screen, "yes"))
-+ callingpres = AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN;
-+ else if (!strcasecmp(screen, "no"))
-+ callingpres = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
-+ } else {
-+ if (!strcasecmp(screen, "yes"))
-+ callingpres = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
-+ else if (!strcasecmp(screen, "no"))
-+ callingpres = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
-+ }
-+ }
-+
-+ /* Only return true if the supplied caller id is different */
-+ if (!strcasecmp(p->cid_num, cid_num) && !strcasecmp(p->cid_name, cid_name) && p->callingpres == callingpres)
-+ return 0;
-+
-+ ast_string_field_set(p, cid_num, cid_num);
-+ ast_string_field_set(p, cid_name, cid_name);
-+ p->callingpres = callingpres;
-+
-+ if (p->owner) {
-+ ast_set_callerid(p->owner, cid_num, cid_name, NULL);
-+ p->owner->cid.cid_pres = callingpres;
-+ }
-+
-+ return 1;
-+}
-+
- /*! \brief Get referring dnis */
--static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq)
-+static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq, char **name, char **number, int *reason)
- {
-- char tmp[256], *exten, *rexten, *rdomain;
-- char *params, *reason = NULL;
-+ char tmp[256], *exten, *rexten, *rdomain, *rname = NULL;
-+ char *params, *reason_param = NULL;
- struct sip_request *req;
--
-+
- req = oreq ? oreq : &p->initreq;
-
- ast_copy_string(tmp, get_header(req, "Diversion"), sizeof(tmp));
- if (ast_strlen_zero(tmp))
-- return 0;
-+ return -1;
-
-- /*! \todo This function does not take user-parameters into consideration.
-- First look for @, then start looking for ; to find uri-parameters.
-- */
-- params = strchr(tmp, ';');
-+ if ((params = strchr(tmp, '>'))) {
-+ params = strchr(params, ';');
-+ }
-
- exten = get_in_brackets(tmp);
- if (!strncasecmp(exten, "sip:", 4)) {
-@@ -12213,16 +12653,16 @@
- while (*params == ';' || *params == ' ')
- params++;
- /* Check if we have a reason parameter */
-- if ((reason = strcasestr(params, "reason="))) {
-- reason+=7;
-+ if ((reason_param = strcasestr(params, "reason="))) {
-+ reason_param+=7;
- /* Remove enclosing double-quotes */
-- if (*reason == '"')
-- ast_strip_quoted(reason, "\"", "\"");
-- if (!ast_strlen_zero(reason)) {
-- sip_set_redirstr(p, reason);
-+ if (*reason_param == '"')
-+ ast_strip_quoted(reason_param, "\"", "\"");
-+ if (!ast_strlen_zero(reason_param)) {
-+ sip_set_redirstr(p, reason_param);
- if (p->owner) {
- pbx_builtin_setvar_helper(p->owner, "__PRIREDIRECTREASON", p->redircause);
-- pbx_builtin_setvar_helper(p->owner, "__SIPREDIRECTREASON", reason);
-+ pbx_builtin_setvar_helper(p->owner, "__SIPREDIRECTREASON", reason_param);
- }
- }
- }
-@@ -12230,14 +12670,33 @@
-
- rdomain = exten;
- rexten = strsep(&rdomain, "@"); /* trim anything after @ */
-- if (p->owner)
-+ if (p->owner)
- pbx_builtin_setvar_helper(p->owner, "__SIPRDNISDOMAIN", rdomain);
-
- if (sip_debug_test_pvt(p))
-- ast_verbose("RDNIS for this call is is %s (reason %s)\n", exten, reason ? reason : "");
-+ ast_verbose("RDNIS for this call is %s (reason %s)\n", exten, reason ? reason_param : "");
-
-- ast_string_field_set(p, rdnis, rexten);
-+ /*ast_string_field_set(p, rdnis, rexten);*/
-
-+ if (*tmp == '\"') {
-+ char *end_quote;
-+ rname = tmp + 1;
-+ end_quote = strchr(rname, '\"');
-+ *end_quote = '\0';
-+ }
-+
-+ if (number) {
-+ *number = ast_strdup(rexten);
-+ }
-+
-+ if (name && rname) {
-+ *name = ast_strdup(rname);
-+ }
-+
-+ if (reason && !ast_strlen_zero(reason_param)) {
-+ *reason = sip_reason_str_to_code(reason_param);
-+ }
-+
- return 0;
- }
-
-@@ -12849,58 +13308,12 @@
- return output;
- }
-
--/*! \brief Get caller id number from Remote-Party-ID header field
-- * Returns true if number should be restricted (privacy setting found)
-- * output is set to NULL if no number found
-- */
--static int get_rpid_num(const char *input, char *output, int maxlen)
--{
-- char *start;
-- char *end;
-
-- start = strchr(input, ':');
-- if (!start) {
-- output[0] = '\0';
-- return 0;
-- }
-- start++;
--
-- /* we found "number" */
-- ast_copy_string(output, start, maxlen);
-- output[maxlen-1] = '\0';
--
-- end = strchr(output, '@');
-- if (end)
-- *end = '\0';
-- else
-- output[0] = '\0';
-- if (strstr(input, "privacy=full") || strstr(input, "privacy=uri"))
-- return AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
--
-- return 0;
--}
--
--
--/*! \brief helper function for check_{user|peer}_ok() */
--static void replace_cid(struct sip_pvt *p, const char *rpid_num, const char *calleridname)
--{
-- /* replace callerid if rpid found, and not restricted */
-- if (!ast_strlen_zero(rpid_num) && ast_test_flag(&p->flags[0], SIP_TRUSTRPID)) {
-- char *tmp = ast_strdupa(rpid_num); /* XXX the copy can be done later */
-- if (!ast_strlen_zero(calleridname))
-- ast_string_field_set(p, cid_name, calleridname);
-- if (ast_is_shrinkable_phonenumber(tmp))
-- ast_shrink_phone_number(tmp);
-- ast_string_field_set(p, cid_num, tmp);
-- }
--}
--
- /*! \brief Validate device authentication */
- static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
- struct sip_request *req, int sipmethod, struct sockaddr_in *sin,
- struct sip_peer **authpeer,
-- enum xmittype reliable,
-- char *rpid_num, char *calleridname, char *uri2)
-+ enum xmittype reliable, char *calleridname, char *uri2)
- {
- enum check_auth_result res;
- int debug=sip_debug_test_addr(sin);
-@@ -12935,7 +13348,7 @@
- /* XXX what about p->prefs = peer->prefs; ? */
- /* Set Frame packetization */
- if (p->rtp) {
-- ast_rtp_codec_setpref(p->rtp, &peer->prefs);
-+ ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, &peer->prefs);
- p->autoframing = peer->autoframing;
- }
-
-@@ -12948,7 +13361,6 @@
- if (p->sipoptions)
- peer->sipoptions = p->sipoptions;
-
-- replace_cid(p, rpid_num, calleridname);
- do_setnat(p, ast_test_flag(&p->flags[0], SIP_NAT_ROUTE));
-
- ast_string_field_set(p, peersecret, peer->secret);
-@@ -12957,6 +13369,7 @@
- ast_string_field_set(p, mohinterpret, peer->mohinterpret);
- ast_string_field_set(p, mohsuggest, peer->mohsuggest);
- ast_string_field_set(p, parkinglot, peer->parkinglot);
-+ ast_string_field_set(p, engine, peer->engine);
- if (peer->callingpres) /* Peer calling pres setting will override RPID */
- p->callingpres = peer->callingpres;
- if (peer->maxms && peer->lastms)
-@@ -13000,14 +13413,18 @@
- /* XXX this takes the name from the caller... can we override ? */
- ast_string_field_set(p, authname, peer->username);
- }
-- if (!ast_strlen_zero(peer->cid_num)) {
-- char *tmp = ast_strdupa(peer->cid_num);
-- if (ast_is_shrinkable_phonenumber(tmp))
-- ast_shrink_phone_number(tmp);
-- ast_string_field_set(p, cid_num, tmp);
-+ if (!get_rpid(p, req)) {
-+ if (!ast_strlen_zero(peer->cid_num)) {
-+ char *tmp = ast_strdupa(peer->cid_num);
-+ if (ast_is_shrinkable_phonenumber(tmp))
-+ ast_shrink_phone_number(tmp);
-+ ast_string_field_set(p, cid_num, tmp);
-+ }
-+ if (!ast_strlen_zero(peer->cid_name))
-+ ast_string_field_set(p, cid_name, peer->cid_name);
-+ if (peer->callingpres)
-+ p->callingpres = peer->callingpres;
- }
-- if (!ast_strlen_zero(peer->cid_name))
-- ast_string_field_set(p, cid_name, peer->cid_name);
- ast_string_field_set(p, fullcontact, peer->fullcontact);
- if (!ast_strlen_zero(peer->context))
- ast_string_field_set(p, context, peer->context);
-@@ -13024,17 +13441,6 @@
- if (p->peercapability)
- p->jointcapability &= p->peercapability;
- p->maxcallbitrate = peer->maxcallbitrate;
-- if (!ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT_ALWAYS) &&
-- (!ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT) ||
-- !(p->capability & AST_FORMAT_VIDEO_MASK)) &&
-- p->vrtp) {
-- ast_rtp_destroy(p->vrtp);
-- p->vrtp = NULL;
-- }
-- if ((!ast_test_flag(&p->flags[1], SIP_PAGE2_TEXTSUPPORT) || !(p->capability & AST_FORMAT_TEXT_MASK)) && p->trtp) {
-- ast_rtp_destroy(p->trtp);
-- p->trtp = NULL;
-- }
- if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) ||
- (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO))
- p->noncodeccapability |= AST_RTP_DTMF;
-@@ -13043,6 +13449,12 @@
- p->jointnoncodeccapability = p->noncodeccapability;
- if (p->t38.peercapability)
- p->t38.jointcapability &= p->t38.peercapability;
-+ if (!dialog_initialize_rtp(p)) {
-+ ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, &peer->prefs);
-+ p->autoframing = peer->autoframing;
-+ } else {
-+ res = AUTH_RTP_FAILED;
-+ }
- }
- unref_peer(peer, "check_peer_ok: unref_peer: tossing temp ptr to peer from find_peer");
- return res;
-@@ -13062,8 +13474,6 @@
- char *dummy; /* dummy return value for parse_uri */
- char *domain; /* dummy return value for parse_uri */
- char *of, *of2;
-- char rpid_num[50];
-- const char *rpid;
- enum check_auth_result res;
- char calleridname[50];
- char *uri2 = ast_strdupa(uri);
-@@ -13079,11 +13489,6 @@
- if (calleridname[0])
- ast_string_field_set(p, cid_name, calleridname);
-
-- rpid = get_header(req, "Remote-Party-ID");
-- memset(rpid_num, 0, sizeof(rpid_num));
-- if (!ast_strlen_zero(rpid))
-- p->callingpres = get_rpid_num(rpid, rpid_num, sizeof(rpid_num));
--
- of = get_in_brackets(from);
- if (ast_strlen_zero(p->exten)) {
- char *t = uri2;
-@@ -13157,14 +13562,18 @@
- }
-
- res = check_peer_ok(p, of, req, sipmethod, sin,
-- authpeer, reliable, rpid_num, calleridname, uri2);
-+ authpeer, reliable, calleridname, uri2);
- if (res != AUTH_DONT_KNOW)
- return res;
-
- /* Finally, apply the guest policy */
- if (sip_cfg.allowguest) {
-- replace_cid(p, rpid_num, calleridname);
-- res = AUTH_SUCCESSFUL;
-+ get_rpid(p, req);
-+ if (!dialog_initialize_rtp(p)) {
-+ res = AUTH_SUCCESSFUL;
-+ } else {
-+ res = AUTH_RTP_FAILED;
-+ }
- } else if (sip_cfg.alwaysauthreject)
- res = AUTH_FAKE_AUTH; /* reject with fake authorization request */
- else
-@@ -13961,7 +14370,20 @@
- */
- return 0;
- }
--
-+
-+ /* We absolutely cannot destroy the rtp struct while a bridge is active or we WILL crash */
-+ if (dialog->rtp && ast_rtp_instance_get_bridged(dialog->rtp)) {
-+ ast_debug(2, "Bridge still active. Delaying destroy of SIP dialog '%s' Method: %s\n", dialog->callid, sip_methods[dialog->method].text);
-+ sip_pvt_unlock(dialog);
-+ return 0;
-+ }
-+
-+ if (dialog->vrtp && ast_rtp_instance_get_bridged(dialog->vrtp)) {
-+ ast_debug(2, "Bridge still active. Delaying destroy of SIP dialog '%s' Method: %s\n", dialog->callid, sip_methods[dialog->method].text);
-+ sip_pvt_unlock(dialog);
-+ return 0;
-+ }
-+
- /* Check RTP timeouts and kill calls if we have a timeout set and do not get RTP */
- check_rtp_timeout(dialog, *t);
-
-@@ -13970,13 +14392,13 @@
- - if that's the case, wait with destruction */
- if (dialog->needdestroy && !dialog->packets && !dialog->owner) {
- /* We absolutely cannot destroy the rtp struct while a bridge is active or we WILL crash */
-- if (dialog->rtp && ast_rtp_get_bridged(dialog->rtp)) {
-+ if (dialog->rtp && ast_rtp_instance_get_bridged(dialog->rtp)) {
- ast_debug(2, "Bridge still active. Delaying destruction of SIP dialog '%s' Method: %s\n", dialog->callid, sip_methods[dialog->method].text);
- sip_pvt_unlock(dialog);
- return 0;
- }
-
-- if (dialog->vrtp && ast_rtp_get_bridged(dialog->vrtp)) {
-+ if (dialog->vrtp && ast_rtp_instance_get_bridged(dialog->vrtp)) {
- ast_debug(2, "Bridge still active. Delaying destroy of SIP dialog '%s' Method: %s\n", dialog->callid, sip_methods[dialog->method].text);
- sip_pvt_unlock(dialog);
- return 0;
-@@ -14466,6 +14888,7 @@
- ast_cli(fd, " Sess-Refresh : %s\n", strefresher2str(peer->stimer.st_ref));
- ast_cli(fd, " Sess-Expires : %d secs\n", peer->stimer.st_max_se);
- ast_cli(fd, " Min-Sess : %d secs\n", peer->stimer.st_min_se);
-+ ast_cli(fd, " RTP Engine : %s\n", peer->engine);
- ast_cli(fd, "\n");
- peer = unref_peer(peer, "sip_show_peer: unref_peer: done with peer ptr");
- } else if (peer && type == 1) { /* manager listing */
-@@ -14513,6 +14936,7 @@
- astman_append(s, "SIP-Sess-Refresh: %s\r\n", strefresher2str(peer->stimer.st_ref));
- astman_append(s, "SIP-Sess-Expires: %d\r\n", peer->stimer.st_max_se);
- astman_append(s, "SIP-Sess-Min: %d\r\n", peer->stimer.st_min_se);
-+ astman_append(s, "SIP-RTP-Engine: %s\r\n", peer->engine);
-
- /* - is enumerated */
- astman_append(s, "SIP-DTMFmode: %s\r\n", dtmfmode2str(ast_test_flag(&peer->flags[0], SIP_DTMF)));
-@@ -14645,6 +15069,7 @@
- ast_cli(a->fd, " Sess-Refresh : %s\n", strefresher2str(user->stimer.st_ref));
- ast_cli(a->fd, " Sess-Expires : %d secs\n", user->stimer.st_max_se);
- ast_cli(a->fd, " Sess-Min-SE : %d secs\n", user->stimer.st_min_se);
-+ ast_cli(a->fd, " RTP Engine : %s\n", user->engine);
-
- ast_cli(a->fd, " Codec Order : (");
- print_codec_to_cli(a->fd, &user->prefs);
-@@ -14799,11 +15224,10 @@
- #define FORMAT2 "%-15.15s %-11.11s %-8.8s %-10.10s %-10.10s (%-2.2s) %-6.6s %-10.10s %-10.10s ( %%) %-6.6s\n"
- #define FORMAT "%-15.15s %-11.11s %-8.8s %-10.10u%-1.1s %-10.10u (%-2.2u%%) %-6.6u %-10.10u%-1.1s %-10.10u (%-2.2u%%) %-6.6u\n"
- struct sip_pvt *cur = __cur;
-- unsigned int rxcount;
-- unsigned int txcount;
-+ struct ast_rtp_instance_stats stats;
- char durbuf[10];
-- int duration;
-- int durh, durm, durs;
-+ int duration;
-+ int durh, durm, durs;
- struct ast_channel *c = cur->owner;
- struct __show_chan_arg *arg = __arg;
- int fd = arg->fd;
-@@ -14817,10 +15241,9 @@
- ast_cli(fd, "%-15.15s %-11.11s (inv state: %s) -- %s\n", ast_inet_ntoa(cur->sa.sin_addr), cur->callid, invitestate2string[cur->invitestate].desc, "-- No RTP active");
- return 0; /* don't care, we scan all channels */
- }
-- rxcount = ast_rtp_get_qosvalue(cur->rtp, AST_RTP_RXCOUNT);
-- txcount = ast_rtp_get_qosvalue(cur->rtp, AST_RTP_TXCOUNT);
-
-- /* Find the duration of this channel */
-+ ast_rtp_instance_get_stats(cur->rtp, &stats, AST_RTP_INSTANCE_STAT_ALL);
-+
- if (c && c->cdr && !ast_tvzero(c->cdr->start)) {
- duration = (int)(ast_tvdiff_ms(ast_tvnow(), c->cdr->start) / 1000);
- durh = duration / 3600;
-@@ -14830,21 +15253,21 @@
- } else {
- durbuf[0] = '\0';
- }
-- /* Print stats for every call with RTP */
-+
- ast_cli(fd, FORMAT,
- ast_inet_ntoa(cur->sa.sin_addr),
- cur->callid,
- durbuf,
-- rxcount > (unsigned int) 100000 ? (unsigned int) (rxcount)/(unsigned int) 1000 : rxcount,
-- rxcount > (unsigned int) 100000 ? "K":" ",
-- ast_rtp_get_qosvalue(cur->rtp, AST_RTP_RXPLOSS),
-- rxcount > ast_rtp_get_qosvalue(cur->rtp, AST_RTP_RXPLOSS) ? (unsigned int) (ast_rtp_get_qosvalue(cur->rtp, AST_RTP_RXPLOSS) / rxcount * 100) : 0,
-- ast_rtp_get_qosvalue(cur->rtp, AST_RTP_RXJITTER),
-- txcount > (unsigned int) 100000 ? (unsigned int) (txcount)/(unsigned int) 1000 : txcount,
-- txcount > (unsigned int) 100000 ? "K":" ",
-- ast_rtp_get_qosvalue(cur->rtp, AST_RTP_TXPLOSS),
-- txcount > ast_rtp_get_qosvalue(cur->rtp, AST_RTP_TXPLOSS) ? (unsigned int) (ast_rtp_get_qosvalue(cur->rtp, AST_RTP_TXPLOSS)/ txcount * 100) : 0,
-- ast_rtp_get_qosvalue(cur->rtp, AST_RTP_TXJITTER)
-+ stats.rxcount > (unsigned int) 100000 ? (unsigned int) (stats.rxcount)/(unsigned int) 1000 : stats.rxcount,
-+ stats.rxcount > (unsigned int) 100000 ? "K":" ",
-+ stats.rxploss,
-+ stats.rxcount > stats.rxploss ? (stats.rxploss / stats.rxcount * 100) : 0,
-+ stats.rxjitter,
-+ stats.txcount > (unsigned int) 100000 ? (unsigned int) (stats.txcount)/(unsigned int) 1000 : stats.txcount,
-+ stats.txcount > (unsigned int) 100000 ? "K":" ",
-+ stats.txploss,
-+ stats.txcount > stats.txploss ? (stats.txploss / stats.txcount * 100) : 0,
-+ stats.txjitter
- );
- arg->numchans++;
-
-@@ -16387,29 +16810,150 @@
- .read = function_sipchaninfo_read,
- };
-
-+static int read_to_parts(struct sip_pvt *p, struct sip_request *req, char **name, char **number)
-+{
-+
-+ char to_header[256];
-+ char *to_name = NULL;
-+ char *to_number = NULL;
-+ char *separator;
-+
-+ ast_copy_string(to_header, get_header(req, "To"), sizeof(to_header));
-+
-+ /* Let's get that number first! */
-+ to_number = get_in_brackets(to_header);
-+
-+ if (!strncasecmp(to_number, "sip:", 4)) {
-+ to_number += 4;
-+ } else if (!strncasecmp(to_number, "sips:", 5)) {
-+ to_number += 5;
-+ } else {
-+ ast_log(LOG_WARNING, "Not a SIP URI? (%s)!\n", to_number);
-+ return -1;
-+ }
-+
-+ /* Remove the host and such since we just want the number */
-+ if ((separator = strchr(to_number, '@'))) {
-+ *separator = '\0';
-+ }
-+
-+ /* We have the number. Let's get the name now. */
-+
-+ if (*to_header == '\"') {
-+ to_name = to_header + 1;
-+ if (!(separator = (char *)find_closing_quote(to_name, NULL))) {
-+ ast_log(LOG_NOTICE, "No closing quote in name section of To: header (%s)\n", to_header);
-+ return -1;
-+ }
-+ *separator = '\0';
-+ }
-+
-+ if (number) {
-+ *number = ast_strdup(to_number);
-+ }
-+ if (name && !ast_strlen_zero(to_name)) {
-+ *name = ast_strdup(to_name);
-+ }
-+
-+ return 0;
-+}
-+
-+/*! \brief update redirecting information for a channel based on headers
-+ *
-+ */
-+static void change_redirecting_information(struct sip_pvt *p, struct sip_request *req, struct ast_party_redirecting *redirecting, int set_call_forward)
-+{
-+ char *redirecting_from_name = NULL;
-+ char *redirecting_from_number = NULL;
-+ char *redirecting_to_name = NULL;
-+ char *redirecting_to_number = NULL;
-+ int reason = AST_REDIRECTING_REASON_UNCONDITIONAL;
-+ int is_response = req->method == SIP_RESPONSE;
-+ int res = 0;
-+
-+ res = get_rdnis(p, req, &redirecting_from_name, &redirecting_from_number, &reason);
-+ if (res == -1) {
-+ if (is_response) {
-+ read_to_parts(p, req, &redirecting_from_name, &redirecting_from_number);
-+ } else {
-+ return;
-+ }
-+ }
-+
-+ /* At this point, all redirecting "from" info should be filled in appropriately
-+ * on to the "to" info
-+ */
-+
-+ if (is_response) {
-+ parse_moved_contact(p, req, &redirecting_to_name, &redirecting_to_number, set_call_forward);
-+ } else {
-+ read_to_parts(p, req, &redirecting_to_name, &redirecting_to_number);
-+ }
-+
-+ if (!ast_strlen_zero(redirecting_from_number)) {
-+ if (redirecting->from.number) {
-+ ast_free(redirecting->from.number);
-+ }
-+ ast_debug(3, "Got redirecting from number %s\n", redirecting_from_number);
-+ redirecting->from.number = redirecting_from_number;
-+ }
-+ if (!ast_strlen_zero(redirecting_from_name)) {
-+ if (redirecting->from.name) {
-+ ast_free(redirecting->from.name);
-+ }
-+ ast_debug(3, "Got redirecting from name %s\n", redirecting_from_name);
-+ redirecting->from.name = redirecting_from_name;
-+ }
-+ if (!ast_strlen_zero(redirecting_to_number)) {
-+ if (redirecting->to.number) {
-+ ast_free(redirecting->to.number);
-+ }
-+ ast_debug(3, "Got redirecting to number %s\n", redirecting_to_number);
-+ redirecting->to.number = redirecting_to_number;
-+ }
-+ if (!ast_strlen_zero(redirecting_to_name)) {
-+ if (redirecting->to.name) {
-+ ast_free(redirecting->to.name);
-+ }
-+ ast_debug(3, "Got redirecting to name %s\n", redirecting_from_number);
-+ redirecting->to.name = redirecting_to_name;
-+ }
-+ redirecting->reason = reason;
-+}
-+
- /*! \brief Parse 302 Moved temporalily response
- \todo XXX Doesn't redirect over TLS on sips: uri's.
- If we get a redirect to a SIPS: uri, this needs to be going back to the
- dialplan (this is a request for a secure signalling path).
- Note that transport=tls is deprecated, but we need to support it on incoming requests.
- */
--static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req)
-+static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req, char **name, char **number, int set_call_forward)
- {
-- char tmp[SIPBUFSIZE];
-- char *s, *e, *t, *trans;
-+ char contact[SIPBUFSIZE];
-+ char *contact_name = NULL;
-+ char *contact_number = NULL;
-+ char *separator, *trans;
- char *domain;
- enum sip_transport transport = SIP_TRANSPORT_UDP;
-
-- ast_copy_string(tmp, get_header(req, "Contact"), sizeof(tmp));
-- if ((t = strchr(tmp, ',')))
-- *t = '\0';
-+ ast_copy_string(contact, get_header(req, "Contact"), sizeof(contact));
-+ if ((separator = strchr(contact, ',')))
-+ *separator = '\0';
-
-- s = get_in_brackets(tmp);
-- if ((trans = strcasestr(s, ";transport="))) do {
-+ /* ooh, a name */
-+ if (*contact == '"') {
-+ contact_name = contact + 1;
-+ if ((separator = strchr(contact_name, '"'))) {
-+ *separator++ = '\0';
-+ }
-+ }
-+
-+ contact_number = get_in_brackets(contact);
-+ if ((trans = strcasestr(contact_number, ";transport="))) {
- trans += 11;
-
-- if ((e = strchr(trans, ';')))
-- *e = '\0';
-+ if ((separator = strchr(trans, ';')))
-+ *separator = '\0';
-
- if (!strncasecmp(trans, "tcp", 3))
- transport = SIP_TRANSPORT_TCP;
-@@ -16417,12 +16961,12 @@
- transport = SIP_TRANSPORT_TLS;
- else {
- if (strncasecmp(trans, "udp", 3))
-- ast_debug(1, "received contact with an invalid transport, '%s'\n", s);
-+ ast_debug(1, "received contact with an invalid transport, '%s'\n", contact_number);
- /* This will assume UDP for all unknown transports */
- transport = SIP_TRANSPORT_UDP;
- }
-- } while(0);
-- s = remove_uri_parameters(s);
-+ }
-+ contact_number = remove_uri_parameters(contact_number);
-
- if (p->socket.tcptls_session) {
- ao2_ref(p->socket.tcptls_session, -1);
-@@ -16432,51 +16976,70 @@
- p->socket.fd = -1;
- p->socket.type = transport;
-
-- if (ast_test_flag(&p->flags[0], SIP_PROMISCREDIR)) {
-+ if (set_call_forward && ast_test_flag(&p->flags[0], SIP_PROMISCREDIR)) {
- char *host = NULL;
-- if (!strncasecmp(s, "sip:", 4))
-- s += 4;
-- else if (!strncasecmp(s, "sips:", 5))
-- s += 5;
-- e = strchr(s, '/');
-- if (e)
-- *e = '\0';
-- if ((host = strchr(s, '@'))) {
-+ if (!strncasecmp(contact_number, "sip:", 4))
-+ contact_number += 4;
-+ else if (!strncasecmp(contact_number, "sips:", 5))
-+ contact_number += 5;
-+ separator = strchr(contact_number, '/');
-+ if (separator)
-+ *separator = '\0';
-+ if ((host = strchr(contact_number, '@'))) {
- *host++ = '\0';
-- ast_debug(2, "Found promiscuous redirection to 'SIP/%s::::%s@%s'\n", s, get_transport(transport), host);
-+ ast_debug(2, "Found promiscuous redirection to 'SIP/%s::::%s@%s'\n", contact_number, get_transport(transport), host);
- if (p->owner)
-- ast_string_field_build(p->owner, call_forward, "SIP/%s::::%s@%s", s, get_transport(transport), host);
-+ ast_string_field_build(p->owner, call_forward, "SIP/%s::::%s@%s", contact_number, get_transport(transport), host);
- } else {
-- ast_debug(2, "Found promiscuous redirection to 'SIP/::::%s@%s'\n", get_transport(transport), s);
-+ ast_debug(2, "Found promiscuous redirection to 'SIP/::::%s@%s'\n", get_transport(transport), contact_number);
- if (p->owner)
-- ast_string_field_build(p->owner, call_forward, "SIP/::::%s@%s", get_transport(transport), s);
-+ ast_string_field_build(p->owner, call_forward, "SIP/::::%s@%s", get_transport(transport), contact_number);
- }
- } else {
-- e = strchr(tmp, '@');
-- if (e) {
-- *e++ = '\0';
-- domain = e;
-+ separator = strchr(contact, '@');
-+ if (separator) {
-+ *separator++ = '\0';
-+ domain = separator;
- } else {
- /* No username part */
-- domain = tmp;
-+ domain = contact;
- }
-- e = strchr(tmp, '/'); /* WHEN do we hae a forward slash in the URI? */
-- if (e)
-- *e = '\0';
-+ separator = strchr(contact, '/'); /* WHEN do we hae a forward slash in the URI? */
-+ if (separator)
-+ *separator = '\0';
-
-- if (!strncasecmp(s, "sip:", 4))
-- s += 4;
-- else if (!strncasecmp(s, "sips:", 5))
-- s += 5;
-- e = strchr(s, ';'); /* And username ; parameters? */
-- if (e)
-- *e = '\0';
-- ast_debug(2, "Received 302 Redirect to extension '%s' (domain %s)\n", s, domain);
-- if (p->owner) {
-- pbx_builtin_setvar_helper(p->owner, "SIPDOMAIN", domain);
-- ast_string_field_set(p->owner, call_forward, s);
-+ if (!strncasecmp(contact_number, "sip:", 4))
-+ contact_number += 4;
-+ else if (!strncasecmp(contact_number, "sips:", 5))
-+ contact_number += 5;
-+ separator = strchr(contact_number, ';'); /* And username ; parameters? */
-+ if (separator)
-+ *separator = '\0';
-+ if (set_call_forward) {
-+ ast_debug(2, "Received 302 Redirect to extension '%s' (domain %s)\n", contact_number, domain);
-+ if (p->owner) {
-+ pbx_builtin_setvar_helper(p->owner, "SIPDOMAIN", domain);
-+ ast_string_field_set(p->owner, call_forward, contact_number);
-+ }
- }
- }
-+
-+ /* We've gotten the number for the contact, now get the name */
-+
-+ if (*contact == '\"') {
-+ contact_name = contact + 1;
-+ if (!(separator = (char *)find_closing_quote(contact_name, NULL))) {
-+ ast_log(LOG_NOTICE, "No closing quote on name in Contact header? %s\n", contact);
-+ }
-+ *separator = '\0';
-+ }
-+
-+ if (name && !ast_strlen_zero(contact_name)) {
-+ *name = ast_strdup(contact_name);
-+ }
-+ if (number) {
-+ *number = ast_strdup(contact_number);
-+ }
- }
-
- /*! \brief Check pending actions on SIP call */
-@@ -16516,12 +17079,15 @@
- to avoid race conditions between asterisk servers.
- Called from the scheduler.
- */
--static int sip_reinvite_retry(const void *data)
-+static int sip_reinvite_retry(const void *data)
- {
- struct sip_pvt *p = (struct sip_pvt *) data;
-
-- ast_set_flag(&p->flags[0], SIP_NEEDREINVITE);
-+ sip_pvt_lock(p); /* called from schedule thread which requires a lock */
-+ ast_set_flag(&p->flags[0], SIP_NEEDREINVITE);
- p->waitid = -1;
-+ check_pendings(p);
-+ sip_pvt_unlock(p);
- dialog_unref(p, "unref the dialog ptr from sip_reinvite_retry, because it held a dialog ptr");
- return 0;
- }
-@@ -16536,7 +17102,8 @@
- int reinvite = (p->owner && p->owner->_state == AST_STATE_UP);
- char *p_hdrval;
- int rtn;
--
-+ struct ast_party_connected_line connected;
-+
- if (reinvite)
- ast_debug(4, "SIP response %d to RE-invite on %s call %s\n", resp, outgoing ? "outgoing" : "incoming", p->callid);
- else
-@@ -16554,7 +17121,7 @@
- /* RFC3261 says we must treat every 1xx response (but not 100)
- that we don't recognize as if it was 183.
- */
-- if (resp > 100 && resp < 200 && resp!=101 && resp != 180 && resp != 182 && resp != 183)
-+ if (resp > 100 && resp < 200 && resp!=101 && resp != 180 && resp != 181 && resp != 182 && resp != 183)
- resp = 183;
-
- /* Any response between 100 and 199 is PROCEEDING */
-@@ -16582,6 +17149,14 @@
- if (!req->ignore && p->invitestate != INV_CANCELLED && sip_cancel_destroy(p))
- ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n");
- if (!req->ignore && p->owner) {
-+ if (get_rpid(p, req)) {
-+ ast_party_connected_line_init(&connected);
-+ connected.id.number = (char *) p->cid_num;
-+ connected.id.name = (char *) p->cid_name;
-+ connected.id.number_presentation = p->callingpres;
-+ connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
-+ ast_channel_queue_connected_line_update(p->owner, &connected);
-+ }
- ast_queue_control(p->owner, AST_CONTROL_RINGING);
- if (p->owner->_state != AST_STATE_UP) {
- ast_setstate(p->owner, AST_STATE_RINGING);
-@@ -16599,10 +17174,32 @@
- check_pendings(p);
- break;
-
-+ case 181: /* Call Is Being Forwarded */
-+ if (!req->ignore && (p->invitestate != INV_CANCELLED) && sip_cancel_destroy(p))
-+ ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n");
-+ if (!req->ignore && p->owner) {
-+ struct ast_party_redirecting redirecting = {{0,},};
-+ change_redirecting_information(p, req, &redirecting, FALSE);
-+ ast_channel_queue_redirecting_update(p->owner, &redirecting);
-+ }
-+ check_pendings(p);
-+ break;
-+
- case 183: /* Session progress */
- if (!req->ignore && (p->invitestate != INV_CANCELLED) && sip_cancel_destroy(p))
- ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n");
- /* Ignore 183 Session progress without SDP */
-+ if (!req->ignore && p->owner) {
-+ if (get_rpid(p, req)) {
-+ /* Queue a connected line update */
-+ ast_party_connected_line_init(&connected);
-+ connected.id.number = (char *) p->cid_num;
-+ connected.id.name = (char *) p->cid_name;
-+ connected.id.number_presentation = p->callingpres;
-+ connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
-+ ast_channel_queue_connected_line_update(p->owner, &connected);
-+ }
-+ }
- if (find_sdp(req)) {
- if (p->invitestate != INV_CANCELLED)
- p->invitestate = INV_EARLY_MEDIA;
-@@ -16624,9 +17221,19 @@
- if (!reinvite)
- /* This 200 OK's SDP is not acceptable, so we need to ack, then hangup */
- /* For re-invites, we try to recover */
-- ast_set_flag(&p->flags[0], SIP_PENDINGBYE);
-+ ast_set_flag(&p->flags[0], SIP_PENDINGBYE);
- }
-
-+ if (!req->ignore && p->owner && get_rpid(p, req)) {
-+ /* Queue a connected line update */
-+ ast_party_connected_line_init(&connected);
-+ connected.id.number = (char *) p->cid_num;
-+ connected.id.name = (char *) p->cid_name;
-+ connected.id.number_presentation = p->callingpres;
-+ connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
-+ ast_channel_queue_connected_line_update(p->owner, &connected);
-+ }
-+
- /* Parse contact header for continued conversation */
- /* When we get 200 OK, we know which device (and IP) to contact for this call */
- /* This is important when we have a SIP proxy between us and the phone */
-@@ -16648,6 +17255,9 @@
-
- if (!req->ignore && p->owner) {
- if (!reinvite) {
-+ struct ast_party_connected_line connected;
-+ ast_party_connected_line_collect_caller(&connected, &p->owner->cid);
-+ ast_channel_queue_connected_line_update(p->owner, &connected);
- ast_queue_control(p->owner, AST_CONTROL_ANSWER);
- if (sip_cfg.callevents)
- manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate",
-@@ -16788,24 +17398,10 @@
- if (p->udptl && p->t38.state == T38_LOCAL_REINVITE) {
- change_t38_state(p, T38_DISABLED);
- /* Try to reset RTP timers */
-- ast_rtp_set_rtptimers_onhold(p->rtp);
-+ //ast_rtp_set_rtptimers_onhold(p->rtp);
-
- /* Trigger a reinvite back to audio */
- transmit_reinvite_with_sdp(p, FALSE, FALSE);
-- } else if (p->udptl && p->t38.state == T38_LOCAL_DIRECT) {
-- /* We tried to send T.38 out in an initial INVITE and the remote side rejected it,
-- right now we can't fall back to audio so totally abort.
-- */
-- /* Try to reset RTP timers */
-- ast_rtp_set_rtptimers_onhold(p->rtp);
-- ast_log(LOG_ERROR, "Got error on T.38 initial invite. Bailing out.\n");
--
-- change_t38_state(p, T38_DISABLED);
-- /* The dialog is now terminated */
-- if (p->owner && !req->ignore)
-- ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
-- pvt_set_needdestroy(p, "got error on T.38 initial invite");
-- sip_alreadygone(p);
- } else {
- /* We can't set up this call, so give up */
- if (p->owner && !req->ignore)
-@@ -16826,8 +17422,15 @@
- /* This is a re-invite that failed. */
- /* Reset the flag after a while
- */
-- int wait = 3 + ast_random() % 5;
-- p->waitid = ast_sched_add(sched, wait, sip_reinvite_retry, dialog_ref(p, "passing dialog ptr into sched structure based on waitid for sip_reinvite_retry."));
-+ int wait;
-+ /* RFC 3261, if owner of call, wait between 2.1 to 4 seconds,
-+ * if not owner of call, wait 0 to 2 seconds */
-+ if (p->outgoing_call) {
-+ wait = 2100 + ast_random() % 2000;
-+ } else {
-+ wait = ast_random() % 2000;
-+ }
-+ p->waitid = ast_sched_add(sched, wait, sip_reinvite_retry, dialog_ref(p, "passing dialog ptr into sched structure based on waitid for sip_reinvite_retry."));
- ast_log(LOG_WARNING, "just did sched_add waitid(%d) for sip_reinvite_retry for dialog %s in handle_response_invite\n", p->waitid, p->callid);
- ast_debug(2, "Reinvite race. Waiting %d secs before retry\n", wait);
- }
-@@ -16953,6 +17556,8 @@
- */
- static void handle_response_refer(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno)
- {
-+ enum ast_control_transfer message = AST_TRANSFER_FAILED;
-+
- /* If no refer structure exists, then do nothing */
- if (!p->refer)
- return;
-@@ -16972,12 +17577,18 @@
- if (ast_strlen_zero(p->authname)) {
- ast_log(LOG_WARNING, "Asked to authenticate REFER to %s:%d but we have no matching peer or realm auth!\n",
- ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port));
-+ if (p->owner) {
-+ ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message));
-+ }
- pvt_set_needdestroy(p, "unable to authenticate REFER");
- }
- if (p->authtries > 1 || do_proxy_auth(p, req, resp, SIP_REFER, 0)) {
- ast_log(LOG_NOTICE, "Failed to authenticate on REFER to '%s'\n", get_header(&p->initreq, "From"));
- p->refer->status = REFER_NOAUTH;
-- pvt_set_needdestroy(p, "failed to authenticat REFER");
-+ if (p->owner) {
-+ ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message));
-+ }
-+ pvt_set_needdestroy(p, "failed to authenticate REFER");
- }
- break;
- case 481: /* Call leg does not exist */
-@@ -16998,11 +17609,17 @@
- ast_log(LOG_NOTICE, "SIP transfer to %s failed, call miserably fails. \n", p->refer->refer_to);
- pvt_set_needdestroy(p, "received 500/501 response");
- p->refer->status = REFER_FAILED;
-+ if (p->owner) {
-+ ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message));
-+ }
- break;
- case 603: /* Transfer declined */
- ast_log(LOG_NOTICE, "SIP transfer to %s declined, call miserably fails. \n", p->refer->refer_to);
- p->refer->status = REFER_FAILED;
- pvt_set_needdestroy(p, "received 603 response");
-+ if (p->owner) {
-+ ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message));
-+ }
- break;
- }
- }
-@@ -17215,11 +17832,11 @@
- {
- /* Immediately stop RTP, VRTP and UDPTL as applicable */
- if (p->rtp)
-- ast_rtp_stop(p->rtp);
-+ ast_rtp_instance_stop(p->rtp);
- if (p->vrtp)
-- ast_rtp_stop(p->vrtp);
-+ ast_rtp_instance_stop(p->vrtp);
- if (p->trtp)
-- ast_rtp_stop(p->trtp);
-+ ast_rtp_instance_stop(p->trtp);
- if (p->udptl)
- ast_udptl_stop(p->udptl);
- }
-@@ -17296,6 +17913,7 @@
- case 183: /* 183 Session Progress */
- case 180: /* 180 Ringing */
- case 182: /* 182 Queued */
-+ case 181: /* 181 Call Is Being Forwarded */
- if (sipmethod == SIP_INVITE)
- handle_response_invite(p, resp, rest, req, seqno);
- break;
-@@ -17463,7 +18081,11 @@
- case 301: /* Moved permanently */
- case 302: /* Moved temporarily */
- case 305: /* Use Proxy */
-- parse_moved_contact(p, req);
-+ {
-+ struct ast_party_redirecting redirecting = {{0,},};
-+ change_redirecting_information(p, req, &redirecting, TRUE);
-+ ast_channel_set_redirecting(p->owner, &redirecting);
-+ }
- /* Fall through */
- case 486: /* Busy here */
- case 600: /* Busy everywhere */
-@@ -18037,7 +18659,11 @@
- if (!success) {
- ast_log(LOG_NOTICE, "Transfer failed. Sorry. Nothing further to do with this call\n");
- }
--
-+
-+ if (p->owner) {
-+ enum ast_control_transfer message = success ? AST_TRANSFER_SUCCESS : AST_TRANSFER_FAILED;
-+ ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message));
-+ }
- /* Confirm that we received this packet */
- transmit_response(p, "200 OK", req);
- } else if (p->mwi && !strcmp(event, "message-summary")) {
-@@ -18054,10 +18680,7 @@
- AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, atoi(new),
- AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, atoi(old),
- AST_EVENT_IE_END))) {
-- ast_event_queue_and_cache(event,
-- AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR,
-- AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR,
-- AST_EVENT_IE_END);
-+ ast_event_queue_and_cache(event);
- }
- }
-
-@@ -18158,7 +18781,7 @@
- /* We should answer something here. If we are here, the
- call we are replacing exists, so an accepted
- can't harm */
-- transmit_response_with_sdp(p, "200 OK", req, XMIT_RELIABLE, FALSE);
-+ transmit_response_with_sdp(p, "200 OK", req, XMIT_RELIABLE, FALSE, FALSE);
- /* Do something more clever here */
- ast_channel_unlock(c);
- sip_pvt_unlock(p->refer->refer_call);
-@@ -18192,7 +18815,7 @@
- Targetcall is not touched by the masq */
-
- /* Answer the incoming call and set channel to UP state */
-- transmit_response_with_sdp(p, "200 OK", req, XMIT_RELIABLE, FALSE);
-+ transmit_response_with_sdp(p, "200 OK", req, XMIT_RELIABLE, FALSE, FALSE);
-
- ast_setstate(c, AST_STATE_UP);
-
-@@ -18592,10 +19215,11 @@
- return 0;
- }
-
--/*! \brief Handle incoming INVITE request
--\note If the INVITE has a Replaces header, it is part of an
-+/*!
-+ * \brief Handle incoming INVITE request
-+ * \note If the INVITE has a Replaces header, it is part of an
- * attended transfer. If so, we do not go through the dial
-- * plan but tries to find the active call and masquerade
-+ * plan but try to find the active call and masquerade
- * into it
- */
- static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int debug, int seqno, struct sockaddr_in *sin, int *recount, char *e, int *nounlock)
-@@ -18704,9 +19328,10 @@
- return transmit_invite(p, SIP_INVITE, 1, 3);
- }
- }
--
-+
- if (!req->ignore && p->pendinginvite) {
- /* We already have a pending invite. Sorry. You are on hold. */
-+ p->glareinvite = seqno; /* must hold on to this seqno to process ack and retransmit correctly */
- transmit_response_reliable(p, "491 Request Pending", req);
- ast_debug(1, "Got INVITE on call where we already have pending INVITE, deferring that - %s\n", p->callid);
- /* Don't destroy dialog here */
-@@ -18865,6 +19490,16 @@
- parse_ok_contact(p, req);
- } else { /* Re-invite on existing call */
- ast_clear_flag(&p->flags[0], SIP_OUTGOING); /* This is now an inbound dialog */
-+ if (get_rpid(p, req)) {
-+ struct ast_party_connected_line connected;
-+
-+ ast_party_connected_line_init(&connected);
-+ connected.id.number = (char *) p->cid_num;
-+ connected.id.name = (char *) p->cid_name;
-+ connected.id.number_presentation = p->callingpres;
-+ connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
-+ ast_channel_queue_connected_line_update(p->owner, &connected);
-+ }
- /* Handle SDP here if we already have an owner */
- if (find_sdp(req)) {
- if (process_sdp(p, req, SDP_T38_INITIATE)) {
-@@ -18887,6 +19522,7 @@
- if (!p->lastinvite && !req->ignore && !p->owner) {
- /* This is a new invite */
- /* Handle authentication if this is our first invite */
-+ struct ast_party_redirecting redirecting = {{0,},};
- res = check_user(p, req, SIP_INVITE, e, XMIT_RELIABLE, sin);
- if (res == AUTH_CHALLENGE_SENT) {
- p->invitestate = INV_COMPLETED; /* Needs to restart in another INVITE transaction */
-@@ -18895,7 +19531,7 @@
- if (res < 0) { /* Something failed in authentication */
- if (res == AUTH_FAKE_AUTH) {
- ast_log(LOG_NOTICE, "Sending fake auth rejection for device %s\n", get_header(req, "From"));
-- transmit_fake_auth_response(p, req, XMIT_RELIABLE);
-+ transmit_fake_auth_response(p, SIP_INVITE, req, XMIT_RELIABLE);
- } else {
- ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", get_header(req, "From"));
- transmit_response_reliable(p, "403 Forbidden", req);
-@@ -18944,13 +19580,13 @@
- return 0;
- }
- gotdest = get_destination(p, NULL); /* Get destination right away */
-- get_rdnis(p, NULL); /* Get redirect information */
-+ change_redirecting_information(p, req, &redirecting, FALSE); /*Will return immediately if no Diversion header is present */
- extract_uri(p, req); /* Get the Contact URI */
- build_contact(p); /* Build our contact header */
-
- if (p->rtp) {
-- ast_rtp_setdtmf(p->rtp, ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
-- ast_rtp_setdtmfcompensate(p->rtp, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
-+ ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_DTMF, ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
-+ ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
- }
-
- if (!replace_id && gotdest) { /* No matching extension found */
-@@ -18988,9 +19624,11 @@
- if (c) {
- /* Pre-lock the call */
- ast_channel_lock(c);
-+ ast_channel_set_redirecting(c, &redirecting);
- }
- }
- } else {
-+ struct ast_party_redirecting redirecting = {{0,},};
- if (sipdebug) {
- if (!req->ignore)
- ast_debug(2, "Got a SIP re-invite for call %s\n", p->callid);
-@@ -19000,6 +19638,10 @@
- if (!req->ignore)
- reinvite = 1;
- c = p->owner;
-+ change_redirecting_information(p, req, &redirecting, FALSE); /*Will return immediately if no Diversion header is present */
-+ if (c) {
-+ ast_channel_set_redirecting(c, &redirecting);
-+ }
- }
-
- /* Session-Timers */
-@@ -19210,7 +19852,6 @@
- c->hangupcause = AST_CAUSE_CALL_REJECTED;
- } else {
- sip_pvt_unlock(p);
-- ast_setstate(c, AST_STATE_DOWN);
- c->hangupcause = AST_CAUSE_NORMAL_CLEARING;
- }
- p->invitestate = INV_COMPLETED;
-@@ -19240,7 +19881,7 @@
- } else if (p->t38.state == T38_DISABLED) {
- /* If this is not a re-invite or something to ignore - it's critical */
- ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
-- transmit_response_with_sdp(p, "200 OK", req, (reinvite ? XMIT_RELIABLE : (req->ignore ? XMIT_UNRELIABLE : XMIT_CRITICAL)), p->session_modify == TRUE ? FALSE:TRUE);
-+ transmit_response_with_sdp(p, "200 OK", req, (reinvite ? XMIT_RELIABLE : (req->ignore ? XMIT_UNRELIABLE : XMIT_CRITICAL)), p->session_modify == TRUE ? FALSE : TRUE, FALSE);
- }
-
- p->invitestate = INV_TERMINATED;
-@@ -19358,6 +19999,8 @@
- else
- ast_clear_flag(&transferer->flags[0], SIP_DEFER_BYE_ON_TRANSFER);
- } else {
-+ struct ast_party_connected_line connected_caller;
-+
- /* Transfer succeeded! */
- const char *xfersound = pbx_builtin_getvar_helper(target.chan1, "ATTENDED_TRANSFER_COMPLETE_SOUND");
-
-@@ -19372,6 +20015,45 @@
- ast_debug(1, "SIP attended transfer: Unlocking channel %s\n", targetcall_pvt->owner->name);
- ast_channel_unlock(targetcall_pvt->owner);
- }
-+
-+ if (target.chan2) {
-+ if (current->chan2) {
-+ /* Tell each of the other channels to whom they are now connected */
-+ ast_channel_lock(current->chan2);
-+ ast_connected_line_copy_from_caller(&connected_caller, &current->chan2->cid);
-+ ast_channel_unlock(current->chan2);
-+ connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
-+ ast_channel_update_connected_line(target.chan2, &connected_caller);
-+ ast_channel_lock(target.chan2);
-+ ast_connected_line_copy_from_caller(&connected_caller, &target.chan2->cid);
-+ ast_channel_unlock(target.chan2);
-+ connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
-+ ast_channel_update_connected_line(current->chan2, &connected_caller);
-+ ast_party_connected_line_free(&connected_caller);
-+ }
-+ } else {
-+ /* Notify the first other party that they are connected to someone else assuming that target.chan1
-+ has progressed far enough through the dialplan to have it's called party information set. */
-+ if (current->chan2) {
-+ ast_channel_lock(target.chan1);
-+ ast_party_connected_line_copy(&connected_caller, &target.chan1->connected);
-+ ast_channel_unlock(target.chan1);
-+ connected_caller = target.chan1->connected;
-+ connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
-+ ast_channel_update_connected_line(current->chan2, &connected_caller);
-+ ast_party_connected_line_free(&connected_caller);
-+ }
-+
-+ /* We can't indicate to the called channel directly so we force the masquerade to complete
-+ and queue and update to be read and passed-through */
-+ ast_channel_lock(target.chan1);
-+ ast_do_masquerade(target.chan1);
-+ ast_channel_unlock(target.chan1);
-+
-+ ast_party_connected_line_collect_caller(&connected_caller, &target.chan1->cid);
-+ connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
-+ ast_channel_queue_connected_line_update(target.chan1, &connected_caller);
-+ }
- }
- if (targetcall_pvt)
- ao2_t_ref(targetcall_pvt, -1, "drop targetcall_pvt");
-@@ -19769,7 +20451,7 @@
- static int acf_channel_read(struct ast_channel *chan, const char *funcname, char *preparse, char *buf, size_t buflen)
- {
- struct sip_pvt *p = chan->tech_pvt;
-- char *all = "", *parse = ast_strdupa(preparse);
-+ char *parse = ast_strdupa(preparse);
- int res = 0;
- AST_DECLARE_APP_ARGS(args,
- AST_APP_ARG(param);
-@@ -19807,61 +20489,70 @@
- args.type = "audio";
-
- if (!strcasecmp(args.type, "audio"))
-- ast_rtp_get_peer(p->rtp, &sin);
-+ ast_rtp_instance_get_remote_address(p->rtp, &sin);
- else if (!strcasecmp(args.type, "video"))
-- ast_rtp_get_peer(p->vrtp, &sin);
-+ ast_rtp_instance_get_remote_address(p->vrtp, &sin);
- else if (!strcasecmp(args.type, "text"))
-- ast_rtp_get_peer(p->trtp, &sin);
-+ ast_rtp_instance_get_remote_address(p->trtp, &sin);
- else
- return -1;
-
- snprintf(buf, buflen, "%s:%d", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
- } else if (!strcasecmp(args.param, "rtpqos")) {
-- struct ast_rtp_quality qos;
-- struct ast_rtp *rtp = p->rtp;
--
-- memset(&qos, 0, sizeof(qos));
-+ struct ast_rtp_instance *rtp = NULL;
-
-- if (ast_strlen_zero(args.type))
-+ if (ast_strlen_zero(args.type)) {
- args.type = "audio";
-- if (ast_strlen_zero(args.field))
-- args.field = "all";
--
-- if (!strcasecmp(args.type, "AUDIO")) {
-- all = ast_rtp_get_quality(rtp = p->rtp, &qos, RTPQOS_SUMMARY);
-- } else if (!strcasecmp(args.type, "VIDEO")) {
-- all = ast_rtp_get_quality(rtp = p->vrtp, &qos, RTPQOS_SUMMARY);
-- } else if (!strcasecmp(args.type, "TEXT")) {
-- all = ast_rtp_get_quality(rtp = p->trtp, &qos, RTPQOS_SUMMARY);
-+ }
-+
-+ if (!strcasecmp(args.type, "audio")) {
-+ rtp = p->rtp;
-+ } else if (!strcasecmp(args.type, "video")) {
-+ rtp = p->vrtp;
-+ } else if (!strcasecmp(args.type, "text")) {
-+ rtp = p->trtp;
- } else {
-- return -1;
-+ return -1;
- }
--
-- if (!strcasecmp(args.field, "local_ssrc"))
-- snprintf(buf, buflen, "%u", qos.local_ssrc);
-- else if (!strcasecmp(args.field, "local_lostpackets"))
-- snprintf(buf, buflen, "%u", qos.local_lostpackets);
-- else if (!strcasecmp(args.field, "local_jitter"))
-- snprintf(buf, buflen, "%.0f", qos.local_jitter * 1000.0);
-- else if (!strcasecmp(args.field, "local_count"))
-- snprintf(buf, buflen, "%u", qos.local_count);
-- else if (!strcasecmp(args.field, "remote_ssrc"))
-- snprintf(buf, buflen, "%u", qos.remote_ssrc);
-- else if (!strcasecmp(args.field, "remote_lostpackets"))
-- snprintf(buf, buflen, "%u", qos.remote_lostpackets);
-- else if (!strcasecmp(args.field, "remote_jitter"))
-- snprintf(buf, buflen, "%.0f", qos.remote_jitter * 1000.0);
-- else if (!strcasecmp(args.field, "remote_count"))
-- snprintf(buf, buflen, "%u", qos.remote_count);
-- else if (!strcasecmp(args.field, "rtt"))
-- snprintf(buf, buflen, "%.0f", qos.rtt * 1000.0);
-- else if (!strcasecmp(args.field, "all"))
-- ast_copy_string(buf, all, buflen);
-- else if (!ast_rtp_get_qos(rtp, args.field, buf, buflen))
-- ;
-- else {
-- ast_log(LOG_WARNING, "Unrecognized argument '%s' to %s\n", preparse, funcname);
-- return -1;
-+
-+ if (ast_strlen_zero(args.field) || !strcasecmp(args.field, "all")) {
-+ char quality_buf[AST_MAX_USER_FIELD], *quality;
-+
-+ if (!(quality = ast_rtp_instance_get_quality(rtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, quality_buf, sizeof(quality_buf)))) {
-+ return -1;
-+ }
-+
-+ ast_copy_string(buf, quality_buf, buflen);
-+ return res;
-+ } else {
-+ struct ast_rtp_instance_stats stats;
-+
-+ if (ast_rtp_instance_get_stats(rtp, &stats, AST_RTP_INSTANCE_STAT_ALL)) {
-+ return -1;
-+ }
-+
-+ if (!strcasecmp(args.field, "local_ssrc")) {
-+ snprintf(buf, buflen, "%u", stats.local_ssrc);
-+ } else if (!strcasecmp(args.field, "local_lostpackets")) {
-+ snprintf(buf, buflen, "%u", stats.rxploss);
-+ } else if (!strcasecmp(args.field, "local_jitter")) {
-+ snprintf(buf, buflen, "%u", stats.rxjitter);
-+ } else if (!strcasecmp(args.field, "local_count")) {
-+ snprintf(buf, buflen, "%u", stats.rxcount);
-+ } else if (!strcasecmp(args.field, "remote_ssrc")) {
-+ snprintf(buf, buflen, "%u", stats.remote_ssrc);
-+ } else if (!strcasecmp(args.field, "remote_lostpackets")) {
-+ snprintf(buf, buflen, "%u", stats.txploss);
-+ } else if (!strcasecmp(args.field, "remote_jitter")) {
-+ snprintf(buf, buflen, "%u", stats.txjitter);
-+ } else if (!strcasecmp(args.field, "remote_count")) {
-+ snprintf(buf, buflen, "%u", stats.txcount);
-+ } else if (!strcasecmp(args.field, "rtt")) {
-+ snprintf(buf, buflen, "%u", stats.rtt);
-+ } else {
-+ ast_log(LOG_WARNING, "Unrecognized argument '%s' to %s\n", preparse, funcname);
-+ return -1;
-+ }
- }
- } else {
- res = -1;
-@@ -19893,53 +20584,53 @@
-
- /* Get RTCP quality before end of call */
- if (p->do_history || p->owner) {
-+ char quality_buf[AST_MAX_USER_FIELD], *quality;
- struct ast_channel *bridge = p->owner ? ast_bridged_channel(p->owner) : NULL;
-- char *videoqos, *textqos;
-
-- if (p->rtp) {
-+ if (p->rtp && (quality = ast_rtp_instance_get_quality(p->rtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, quality_buf, sizeof(quality_buf)))) {
- if (p->do_history) {
-- char *audioqos,
-- *audioqos_jitter,
-- *audioqos_loss,
-- *audioqos_rtt;
-+ append_history(p, "RTCPaudio", "Quality:%s", quality);
-
-- audioqos = ast_rtp_get_quality(p->rtp, NULL, RTPQOS_SUMMARY);
-- audioqos_jitter = ast_rtp_get_quality(p->rtp, NULL, RTPQOS_JITTER);
-- audioqos_loss = ast_rtp_get_quality(p->rtp, NULL, RTPQOS_LOSS);
-- audioqos_rtt = ast_rtp_get_quality(p->rtp, NULL, RTPQOS_RTT);
-+ if ((quality = ast_rtp_instance_get_quality(p->rtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY_JITTER, quality_buf, sizeof(quality_buf)))) {
-+ append_history(p, "RTCPaudioJitter", "Quality:%s", quality);
-+ }
-+ if ((quality = ast_rtp_instance_get_quality(p->rtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY_LOSS, quality_buf, sizeof(quality_buf)))) {
-+ append_history(p, "RTCPaudioLoss", "Quality:%s", quality);
-+ }
-+ if ((quality = ast_rtp_instance_get_quality(p->rtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY_RTT, quality_buf, sizeof(quality_buf)))) {
-+ append_history(p, "RTCPaudioRTT", "Quality:%s", quality);
-+ }
-+ }
-
-- append_history(p, "RTCPaudio", "Quality:%s", audioqos);
-- append_history(p, "RTCPaudioJitter", "Quality:%s", audioqos_jitter);
-- append_history(p, "RTCPaudioLoss", "Quality:%s", audioqos_loss);
-- append_history(p, "RTCPaudioRTT", "Quality:%s", audioqos_rtt);
-- }
--
- if (p->owner) {
-- ast_rtp_set_vars(p->owner, p->rtp);
-+ ast_rtp_instance_set_stats_vars(p->owner, p->rtp);
- }
-+
- }
-
- if (bridge) {
- struct sip_pvt *q = bridge->tech_pvt;
-
-- if (IS_SIP_TECH(bridge->tech) && q->rtp)
-- ast_rtp_set_vars(bridge, q->rtp);
-+ if (IS_SIP_TECH(bridge->tech) && q->rtp) {
-+ ast_rtp_instance_set_stats_vars(bridge, q->rtp);
-+ }
- }
-
-- if (p->vrtp) {
-- videoqos = ast_rtp_get_quality(p->vrtp, NULL, RTPQOS_SUMMARY);
-- if (p->do_history)
-- append_history(p, "RTCPvideo", "Quality:%s", videoqos);
-- if (p->owner)
-- pbx_builtin_setvar_helper(p->owner, "RTPVIDEOQOS", videoqos);
-+ if (p->vrtp && (quality = ast_rtp_instance_get_quality(p->vrtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, quality_buf, sizeof(quality_buf)))) {
-+ if (p->do_history) {
-+ append_history(p, "RTCPvideo", "Quality:%s", quality);
-+ }
-+ if (p->owner) {
-+ pbx_builtin_setvar_helper(p->owner, "RTPVIDEOQOS", quality);
-+ }
- }
--
-- if (p->trtp) {
-- textqos = ast_rtp_get_quality(p->trtp, NULL, RTPQOS_SUMMARY);
-- if (p->do_history)
-- append_history(p, "RTCPtext", "Quality:%s", textqos);
-- if (p->owner)
-- pbx_builtin_setvar_helper(p->owner, "RTPTEXTQOS", textqos);
-+ if (p->trtp && (quality = ast_rtp_instance_get_quality(p->trtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, quality_buf, sizeof(quality_buf)))) {
-+ if (p->do_history) {
-+ append_history(p, "RTCPtext", "Quality:%s", quality);
-+ }
-+ if (p->owner) {
-+ pbx_builtin_setvar_helper(p->owner, "RTPTEXTQOS", quality);
-+ }
- }
- }
-
-@@ -20092,7 +20783,7 @@
- if (res < 0) {
- if (res == AUTH_FAKE_AUTH) {
- ast_log(LOG_NOTICE, "Sending fake auth rejection for device %s\n", get_header(req, "From"));
-- transmit_fake_auth_response(p, req, XMIT_UNRELIABLE);
-+ transmit_fake_auth_response(p, SIP_SUBSCRIBE, req, XMIT_UNRELIABLE);
- } else {
- ast_log(LOG_NOTICE, "Failed to authenticate device %s for SUBSCRIBE\n", get_header(req, "From"));
- transmit_response_reliable(p, "403 Forbidden", req);
-@@ -20436,10 +21127,10 @@
- */
- int ret = 0;
-
-- if (p->ocseq < seqno && seqno != p->lastnoninvite) {
-+ if (p->ocseq < seqno && p->lastinvite != seqno && p->lastnoninvite != seqno) {
- ast_debug(1, "Ignoring out of order response %d (expecting %d)\n", seqno, p->ocseq);
- ret = -1;
-- } else if (p->ocseq != seqno && seqno != p->lastnoninvite) {
-+ } else if (p->ocseq != seqno && p->lastinvite != seqno && p->lastnoninvite != seqno) {
- /* ignore means "don't do anything with it" but still have to
- * respond appropriately.
- * But in this case this is a response already, so we really
-@@ -20580,8 +21271,12 @@
- if (find_sdp(req)) {
- if (process_sdp(p, req, SDP_T38_NONE))
- return -1;
-- }
-+ }
- check_pendings(p);
-+ } else if (p->glareinvite == seqno) {
-+ /* handle ack for the 491 pending sent for glareinvite */
-+ p->glareinvite = 0;
-+ __sip_ack(p, seqno, 1, 0);
- }
- /* Got an ACK that we did not match. Ignore silently */
- if (!p->lastinvite && ast_strlen_zero(p->randdata)) {
-@@ -21033,8 +21728,6 @@
- event = ast_event_get_cached(AST_EVENT_MWI,
- AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox->mailbox,
- AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, S_OR(mailbox->context, "default"),
-- AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
-- AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
- AST_EVENT_IE_END);
- if (!event)
- continue;
-@@ -21126,15 +21819,8 @@
- return;
-
- /* If we have no timers set, return now */
-- if ((ast_rtp_get_rtpkeepalive(dialog->rtp) == 0) && (ast_rtp_get_rtptimeout(dialog->rtp) == 0) && (ast_rtp_get_rtpholdtimeout(dialog->rtp) == 0))
-+ if (!ast_rtp_instance_get_timeout(dialog->rtp) && !ast_rtp_instance_get_hold_timeout(dialog->rtp)) {
- return;
--
-- /* Check AUDIO RTP keepalives */
-- if (dialog->lastrtptx && ast_rtp_get_rtpkeepalive(dialog->rtp) &&
-- (t > dialog->lastrtptx + ast_rtp_get_rtpkeepalive(dialog->rtp))) {
-- /* Need to send an empty RTP packet */
-- dialog->lastrtptx = time(NULL);
-- ast_rtp_sendcng(dialog->rtp, 0);
- }
-
- /*! \todo Check video RTP keepalives
-@@ -21144,16 +21830,10 @@
- */
-
- /* Check AUDIO RTP timers */
-- if (dialog->lastrtprx && (ast_rtp_get_rtptimeout(dialog->rtp) || ast_rtp_get_rtpholdtimeout(dialog->rtp)) &&
-- (t > dialog->lastrtprx + ast_rtp_get_rtptimeout(dialog->rtp))) {
--
-- /* Might be a timeout now -- see if we're on hold */
-- struct sockaddr_in sin;
-- ast_rtp_get_peer(dialog->rtp, &sin);
-- if (!ast_test_flag(&dialog->flags[1], SIP_PAGE2_CALL_ONHOLD) || (ast_rtp_get_rtpholdtimeout(dialog->rtp) &&
-- (t > dialog->lastrtprx + ast_rtp_get_rtpholdtimeout(dialog->rtp)))) {
-+ if (dialog->lastrtprx && (ast_rtp_instance_get_timeout(dialog->rtp) || ast_rtp_instance_get_hold_timeout(dialog->rtp)) && (t > dialog->lastrtprx + ast_rtp_instance_get_timeout(dialog->rtp))) {
-+ if (!ast_test_flag(&dialog->flags[1], SIP_PAGE2_CALL_ONHOLD) || (ast_rtp_instance_get_hold_timeout(dialog->rtp) && (t > dialog->lastrtprx + ast_rtp_instance_get_hold_timeout(dialog->rtp)))) {
- /* Needs a hangup */
-- if (ast_rtp_get_rtptimeout(dialog->rtp)) {
-+ if (ast_rtp_instance_get_timeout(dialog->rtp)) {
- while (dialog->owner && ast_channel_trylock(dialog->owner)) {
- sip_pvt_unlock(dialog);
- usleep(1);
-@@ -21168,11 +21848,11 @@
- has already been requested and we don't want to
- repeatedly request hangups
- */
-- ast_rtp_set_rtptimeout(dialog->rtp, 0);
-- ast_rtp_set_rtpholdtimeout(dialog->rtp, 0);
-+ ast_rtp_instance_set_timeout(dialog->rtp, 0);
-+ ast_rtp_instance_set_hold_timeout(dialog->rtp, 0);
- if (dialog->vrtp) {
-- ast_rtp_set_rtptimeout(dialog->vrtp, 0);
-- ast_rtp_set_rtpholdtimeout(dialog->vrtp, 0);
-+ ast_rtp_instance_set_timeout(dialog->vrtp, 0);
-+ ast_rtp_instance_set_hold_timeout(dialog->vrtp, 0);
- }
- }
- }
-@@ -22024,7 +22704,16 @@
- ast_set2_flag(&flags[0], ast_true(v->value), SIP_TRUSTRPID);
- } else if (!strcasecmp(v->name, "sendrpid")) {
- ast_set_flag(&mask[0], SIP_SENDRPID);
-- ast_set2_flag(&flags[0], ast_true(v->value), SIP_SENDRPID);
-+ if (!strcasecmp(v->value, "pai")) {
-+ ast_set_flag(&flags[0], SIP_SENDRPID_PAI);
-+ } else if (!strcasecmp(v->value, "rpid")) {
-+ ast_set_flag(&flags[0], SIP_SENDRPID_RPID);
-+ } else if (ast_true(v->value)) {
-+ ast_set_flag(&flags[0], SIP_SENDRPID_RPID);
-+ }
-+ } else if (!strcasecmp(v->name, "rpid_immediate")) {
-+ ast_set_flag(&mask[1], SIP_PAGE2_RPID_IMMEDIATE);
-+ ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_RPID_IMMEDIATE);
- } else if (!strcasecmp(v->name, "g726nonstandard")) {
- ast_set_flag(&mask[0], SIP_G726_NONSTANDARD);
- ast_set2_flag(&flags[0], ast_true(v->value), SIP_G726_NONSTANDARD);
-@@ -22332,6 +23021,7 @@
- ast_string_field_set(peer, language, default_language);
- ast_string_field_set(peer, mohinterpret, default_mohinterpret);
- ast_string_field_set(peer, mohsuggest, default_mohsuggest);
-+ ast_string_field_set(peer, engine, default_engine);
- peer->addr.sin_family = AF_INET;
- peer->defaddr.sin_family = AF_INET;
- peer->capability = global_capability;
-@@ -22671,6 +23361,8 @@
- ast_string_field_set(peer, mohsuggest, v->value);
- } else if (!strcasecmp(v->name, "parkinglot")) {
- ast_string_field_set(peer, parkinglot, v->value);
-+ } else if (!strcasecmp(v->name, "rtp_engine")) {
-+ ast_string_field_set(peer, engine, v->value);
- } else if (!strcasecmp(v->name, "mailbox")) {
- add_peer_mailboxes(peer, v->value);
- } else if (!strcasecmp(v->name, "hasvoicemail")) {
-@@ -22697,6 +23389,8 @@
- int error = ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, FALSE);
- if (error)
- ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value);
-+ } else if (!strcasecmp(v->name, "preferred_codec_only")) {
-+ ast_set2_flag(&peer->flags[1], ast_true(v->value), SIP_PAGE2_PREFERRED_CODEC);
- } else if (!strcasecmp(v->name, "registertrying")) {
- ast_set2_flag(&peer->flags[1], ast_true(v->value), SIP_PAGE2_REGISTERTRYING);
- } else if (!strcasecmp(v->name, "autoframing")) {
-@@ -23118,6 +23812,7 @@
- ast_set_flag(&global_flags[0], SIP_DTMF_RFC2833); /*!< Default DTMF setting: RFC2833 */
- ast_set_flag(&global_flags[0], SIP_NAT_RFC3581); /*!< NAT support if requested by device with rport */
- ast_set_flag(&global_flags[0], SIP_CAN_REINVITE); /*!< Allow re-invites */
-+ ast_copy_string(default_engine, DEFAULT_ENGINE, sizeof(default_engine));
-
- /* Debugging settings, always default to off */
- dumphistory = FALSE;
-@@ -23432,6 +24127,8 @@
- int error = ast_parse_allow_disallow(&default_prefs, &global_capability, v->value, FALSE);
- if (error)
- ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value);
-+ } else if (!strcasecmp(v->name, "preferred_codec_only")) {
-+ ast_set2_flag(&global_flags[1], ast_true(v->value), SIP_PAGE2_PREFERRED_CODEC);
- } else if (!strcasecmp(v->name, "autoframing")) {
- global_autoframing = ast_true(v->value);
- } else if (!strcasecmp(v->name, "allowexternaldomains")) {
-@@ -23856,156 +24553,176 @@
- return 0;
- }
-
--/*! \brief Returns null if we can't reinvite audio (part of RTP interface) */
--static enum ast_rtp_get_result sip_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
-+static enum ast_rtp_glue_result sip_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
- {
-- struct sip_pvt *p = NULL;
-- enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL;
-+ struct sip_pvt *p = NULL;
-+ enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_LOCAL;
-
-- if (!(p = chan->tech_pvt))
-- return AST_RTP_GET_FAILED;
--
-- sip_pvt_lock(p);
-- if (!(p->rtp)) {
-- sip_pvt_unlock(p);
-- return AST_RTP_GET_FAILED;
-+ if (!(p = chan->tech_pvt)) {
-+ return AST_RTP_GLUE_RESULT_FORBID;
- }
-
-- *rtp = p->rtp;
-+ sip_pvt_lock(p);
-+ if (!(p->rtp)) {
-+ sip_pvt_unlock(p);
-+ return AST_RTP_GLUE_RESULT_FORBID;
-+ }
-
-- if (ast_rtp_getnat(*rtp) && !ast_test_flag(&p->flags[0], SIP_CAN_REINVITE_NAT))
-- res = AST_RTP_TRY_PARTIAL;
-- else if (ast_test_flag(&p->flags[0], SIP_CAN_REINVITE))
-- res = AST_RTP_TRY_NATIVE;
-- else if (ast_test_flag(&global_jbconf, AST_JB_FORCED))
-- res = AST_RTP_GET_FAILED;
-+ ao2_ref(p->rtp, +1);
-+ *instance = p->rtp;
-
-- sip_pvt_unlock(p);
-+ if (!ast_test_flag(&p->flags[0], SIP_CAN_REINVITE_NAT)) {
-+ res = AST_RTP_GLUE_RESULT_LOCAL;
-+ } else if (ast_test_flag(&p->flags[0], SIP_CAN_REINVITE)) {
-+ res = AST_RTP_GLUE_RESULT_REMOTE;
-+ } else if (ast_test_flag(&global_jbconf, AST_JB_FORCED)) {
-+ res = AST_RTP_GLUE_RESULT_FORBID;
-+ }
-
-- return res;
-+ sip_pvt_unlock(p);
-+
-+ return res;
- }
-
--/*! \brief Returns null if we can't reinvite video (part of RTP interface) */
--static enum ast_rtp_get_result sip_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
-+static enum ast_rtp_glue_result sip_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
- {
- struct sip_pvt *p = NULL;
-- enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL;
--
-- if (!(p = chan->tech_pvt))
-- return AST_RTP_GET_FAILED;
-+ enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_FORBID;
-
-+ if (!(p = chan->tech_pvt)) {
-+ return AST_RTP_GLUE_RESULT_FORBID;
-+ }
-+
- sip_pvt_lock(p);
- if (!(p->vrtp)) {
- sip_pvt_unlock(p);
-- return AST_RTP_GET_FAILED;
-+ return AST_RTP_GLUE_RESULT_FORBID;
- }
-
-- *rtp = p->vrtp;
-+ ao2_ref(p->vrtp, +1);
-+ *instance = p->vrtp;
-
-- if (ast_test_flag(&p->flags[0], SIP_CAN_REINVITE))
-- res = AST_RTP_TRY_NATIVE;
-+ if (ast_test_flag(&p->flags[0], SIP_CAN_REINVITE)) {
-+ res = AST_RTP_GLUE_RESULT_REMOTE;
-+ }
-
- sip_pvt_unlock(p);
-
- return res;
- }
-
--/*! \brief Returns null if we can't reinvite text (part of RTP interface) */
--static enum ast_rtp_get_result sip_get_trtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
-+static enum ast_rtp_glue_result sip_get_trtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
- {
-- struct sip_pvt *p = NULL;
-- enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL;
--
-- if (!(p = chan->tech_pvt))
-- return AST_RTP_GET_FAILED;
-+ struct sip_pvt *p = NULL;
-+ enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_FORBID;
-
-- sip_pvt_lock(p);
-- if (!(p->trtp)) {
-- sip_pvt_unlock(p);
-- return AST_RTP_GET_FAILED;
-- }
-+ if (!(p = chan->tech_pvt)) {
-+ return AST_RTP_GLUE_RESULT_FORBID;
-+ }
-
-- *rtp = p->trtp;
-+ sip_pvt_lock(p);
-+ if (!(p->trtp)) {
-+ sip_pvt_unlock(p);
-+ return AST_RTP_GLUE_RESULT_FORBID;
-+ }
-
-- if (ast_test_flag(&p->flags[0], SIP_CAN_REINVITE))
-- res = AST_RTP_TRY_NATIVE;
-+ ao2_ref(p->trtp, +1);
-+ *instance = p->trtp;
-
-- sip_pvt_unlock(p);
-+ if (ast_test_flag(&p->flags[0], SIP_CAN_REINVITE)) {
-+ res = AST_RTP_GLUE_RESULT_REMOTE;
-+ }
-
-- return res;
-+ sip_pvt_unlock(p);
-+
-+ return res;
- }
-
--/*! \brief Set the RTP peer for this call */
--static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active)
-+static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *instance, struct ast_rtp_instance *vinstance, struct ast_rtp_instance *tinstance, int codecs, int nat_active)
- {
-- struct sip_pvt *p;
-- int changed = 0;
-+ struct sip_pvt *p;
-+ int changed = 0;
-
-- p = chan->tech_pvt;
-- if (!p)
-- return -1;
-+ p = chan->tech_pvt;
-+ if (!p)
-+ return -1;
-
- /* Disable early RTP bridge */
- if (chan->_state != AST_STATE_UP && !sip_cfg.directrtpsetup) /* We are in early state */
- return 0;
-
-- sip_pvt_lock(p);
-- if (p->alreadygone) {
-- /* If we're destroyed, don't bother */
-- sip_pvt_unlock(p);
-- return 0;
-- }
-+ sip_pvt_lock(p);
-+ if (p->alreadygone) {
-+ /* If we're destroyed, don't bother */
-+ sip_pvt_unlock(p);
-+ return 0;
-+ }
-
-- /* if this peer cannot handle reinvites of the media stream to devices
-- that are known to be behind a NAT, then stop the process now
-+ /* if this peer cannot handle reinvites of the media stream to devices
-+ that are known to be behind a NAT, then stop the process now
- */
-- if (nat_active && !ast_test_flag(&p->flags[0], SIP_CAN_REINVITE_NAT)) {
-- sip_pvt_unlock(p);
-- return 0;
-- }
-+ if (nat_active && !ast_test_flag(&p->flags[0], SIP_CAN_REINVITE_NAT)) {
-+ sip_pvt_unlock(p);
-+ return 0;
-+ }
-
-- if (rtp) {
-- changed |= ast_rtp_get_peer(rtp, &p->redirip);
-- } else if (p->redirip.sin_addr.s_addr || ntohs(p->redirip.sin_port) != 0) {
-- memset(&p->redirip, 0, sizeof(p->redirip));
-- changed = 1;
-- }
-- if (vrtp) {
-- changed |= ast_rtp_get_peer(vrtp, &p->vredirip);
-- } else if (p->vredirip.sin_addr.s_addr || ntohs(p->vredirip.sin_port) != 0) {
-- memset(&p->vredirip, 0, sizeof(p->vredirip));
-- changed = 1;
-- }
-- if (trtp) {
-- changed |= ast_rtp_get_peer(trtp, &p->tredirip);
-- } else if (p->tredirip.sin_addr.s_addr || ntohs(p->tredirip.sin_port) != 0) {
-- memset(&p->tredirip, 0, sizeof(p->tredirip));
-- changed = 1;
-- }
-- if (codecs && (p->redircodecs != codecs)) {
-- p->redircodecs = codecs;
-- changed = 1;
-- }
-- if (changed && !ast_test_flag(&p->flags[0], SIP_GOTREFER) && !ast_test_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER)) {
-- if (chan->_state != AST_STATE_UP) { /* We are in early state */
-- if (p->do_history)
-- append_history(p, "ExtInv", "Initial invite sent with remote bridge proposal.");
-- ast_debug(1, "Early remote bridge setting SIP '%s' - Sending media to %s\n", p->callid, ast_inet_ntoa(rtp ? p->redirip.sin_addr : p->ourip.sin_addr));
-- } else if (!p->pendinginvite) { /* We are up, and have no outstanding invite */
-- ast_debug(3, "Sending reinvite on SIP '%s' - It's audio soon redirected to IP %s\n", p->callid, ast_inet_ntoa(rtp ? p->redirip.sin_addr : p->ourip.sin_addr));
-- transmit_reinvite_with_sdp(p, FALSE, FALSE);
-- } else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) {
-- ast_debug(3, "Deferring reinvite on SIP '%s' - It's audio will be redirected to IP %s\n", p->callid, ast_inet_ntoa(rtp ? p->redirip.sin_addr : p->ourip.sin_addr));
-- /* We have a pending Invite. Send re-invite when we're done with the invite */
-- ast_set_flag(&p->flags[0], SIP_NEEDREINVITE);
-- }
-- }
-- /* Reset lastrtprx timer */
-- p->lastrtprx = p->lastrtptx = time(NULL);
-- sip_pvt_unlock(p);
-- return 0;
-+ if (instance) {
-+ changed |= ast_rtp_instance_get_remote_address(instance, &p->redirip);
-+ } else if (p->redirip.sin_addr.s_addr || ntohs(p->redirip.sin_port) != 0) {
-+ memset(&p->redirip, 0, sizeof(p->redirip));
-+ changed = 1;
-+ }
-+ if (vinstance) {
-+ changed |= ast_rtp_instance_get_remote_address(vinstance, &p->vredirip);
-+ } else if (p->vredirip.sin_addr.s_addr || ntohs(p->vredirip.sin_port) != 0) {
-+ memset(&p->vredirip, 0, sizeof(p->vredirip));
-+ changed = 1;
-+ }
-+ if (tinstance) {
-+ changed |= ast_rtp_instance_get_remote_address(tinstance, &p->tredirip);
-+ } else if (p->tredirip.sin_addr.s_addr || ntohs(p->tredirip.sin_port) != 0) {
-+ memset(&p->tredirip, 0, sizeof(p->tredirip));
-+ changed = 1;
-+ }
-+ if (codecs && (p->redircodecs != codecs)) {
-+ p->redircodecs = codecs;
-+ changed = 1;
-+ }
-+ if (changed && !ast_test_flag(&p->flags[0], SIP_GOTREFER) && !ast_test_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER)) {
-+ if (chan->_state != AST_STATE_UP) { /* We are in early state */
-+ if (p->do_history)
-+ append_history(p, "ExtInv", "Initial invite sent with remote bridge proposal.");
-+ ast_debug(1, "Early remote bridge setting SIP '%s' - Sending media to %s\n", p->callid, ast_inet_ntoa(instance ? p->redirip.sin_addr : p->ourip.sin_addr));
-+ } else if (!p->pendinginvite) { /* We are up, and have no outstanding invite */
-+ ast_debug(3, "Sending reinvite on SIP '%s' - It's audio soon redirected to IP %s\n", p->callid, ast_inet_ntoa(instance ? p->redirip.sin_addr : p->ourip.sin_addr));
-+ transmit_reinvite_with_sdp(p, FALSE, FALSE);
-+ } else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) {
-+ ast_debug(3, "Deferring reinvite on SIP '%s' - It's audio will be redirected to IP %s\n", p->callid, ast_inet_ntoa(instance ? p->redirip.sin_addr : p->ourip.sin_addr));
-+ /* We have a pending Invite. Send re-invite when we're done with the invite */
-+ ast_set_flag(&p->flags[0], SIP_NEEDREINVITE);
-+ }
-+ }
-+ /* Reset lastrtprx timer */
-+ p->lastrtprx = p->lastrtptx = time(NULL);
-+ sip_pvt_unlock(p);
-+ return 0;
- }
-
-+static int sip_get_codec(struct ast_channel *chan)
-+{
-+ struct sip_pvt *p = chan->tech_pvt;
-+ return p->peercapability ? p->peercapability : p->capability;
-+}
-+
-+static struct ast_rtp_glue sip_rtp_glue = {
-+ .type = "SIP",
-+ .get_rtp_info = sip_get_rtp_peer,
-+ .get_vrtp_info = sip_get_vrtp_peer,
-+ .get_trtp_info = sip_get_trtp_peer,
-+ .update_peer = sip_set_rtp_peer,
-+ .get_codec = sip_get_codec,
-+};
-+
- static char *app_dtmfmode = "SIPDtmfMode";
- static char *app_sipaddheader = "SIPAddHeader";
- static char *app_sipremoveheader = "SIPRemoveHeader";
-@@ -24051,7 +24768,7 @@
- } else
- ast_log(LOG_WARNING, "I don't know about this dtmf mode: %s\n", mode);
- if (p->rtp)
-- ast_rtp_setdtmf(p->rtp, ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
-+ ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_DTMF, ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
- if (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) {
- if (!p->vad) {
- p->vad = ast_dsp_new();
-@@ -24195,17 +24912,15 @@
-
- sip_scheddestroy(p, SIP_TRANS_TIMEOUT); /* Make sure we stop send this reply. */
- sip_alreadygone(p);
-+
-+ if (p->owner) {
-+ enum ast_control_transfer message = AST_TRANSFER_SUCCESS;
-+ ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message));
-+ }
- /* hangup here */
- return 0;
- }
-
--/*! \brief Return SIP UA's codec (part of the RTP interface) */
--static int sip_get_codec(struct ast_channel *chan)
--{
-- struct sip_pvt *p = chan->tech_pvt;
-- return p->jointcapability ? p->jointcapability : p->capability;
--}
--
- /*! \brief Send a poke to all known peers */
- static void sip_poke_all_peers(void)
- {
-@@ -24413,12 +25128,12 @@
- /* Register all CLI functions for SIP */
- ast_cli_register_multiple(cli_sip, ARRAY_LEN(cli_sip));
-
-- /* Tell the RTP subdriver that we're here */
-- ast_rtp_proto_register(&sip_rtp);
--
- /* Tell the UDPTL subdriver that we're here */
- ast_udptl_proto_register(&sip_udptl);
-
-+ /* Tell the RTP engine about our RTP glue */
-+ ast_rtp_glue_register(&sip_rtp_glue);
-+
- /* Register dialplan applications */
- ast_register_application_xml(app_dtmfmode, sip_dtmfmode);
- ast_register_application_xml(app_sipaddheader, sip_addheader);
-@@ -24489,12 +25204,12 @@
- /* Unregister CLI commands */
- ast_cli_unregister_multiple(cli_sip, ARRAY_LEN(cli_sip));
-
-- /* Disconnect from the RTP subsystem */
-- ast_rtp_proto_unregister(&sip_rtp);
--
- /* Disconnect from UDPTL */
- ast_udptl_proto_unregister(&sip_udptl);
-
-+ /* Disconnect from RTP engine */
-+ ast_rtp_glue_unregister(&sip_rtp_glue);
-+
- /* Unregister AMI actions */
- ast_manager_unregister("SIPpeers");
- ast_manager_unregister("SIPshowpeer");
-Index: channels/chan_agent.c
-===================================================================
---- a/channels/chan_agent.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/channels/chan_agent.c (.../trunk) (revision 186562)
-@@ -52,7 +52,6 @@
- #include "asterisk/pbx.h"
- #include "asterisk/sched.h"
- #include "asterisk/io.h"
--#include "asterisk/rtp.h"
- #include "asterisk/acl.h"
- #include "asterisk/callerid.h"
- #include "asterisk/file.h"
-@@ -758,8 +757,7 @@
- time(&p->start);
- /* Call on this agent */
- ast_verb(3, "outgoing agentcall, to agent '%s', on '%s'\n", p->agent, p->chan->name);
-- ast_set_callerid(p->chan,
-- ast->cid.cid_num, ast->cid.cid_name, NULL);
-+ ast_channel_set_connected_line(p->chan, &ast->connected);
- ast_channel_inherit_variables(ast, p->chan);
- res = ast_call(p->chan, p->loginchan, 0);
- CLEANUP(ast,p);
-Index: channels/Makefile
-===================================================================
---- a/channels/Makefile (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/channels/Makefile (.../trunk) (revision 186562)
-@@ -57,25 +57,14 @@
- LIBS+= -lres_monitor.so -lres_features.so
- endif
-
--clean::
-- $(MAKE) -C misdn clean
--
- ifneq ($(wildcard h323/Makefile.ast),)
-- include h323/Makefile.ast
-+include h323/Makefile.ast
-+endif
- H323LDFLAGS+=-Wl,--version-script=h323/noexport.map
-+
- clean::
-+ $(MAKE) -C misdn clean
- if [ -f h323/Makefile ]; then $(MAKE) -C h323 clean; fi
--else
--h323/libchanh323.a h323/Makefile.ast:
-- $(CMD_PREFIX) $(MAKE) -C h323
-- $(CMD_PREFIX) rm -f ../main/asterisk
-- $(CMD_PREFIX) echo "***************************************************************"
-- $(CMD_PREFIX) echo
-- $(CMD_PREFIX) echo "********** Re-run 'make' to pick up H.323 parameters **********"
-- $(CMD_PREFIX) echo
-- $(CMD_PREFIX) echo "***************************************************************"
-- $(CMD_PREFIX) exit 1
--endif
-
- dist-clean::
- rm -f h323/Makefile
-@@ -107,4 +96,10 @@
- chan_usbradio.so: LIBS+=-lusb -lasound
- chan_usbradio.so: ASTCFLAGS+=-DNDEBUG
-
-+h323/Makefile.ast:
-+ $(CMD_PREFIX) $(MAKE) -C h323 Makefile.ast
-
-+h323/libchanh323.a:
-+ $(CMD_PREFIX) $(MAKE) -C h323 libchanh323.a
-+
-+
-Index: channels/chan_iax2.c
-===================================================================
---- a/channels/chan_iax2.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/channels/chan_iax2.c (.../trunk) (revision 186562)
-@@ -88,6 +88,7 @@
- #include "asterisk/event.h"
- #include "asterisk/astobj2.h"
- #include "asterisk/timing.h"
-+#include "asterisk/taskprocessor.h"
-
- #include "iax2.h"
- #include "iax2-parser.h"
-@@ -257,7 +258,7 @@
-
- static int srvlookup = 0;
-
--static int timingfd = -1; /* Timing file descriptor */
-+static struct ast_timer *timer; /* Timer for trunking */
-
- static struct ast_netsock_list *netsock;
- static struct ast_netsock_list *outsock; /*!< used if sourceaddress specified and bindaddr == INADDR_ANY */
-@@ -270,6 +271,9 @@
- /* T1, maybe ISDN */
- #define IAX_CAPABILITY_MEDBANDWIDTH (IAX_CAPABILITY_FULLBANDWIDTH & \
- ~AST_FORMAT_SLINEAR & \
-+ ~AST_FORMAT_SLINEAR16 & \
-+ ~AST_FORMAT_SIREN7 & \
-+ ~AST_FORMAT_SIREN14 & \
- ~AST_FORMAT_ULAW & \
- ~AST_FORMAT_ALAW & \
- ~AST_FORMAT_G722)
-@@ -376,7 +380,9 @@
- them before sending voice or anything else*/
- IAX_ALLOWFWDOWNLOAD = (1 << 26), /*!< Allow the FWDOWNL command? */
- IAX_IMMEDIATE = (1 << 27), /*!< Allow immediate off-hook to extension s */
-- IAX_FORCE_ENCRYPT = (1 << 28), /*!< Forces call encryption, if encryption not possible hangup */
-+ IAX_SENDCONNECTEDLINE = (1 << 28), /*!< Allow sending of connected line updates */
-+ IAX_RECVCONNECTEDLINE = (1 << 29), /*!< Allow receiving of connected line updates */
-+ IAX_FORCE_ENCRYPT = (1 << 30), /*!< Forces call encryption, if encryption not possible hangup */
- };
-
- static int global_rtautoclear = 120;
-@@ -755,9 +761,13 @@
- * \note The contents of this list do not need to be explicitly destroyed
- * on module unload. This is because all active calls are destroyed, and
- * all frames in this queue will get destroyed as a part of that process.
-+ *
-+ * \note Contents protected by the iaxsl[] locks
- */
--static AST_LIST_HEAD_STATIC(frame_queue, iax_frame);
-+static AST_LIST_HEAD_NOLOCK(, iax_frame) frame_queue[IAX_MAX_CALLS];
-
-+static struct ast_taskprocessor *transmit_processor;
-+
- /*!
- * This module will get much higher performance when doing a lot of
- * user and peer lookups if the number of buckets is increased from 1.
-@@ -1585,21 +1595,19 @@
- struct iax_frame *cur = NULL;
-
- ast_mutex_lock(&iaxsl[pvt->callno]);
-+
- iax2_destroy_helper(pvt);
-- ast_mutex_unlock(&iaxsl[pvt->callno]);
-
- /* Already gone */
-- ast_set_flag(pvt, IAX_ALREADYGONE);
-+ ast_set_flag(pvt, IAX_ALREADYGONE);
-
-- AST_LIST_LOCK(&frame_queue);
-- AST_LIST_TRAVERSE(&frame_queue, cur, list) {
-+ AST_LIST_TRAVERSE(&frame_queue[pvt->callno], cur, list) {
- /* Cancel any pending transmissions */
-- if (cur->callno == pvt->callno) {
-- cur->retries = -1;
-- }
-+ cur->retries = -1;
- }
-- AST_LIST_UNLOCK(&frame_queue);
-
-+ ast_mutex_unlock(&iaxsl[pvt->callno]);
-+
- if (pvt->reg) {
- pvt->reg->callno = 0;
- }
-@@ -1970,7 +1978,7 @@
- iaxs[x]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, (void *)(long)x);
- iaxs[x]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, (void *)(long)x);
- iaxs[x]->amaflags = amaflags;
-- ast_copy_flags(iaxs[x], &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_FORCE_ENCRYPT);
-+ ast_copy_flags(iaxs[x], &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE | IAX_FORCE_ENCRYPT);
- ast_string_field_set(iaxs[x], accountcode, accountcode);
- ast_string_field_set(iaxs[x], mohinterpret, mohinterpret);
- ast_string_field_set(iaxs[x], mohsuggest, mohsuggest);
-@@ -2620,17 +2628,16 @@
- f->retries = -1;
- freeme = 1;
- }
-- if (callno)
-- ast_mutex_unlock(&iaxsl[callno]);
-- /* Do not try again */
-+
- if (freeme) {
- /* Don't attempt delivery, just remove it from the queue */
-- AST_LIST_LOCK(&frame_queue);
-- AST_LIST_REMOVE(&frame_queue, f, list);
-- AST_LIST_UNLOCK(&frame_queue);
-+ AST_LIST_REMOVE(&frame_queue[callno], f, list);
-+ ast_mutex_unlock(&iaxsl[callno]);
- f->retrans = -1;
- /* Free the IAX frame */
- iax2_frame_free(f);
-+ } else if (callno) {
-+ ast_mutex_unlock(&iaxsl[callno]);
- }
- }
-
-@@ -2920,7 +2927,7 @@
- static char *handle_cli_iax2_show_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
- {
- struct iax_frame *cur;
-- int cnt = 0, dead = 0, final = 0;
-+ int cnt = 0, dead = 0, final = 0, i = 0;
-
- switch (cmd) {
- case CLI_INIT:
-@@ -2936,15 +2943,17 @@
- if (a->argc != 3)
- return CLI_SHOWUSAGE;
-
-- AST_LIST_LOCK(&frame_queue);
-- AST_LIST_TRAVERSE(&frame_queue, cur, list) {
-- if (cur->retries < 0)
-- dead++;
-- if (cur->final)
-- final++;
-- cnt++;
-+ for (i = 0; i < ARRAY_LEN(frame_queue); i++) {
-+ ast_mutex_lock(&iaxsl[i]);
-+ AST_LIST_TRAVERSE(&frame_queue[i], cur, list) {
-+ if (cur->retries < 0)
-+ dead++;
-+ if (cur->final)
-+ final++;
-+ cnt++;
-+ }
-+ ast_mutex_unlock(&iaxsl[i]);
- }
-- AST_LIST_UNLOCK(&frame_queue);
-
- ast_cli(a->fd, " IAX Statistics\n");
- ast_cli(a->fd, "---------------------\n");
-@@ -3301,23 +3310,39 @@
- return 0;
- }
-
--static int iax2_transmit(struct iax_frame *fr)
-+static int transmit_frame(void *data)
- {
-- /* Lock the queue and place this packet at the end */
-- /* By setting this to 0, the network thread will send it for us, and
-- queue retransmission if necessary */
-- fr->sentyet = 0;
-- AST_LIST_LOCK(&frame_queue);
-- AST_LIST_INSERT_TAIL(&frame_queue, fr, list);
-- AST_LIST_UNLOCK(&frame_queue);
-- /* Wake up the network and scheduler thread */
-- if (netthreadid != AST_PTHREADT_NULL)
-- pthread_kill(netthreadid, SIGURG);
-- ast_sched_thread_poke(sched);
-+ struct iax_frame *fr = data;
-+
-+ ast_mutex_lock(&iaxsl[fr->callno]);
-+
-+ fr->sentyet = 1;
-+
-+ if (iaxs[fr->callno]) {
-+ send_packet(fr);
-+ }
-+
-+ if (fr->retries < 0) {
-+ ast_mutex_unlock(&iaxsl[fr->callno]);
-+ /* No retransmit requested */
-+ iax_frame_free(fr);
-+ } else {
-+ /* We need reliable delivery. Schedule a retransmission */
-+ AST_LIST_INSERT_TAIL(&frame_queue[fr->callno], fr, list);
-+ ast_mutex_unlock(&iaxsl[fr->callno]);
-+ fr->retries++;
-+ fr->retrans = iax2_sched_add(sched, fr->retrytime, attempt_transmit, fr);
-+ }
-+
- return 0;
- }
-
-+static int iax2_transmit(struct iax_frame *fr)
-+{
-+ fr->sentyet = 0;
-
-+ return ast_taskprocessor_push(transmit_processor, transmit_frame, fr);
-+}
-
- static int iax2_digit_begin(struct ast_channel *c, char digit)
- {
-@@ -3578,6 +3603,8 @@
- char outkey[80];
- char timezone[80];
- char prefs[32];
-+ char cid_num[80];
-+ char cid_name[80];
- char context[AST_MAX_CONTEXT];
- char peercontext[AST_MAX_CONTEXT];
- char mohinterpret[MAX_MUSICCLASS];
-@@ -3621,7 +3648,7 @@
- if (peer->maxms && ((peer->lastms > peer->maxms) || (peer->lastms < 0)))
- goto return_unref;
-
-- ast_copy_flags(cai, peer, IAX_SENDANI | IAX_TRUNK | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_FORCE_ENCRYPT);
-+ ast_copy_flags(cai, peer, IAX_SENDANI | IAX_TRUNK | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE | IAX_FORCE_ENCRYPT);
- cai->maxtime = peer->maxms;
- cai->capability = peer->capability;
- cai->encmethods = peer->encmethods;
-@@ -3639,6 +3666,8 @@
- ast_copy_string(cai->username, peer->username, sizeof(cai->username));
- ast_copy_string(cai->timezone, peer->zonetag, sizeof(cai->timezone));
- ast_copy_string(cai->outkey, peer->outkey, sizeof(cai->outkey));
-+ ast_copy_string(cai->cid_num, peer->cid_num, sizeof(cai->cid_num));
-+ ast_copy_string(cai->cid_name, peer->cid_name, sizeof(cai->cid_name));
- ast_copy_string(cai->mohinterpret, peer->mohinterpret, sizeof(cai->mohinterpret));
- ast_copy_string(cai->mohsuggest, peer->mohsuggest, sizeof(cai->mohsuggest));
- if (ast_strlen_zero(peer->dbsecret)) {
-@@ -3847,8 +3876,8 @@
- if (pds.port)
- sin.sin_port = htons(atoi(pds.port));
-
-- l = c->cid.cid_num;
-- n = c->cid.cid_name;
-+ l = c->connected.id.number;
-+ n = c->connected.id.name;
-
- /* Now build request */
- memset(&ied, 0, sizeof(ied));
-@@ -3865,21 +3894,21 @@
-
- if (l) {
- iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, l);
-- iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres);
-+ iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->connected.id.number_presentation);
- } else {
- if (n)
-- iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres);
-+ iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->connected.id.number_presentation);
- else
- iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, AST_PRES_NUMBER_NOT_AVAILABLE);
- }
-
-- iax_ie_append_byte(&ied, IAX_IE_CALLINGTON, c->cid.cid_ton);
-+ iax_ie_append_byte(&ied, IAX_IE_CALLINGTON, c->connected.id.number_type);
- iax_ie_append_short(&ied, IAX_IE_CALLINGTNS, c->cid.cid_tns);
-
- if (n)
- iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, n);
-- if (ast_test_flag(iaxs[callno], IAX_SENDANI) && c->cid.cid_ani)
-- iax_ie_append_str(&ied, IAX_IE_CALLING_ANI, c->cid.cid_ani);
-+ if (ast_test_flag(iaxs[callno], IAX_SENDANI) && c->connected.ani)
-+ iax_ie_append_str(&ied, IAX_IE_CALLING_ANI, c->connected.ani);
-
- if (!ast_strlen_zero(c->language))
- iax_ie_append_str(&ied, IAX_IE_LANGUAGE, c->language);
-@@ -4375,6 +4404,11 @@
- ast_moh_stop(c);
- goto done;
- }
-+ break;
-+ case AST_CONTROL_CONNECTED_LINE:
-+ if (!ast_test_flag(pvt, IAX_SENDCONNECTEDLINE))
-+ goto done;
-+ break;
- }
-
- res = send_command(pvt, AST_FRAME_CONTROL, condition, 0, data, datalen, -1);
-@@ -4390,6 +4424,7 @@
- unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
- struct iax_ie_data ied = { "", };
- char tmp[256], *context;
-+ enum ast_control_transfer message = AST_TRANSFER_SUCCESS;
- ast_copy_string(tmp, dest, sizeof(tmp));
- context = strchr(tmp, '@');
- if (context) {
-@@ -4400,6 +4435,7 @@
- if (context)
- iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, context);
- ast_debug(1, "Transferring '%s' to '%s'\n", c->name, dest);
-+ ast_queue_control_data(c, AST_CONTROL_TRANSFER, &message, sizeof(message));
- return send_command_locked(callno, AST_FRAME_IAX, IAX_COMMAND_TRANSFER, 0, ied.buf, ied.pos, -1);
- }
-
-@@ -6356,7 +6392,7 @@
- iaxs[callno]->amaflags = user->amaflags;
- if (!ast_strlen_zero(user->language))
- ast_string_field_set(iaxs[callno], language, user->language);
-- ast_copy_flags(iaxs[callno], user, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
-+ ast_copy_flags(iaxs[callno], user, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
- /* Keep this check last */
- if (!ast_strlen_zero(user->dbsecret)) {
- char *family, *key=NULL;
-@@ -6682,15 +6718,20 @@
- ast_devstate_changed(AST_DEVICE_UNKNOWN, "IAX2/%s", p->name); /* Activate notification */
-
- return_unref:
-- ast_string_field_set(iaxs[callno], peer, peer);
-- /* Choose lowest expiry number */
-- if (expire && (expire < iaxs[callno]->expiry))
-- iaxs[callno]->expiry = expire;
-+ if (iaxs[callno]) {
-+ ast_string_field_set(iaxs[callno], peer, peer);
-
-+ /* Choose lowest expiry number */
-+ if (expire && (expire < iaxs[callno]->expiry)) {
-+ iaxs[callno]->expiry = expire;
-+ }
-+ }
-+
- res = 0;
-
-- if (p)
-+ if (p) {
- peer_unref(p);
-+ }
-
- return res;
- }
-@@ -7007,16 +7048,13 @@
- pvt->lastsent = 0;
- pvt->nextpred = 0;
- pvt->pingtime = DEFAULT_RETRY_TIME;
-- AST_LIST_LOCK(&frame_queue);
-- AST_LIST_TRAVERSE(&frame_queue, cur, list) {
-+ AST_LIST_TRAVERSE(&frame_queue[callno], cur, list) {
- /* We must cancel any packets that would have been transmitted
- because now we're talking to someone new. It's okay, they
- were transmitted to someone that didn't care anyway. */
-- if (callno == cur->callno)
-- cur->retries = -1;
-+ cur->retries = -1;
- }
-- AST_LIST_UNLOCK(&frame_queue);
-- return 0;
-+ return 0;
- }
-
- /*! \brief Acknowledgment received for OUR registration */
-@@ -7386,8 +7424,6 @@
- event = ast_event_get_cached(AST_EVENT_MWI,
- AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
- AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
-- AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
-- AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
- AST_EVENT_IE_END);
- if (event) {
- new = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
-@@ -7621,16 +7657,13 @@
- {
- struct iax_frame *f;
-
-- AST_LIST_LOCK(&frame_queue);
-- AST_LIST_TRAVERSE(&frame_queue, f, list) {
-+ AST_LIST_TRAVERSE(&frame_queue[callno], f, list) {
- /* Send a copy immediately */
-- if ((f->callno == callno) && iaxs[f->callno] &&
-- ((unsigned char ) (f->oseqno - last) < 128) &&
-- (f->retries >= 0)) {
-+ if (((unsigned char) (f->oseqno - last) < 128) &&
-+ (f->retries >= 0)) {
- send_packet(f);
- }
- }
-- AST_LIST_UNLOCK(&frame_queue);
- }
-
- static void __iax2_poke_peer_s(const void *data)
-@@ -7711,8 +7744,8 @@
- if (iaxtrunkdebug)
- ast_verbose("Beginning trunk processing. Trunk queue ceiling is %d bytes per host\n", trunkmaxsize);
-
-- if (timingfd > -1) {
-- ast_timer_ack(timingfd, 1);
-+ if (timer) {
-+ ast_timer_ack(timer, 1);
- }
-
- /* For each peer that supports trunking... */
-@@ -8647,17 +8680,15 @@
- if (iaxdebug)
- ast_debug(1, "Cancelling transmission of packet %d\n", x);
- call_to_destroy = 0;
-- AST_LIST_LOCK(&frame_queue);
-- AST_LIST_TRAVERSE(&frame_queue, cur, list) {
-+ AST_LIST_TRAVERSE(&frame_queue[fr->callno], cur, list) {
- /* If it's our call, and our timestamp, mark -1 retries */
-- if ((fr->callno == cur->callno) && (x == cur->oseqno)) {
-+ if (x == cur->oseqno) {
- cur->retries = -1;
- /* Destroy call if this is the end */
- if (cur->final)
- call_to_destroy = fr->callno;
- }
- }
-- AST_LIST_UNLOCK(&frame_queue);
- if (call_to_destroy) {
- if (iaxdebug)
- ast_debug(1, "Really destroying %d, having been acked on final message\n", call_to_destroy);
-@@ -8899,13 +8930,12 @@
- case IAX_COMMAND_TXACC:
- if (iaxs[fr->callno]->transferring == TRANSFER_BEGIN) {
- /* Ack the packet with the given timestamp */
-- AST_LIST_LOCK(&frame_queue);
-- AST_LIST_TRAVERSE(&frame_queue, cur, list) {
-+ AST_LIST_TRAVERSE(&frame_queue[fr->callno], cur, list) {
- /* Cancel any outstanding txcnt's */
-- if ((fr->callno == cur->callno) && (cur->transfer))
-+ if (cur->transfer) {
- cur->retries = -1;
-+ }
- }
-- AST_LIST_UNLOCK(&frame_queue);
- memset(&ied1, 0, sizeof(ied1));
- iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->callno);
- send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXREADY, 0, ied1.buf, ied1.pos, -1);
-@@ -9804,13 +9834,12 @@
- break;
- case IAX_COMMAND_TXMEDIA:
- if (iaxs[fr->callno]->transferring == TRANSFER_READY) {
-- AST_LIST_LOCK(&frame_queue);
-- AST_LIST_TRAVERSE(&frame_queue, cur, list) {
-+ AST_LIST_TRAVERSE(&frame_queue[fr->callno], cur, list) {
- /* Cancel any outstanding frames and start anew */
-- if ((fr->callno == cur->callno) && (cur->transfer))
-+ if (cur->transfer) {
- cur->retries = -1;
-+ }
- }
-- AST_LIST_UNLOCK(&frame_queue);
- /* Start sending our media to the transfer address, but otherwise leave the call as-is */
- iaxs[fr->callno]->transferring = TRANSFER_MEDIAPASS;
- }
-@@ -9936,6 +9965,31 @@
- ast_mutex_unlock(&iaxsl[fr->callno]);
- return 1;
- }
-+ /* Don't allow connected line updates unless we are configured to */
-+ if (f.frametype == AST_FRAME_CONTROL && f.subclass == AST_CONTROL_CONNECTED_LINE) {
-+ struct ast_party_connected_line connected;
-+
-+ if (!ast_test_flag(iaxs[fr->callno], IAX_RECVCONNECTEDLINE)) {
-+ ast_mutex_unlock(&iaxsl[fr->callno]);
-+ return 1;
-+ }
-+
-+ /* Initialize defaults */
-+ ast_party_connected_line_init(&connected);
-+ connected.id.number_presentation = iaxs[fr->callno]->calling_pres;
-+
-+ if (!ast_connected_line_parse_data(f.data.ptr, f.datalen, &connected)) {
-+ ast_string_field_set(iaxs[fr->callno], cid_num, connected.id.number);
-+ ast_string_field_set(iaxs[fr->callno], cid_name, connected.id.name);
-+ iaxs[fr->callno]->calling_pres = connected.id.number_presentation;
-+
-+ if (iaxs[fr->callno]->owner) {
-+ ast_set_callerid(iaxs[fr->callno]->owner, S_OR(connected.id.number, ""), S_OR(connected.id.name, ""), NULL);
-+ iaxs[fr->callno]->owner->cid.cid_pres = connected.id.number_presentation;
-+ }
-+ }
-+ ast_party_connected_line_free(&connected);
-+ }
- /* Common things */
- f.src = "IAX2";
- f.mallocd = 0;
-@@ -10431,7 +10485,7 @@
- memset(&cai, 0, sizeof(cai));
- cai.capability = iax2_capability;
-
-- ast_copy_flags(&cai, &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
-+ ast_copy_flags(&cai, &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
-
- /* Populate our address from the given */
- if (create_addr(pds.peer, NULL, &sin, &cai)) {
-@@ -10450,7 +10504,7 @@
- }
-
- /* If this is a trunk, update it now */
-- ast_copy_flags(iaxs[callno], &cai, IAX_TRUNK | IAX_SENDANI | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
-+ ast_copy_flags(iaxs[callno], &cai, IAX_TRUNK | IAX_SENDANI | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
- if (ast_test_flag(&cai, IAX_TRUNK)) {
- int new_callno;
- if ((new_callno = make_trunk(callno, 1)) != -1)
-@@ -10489,66 +10543,18 @@
-
- static void *network_thread(void *ignore)
- {
-- /* Our job is simple: Send queued messages, retrying if necessary. Read frames
-- from the network, and queue them for delivery to the channels */
-- int res, count, wakeup;
-- struct iax_frame *f;
-+ if (timer) {
-+ ast_io_add(io, ast_timer_fd(timer), timing_read, AST_IO_IN | AST_IO_PRI, NULL);
-+ }
-
-- if (timingfd > -1)
-- ast_io_add(io, timingfd, timing_read, AST_IO_IN | AST_IO_PRI, NULL);
--
-- for(;;) {
-+ for (;;) {
- pthread_testcancel();
-+ /* Wake up once a second just in case SIGURG was sent while
-+ * we weren't in poll(), to make sure we don't hang when trying
-+ * to unload. */
-+ ast_io_wait(io, 1000);
-+ }
-
-- /* Go through the queue, sending messages which have not yet been
-- sent, and scheduling retransmissions if appropriate */
-- AST_LIST_LOCK(&frame_queue);
-- count = 0;
-- wakeup = -1;
-- AST_LIST_TRAVERSE_SAFE_BEGIN(&frame_queue, f, list) {
-- if (f->sentyet)
-- continue;
--
-- /* Try to lock the pvt, if we can't... don't fret - defer it till later */
-- if (ast_mutex_trylock(&iaxsl[f->callno])) {
-- wakeup = 1;
-- continue;
-- }
--
-- f->sentyet = 1;
--
-- if (iaxs[f->callno]) {
-- send_packet(f);
-- count++;
-- }
--
-- ast_mutex_unlock(&iaxsl[f->callno]);
--
-- if (f->retries < 0) {
-- /* This is not supposed to be retransmitted */
-- AST_LIST_REMOVE_CURRENT(list);
-- /* Free the iax frame */
-- iax_frame_free(f);
-- } else {
-- /* We need reliable delivery. Schedule a retransmission */
-- f->retries++;
-- f->retrans = iax2_sched_add(sched, f->retrytime, attempt_transmit, f);
-- }
-- }
-- AST_LIST_TRAVERSE_SAFE_END;
-- AST_LIST_UNLOCK(&frame_queue);
--
-- pthread_testcancel();
-- if (count >= 20)
-- ast_debug(1, "chan_iax2: Sent %d queued outbound frames all at once\n", count);
--
-- /* Now do the IO, and run scheduled tasks */
-- res = ast_io_wait(io, wakeup);
-- if (res >= 0) {
-- if (res >= 20)
-- ast_debug(1, "chan_iax2: ast_io_wait ran %d I/Os all at once\n", res);
-- }
-- }
- return NULL;
- }
-
-@@ -10761,7 +10767,7 @@
-
- if (peer) {
- if (firstpass) {
-- ast_copy_flags(peer, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_FORCE_ENCRYPT);
-+ ast_copy_flags(peer, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE | IAX_FORCE_ENCRYPT);
- peer->encmethods = iax2_encryption;
- peer->adsi = adsi;
- ast_string_field_set(peer,secret,"");
-@@ -10803,7 +10809,7 @@
- ast_string_field_set(peer, dbsecret, v->value);
- } else if (!strcasecmp(v->name, "trunk")) {
- ast_set2_flag(peer, ast_true(v->value), IAX_TRUNK);
-- if (ast_test_flag(peer, IAX_TRUNK) && (timingfd < 0)) {
-+ if (ast_test_flag(peer, IAX_TRUNK) && !timer) {
- ast_log(LOG_WARNING, "Unable to support trunking on peer '%s' without a timing interface\n", peer->name);
- ast_clear_flag(peer, IAX_TRUNK);
- }
-@@ -10934,6 +10940,18 @@
- ast_string_field_set(peer, zonetag, v->value);
- } else if (!strcasecmp(v->name, "adsi")) {
- peer->adsi = ast_true(v->value);
-+ } else if (!strcasecmp(v->name, "connectedline")) {
-+ if (ast_true(v->value)) {
-+ ast_set_flag(peer, IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
-+ } else if (!strcasecmp(v->value, "send")) {
-+ ast_clear_flag(peer, IAX_RECVCONNECTEDLINE);
-+ ast_set_flag(peer, IAX_SENDCONNECTEDLINE);
-+ } else if (!strcasecmp(v->value, "receive")) {
-+ ast_clear_flag(peer, IAX_SENDCONNECTEDLINE);
-+ ast_set_flag(peer, IAX_RECVCONNECTEDLINE);
-+ } else {
-+ ast_clear_flag(peer, IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
-+ }
- }/* else if (strcasecmp(v->name,"type")) */
- /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
- v = v->next;
-@@ -11032,7 +11050,7 @@
- user->adsi = adsi;
- ast_string_field_set(user, name, name);
- ast_string_field_set(user, language, language);
-- ast_copy_flags(user, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_CODEC_USER_FIRST | IAX_CODEC_NOPREFS | IAX_CODEC_NOCAP | IAX_FORCE_ENCRYPT);
-+ ast_copy_flags(user, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_CODEC_USER_FIRST | IAX_CODEC_NOPREFS | IAX_CODEC_NOCAP | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE | IAX_FORCE_ENCRYPT);
- ast_clear_flag(user, IAX_HASCALLERID);
- ast_string_field_set(user, cid_name, "");
- ast_string_field_set(user, cid_num, "");
-@@ -11070,7 +11088,7 @@
- ast_parse_allow_disallow(&user->prefs, &user->capability,v->value, 0);
- } else if (!strcasecmp(v->name, "trunk")) {
- ast_set2_flag(user, ast_true(v->value), IAX_TRUNK);
-- if (ast_test_flag(user, IAX_TRUNK) && (timingfd < 0)) {
-+ if (ast_test_flag(user, IAX_TRUNK) && !timer) {
- ast_log(LOG_WARNING, "Unable to support trunking on user '%s' without a timing interface\n", user->name);
- ast_clear_flag(user, IAX_TRUNK);
- }
-@@ -11177,6 +11195,18 @@
- user->maxauthreq = 0;
- } else if (!strcasecmp(v->name, "adsi")) {
- user->adsi = ast_true(v->value);
-+ } else if (!strcasecmp(v->name, "connectedline")) {
-+ if (ast_true(v->value)) {
-+ ast_set_flag(user, IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
-+ } else if (!strcasecmp(v->value, "send")) {
-+ ast_clear_flag(user, IAX_RECVCONNECTEDLINE);
-+ ast_set_flag(user, IAX_SENDCONNECTEDLINE);
-+ } else if (!strcasecmp(v->value, "receive")) {
-+ ast_clear_flag(user, IAX_SENDCONNECTEDLINE);
-+ ast_set_flag(user, IAX_RECVCONNECTEDLINE);
-+ } else {
-+ ast_clear_flag(user, IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
-+ }
- }/* else if (strcasecmp(v->name,"type")) */
- /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
- v = v->next;
-@@ -11292,10 +11322,8 @@
- trunkmaxsize = MAX_TRUNKDATA;
- amaflags = 0;
- delayreject = 0;
-- ast_clear_flag((&globalflags), IAX_NOTRANSFER);
-- ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA);
-- ast_clear_flag((&globalflags), IAX_USEJITTERBUF);
-- ast_clear_flag((&globalflags), IAX_FORCEJITTERBUF);
-+ ast_clear_flag((&globalflags), IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF |
-+ IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
- delete_users();
- }
-
-@@ -11599,6 +11627,18 @@
- adsi = ast_true(v->value);
- } else if (!strcasecmp(v->name, "srvlookup")) {
- srvlookup = ast_true(v->value);
-+ } else if (!strcasecmp(v->name, "connectedline")) {
-+ if (ast_true(v->value)) {
-+ ast_set_flag((&globalflags), IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
-+ } else if (!strcasecmp(v->value, "send")) {
-+ ast_clear_flag((&globalflags), IAX_RECVCONNECTEDLINE);
-+ ast_set_flag((&globalflags), IAX_SENDCONNECTEDLINE);
-+ } else if (!strcasecmp(v->value, "receive")) {
-+ ast_clear_flag((&globalflags), IAX_SENDCONNECTEDLINE);
-+ ast_set_flag((&globalflags), IAX_RECVCONNECTEDLINE);
-+ } else {
-+ ast_clear_flag((&globalflags), IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
-+ }
- } /*else if (strcasecmp(v->name,"type")) */
- /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
- v = v->next;
-@@ -12420,19 +12460,14 @@
- struct ast_context *con;
- int x;
-
-- /* Make sure threads do not hold shared resources when they are canceled */
--
-- /* Grab the sched lock resource to keep it away from threads about to die */
-- /* Cancel the network thread, close the net socket */
- if (netthreadid != AST_PTHREADT_NULL) {
-- AST_LIST_LOCK(&frame_queue);
- pthread_cancel(netthreadid);
-- AST_LIST_UNLOCK(&frame_queue);
-+ pthread_kill(netthreadid, SIGURG);
- pthread_join(netthreadid, NULL);
- }
-
- sched = ast_sched_thread_destroy(sched);
--
-+
- /* Call for all threads to halt */
- AST_LIST_LOCK(&idle_list);
- while ((thread = AST_LIST_REMOVE_HEAD(&idle_list, list)))
-@@ -12480,9 +12515,10 @@
- ao2_ref(users, -1);
- ao2_ref(iax_peercallno_pvts, -1);
- ao2_ref(iax_transfercallno_pvts, -1);
-- if (timingfd > -1) {
-- ast_timer_close(timingfd);
-+ if (timer) {
-+ ast_timer_close(timer);
- }
-+ transmit_processor = ast_taskprocessor_unreference(transmit_processor);
-
- con = ast_context_find(regcontext);
- if (con)
-@@ -12551,19 +12587,23 @@
- struct iax2_registry *reg = NULL;
-
- peers = ao2_container_alloc(MAX_PEER_BUCKETS, peer_hash_cb, peer_cmp_cb);
-- if (!peers)
-+ if (!peers) {
- return AST_MODULE_LOAD_FAILURE;
-+ }
-+
- users = ao2_container_alloc(MAX_USER_BUCKETS, user_hash_cb, user_cmp_cb);
- if (!users) {
- ao2_ref(peers, -1);
- return AST_MODULE_LOAD_FAILURE;
- }
-+
- iax_peercallno_pvts = ao2_container_alloc(IAX_MAX_CALLS, pvt_hash_cb, pvt_cmp_cb);
- if (!iax_peercallno_pvts) {
- ao2_ref(peers, -1);
- ao2_ref(users, -1);
- return AST_MODULE_LOAD_FAILURE;
- }
-+
- iax_transfercallno_pvts = ao2_container_alloc(IAX_MAX_CALLS, transfercallno_pvt_hash_cb, transfercallno_pvt_cmp_cb);
- if (!iax_transfercallno_pvts) {
- ao2_ref(peers, -1);
-@@ -12571,6 +12611,16 @@
- ao2_ref(iax_peercallno_pvts, -1);
- return AST_MODULE_LOAD_FAILURE;
- }
-+
-+ transmit_processor = ast_taskprocessor_get("iax2_transmit", TPS_REF_DEFAULT);
-+ if (!transmit_processor) {
-+ ao2_ref(peers, -1);
-+ ao2_ref(users, -1);
-+ ao2_ref(iax_peercallno_pvts, -1);
-+ ao2_ref(iax_transfercallno_pvts, -1);
-+ return AST_MODULE_LOAD_FAILURE;
-+ }
-+
- ast_custom_function_register(&iaxpeer_function);
- ast_custom_function_register(&iaxvar_function);
-
-@@ -12621,9 +12671,8 @@
- ast_manager_register( "IAXnetstats", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_iax2_show_netstats, "Show IAX Netstats" );
- ast_manager_register( "IAXregistry", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_iax2_show_registry, "Show IAX registrations");
-
-- timingfd = ast_timer_open();
-- if (timingfd > -1) {
-- ast_timer_set_rate(timingfd, trunkfreq);
-+ if ((timer = ast_timer_open())) {
-+ ast_timer_set_rate(timer, trunkfreq);
- }
-
- if (set_config(config, 0) == -1) {
-Index: channels/chan_misdn.c
-===================================================================
---- a/channels/chan_misdn.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/channels/chan_misdn.c (.../trunk) (revision 186562)
-@@ -1,6 +1,6 @@
- /*
- * Asterisk -- An open source telephony toolkit.
-- *
-+ *
- * Copyright (C) 2004 - 2006, Christian Richter
- *
- * Christian Richter <crich@beronet.com>
-@@ -47,6 +47,7 @@
- #include <signal.h>
- #include <sys/file.h>
- #include <semaphore.h>
-+#include <ctype.h>
-
- #include "asterisk/channel.h"
- #include "asterisk/config.h"
-@@ -88,8 +89,6 @@
- ast_mutex_t mutexjb;
- };
-
--
--
- /*! \brief allocates the jb-structure and initialize the elements */
- struct misdn_jb *misdn_jb_init(int size, int upper_threshold);
-
-@@ -135,7 +134,6 @@
- MISDN_HUNGUP_FROM_AST, /*!< when DISCONNECT/RELEASE/REL_COMP came out of misdn_hangup */
- MISDN_HOLDED, /*!< when on hold */
- MISDN_HOLD_DISCONNECT, /*!< when on hold */
--
- };
-
- #define ORG_AST 1
-@@ -143,13 +141,13 @@
-
- struct hold_info {
- /*!
-- * \brief Logical port the channel call record is HOLDED on
-- * because the B channel is no longer associated.
-+ * \brief Logical port the channel call record is HOLDED on
-+ * because the B channel is no longer associated.
- */
- int port;
-
- /*!
-- * \brief Original B channel number the HOLDED call was using.
-+ * \brief Original B channel number the HOLDED call was using.
- * \note Used only for debug display messages.
- */
- int channel;
-@@ -159,18 +157,18 @@
- * \brief Channel call record structure
- */
- struct chan_list {
-- /*!
-+ /*!
- * \brief The "allowed_bearers" string read in from /etc/asterisk/misdn.conf
- */
- char allowed_bearers[BUFFERSIZE + 1];
--
-- /*!
-+
-+ /*!
- * \brief State of the channel
- */
- enum misdn_chan_state state;
-
-- /*!
-- * \brief TRUE if a hangup needs to be queued
-+ /*!
-+ * \brief TRUE if a hangup needs to be queued
- * \note This is a debug flag only used to catch calls to hangup_chan() that are already hungup.
- */
- int need_queue_hangup;
-@@ -184,30 +182,30 @@
- * \brief TRUE if we could send an AST_CONTROL_BUSY if needed.
- */
- int need_busy;
--
-+
- /*!
- * \brief Who originally created this channel. ORG_AST or ORG_MISDN
- */
- int originator;
-
-- /*!
-+ /*!
- * \brief TRUE of we are not to respond immediately to a SETUP message. Check the dialplan first.
- * \note The "noautorespond_on_setup" boolean read in from /etc/asterisk/misdn.conf
- */
- int noautorespond_on_setup;
--
-+
- int norxtone; /*!< Boolean assigned values but the value is not used. */
-
- /*!
- * \brief TRUE if we are not to generate tones (Playtones)
- */
-- int notxtone;
-+ int notxtone;
-
- /*!
- * \brief TRUE if echo canceller is enabled. Value is toggled.
- */
- int toggle_ec;
--
-+
- /*!
- * \brief TRUE if you want to send Tone Indications to an incoming
- * ISDN channel on a TE Port.
-@@ -222,8 +220,8 @@
- int ignore_dtmf;
-
- /*!
-- * \brief Pipe file descriptor handles array.
-- * Read from pipe[0], write to pipe[1]
-+ * \brief Pipe file descriptor handles array.
-+ * Read from pipe[0], write to pipe[1]
- */
- int pipe[2];
-
-@@ -282,31 +280,31 @@
- /*!
- * \brief Allocated jitterbuffer controller
- * \note misdn_jb_init() creates the jitterbuffer.
-- * \note Must use misdn_jb_destroy() to clean up.
-+ * \note Must use misdn_jb_destroy() to clean up.
- */
- struct misdn_jb *jb;
--
-+
- /*!
- * \brief Allocated DSP controller
- * \note ast_dsp_new() creates the DSP controller.
-- * \note Must use ast_dsp_free() to clean up.
-+ * \note Must use ast_dsp_free() to clean up.
- */
- struct ast_dsp *dsp;
-
- /*!
- * \brief Allocated audio frame sample translator
- * \note ast_translator_build_path() creates the translator path.
-- * \note Must use ast_translator_free_path() to clean up.
-+ * \note Must use ast_translator_free_path() to clean up.
- */
- struct ast_trans_pvt *trans;
--
-+
- /*!
- * \brief Associated Asterisk channel structure.
- */
- struct ast_channel * ast;
-
- //int dummy; /* Not used */
--
-+
- /*!
- * \brief Associated B channel structure.
- */
-@@ -317,13 +315,13 @@
- */
- struct hold_info hold_info;
-
-- /*!
-- * \brief From associated B channel: Layer 3 process ID
-- * \note Used to find the HOLDED channel call record when retrieving a call.
-+ /*!
-+ * \brief From associated B channel: Layer 3 process ID
-+ * \note Used to find the HOLDED channel call record when retrieving a call.
- */
- unsigned int l3id;
-
-- /*!
-+ /*!
- * \brief From associated B channel: B Channel mISDN driver layer ID from mISDN_get_layerid()
- * \note Used only for debug display messages.
- */
-@@ -341,10 +339,6 @@
- */
- char mohinterpret[MAX_MUSICCLASS];
-
--#if 0
-- int zero_read_cnt; /* Not used */
--#endif
--
- /*!
- * \brief Number of outgoing audio frames dropped since last debug gripe message.
- */
-@@ -363,24 +357,24 @@
- int nttimeout;
-
- /*!
-- * \brief Other channel call record PID
-- * \note Value imported from Asterisk environment variable MISDN_PID
-+ * \brief Other channel call record PID
-+ * \note Value imported from Asterisk environment variable MISDN_PID
- */
- int other_pid;
-
- /*!
- * \brief Bridged other channel call record
-- * \note Pointer set when other_pid imported from Asterisk environment
-+ * \note Pointer set when other_pid imported from Asterisk environment
- * variable MISDN_PID by either side.
- */
- struct chan_list *other_ch;
-
- /*!
- * \brief Tone zone sound used for dialtone generation.
-- * \note Used as a boolean. Non-NULL to prod generation if enabled.
-+ * \note Used as a boolean. Non-NULL to prod generation if enabled.
- */
- struct ast_tone_zone_sound *ts;
--
-+
- /*!
- * \brief Enables overlap dialing for the set amount of seconds. (0 = Disabled)
- * \note The "overlapdial" value read in from /etc/asterisk/misdn.conf
-@@ -402,18 +396,10 @@
- */
- struct timeval overlap_tv;
-
--#if 0
-- struct chan_list *peer; /* Not used */
--#endif
--
- /*!
- * \brief Next channel call record in the list.
- */
- struct chan_list *next;
--#if 0
-- struct chan_list *prev; /* Not used */
-- struct chan_list *first; /* Not used */
--#endif
- };
-
-
-@@ -424,13 +410,14 @@
- void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
- static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame);
-
--static struct robin_list {
-+struct robin_list {
- char *group;
- int port;
- int channel;
- struct robin_list *next;
- struct robin_list *prev;
--} *robin = NULL;
-+};
-+static struct robin_list *robin = NULL;
-
-
- static inline void free_robin_list_r(struct robin_list *r)
-@@ -450,7 +437,7 @@
- robin = NULL;
- }
-
--static struct robin_list* get_robin_position(char *group)
-+static struct robin_list* get_robin_position(char *group)
- {
- struct robin_list *new;
- struct robin_list *iter = robin;
-@@ -539,7 +526,7 @@
-
- int chan_misdn_jb_empty(struct misdn_bchannel *bc, char *buf, int len);
-
--void debug_numplan(int port, int numplan, char *type);
-+void debug_numtype(int port, int numtype, char *type);
-
- int add_out_calls(int port);
- int add_in_calls(int port);
-@@ -558,31 +545,559 @@
- static struct chan_list * get_chan_by_ast(struct ast_channel *ast)
- {
- struct chan_list *tmp;
--
-+
- for (tmp = cl_te; tmp; tmp = tmp->next) {
- if (tmp->ast == ast) {
- return tmp;
- }
- }
--
-+
- return NULL;
- }
-
- static struct chan_list * get_chan_by_ast_name(char *name)
- {
- struct chan_list *tmp;
--
-+
- for (tmp = cl_te; tmp; tmp = tmp->next) {
- if (tmp->ast && strcmp(tmp->ast->name, name) == 0) {
- return tmp;
- }
- }
--
-+
- return NULL;
- }
-
-+/*!
-+ * \internal
-+ * \brief Convert the mISDN type of number code to a string
-+ *
-+ * \param number_type mISDN type of number code.
-+ *
-+ * \return The mISDN type of number code as a string
-+ */
-+static const char *misdn_to_str_ton(enum mISDN_NUMBER_TYPE number_type)
-+{
-+ const char *str;
-
-+ switch (number_type) {
-+ default:
-+ case NUMTYPE_UNKNOWN:
-+ str = "Unknown";
-+ break;
-
-+ case NUMTYPE_INTERNATIONAL:
-+ str = "International";
-+ break;
-+
-+ case NUMTYPE_NATIONAL:
-+ str = "National";
-+ break;
-+
-+ case NUMTYPE_NETWORK_SPECIFIC:
-+ str = "Network Specific";
-+ break;
-+
-+ case NUMTYPE_SUBSCRIBER:
-+ str = "Subscriber";
-+ break;
-+
-+ case NUMTYPE_ABBREVIATED:
-+ str = "Abbreviated";
-+ break;
-+ }
-+
-+ return str;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Convert the mISDN type of number code to Asterisk type of number code
-+ *
-+ * \param number_type mISDN type of number code.
-+ *
-+ * \return Asterisk type of number code
-+ */
-+static int misdn_to_ast_ton(enum mISDN_NUMBER_TYPE number_type)
-+{
-+ int ast_number_type;
-+
-+ switch (number_type) {
-+ default:
-+ case NUMTYPE_UNKNOWN:
-+ ast_number_type = NUMTYPE_UNKNOWN << 4;
-+ break;
-+
-+ case NUMTYPE_INTERNATIONAL:
-+ ast_number_type = NUMTYPE_INTERNATIONAL << 4;
-+ break;
-+
-+ case NUMTYPE_NATIONAL:
-+ ast_number_type = NUMTYPE_NATIONAL << 4;
-+ break;
-+
-+ case NUMTYPE_NETWORK_SPECIFIC:
-+ ast_number_type = NUMTYPE_NETWORK_SPECIFIC << 4;
-+ break;
-+
-+ case NUMTYPE_SUBSCRIBER:
-+ ast_number_type = NUMTYPE_SUBSCRIBER << 4;
-+ break;
-+
-+ case NUMTYPE_ABBREVIATED:
-+ ast_number_type = NUMTYPE_ABBREVIATED << 4;
-+ break;
-+ }
-+
-+ return ast_number_type;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Convert the Asterisk type of number code to mISDN type of number code
-+ *
-+ * \param ast_number_type Asterisk type of number code.
-+ *
-+ * \return mISDN type of number code
-+ */
-+static enum mISDN_NUMBER_TYPE ast_to_misdn_ton(unsigned ast_number_type)
-+{
-+ enum mISDN_NUMBER_TYPE number_type;
-+
-+ switch ((ast_number_type >> 4) & 0x07) {
-+ default:
-+ case NUMTYPE_UNKNOWN:
-+ number_type = NUMTYPE_UNKNOWN;
-+ break;
-+
-+ case NUMTYPE_INTERNATIONAL:
-+ number_type = NUMTYPE_INTERNATIONAL;
-+ break;
-+
-+ case NUMTYPE_NATIONAL:
-+ number_type = NUMTYPE_NATIONAL;
-+ break;
-+
-+ case NUMTYPE_NETWORK_SPECIFIC:
-+ number_type = NUMTYPE_NETWORK_SPECIFIC;
-+ break;
-+
-+ case NUMTYPE_SUBSCRIBER:
-+ number_type = NUMTYPE_SUBSCRIBER;
-+ break;
-+
-+ case NUMTYPE_ABBREVIATED:
-+ number_type = NUMTYPE_ABBREVIATED;
-+ break;
-+ }
-+
-+ return number_type;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Convert the mISDN numbering plan code to a string
-+ *
-+ * \param number_plan mISDN numbering plan code.
-+ *
-+ * \return The mISDN numbering plan code as a string
-+ */
-+static const char *misdn_to_str_plan(enum mISDN_NUMBER_PLAN number_plan)
-+{
-+ const char *str;
-+
-+ switch (number_plan) {
-+ default:
-+ case NUMPLAN_UNKNOWN:
-+ str = "Unknown";
-+ break;
-+
-+ case NUMPLAN_ISDN:
-+ str = "ISDN";
-+ break;
-+
-+ case NUMPLAN_DATA:
-+ str = "Data";
-+ break;
-+
-+ case NUMPLAN_TELEX:
-+ str = "Telex";
-+ break;
-+
-+ case NUMPLAN_NATIONAL:
-+ str = "National";
-+ break;
-+
-+ case NUMPLAN_PRIVATE:
-+ str = "Private";
-+ break;
-+ }
-+
-+ return str;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Convert the mISDN numbering plan code to Asterisk numbering plan code
-+ *
-+ * \param number_plan mISDN numbering plan code.
-+ *
-+ * \return Asterisk numbering plan code
-+ */
-+static int misdn_to_ast_plan(enum mISDN_NUMBER_PLAN number_plan)
-+{
-+ int ast_number_plan;
-+
-+ switch (number_plan) {
-+ default:
-+ case NUMPLAN_UNKNOWN:
-+ ast_number_plan = NUMPLAN_UNKNOWN;
-+ break;
-+
-+ case NUMPLAN_ISDN:
-+ ast_number_plan = NUMPLAN_ISDN;
-+ break;
-+
-+ case NUMPLAN_DATA:
-+ ast_number_plan = NUMPLAN_DATA;
-+ break;
-+
-+ case NUMPLAN_TELEX:
-+ ast_number_plan = NUMPLAN_TELEX;
-+ break;
-+
-+ case NUMPLAN_NATIONAL:
-+ ast_number_plan = NUMPLAN_NATIONAL;
-+ break;
-+
-+ case NUMPLAN_PRIVATE:
-+ ast_number_plan = NUMPLAN_PRIVATE;
-+ break;
-+ }
-+
-+ return ast_number_plan;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Convert the Asterisk numbering plan code to mISDN numbering plan code
-+ *
-+ * \param ast_number_plan Asterisk numbering plan code.
-+ *
-+ * \return mISDN numbering plan code
-+ */
-+static enum mISDN_NUMBER_PLAN ast_to_misdn_plan(unsigned ast_number_plan)
-+{
-+ enum mISDN_NUMBER_PLAN number_plan;
-+
-+ switch (ast_number_plan & 0x0F) {
-+ default:
-+ case NUMPLAN_UNKNOWN:
-+ number_plan = NUMPLAN_UNKNOWN;
-+ break;
-+
-+ case NUMPLAN_ISDN:
-+ number_plan = NUMPLAN_ISDN;
-+ break;
-+
-+ case NUMPLAN_DATA:
-+ number_plan = NUMPLAN_DATA;
-+ break;
-+
-+ case NUMPLAN_TELEX:
-+ number_plan = NUMPLAN_TELEX;
-+ break;
-+
-+ case NUMPLAN_NATIONAL:
-+ number_plan = NUMPLAN_NATIONAL;
-+ break;
-+
-+ case NUMPLAN_PRIVATE:
-+ number_plan = NUMPLAN_PRIVATE;
-+ break;
-+ }
-+
-+ return number_plan;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Convert the mISDN presentation code to a string
-+ *
-+ * \param presentation mISDN number presentation restriction code.
-+ *
-+ * \return The mISDN presentation code as a string
-+ */
-+static const char *misdn_to_str_pres(int presentation)
-+{
-+ const char *str;
-+
-+ switch (presentation) {
-+ case 0:
-+ str = "Allowed";
-+ break;
-+
-+ case 1:
-+ str = "Restricted";
-+ break;
-+
-+ case 2:
-+ str = "Unavailable";
-+ break;
-+
-+ default:
-+ str = "Unknown";
-+ break;
-+ }
-+
-+ return str;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Convert the mISDN presentation code to Asterisk presentation code
-+ *
-+ * \param presentation mISDN number presentation restriction code.
-+ *
-+ * \return Asterisk presentation code
-+ */
-+static int misdn_to_ast_pres(int presentation)
-+{
-+ switch (presentation) {
-+ default:
-+ case 0:
-+ presentation = AST_PRES_ALLOWED;
-+ break;
-+
-+ case 1:
-+ presentation = AST_PRES_RESTRICTED;
-+ break;
-+
-+ case 2:
-+ presentation = AST_PRES_UNAVAILABLE;
-+ break;
-+ }
-+
-+ return presentation;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Convert the Asterisk presentation code to mISDN presentation code
-+ *
-+ * \param presentation Asterisk number presentation restriction code.
-+ *
-+ * \return mISDN presentation code
-+ */
-+static int ast_to_misdn_pres(int presentation)
-+{
-+ switch (presentation & AST_PRES_RESTRICTION) {
-+ default:
-+ case AST_PRES_ALLOWED:
-+ presentation = 0;
-+ break;
-+
-+ case AST_PRES_RESTRICTED:
-+ presentation = 1;
-+ break;
-+
-+ case AST_PRES_UNAVAILABLE:
-+ presentation = 2;
-+ break;
-+ }
-+
-+ return presentation;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Convert the mISDN screening code to a string
-+ *
-+ * \param screening mISDN number screening code.
-+ *
-+ * \return The mISDN screening code as a string
-+ */
-+static const char *misdn_to_str_screen(int screening)
-+{
-+ const char *str;
-+
-+ switch (screening) {
-+ case 0:
-+ str = "Unscreened";
-+ break;
-+
-+ case 1:
-+ str = "Passed Screen";
-+ break;
-+
-+ case 2:
-+ str = "Failed Screen";
-+ break;
-+
-+ case 3:
-+ str = "Network Number";
-+ break;
-+
-+ default:
-+ str = "Unknown";
-+ break;
-+ }
-+
-+ return str;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Convert the mISDN screening code to Asterisk screening code
-+ *
-+ * \param screening mISDN number screening code.
-+ *
-+ * \return Asterisk screening code
-+ */
-+static int misdn_to_ast_screen(int screening)
-+{
-+ switch (screening) {
-+ default:
-+ case 0:
-+ screening = AST_PRES_USER_NUMBER_UNSCREENED;
-+ break;
-+
-+ case 1:
-+ screening = AST_PRES_USER_NUMBER_PASSED_SCREEN;
-+ break;
-+
-+ case 2:
-+ screening = AST_PRES_USER_NUMBER_FAILED_SCREEN;
-+ break;
-+
-+ case 3:
-+ screening = AST_PRES_NETWORK_NUMBER;
-+ break;
-+ }
-+
-+ return screening;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Convert the Asterisk screening code to mISDN screening code
-+ *
-+ * \param screening Asterisk number screening code.
-+ *
-+ * \return mISDN screening code
-+ */
-+static int ast_to_misdn_screen(int screening)
-+{
-+ switch (screening & AST_PRES_NUMBER_TYPE) {
-+ default:
-+ case AST_PRES_USER_NUMBER_UNSCREENED:
-+ screening = 0;
-+ break;
-+
-+ case AST_PRES_USER_NUMBER_PASSED_SCREEN:
-+ screening = 1;
-+ break;
-+
-+ case AST_PRES_USER_NUMBER_FAILED_SCREEN:
-+ screening = 2;
-+ break;
-+
-+ case AST_PRES_NETWORK_NUMBER:
-+ screening = 3;
-+ break;
-+ }
-+
-+ return screening;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Convert Asterisk redirecting reason to mISDN redirecting reason code.
-+ *
-+ * \param ast Asterisk redirecting reason code.
-+ *
-+ * \return mISDN reason code
-+ */
-+static enum mISDN_REDIRECTING_REASON ast_to_misdn_reason(const enum AST_REDIRECTING_REASON ast)
-+{
-+ unsigned index;
-+
-+ static const struct misdn_reasons {
-+ enum AST_REDIRECTING_REASON ast;
-+ enum mISDN_REDIRECTING_REASON q931;
-+ } misdn_reason_table[] = {
-+ /* *INDENT-OFF* */
-+ { AST_REDIRECTING_REASON_UNKNOWN, mISDN_REDIRECTING_REASON_UNKNOWN },
-+ { AST_REDIRECTING_REASON_USER_BUSY, mISDN_REDIRECTING_REASON_CALL_FWD_BUSY },
-+ { AST_REDIRECTING_REASON_NO_ANSWER, mISDN_REDIRECTING_REASON_NO_REPLY },
-+ { AST_REDIRECTING_REASON_UNAVAILABLE, mISDN_REDIRECTING_REASON_NO_REPLY },
-+ { AST_REDIRECTING_REASON_UNCONDITIONAL, mISDN_REDIRECTING_REASON_CALL_FWD },
-+ { AST_REDIRECTING_REASON_TIME_OF_DAY, mISDN_REDIRECTING_REASON_UNKNOWN },
-+ { AST_REDIRECTING_REASON_DO_NOT_DISTURB, mISDN_REDIRECTING_REASON_UNKNOWN },
-+ { AST_REDIRECTING_REASON_DEFLECTION, mISDN_REDIRECTING_REASON_DEFLECTION },
-+ { AST_REDIRECTING_REASON_FOLLOW_ME, mISDN_REDIRECTING_REASON_UNKNOWN },
-+ { AST_REDIRECTING_REASON_OUT_OF_ORDER, mISDN_REDIRECTING_REASON_OUT_OF_ORDER },
-+ { AST_REDIRECTING_REASON_AWAY, mISDN_REDIRECTING_REASON_UNKNOWN },
-+ { AST_REDIRECTING_REASON_CALL_FWD_DTE, mISDN_REDIRECTING_REASON_CALL_FWD_DTE }
-+ /* *INDENT-ON* */
-+ };
-+
-+ for (index = 0; index < ARRAY_LEN(misdn_reason_table); ++index) {
-+ if (misdn_reason_table[index].ast == ast) {
-+ return misdn_reason_table[index].q931;
-+ }
-+ }
-+ return mISDN_REDIRECTING_REASON_UNKNOWN;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Convert the mISDN redirecting reason to Asterisk redirecting reason code
-+ *
-+ * \param q931 mISDN redirecting reason code.
-+ *
-+ * \return Asterisk redirecting reason code
-+ */
-+static enum AST_REDIRECTING_REASON misdn_to_ast_reason(const enum mISDN_REDIRECTING_REASON q931)
-+{
-+ enum AST_REDIRECTING_REASON ast;
-+
-+ switch (q931) {
-+ default:
-+ case mISDN_REDIRECTING_REASON_UNKNOWN:
-+ ast = AST_REDIRECTING_REASON_UNKNOWN;
-+ break;
-+
-+ case mISDN_REDIRECTING_REASON_CALL_FWD_BUSY:
-+ ast = AST_REDIRECTING_REASON_USER_BUSY;
-+ break;
-+
-+ case mISDN_REDIRECTING_REASON_NO_REPLY:
-+ ast = AST_REDIRECTING_REASON_NO_ANSWER;
-+ break;
-+
-+ case mISDN_REDIRECTING_REASON_DEFLECTION:
-+ ast = AST_REDIRECTING_REASON_DEFLECTION;
-+ break;
-+
-+ case mISDN_REDIRECTING_REASON_OUT_OF_ORDER:
-+ ast = AST_REDIRECTING_REASON_OUT_OF_ORDER;
-+ break;
-+
-+ case mISDN_REDIRECTING_REASON_CALL_FWD_DTE:
-+ ast = AST_REDIRECTING_REASON_CALL_FWD_DTE;
-+ break;
-+
-+ case mISDN_REDIRECTING_REASON_CALL_FWD:
-+ ast = AST_REDIRECTING_REASON_UNCONDITIONAL;
-+ break;
-+ }
-+
-+ return ast;
-+}
-+
-+
-+
- struct allowed_bearers {
- char *name; /*!< Bearer capability name string used in /etc/misdn.conf allowed_bearers */
- char *display; /*!< Bearer capability displayable name */
-@@ -591,7 +1106,7 @@
- };
-
- /* *INDENT-OFF* */
--static const struct allowed_bearers allowed_bearers_array[]= {
-+static const struct allowed_bearers allowed_bearers_array[] = {
- /* Name, Displayable Name Bearer Capability, Deprecated */
- { "speech", "Speech", INFO_CAPABILITY_SPEECH, 0 },
- { "3_1khz", "3.1KHz Audio", INFO_CAPABILITY_AUDIO_3_1K, 0 },
-@@ -610,7 +1125,7 @@
- if (allowed_bearers_array[index].cap == cap) {
- return allowed_bearers_array[index].display;
- }
-- } /* end for */
-+ }
-
- return "Unknown Bearer";
- }
-@@ -669,10 +1184,10 @@
- }
- }
-
--static void print_bearer(struct misdn_bchannel *bc)
-+static void print_bearer(struct misdn_bchannel *bc)
- {
- chan_misdn_log(2, bc->port, " --> Bearer: %s\n", bearer2str(bc->capability));
--
-+
- switch(bc->law) {
- case INFO_CODEC_ALAW:
- chan_misdn_log(2, bc->port, " --> Codec: Alaw\n");
-@@ -683,6 +1198,95 @@
- }
- }
-
-+/*!
-+ * \internal
-+ * \brief Prefix a string to another string in place.
-+ *
-+ * \param str_prefix String to prefix to the main string.
-+ * \param str_main String to get the prefix added to it.
-+ * \param size Buffer size of the main string (Includes null terminator).
-+ *
-+ * \note The str_main buffer size must be greater than one.
-+ *
-+ * \return Nothing
-+ */
-+static void misdn_prefix_string(const char *str_prefix, char *str_main, size_t size)
-+{
-+ size_t len_over;
-+ size_t len_total;
-+ size_t len_main;
-+ size_t len_prefix;
-+
-+ len_prefix = strlen(str_prefix);
-+ if (!len_prefix) {
-+ /* There is no prefix to prepend. */
-+ return;
-+ }
-+ len_main = strlen(str_main);
-+ len_total = len_prefix + len_main;
-+ if (size <= len_total) {
-+ /* We need to truncate since the buffer is too small. */
-+ len_over = len_total + 1 - size;
-+ if (len_over <= len_main) {
-+ len_main -= len_over;
-+ } else {
-+ len_over -= len_main;
-+ len_main = 0;
-+ len_prefix -= len_over;
-+ }
-+ }
-+ if (len_main) {
-+ memmove(str_main + len_prefix, str_main, len_main);
-+ }
-+ memcpy(str_main, str_prefix, len_prefix);
-+ str_main[len_prefix + len_main] = '\0';
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Add a configured prefix to the given number.
-+ *
-+ * \param port Logical port number
-+ * \param number_type Type-of-number passed in.
-+ * \param number Given number string to add prefix
-+ * \param size Buffer size number string occupies.
-+ *
-+ * \return Nothing
-+ */
-+static void misdn_add_number_prefix(int port, enum mISDN_NUMBER_TYPE number_type, char *number, size_t size)
-+{
-+ enum misdn_cfg_elements type_prefix;
-+ char num_prefix[MISDN_MAX_NUMBER_LEN];
-+
-+ /* Get prefix string. */
-+ switch (number_type) {
-+ case NUMTYPE_UNKNOWN:
-+ type_prefix = MISDN_CFG_TON_PREFIX_UNKNOWN;
-+ break;
-+ case NUMTYPE_INTERNATIONAL:
-+ type_prefix = MISDN_CFG_TON_PREFIX_INTERNATIONAL;
-+ break;
-+ case NUMTYPE_NATIONAL:
-+ type_prefix = MISDN_CFG_TON_PREFIX_NATIONAL;
-+ break;
-+ case NUMTYPE_NETWORK_SPECIFIC:
-+ type_prefix = MISDN_CFG_TON_PREFIX_NETWORK_SPECIFIC;
-+ break;
-+ case NUMTYPE_SUBSCRIBER:
-+ type_prefix = MISDN_CFG_TON_PREFIX_SUBSCRIBER;
-+ break;
-+ case NUMTYPE_ABBREVIATED:
-+ type_prefix = MISDN_CFG_TON_PREFIX_ABBREVIATED;
-+ break;
-+ default:
-+ /* Type-of-number does not have a prefix that can be added. */
-+ return;
-+ }
-+ misdn_cfg_get(port, type_prefix, num_prefix, sizeof(num_prefix));
-+
-+ misdn_prefix_string(num_prefix, number, size);
-+}
-+
- static void export_aoc_vars(int originator, struct ast_channel *ast, struct misdn_bchannel *bc)
- {
- char buf[128];
-@@ -692,7 +1296,8 @@
- }
-
- if (originator == ORG_AST) {
-- if (!(ast = ast_bridged_channel(ast))) {
-+ ast = ast_bridged_channel(ast);
-+ if (!ast) {
- return;
- }
- }
-@@ -739,14 +1344,15 @@
- default:
- break;
- }
--
-+
- bc->AOCD_need_export = 0;
- }
-
- /*************** Helpers END *************/
-
- static void sighandler(int sig)
--{}
-+{
-+}
-
- static void *misdn_tasks_thread_func(void *data)
- {
-@@ -758,7 +1364,7 @@
- sigemptyset(&sa.sa_mask);
- sigaddset(&sa.sa_mask, SIGUSR1);
- sigaction(SIGUSR1, &sa, NULL);
--
-+
- sem_post((sem_t *)data);
-
- while (1) {
-@@ -785,7 +1391,7 @@
- }
-
- chan_misdn_log(4, 0, "Starting misdn_tasks thread\n");
--
-+
- misdn_tasks = sched_context_create();
- pthread_create(&misdn_tasks_thread, NULL, misdn_tasks_thread_func, &blocker);
-
-@@ -841,6 +1447,7 @@
- static int misdn_l1_task(const void *vdata)
- {
- const int *data = vdata;
-+
- misdn_lib_isdn_l1watcher(*data);
- chan_misdn_log(5, *data, "L1watcher timeout\n");
- return 1;
-@@ -867,21 +1474,22 @@
- tv_end.tv_sec += ch->overlap_dial;
- tv_now = ast_tvnow();
-
-- if ((diff = ast_tvdiff_ms(tv_end, tv_now)) > 100) {
-+ diff = ast_tvdiff_ms(tv_end, tv_now);
-+ if (100 < diff) {
- return diff;
- }
-
- /* if we are 100ms near the timeout, we are satisfied.. */
- stop_indicate(ch);
-
-- if (ast_strlen_zero(ch->bc->dad)) {
-+ if (ast_strlen_zero(ch->bc->dialed.number)) {
- dad = "s";
-- ast_copy_string(ch->ast->exten, "s", sizeof(ch->ast->exten));
-+ strcpy(ch->ast->exten, dad);
- } else {
-- dad = ch->bc->dad;
-+ dad = ch->bc->dialed.number;
- }
-
-- if (ast_exists_extension(ch->ast, ch->context, dad, 1, ch->bc->oad)) {
-+ if (ast_exists_extension(ch->ast, ch->context, dad, 1, ch->bc->caller.number)) {
- ch->state = MISDN_DIALING;
- if (pbx_start_chan(ch) < 0) {
- chan_misdn_log(-1, ch->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
-@@ -918,8 +1526,8 @@
- "!941+1209/100,!0/100", /* * */
- "!941+1477/100,!0/100", /* # */
- };
-- struct ast_channel *chan = cl->ast;
--
-+ struct ast_channel *chan = cl->ast;
-+
- if (digit >= '0' && digit <='9') {
- ast_playtones_start(chan, 0, dtmf_tones[digit - '0'], 0);
- } else if (digit >= 'A' && digit <= 'D') {
-@@ -958,8 +1566,10 @@
- level = 1;
- } else if (!strcasecmp(a->argv[3], "off")) {
- level = 0;
-+ } else if (isdigit(a->argv[3][0])) {
-+ level = atoi(a->argv[3]);
- } else {
-- level = atoi(a->argv[3]);
-+ return CLI_SHOWUSAGE;
- }
-
- switch (a->argc) {
-@@ -975,7 +1585,7 @@
- only = 1;
- }
- }
--
-+
- for (i = 0; i <= max_ports; i++) {
- misdn_debug[i] = level;
- misdn_debug_only[i] = only;
-@@ -1267,18 +1877,18 @@
- for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
- misdn_cfg_get_config_string(port, elem, buffer, sizeof(buffer));
- ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
-- }
-+ }
- ast_cli(a->fd, "\n");
- }
- }
--
-+
- if (onlyport > 0) {
- if (misdn_cfg_is_port_valid(onlyport)) {
- ast_cli(a->fd, "[PORT %d]\n", onlyport);
- for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
- misdn_cfg_get_config_string(onlyport, elem, buffer, sizeof(buffer));
- ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
-- }
-+ }
- ast_cli(a->fd, "\n");
- } else {
- ast_cli(a->fd, "Port %d is not active!\n", onlyport);
-@@ -1294,38 +1904,40 @@
- };
-
- static struct state_struct state_array[] = {
-+/* *INDENT-OFF* */
- { MISDN_NOTHING, "NOTHING" }, /* at beginning */
-- { MISDN_WAITING4DIGS, "WAITING4DIGS" }, /* when waiting for infos */
-- { MISDN_EXTCANTMATCH, "EXTCANTMATCH" }, /* when asterisk couldn't match our ext */
-- { MISDN_INCOMING_SETUP, "INCOMING SETUP" }, /* when pbx_start */
-- { MISDN_DIALING, "DIALING" }, /* when pbx_start */
-- { MISDN_PROGRESS, "PROGRESS" }, /* when pbx_start */
-- { MISDN_PROCEEDING, "PROCEEDING" }, /* when pbx_start */
-- { MISDN_CALLING, "CALLING" }, /* when misdn_call is called */
-- { MISDN_CALLING_ACKNOWLEDGE, "CALLING_ACKNOWLEDGE" }, /* when misdn_call is called */
-- { MISDN_ALERTING, "ALERTING" }, /* when Alerting */
-- { MISDN_BUSY, "BUSY" }, /* when BUSY */
-- { MISDN_CONNECTED, "CONNECTED" }, /* when connected */
-- { MISDN_PRECONNECTED, "PRECONNECTED" }, /* when connected */
-- { MISDN_DISCONNECTED, "DISCONNECTED" }, /* when connected */
-- { MISDN_RELEASED, "RELEASED" }, /* when connected */
-- { MISDN_BRIDGED, "BRIDGED" }, /* when bridged */
-+ { MISDN_WAITING4DIGS, "WAITING4DIGS" }, /* when waiting for infos */
-+ { MISDN_EXTCANTMATCH, "EXTCANTMATCH" }, /* when asterisk couldn't match our ext */
-+ { MISDN_INCOMING_SETUP, "INCOMING SETUP" }, /* when pbx_start */
-+ { MISDN_DIALING, "DIALING" }, /* when pbx_start */
-+ { MISDN_PROGRESS, "PROGRESS" }, /* when pbx_start */
-+ { MISDN_PROCEEDING, "PROCEEDING" }, /* when pbx_start */
-+ { MISDN_CALLING, "CALLING" }, /* when misdn_call is called */
-+ { MISDN_CALLING_ACKNOWLEDGE, "CALLING_ACKNOWLEDGE" }, /* when misdn_call is called */
-+ { MISDN_ALERTING, "ALERTING" }, /* when Alerting */
-+ { MISDN_BUSY, "BUSY" }, /* when BUSY */
-+ { MISDN_CONNECTED, "CONNECTED" }, /* when connected */
-+ { MISDN_PRECONNECTED, "PRECONNECTED" }, /* when connected */
-+ { MISDN_DISCONNECTED, "DISCONNECTED" }, /* when connected */
-+ { MISDN_RELEASED, "RELEASED" }, /* when connected */
-+ { MISDN_BRIDGED, "BRIDGED" }, /* when bridged */
- { MISDN_CLEANING, "CLEANING" }, /* when hangup from * but we were connected before */
-- { MISDN_HUNGUP_FROM_MISDN, "HUNGUP_FROM_MISDN" }, /* when DISCONNECT/RELEASE/REL_COMP came from misdn */
-- { MISDN_HOLDED, "HOLDED" }, /* when DISCONNECT/RELEASE/REL_COMP came from misdn */
-- { MISDN_HOLD_DISCONNECT, "HOLD_DISCONNECT" }, /* when DISCONNECT/RELEASE/REL_COMP came from misdn */
-+ { MISDN_HUNGUP_FROM_MISDN, "HUNGUP_FROM_MISDN" }, /* when DISCONNECT/RELEASE/REL_COMP came from misdn */
-+ { MISDN_HOLDED, "HOLDED" }, /* when DISCONNECT/RELEASE/REL_COMP came from misdn */
-+ { MISDN_HOLD_DISCONNECT, "HOLD_DISCONNECT" }, /* when DISCONNECT/RELEASE/REL_COMP came from misdn */
- { MISDN_HUNGUP_FROM_AST, "HUNGUP_FROM_AST" }, /* when DISCONNECT/RELEASE/REL_COMP came out of misdn_hangup */
-+/* *INDENT-ON* */
- };
-
--static const char *misdn_get_ch_state(struct chan_list *p)
-+static const char *misdn_get_ch_state(struct chan_list *p)
- {
- int i;
- static char state[8];
--
-+
- if (!p) {
- return NULL;
- }
--
-+
- for (i = 0; i < ARRAY_LEN(state_array); i++) {
- if (state_array[i].state == p->state) {
- return state_array[i].txt;
-@@ -1346,7 +1958,7 @@
- ast_log(LOG_WARNING, "chan_misdn is not initialized properly, still reloading ?\n");
- return ;
- }
--
-+
- free_robin_list();
- misdn_cfg_reload();
- misdn_cfg_update_ptp();
-@@ -1385,18 +1997,24 @@
- static void print_bc_info (int fd, struct chan_list *help, struct misdn_bchannel *bc)
- {
- struct ast_channel *ast = help->ast;
-+
- ast_cli(fd,
-- "* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s rad:%s ctx:%s state:%s\n",
--
-- bc->pid, bc->port, bc->channel,
-+ "* Pid:%d Port:%d Ch:%d Mode:%s Orig:%s dialed:%s\n"
-+ " --> caller:\"%s\" <%s>\n"
-+ " --> redirecting:\"%s\" <%s>\n"
-+ " --> context:%s state:%s\n",
-+ bc->pid,
-+ bc->port,
-+ bc->channel,
- bc->nt ? "NT" : "TE",
- help->originator == ORG_AST ? "*" : "I",
-- ast ? ast->exten : NULL,
-- ast ? ast->cid.cid_num : NULL,
-- bc->rad,
-- ast ? ast->context : NULL,
-- misdn_get_ch_state(help)
-- );
-+ ast ? ast->exten : "",
-+ (ast && ast->cid.cid_name) ? ast->cid.cid_name : "",
-+ (ast && ast->cid.cid_num) ? ast->cid.cid_num : "",
-+ bc->redirecting.from.name,
-+ bc->redirecting.from.number,
-+ ast ? ast->context : "",
-+ misdn_get_ch_state(help));
- if (misdn_debug[bc->port] > 0) {
- ast_cli(fd,
- " --> astname: %s\n"
-@@ -1419,21 +2037,18 @@
- help->l3id,
- help->addr,
- bc->addr,
-- bc ? bc->l3_id : -1,
-+ bc->l3_id,
- bc->display,
--
- bc->active,
- bc_state2str(bc->bc_state),
- bearer2str(bc->capability),
- #ifdef MISDN_1_2
- bc->pipeline,
- #else
-- bc->ec_enable,
-+ bc->ec_enable,
- #endif
--
- help->norxtone, help->notxtone,
-- bc->holded
-- );
-+ bc->holded);
- }
- }
-
-@@ -1457,11 +2072,11 @@
- }
-
- help = cl_te;
--
-+
- ast_cli(a->fd, "Channel List: %p\n", cl_te);
-
- for (; help; help = help->next) {
-- struct misdn_bchannel *bc = help->bc;
-+ struct misdn_bchannel *bc = help->bc;
- struct ast_channel *ast = help->ast;
- if (!ast) {
- if (!bc) {
-@@ -1481,15 +2096,17 @@
- if (help->state == MISDN_HOLDED) {
- ast_cli(a->fd, "ITS A HOLDED BC:\n");
- ast_cli(a->fd, " --> l3_id: %x\n"
-- " --> dad:%s oad:%s\n"
-- " --> hold_port: %d\n"
-- " --> hold_channel: %d\n",
-- help->l3id,
-- ast->exten,
-- ast->cid.cid_num,
-- help->hold_info.port,
-- help->hold_info.channel
-- );
-+ " --> dialed:%s\n"
-+ " --> caller:\"%s\" <%s>\n"
-+ " --> hold_port: %d\n"
-+ " --> hold_channel: %d\n",
-+ help->l3id,
-+ ast->exten,
-+ ast->cid.cid_name ? ast->cid.cid_name : "",
-+ ast->cid.cid_num ? ast->cid.cid_num : "",
-+ help->hold_info.port,
-+ help->hold_info.channel
-+ );
- } else {
- ast_cli(a->fd, "* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n", ast->exten, ast->cid.cid_num);
- }
-@@ -1523,13 +2140,13 @@
- help = cl_te;
-
- for (; help; help = help->next) {
-- struct misdn_bchannel *bc = help->bc;
-+ struct misdn_bchannel *bc = help->bc;
- struct ast_channel *ast = help->ast;
--
-+
- if (bc && ast) {
- if (!strcasecmp(ast->name, a->argv[3])) {
- print_bc_info(a->fd, help, bc);
-- break;
-+ break;
- }
- }
- }
-@@ -1639,7 +2256,7 @@
- }
-
- port = atoi(a->argv[3]);
--
-+
- ast_cli(a->fd, "BEGIN STACK_LIST:\n");
- get_show_stack_details(port, buf);
- ast_cli(a->fd, " %s Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port] ? "(only)" : "");
-@@ -1649,13 +2266,13 @@
-
- static char *handle_cli_misdn_send_facility(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
- {
-- char *channame;
-+ char *channame;
- char *nr;
- struct chan_list *tmp;
-- int port;
-+ int port;
- char *served_nr;
- struct misdn_bchannel dummy, *bc=&dummy;
--
-+
- switch (cmd) {
- case CLI_INIT:
- e->command = "misdn send facility";
-@@ -1673,7 +2290,7 @@
- if (a->argc < 5) {
- return CLI_SHOWUSAGE;
- }
--
-+
- if (strstr(a->argv[3], "calldeflect")) {
- if (a->argc < 6) {
- ast_verbose("calldeflect requires 1 arg: ToNumber\n\n");
-@@ -1686,15 +2303,15 @@
- tmp = get_chan_by_ast_name(channame);
- if (!tmp) {
- ast_verbose("Sending CD with nr %s to %s failed: Channel does not exist.\n", nr, channame);
-- return 0;
-+ return 0;
- }
-
- if (strlen(nr) >= 15) {
- ast_verbose("Sending CD with nr %s to %s failed: Number too long (up to 15 digits are allowed).\n", nr, channame);
-- return 0;
-+ return 0;
- }
- tmp->bc->fac_out.Function = Fac_CD;
-- ast_copy_string((char *)tmp->bc->fac_out.u.CDeflection.DeflectedToNumber, nr, sizeof(tmp->bc->fac_out.u.CDeflection.DeflectedToNumber));
-+ ast_copy_string((char *) tmp->bc->fac_out.u.CDeflection.DeflectedToNumber, nr, sizeof(tmp->bc->fac_out.u.CDeflection.DeflectedToNumber));
- misdn_lib_send_event(tmp->bc, EVENT_FACILITY);
- } else if (strstr(a->argv[3], "CFActivate")) {
- if (a->argc < 7) {
-@@ -1719,20 +2336,20 @@
- } else if (strstr(a->argv[3], "CFDeactivate")) {
-
- if (a->argc < 6) {
-- ast_verbose("CFActivate requires 1 arg: FromNumber\n\n");
-+ ast_verbose("CFDeactivate requires 1 arg: FromNumber\n\n");
- return 0;
- }
- port = atoi(a->argv[4]);
- served_nr = a->argv[5];
--
-+
- misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
- ast_verbose("Sending CFDeactivate Port:(%d) FromNr. (%s)\n", port, served_nr);
-
- bc->fac_out.Function = Fac_CFDeactivate;
-- bc->fac_out.u.CFDeactivate.BasicService = 0; //All Services
-- bc->fac_out.u.CFDeactivate.Procedure = 0; //Unconditional
--
-- ast_copy_string((char *)bc->fac_out.u.CFActivate.ServedUserNumber, served_nr, sizeof(bc->fac_out.u.CFActivate.ServedUserNumber));
-+ bc->fac_out.u.CFDeactivate.BasicService = 0; /* All Services */
-+ bc->fac_out.u.CFDeactivate.Procedure = 0; /* Unconditional */
-+ ast_copy_string((char *) bc->fac_out.u.CFActivate.ServedUserNumber, served_nr, sizeof(bc->fac_out.u.CFActivate.ServedUserNumber));
-+
- misdn_lib_send_event(bc, EVENT_FACILITY);
- }
-
-@@ -1773,8 +2390,8 @@
-
- static char *handle_cli_misdn_send_digit(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
- {
-- char *channame;
-- char *msg;
-+ char *channame;
-+ char *msg;
- struct chan_list *tmp;
- int i, msglen;
-
-@@ -1803,7 +2420,7 @@
- tmp = get_chan_by_ast_name(channame);
- if (!tmp) {
- ast_cli(a->fd, "Sending %s to %s failed Channel does not exist\n", msg, channame);
-- return CLI_SUCCESS;
-+ return CLI_SUCCESS;
- }
- #if 1
- for (i = 0; i < msglen; i++) {
-@@ -1841,9 +2458,9 @@
- }
-
- channame = a->argv[3];
--
-+
- ast_cli(a->fd, "Toggling EchoCancel on %s\n", channame);
--
-+
- tmp = get_chan_by_ast_name(channame);
- if (!tmp) {
- ast_cli(a->fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
-@@ -1893,7 +2510,7 @@
-
- ast_cli(a->fd, "Sending %s to %s\n", msg, channame);
- tmp = get_chan_by_ast_name(channame);
--
-+
- if (tmp && tmp->bc) {
- ast_copy_string(tmp->bc->display, msg, sizeof(tmp->bc->display));
- misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
-@@ -2010,23 +2627,25 @@
- };
-
- /*! \brief Updates caller ID information from config */
--static int update_config(struct chan_list *ch, int orig)
-+static void update_config(struct chan_list *ch)
- {
- struct ast_channel *ast;
- struct misdn_bchannel *bc;
-- int port, hdlc = 0;
-- int pres, screen;
-+ int port;
-+ int hdlc = 0;
-+ int pres;
-+ int screen;
-
- if (!ch) {
- ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
-- return -1;
-+ return;
- }
-
- ast = ch->ast;
- bc = ch->bc;
- if (! ast || ! bc) {
- ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
-- return -1;
-+ return;
- }
-
- port = bc->port;
-@@ -2034,7 +2653,6 @@
- chan_misdn_log(7, port, "update_config: Getting Config\n");
-
- misdn_cfg_get(port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
--
- if (hdlc) {
- switch (bc->capability) {
- case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
-@@ -2049,50 +2667,19 @@
- misdn_cfg_get(port, MISDN_CFG_PRES, &pres, sizeof(pres));
- misdn_cfg_get(port, MISDN_CFG_SCREEN, &screen, sizeof(screen));
- chan_misdn_log(2, port, " --> pres: %d screen: %d\n", pres, screen);
--
-+
- if (pres < 0 || screen < 0) {
-- chan_misdn_log(2, port, " --> pres: %x\n", ast->cid.cid_pres);
--
-- switch (ast->cid.cid_pres & 0x60) {
-- case AST_PRES_RESTRICTED:
-- bc->pres = 1;
-- chan_misdn_log(2, port, " --> PRES: Restricted (1)\n");
-- break;
-- case AST_PRES_UNAVAILABLE:
-- bc->pres = 2;
-- chan_misdn_log(2, port, " --> PRES: Unavailable (2)\n");
-- break;
-- default:
-- bc->pres = 0;
-- chan_misdn_log(2, port, " --> PRES: Allowed (0)\n");
-- break;
-- }
-+ chan_misdn_log(2, port, " --> pres: %x\n", ast->connected.id.number_presentation);
-
-- switch (ast->cid.cid_pres & 0x3) {
-- default:
-- case AST_PRES_USER_NUMBER_UNSCREENED:
-- bc->screen = 0;
-- chan_misdn_log(2, port, " --> SCREEN: Unscreened (0)\n");
-- break;
-- case AST_PRES_USER_NUMBER_PASSED_SCREEN:
-- bc->screen = 1;
-- chan_misdn_log(2, port, " --> SCREEN: Passed Screen (1)\n");
-- break;
-- case AST_PRES_USER_NUMBER_FAILED_SCREEN:
-- bc->screen = 2;
-- chan_misdn_log(2, port, " --> SCREEN: Failed Screen (2)\n");
-- break;
-- case AST_PRES_NETWORK_NUMBER:
-- bc->screen = 3;
-- chan_misdn_log(2, port, " --> SCREEN: Network Nr. (3)\n");
-- break;
-- }
-+ bc->caller.presentation = ast_to_misdn_pres(ast->connected.id.number_presentation);
-+ chan_misdn_log(2, port, " --> PRES: %s(%d)\n", misdn_to_str_pres(bc->caller.presentation), bc->caller.presentation);
-+
-+ bc->caller.screening = ast_to_misdn_screen(ast->connected.id.number_presentation);
-+ chan_misdn_log(2, port, " --> SCREEN: %s(%d)\n", misdn_to_str_screen(bc->caller.screening), bc->caller.screening);
- } else {
-- bc->screen = screen;
-- bc->pres = pres;
-+ bc->caller.screening = screen;
-+ bc->caller.presentation = pres;
- }
--
-- return 0;
- }
-
-
-@@ -2100,9 +2687,9 @@
- {
- struct misdn_bchannel *bc = ch->bc;
- int len = ch->jb_len, threshold = ch->jb_upper_threshold;
--
-+
- chan_misdn_log(5, bc->port, "config_jb: Called\n");
--
-+
- if (! len) {
- chan_misdn_log(1, bc->port, "config_jb: Deactivating Jitterbuffer\n");
- bc->nojitter=1;
-@@ -2131,20 +2718,26 @@
- }
-
-
--void debug_numplan(int port, int numplan, char *type)
-+void debug_numtype(int port, int numtype, char *type)
- {
-- switch (numplan) {
-- case NUMPLAN_INTERNATIONAL:
-+ switch (numtype) {
-+ case NUMTYPE_UNKNOWN:
-+ chan_misdn_log(2, port, " --> %s: Unknown\n", type);
-+ break;
-+ case NUMTYPE_INTERNATIONAL:
- chan_misdn_log(2, port, " --> %s: International\n", type);
- break;
-- case NUMPLAN_NATIONAL:
-+ case NUMTYPE_NATIONAL:
- chan_misdn_log(2, port, " --> %s: National\n", type);
- break;
-- case NUMPLAN_SUBSCRIBER:
-+ case NUMTYPE_NETWORK_SPECIFIC:
-+ chan_misdn_log(2, port, " --> %s: Network Specific\n", type);
-+ break;
-+ case NUMTYPE_SUBSCRIBER:
- chan_misdn_log(2, port, " --> %s: Subscriber\n", type);
- break;
-- case NUMPLAN_UNKNOWN:
-- chan_misdn_log(2, port, " --> %s: Unknown\n", type);
-+ case NUMTYPE_ABBREVIATED:
-+ chan_misdn_log(2, port, " --> %s: Abbreviated\n", type);
- break;
- /* Maybe we should cut off the prefix if present ? */
- default:
-@@ -2194,7 +2787,7 @@
- #endif
-
-
--static int read_config(struct chan_list *ch, int orig)
-+static int read_config(struct chan_list *ch)
- {
- struct ast_channel *ast;
- struct misdn_bchannel *bc;
-@@ -2218,7 +2811,7 @@
- ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
- return -1;
- }
--
-+
- port = bc->port;
- chan_misdn_log(1, port, "read_config: Getting Config\n");
-
-@@ -2233,9 +2826,8 @@
- misdn_cfg_get(port, MISDN_CFG_INCOMING_EARLY_AUDIO, &ch->incoming_early_audio, sizeof(ch->incoming_early_audio));
-
- misdn_cfg_get(port, MISDN_CFG_SENDDTMF, &bc->send_dtmf, sizeof(bc->send_dtmf));
--
-+
- misdn_cfg_get(port, MISDN_CFG_ASTDTMF, &ch->ast_dsp, sizeof(int));
--
- if (ch->ast_dsp) {
- ch->ignore_dtmf = 1;
- }
-@@ -2252,7 +2844,6 @@
- misdn_cfg_get(port, MISDN_CFG_FAXDETECT, faxdetect, sizeof(faxdetect));
-
- misdn_cfg_get(port, MISDN_CFG_HDLC, &hdlc, sizeof(hdlc));
--
- if (hdlc) {
- switch (bc->capability) {
- case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
-@@ -2261,7 +2852,7 @@
- bc->hdlc = 1;
- break;
- }
--
-+
- }
- /*Initialize new Jitterbuffer*/
- misdn_cfg_get(port, MISDN_CFG_JITTERBUFFER, &ch->jb_len, sizeof(ch->jb_len));
-@@ -2281,14 +2872,16 @@
-
- misdn_cfg_get(bc->port, MISDN_CFG_EARLY_BCONNECT, &bc->early_bconnect, sizeof(bc->early_bconnect));
-
-+ misdn_cfg_get(port, MISDN_CFG_DISPLAY_CONNECTED, &bc->display_connected, sizeof(bc->display_connected));
-+ misdn_cfg_get(port, MISDN_CFG_DISPLAY_SETUP, &bc->display_setup, sizeof(bc->display_setup));
-+
- misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
- misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
--
- chan_misdn_log(5, port, " --> * CallGrp:%s PickupGrp:%s\n", ast_print_group(buf, sizeof(buf), cg), ast_print_group(buf2, sizeof(buf2), pg));
- ast->pickupgroup = pg;
- ast->callgroup = cg;
--
-- if (orig == ORG_AST) {
-+
-+ if (ch->originator == ORG_AST) {
- char callerid[BUFFERSIZE + 1];
-
- /* ORIGINATOR Asterisk (outgoing call) */
-@@ -2301,87 +2894,53 @@
-
- misdn_cfg_get(port, MISDN_CFG_CALLERID, callerid, sizeof(callerid));
- if (!ast_strlen_zero(callerid)) {
-- chan_misdn_log(1, port, " --> * Setting Cid to %s\n", callerid);
-- ast_copy_string(bc->oad, callerid, sizeof(bc->oad));
-+ char *cid_name = NULL;
-+ char *cid_num = NULL;
-+
-+ ast_callerid_parse(callerid, &cid_name, &cid_num);
-+ if (cid_name) {
-+ ast_copy_string(bc->caller.name, cid_name, sizeof(bc->caller.name));
-+ } else {
-+ bc->caller.name[0] = '\0';
-+ }
-+ if (cid_num) {
-+ ast_copy_string(bc->caller.number, cid_num, sizeof(bc->caller.number));
-+ } else {
-+ bc->caller.number[0] = '\0';
-+ }
-+ chan_misdn_log(1, port, " --> * Setting caller to \"%s\" <%s>\n", bc->caller.name, bc->caller.number);
- }
-
-- misdn_cfg_get(port, MISDN_CFG_DIALPLAN, &bc->dnumplan, sizeof(bc->dnumplan));
-- misdn_cfg_get(port, MISDN_CFG_LOCALDIALPLAN, &bc->onumplan, sizeof(bc->onumplan));
-- misdn_cfg_get(port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(bc->cpnnumplan));
-- debug_numplan(port, bc->dnumplan, "TON");
-- debug_numplan(port, bc->onumplan, "LTON");
-- debug_numplan(port, bc->cpnnumplan, "CTON");
-+ misdn_cfg_get(port, MISDN_CFG_DIALPLAN, &bc->dialed.number_type, sizeof(bc->dialed.number_type));
-+ bc->dialed.number_plan = NUMPLAN_ISDN;
-+ debug_numtype(port, bc->dialed.number_type, "TON");
-
- ch->overlap_dial = 0;
- } else {
- /* ORIGINATOR MISDN (incoming call) */
-- char prefix[BUFFERSIZE + 1] = "";
-
- if (strstr(faxdetect, "incoming") || strstr(faxdetect, "both")) {
- ch->faxdetect = (strstr(faxdetect, "nojump")) ? 2 : 1;
- }
-
-- misdn_cfg_get(port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(bc->cpnnumplan));
-- debug_numplan(port, bc->cpnnumplan, "CTON");
-+ /* Add configured prefix to caller.number */
-+ misdn_add_number_prefix(bc->port, bc->caller.number_type, bc->caller.number, sizeof(bc->caller.number));
-
-- switch (bc->onumplan) {
-- case NUMPLAN_INTERNATIONAL:
-- misdn_cfg_get(bc->port, MISDN_CFG_INTERNATPREFIX, prefix, sizeof(prefix));
-- break;
--
-- case NUMPLAN_NATIONAL:
-- misdn_cfg_get(bc->port, MISDN_CFG_NATPREFIX, prefix, sizeof(prefix));
-- break;
-- default:
-- break;
-+ if (ast_strlen_zero(bc->dialed.number) && !ast_strlen_zero(bc->keypad)) {
-+ ast_copy_string(bc->dialed.number, bc->keypad, sizeof(bc->dialed.number));
- }
-
-- ast_copy_string(buf, bc->oad, sizeof(buf));
-- snprintf(bc->oad, sizeof(bc->oad), "%s%s", prefix, buf);
-+ /* Add configured prefix to dialed.number */
-+ misdn_add_number_prefix(bc->port, bc->dialed.number_type, bc->dialed.number, sizeof(bc->dialed.number));
-
-- if (!ast_strlen_zero(bc->dad)) {
-- ast_copy_string(bc->orig_dad, bc->dad, sizeof(bc->orig_dad));
-- }
-+ ast_copy_string(ast->exten, bc->dialed.number, sizeof(ast->exten));
-
-- if (ast_strlen_zero(bc->dad) && !ast_strlen_zero(bc->keypad)) {
-- ast_copy_string(bc->dad, bc->keypad, sizeof(bc->dad));
-- }
--
-- prefix[0] = 0;
--
-- switch (bc->dnumplan) {
-- case NUMPLAN_INTERNATIONAL:
-- misdn_cfg_get(bc->port, MISDN_CFG_INTERNATPREFIX, prefix, sizeof(prefix));
-- break;
-- case NUMPLAN_NATIONAL:
-- misdn_cfg_get(bc->port, MISDN_CFG_NATPREFIX, prefix, sizeof(prefix));
-- break;
-- default:
-- break;
-- }
--
-- ast_copy_string(buf, bc->dad, sizeof(buf));
-- snprintf(bc->dad, sizeof(bc->dad), "%s%s", prefix, buf);
--
-- if (strcmp(bc->dad, ast->exten)) {
-- ast_copy_string(ast->exten, bc->dad, sizeof(ast->exten));
-- }
--
-- ast_set_callerid(ast, bc->oad, NULL, bc->oad);
--
-- if ( !ast_strlen_zero(bc->rad) ) {
-- if (ast->cid.cid_rdnis) {
-- ast_free(ast->cid.cid_rdnis);
-- }
-- ast->cid.cid_rdnis = ast_strdup(bc->rad);
-- }
--
- misdn_cfg_get(bc->port, MISDN_CFG_OVERLAP_DIAL, &ch->overlap_dial, sizeof(ch->overlap_dial));
- ast_mutex_init(&ch->overlap_tv_lock);
- } /* ORIG MISDN END */
-
- ch->overlap_dial_task = -1;
--
-+
- if (ch->faxdetect || ch->ast_dsp) {
- misdn_cfg_get(port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
- if (!ch->dsp) {
-@@ -2401,7 +2960,80 @@
- return 0;
- }
-
-+/*!
-+ * \internal
-+ * \brief Notify peer that the connected line has changed.
-+ *
-+ * \param ast Current Asterisk channel
-+ * \param bc Associated B channel
-+ * \param originator Who originally created this channel. ORG_AST or ORG_MISDN
-+ *
-+ * \return Nothing
-+ */
-+static void misdn_update_connected_line(struct ast_channel *ast, struct misdn_bchannel *bc, int originator)
-+{
-+ int number_type;
-
-+ if (originator == ORG_MISDN) {
-+ /* ORIGINATOR MISDN (incoming call) */
-+
-+ ast_copy_string(bc->connected.name, S_OR(ast->connected.id.name, ""), sizeof(bc->connected.name));
-+ ast_copy_string(bc->connected.number, S_OR(ast->connected.id.number, ""), sizeof(bc->connected.number));
-+ bc->connected.presentation = ast_to_misdn_pres(ast->connected.id.number_presentation);
-+ bc->connected.screening = ast_to_misdn_screen(ast->connected.id.number_presentation);
-+
-+ misdn_cfg_get(bc->port, MISDN_CFG_CPNDIALPLAN, &number_type, sizeof(number_type));
-+ if (number_type < 0) {
-+ bc->connected.number_type = ast_to_misdn_ton(ast->connected.id.number_type);
-+ bc->connected.number_plan = ast_to_misdn_plan(ast->connected.id.number_type);
-+ } else {
-+ /* Force us to send in CONNECT message */
-+ bc->connected.number_type = number_type;
-+ bc->connected.number_plan = NUMPLAN_ISDN;
-+ }
-+ debug_numtype(bc->port, bc->connected.number_type, "CTON");
-+ } else {
-+ /* ORIGINATOR Asterisk (outgoing call) */
-+
-+ ast_copy_string(bc->caller.name, S_OR(ast->connected.id.name, ""), sizeof(bc->caller.name));
-+ ast_copy_string(bc->caller.number, S_OR(ast->connected.id.number, ""), sizeof(bc->caller.number));
-+ bc->caller.presentation = ast_to_misdn_pres(ast->connected.id.number_presentation);
-+ bc->caller.screening = ast_to_misdn_screen(ast->connected.id.number_presentation);
-+
-+ misdn_cfg_get(bc->port, MISDN_CFG_LOCALDIALPLAN, &number_type, sizeof(number_type));
-+ if (number_type < 0) {
-+ bc->caller.number_type = ast_to_misdn_ton(ast->connected.id.number_type);
-+ bc->caller.number_plan = ast_to_misdn_plan(ast->connected.id.number_type);
-+ } else {
-+ /* Force us to send in SETUP message */
-+ bc->caller.number_type = number_type;
-+ bc->caller.number_plan = NUMPLAN_ISDN;
-+ }
-+ debug_numtype(bc->port, bc->caller.number_type, "LTON");
-+ }
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Copy the redirecting info out of the Asterisk channel
-+ *
-+ * \param bc Associated B channel
-+ * \param ast Current Asterisk channel
-+ *
-+ * \return Nothing
-+ */
-+static void misdn_copy_redirecting_from_ast(struct misdn_bchannel *bc, struct ast_channel *ast)
-+{
-+ ast_copy_string(bc->redirecting.from.name, S_OR(ast->redirecting.from.name, ""), sizeof(bc->redirecting.from.name));
-+ ast_copy_string(bc->redirecting.from.number, S_OR(ast->cid.cid_rdnis, ""), sizeof(bc->redirecting.from.number));
-+ bc->redirecting.from.presentation = ast_to_misdn_pres(ast->redirecting.from.number_presentation);
-+ bc->redirecting.from.screening = ast_to_misdn_screen(ast->redirecting.from.number_presentation);
-+ bc->redirecting.from.number_type = ast_to_misdn_ton(ast->redirecting.from.number_type);
-+ bc->redirecting.from.number_plan = ast_to_misdn_plan(ast->redirecting.from.number_type);
-+ bc->redirecting.reason = ast_to_misdn_reason(ast->redirecting.reason);
-+}
-+
-+
- /*****************************/
- /*** AST Indications Start ***/
- /*****************************/
-@@ -2412,22 +3044,17 @@
- int r;
- int exceed;
- int bridging;
-- struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(ast);
-+ int number_type;
-+ struct chan_list *ch;
- struct misdn_bchannel *newbc;
-- char *dest_cp = ast_strdupa(dest);
-+ char *dest_cp;
-+
- AST_DECLARE_APP_ARGS(args,
-- AST_APP_ARG(type);
-- AST_APP_ARG(ext);
-- AST_APP_ARG(opts);
-+ AST_APP_ARG(intf); /* The interface token is discarded. */
-+ AST_APP_ARG(ext); /* extension token */
-+ AST_APP_ARG(opts); /* options token */
- );
-
-- AST_NONSTANDARD_APP_ARGS(args, dest_cp, '/');
--
-- if (ast_strlen_zero(args.ext)) {
-- chan_misdn_log(0, 0, "misdn_call: No Extension given!\n");
-- return -1;
-- }
--
- if (!ast) {
- ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n");
- return -1;
-@@ -2440,58 +3067,85 @@
- return -1;
- }
-
-+ ch = MISDN_ASTERISK_TECH_PVT(ast);
- if (!ch) {
-- ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
-+ ast_log(LOG_WARNING, " --> ! misdn_call called on %s, chan_list *ch==NULL\n", ast->name);
- ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
- ast_setstate(ast, AST_STATE_DOWN);
- return -1;
- }
--
-+
- newbc = ch->bc;
--
- if (!newbc) {
-- ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
-+ ast_log(LOG_WARNING, " --> ! misdn_call called on %s, newbc==NULL\n", ast->name);
- ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
- ast_setstate(ast, AST_STATE_DOWN);
- return -1;
- }
--
-+
-+ /*
-+ * dest is ---v
-+ * Dial(mISDN/g:group_name[/extension[/options]])
-+ * Dial(mISDN/port[:preselected_channel][/extension[/options]])
-+ *
-+ * The dial extension could be empty if you are using MISDN_KEYPAD
-+ * to control ISDN provider features.
-+ */
-+ dest_cp = ast_strdupa(dest);
-+ AST_NONSTANDARD_APP_ARGS(args, dest_cp, '/');
-+ if (!args.ext) {
-+ args.ext = "";
-+ }
-+
- port = newbc->port;
-
-- if ((exceed = add_out_calls(port))) {
-+ exceed = add_out_calls(port);
-+ if (exceed != 0) {
- char tmp[16];
- snprintf(tmp, sizeof(tmp), "%d", exceed);
- pbx_builtin_setvar_helper(ast, "MAX_OVERFLOW", tmp);
-+ ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
-+ ast_setstate(ast, AST_STATE_DOWN);
- return -1;
- }
--
-+
- chan_misdn_log(1, port, "* CALL: %s\n", dest);
--
-- chan_misdn_log(2, port, " --> * dad:%s tech:%s ctx:%s\n", ast->exten, ast->name, ast->context);
--
-- chan_misdn_log(3, port, " --> * adding2newbc ext %s\n", ast->exten);
-- if (ast->exten) {
-- ast_copy_string(ast->exten, args.ext, sizeof(ast->exten));
-- ast_copy_string(newbc->dad, args.ext, sizeof(newbc->dad));
-- }
-
-- ast_copy_string(newbc->rad, S_OR(ast->cid.cid_rdnis, ""), sizeof(newbc->rad));
-+ chan_misdn_log(2, port, " --> * dialed:%s tech:%s context:%s\n", args.ext, ast->name, ast->context);
-
-- chan_misdn_log(3, port, " --> * adding2newbc callerid %s\n", ast->cid.cid_num);
-- if (ast_strlen_zero(newbc->oad) && !ast_strlen_zero(ast->cid.cid_num)) {
-- ast_copy_string(newbc->oad, ast->cid.cid_num, sizeof(newbc->oad));
-+ ast_copy_string(ast->exten, args.ext, sizeof(ast->exten));
-+ ast_copy_string(newbc->dialed.number, args.ext, sizeof(newbc->dialed.number));
-+
-+ if (ast_strlen_zero(newbc->caller.name) && !ast_strlen_zero(ast->connected.id.name)) {
-+ ast_copy_string(newbc->caller.name, ast->connected.id.name, sizeof(newbc->caller.name));
-+ chan_misdn_log(3, port, " --> * set caller:\"%s\" <%s>\n", newbc->caller.name, newbc->caller.number);
- }
-+ if (ast_strlen_zero(newbc->caller.number) && !ast_strlen_zero(ast->connected.id.number)) {
-+ ast_copy_string(newbc->caller.number, ast->connected.id.number, sizeof(newbc->caller.number));
-+ chan_misdn_log(3, port, " --> * set caller:\"%s\" <%s>\n", newbc->caller.name, newbc->caller.number);
-+ }
-
-+ misdn_cfg_get(port, MISDN_CFG_LOCALDIALPLAN, &number_type, sizeof(number_type));
-+ if (number_type < 0) {
-+ newbc->caller.number_type = ast_to_misdn_ton(ast->connected.id.number_type);
-+ newbc->caller.number_plan = ast_to_misdn_plan(ast->connected.id.number_type);
-+ } else {
-+ /* Force us to send in SETUP message */
-+ newbc->caller.number_type = number_type;
-+ newbc->caller.number_plan = NUMPLAN_ISDN;
-+ }
-+ debug_numtype(port, newbc->caller.number_type, "LTON");
-+
- newbc->capability = ast->transfercapability;
- pbx_builtin_setvar_helper(ast, "TRANSFERCAPABILITY", ast_transfercapability2str(newbc->capability));
- if ( ast->transfercapability == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) {
- chan_misdn_log(2, port, " --> * Call with flag Digital\n");
- }
-
-- /* update screening and presentation */
-- update_config(ch, ORG_AST);
--
-- /* fill in some ies from channel vary */
-+ /* update caller screening and presentation */
-+ update_config(ch);
-+
-+ /* fill in some ies from channel dialplan variables */
- import_ch(ast, newbc, ch);
-
- /* Finally The Options Override Everything */
-@@ -2500,7 +3154,12 @@
- } else {
- chan_misdn_log(2, port, "NO OPTS GIVEN\n");
- }
-+ if (newbc->set_presentation) {
-+ newbc->caller.presentation = newbc->presentation;
-+ }
-
-+ misdn_copy_redirecting_from_ast(newbc, ast);
-+
- /*check for bridging*/
- misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
- if (bridging && ch->other_ch) {
-@@ -2520,7 +3179,7 @@
- /** we should have l3id after sending setup **/
- ch->l3id = newbc->l3_id;
-
-- if (r == -ENOCHAN ) {
-+ if (r == -ENOCHAN) {
- chan_misdn_log(0, port, " --> * Theres no Channel at the moment .. !\n");
- chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n", newbc ? newbc->pid : -1);
- ast->hangupcause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION;
-@@ -2538,8 +3197,8 @@
- }
-
- ch->state = MISDN_CALLING;
--
-- return 0;
-+
-+ return 0;
- }
-
-
-@@ -2551,9 +3210,9 @@
- if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) {
- return -1;
- }
--
-+
- chan_misdn_log(1, p ? (p->bc ? p->bc->port : 0) : 0, "* ANSWER:\n");
--
-+
- if (!p) {
- ast_log(LOG_WARNING, " --> Channel not connected ??\n");
- ast_queue_hangup_with_cause(ast, AST_CAUSE_NETWORK_OUT_OF_ORDER);
-@@ -2586,9 +3245,19 @@
- p->state = MISDN_CONNECTED;
- stop_indicate(p);
-
-- if ( ast_strlen_zero(p->bc->cad) ) {
-- chan_misdn_log(2, p->bc->port, " --> empty cad using dad\n");
-- ast_copy_string(p->bc->cad, p->bc->dad, sizeof(p->bc->cad));
-+ if (ast_strlen_zero(p->bc->connected.number)) {
-+ chan_misdn_log(2,p->bc->port," --> empty connected number using dialed number\n");
-+ ast_copy_string(p->bc->connected.number, p->bc->dialed.number, sizeof(p->bc->connected.number));
-+
-+ /*
-+ * Use the misdn_set_opt() application to set the presentation
-+ * before we answer or you can use the CONECTEDLINE() function
-+ * to set everything before using the Answer() application.
-+ */
-+ p->bc->connected.presentation = p->bc->presentation;
-+ p->bc->connected.screening = 0; /* unscreened */
-+ p->bc->connected.number_type = p->bc->dialed.number_type;
-+ p->bc->connected.number_plan = p->bc->dialed.number_plan;
- }
-
- misdn_lib_send_event(p->bc, EVENT_CONNECT);
-@@ -2615,12 +3284,12 @@
-
- bc = p->bc;
- chan_misdn_log(1, bc ? bc->port : 0, "* IND : Digit %c\n", digit);
--
-+
- if (!bc) {
- ast_log(LOG_WARNING, " --> !! Got Digit Event without having bchannel Object\n");
- return -1;
- }
--
-+
- switch (p->state ) {
- case MISDN_CALLING:
- if (strlen(bc->infos_pending) < sizeof(bc->infos_pending) - 1) {
-@@ -2629,15 +3298,15 @@
- break;
- case MISDN_CALLING_ACKNOWLEDGE:
- ast_copy_string(bc->info_dad, buf, sizeof(bc->info_dad));
-- if (strlen(bc->dad) < sizeof(bc->dad) - 1) {
-- strncat(bc->dad, buf, sizeof(bc->dad) - strlen(bc->dad) - 1);
-+ if (strlen(bc->dialed.number) < sizeof(bc->dialed.number) - 1) {
-+ strncat(bc->dialed.number, buf, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
- }
-- ast_copy_string(p->ast->exten, bc->dad, sizeof(p->ast->exten));
-+ ast_copy_string(p->ast->exten, bc->dialed.number, sizeof(p->ast->exten));
- misdn_lib_send_event(bc, EVENT_INFORMATION);
- break;
- default:
- /* Do not send Digits in CONNECTED State, when
-- * the other side is too mISDN. */
-+ * the other side is also mISDN. */
- if (p->other_ch) {
- return 0;
- }
-@@ -2677,18 +3346,18 @@
- ast_log(LOG_WARNING, "Returned -1 in misdn_indication\n");
- return -1;
- }
--
-+
- if (!p->bc ) {
- chan_misdn_log(1, 0, "* IND : Indication from %s\n", ast->exten);
- ast_log(LOG_WARNING, "Private Pointer but no bc ?\n");
- return -1;
- }
--
-+
- chan_misdn_log(5, p->bc->port, "* IND : Indication [%d] from %s\n", cond, ast->exten);
--
-+
- switch (cond) {
- case AST_CONTROL_BUSY:
-- chan_misdn_log(1, p->bc->port, "* IND :\tbusy pid:%d\n", p->bc ? p->bc->pid : -1);
-+ chan_misdn_log(1, p->bc->port, "* IND :\tbusy pid:%d\n", p->bc->pid);
- ast_setstate(ast, AST_STATE_BUSY);
-
- p->bc->out_cause = AST_CAUSE_USER_BUSY;
-@@ -2700,20 +3369,20 @@
- }
- return -1;
- case AST_CONTROL_RING:
-- chan_misdn_log(1, p->bc->port, "* IND :\tring pid:%d\n", p->bc ? p->bc->pid : -1);
-+ chan_misdn_log(1, p->bc->port, "* IND :\tring pid:%d\n", p->bc->pid);
- return -1;
- case AST_CONTROL_RINGING:
-- chan_misdn_log(1, p->bc->port, "* IND :\tringing pid:%d\n", p->bc ? p->bc->pid : -1);
-+ chan_misdn_log(1, p->bc->port, "* IND :\tringing pid:%d\n", p->bc->pid);
- switch (p->state) {
- case MISDN_ALERTING:
-- chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but I was Ringing before, so ignoring it\n", p->bc ? p->bc->pid : -1);
-+ chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but I was Ringing before, so ignoring it\n", p->bc->pid);
- break;
- case MISDN_CONNECTED:
-- chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but Connected, so just send TONE_ALERTING without state changes \n", p->bc ? p->bc->pid : -1);
-+ chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but Connected, so just send TONE_ALERTING without state changes \n", p->bc->pid);
- return -1;
- default:
- p->state = MISDN_ALERTING;
-- chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d\n", p->bc ? p->bc->pid : -1);
-+ chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d\n", p->bc->pid);
- misdn_lib_send_event( p->bc, EVENT_ALERTING);
-
- if (p->other_ch && p->other_ch->bc) {
-@@ -2728,7 +3397,7 @@
- }
- }
-
-- chan_misdn_log(3, p->bc->port, " --> * SEND: State Ring pid:%d\n", p->bc ? p->bc->pid : -1);
-+ chan_misdn_log(3, p->bc->port, " --> * SEND: State Ring pid:%d\n", p->bc->pid);
- ast_setstate(ast, AST_STATE_RING);
-
- if (!p->bc->nt && (p->originator == ORG_MISDN) && !p->incoming_early_audio) {
-@@ -2739,28 +3408,28 @@
- }
- break;
- case AST_CONTROL_ANSWER:
-- chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n", p->bc ? p->bc->pid : -1);
-+ chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n", p->bc->pid);
- start_bc_tones(p);
- break;
- case AST_CONTROL_TAKEOFFHOOK:
-- chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n", p->bc ? p->bc->pid : -1);
-+ chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n", p->bc->pid);
- return -1;
- case AST_CONTROL_OFFHOOK:
-- chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n", p->bc ? p->bc->pid : -1);
-+ chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n", p->bc->pid);
- return -1;
- case AST_CONTROL_FLASH:
-- chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n", p->bc ? p->bc->pid : -1);
-+ chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n", p->bc->pid);
- break;
- case AST_CONTROL_PROGRESS:
-- chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n", p->bc ? p->bc->pid : -1);
-+ chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n", p->bc->pid);
- misdn_lib_send_event( p->bc, EVENT_PROGRESS);
- break;
- case AST_CONTROL_PROCEEDING:
-- chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n", p->bc ? p->bc->pid : -1);
-+ chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n", p->bc->pid);
- misdn_lib_send_event( p->bc, EVENT_PROCEEDING);
- break;
- case AST_CONTROL_CONGESTION:
-- chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n", p->bc ? p->bc->pid : -1);
-+ chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n", p->bc->pid);
-
- p->bc->out_cause = AST_CAUSE_SWITCH_CONGESTION;
- start_bc_tones(p);
-@@ -2771,7 +3440,7 @@
- }
- break;
- case -1 :
-- chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n", p->bc ? p->bc->pid : -1);
-+ chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n", p->bc->pid);
-
- stop_indicate(p);
-
-@@ -2780,17 +3449,26 @@
- }
- break;
- case AST_CONTROL_HOLD:
-- ast_moh_start(ast, data, p->mohinterpret);
-- chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n", p->bc ? p->bc->pid : -1);
-+ ast_moh_start(ast, data, p->mohinterpret);
-+ chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n", p->bc->pid);
- break;
- case AST_CONTROL_UNHOLD:
- ast_moh_stop(ast);
-- chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n", p->bc ? p->bc->pid : -1);
-+ chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n", p->bc->pid);
- break;
-+ case AST_CONTROL_CONNECTED_LINE:
-+ chan_misdn_log(1, p->bc->port, "* IND :\tconnected line update pid:%d\n", p->bc->pid);
-+ misdn_update_connected_line(ast, p->bc, p->originator);
-+ break;
-+ case AST_CONTROL_REDIRECTING:
-+ chan_misdn_log(1, p->bc->port, "* IND :\tredirecting info update pid:%d\n", p->bc->pid);
-+ misdn_copy_redirecting_from_ast(p->bc, ast);
-+ break;
- default:
-- chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n", cond, p->bc ? p->bc->pid : -1);
-+ chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n", cond, p->bc->pid);
-+ break;
- }
--
-+
- return 0;
- }
-
-@@ -2815,8 +3493,10 @@
-
- if (bc) {
- const char *tmp;
-+
- ast_channel_lock(ast);
-- if ((tmp = pbx_builtin_getvar_helper(ast, "MISDN_USERUSER"))) {
-+ tmp = pbx_builtin_getvar_helper(ast, "MISDN_USERUSER");
-+ if (tmp) {
- ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
- strcpy(bc->uu, tmp);
- bc->uulen = strlen(bc->uu);
-@@ -2827,16 +3507,16 @@
- MISDN_ASTERISK_TECH_PVT(ast) = NULL;
- p->ast = NULL;
-
-- if (ast->_state == AST_STATE_RESERVED ||
-- p->state == MISDN_NOTHING ||
-- p->state == MISDN_HOLDED ||
-+ if (ast->_state == AST_STATE_RESERVED ||
-+ p->state == MISDN_NOTHING ||
-+ p->state == MISDN_HOLDED ||
- p->state == MISDN_HOLD_DISCONNECT ) {
-
- CLEAN_CH:
- /* between request and call */
- ast_debug(1, "State Reserved (or nothing) => chanIsAvail\n");
- MISDN_ASTERISK_TECH_PVT(ast) = NULL;
--
-+
- ast_mutex_lock(&release_lock);
- cl_dequeue_chan(&cl_te, p);
- close(p->pipe[0]);
-@@ -2876,17 +3556,23 @@
- }
- ast_channel_unlock(ast);
-
-- chan_misdn_log(1, bc->port, "* IND : HANGUP\tpid:%d ctx:%s dad:%s oad:%s State:%s\n", p->bc ? p->bc->pid : -1, ast->context, ast->exten, ast->cid.cid_num, misdn_get_ch_state(p));
-+ chan_misdn_log(1, bc->port,
-+ "* IND : HANGUP\tpid:%d context:%s dialed:%s caller:\"%s\" <%s> State:%s\n",
-+ p->bc ? p->bc->pid : -1,
-+ ast->context,
-+ ast->exten,
-+ ast->cid.cid_name ? ast->cid.cid_name : "",
-+ ast->cid.cid_num ? ast->cid.cid_num : "",
-+ misdn_get_ch_state(p));
- chan_misdn_log(3, bc->port, " --> l3id:%x\n", p->l3id);
- chan_misdn_log(3, bc->port, " --> cause:%d\n", bc->cause);
- chan_misdn_log(2, bc->port, " --> out_cause:%d\n", bc->out_cause);
-- chan_misdn_log(2, bc->port, " --> state:%s\n", misdn_get_ch_state(p));
-
- switch (p->state) {
- case MISDN_INCOMING_SETUP:
- case MISDN_CALLING:
- p->state = MISDN_CLEANING;
-- /* This is the only place in misdn_hangup, where we
-+ /* This is the only place in misdn_hangup, where we
- * can call release_chan, else it might create lot's of trouble
- * */
- ast_log(LOG_NOTICE, "release channel, in CALLING/INCOMING_SETUP state.. no other events happened\n");
-@@ -2970,7 +3656,7 @@
- if (bc->need_release) {
- misdn_lib_send_event(bc, EVENT_RELEASE);
- }
-- p->state = MISDN_CLEANING;
-+ p->state = MISDN_CLEANING;
- } else {
- if (bc->need_disconnect) {
- misdn_lib_send_event(bc, EVENT_DISCONNECT);
-@@ -2989,7 +3675,7 @@
- static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame)
- {
- struct ast_frame *f,*f2;
--
-+
- if (tmp->trans) {
- f2 = ast_translate(tmp->trans, frame, 0);
- f = ast_dsp_process(tmp->ast, tmp->dsp, f2);
-@@ -3000,9 +3686,9 @@
-
- if (!f || (f->frametype != AST_FRAME_DTMF))
- return frame;
--
-+
- ast_debug(1, "Detected inband DTMF digit: %c\n", f->subclass);
--
-+
- if (tmp->faxdetect && (f->subclass == 'f')) {
- /* Fax tone -- Handle and return NULL */
- if (!tmp->faxhandled) {
-@@ -3035,7 +3721,7 @@
- ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, context);
- }
- } else {
-- ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n", context, ast->exten);
-+ ast_log(LOG_NOTICE, "Fax detected but no fax extension, context:%s exten:%s\n", context, ast->exten);
- }
- } else {
- ast_debug(1, "Already in a fax extension, not redirecting\n");
-@@ -3049,7 +3735,7 @@
- ast_debug(1, "Fax already handled\n");
- }
- }
--
-+
- if (tmp->ast_dsp && (f->subclass != 'f')) {
- chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n", f->subclass);
- }
-@@ -3082,7 +3768,8 @@
- FD_ZERO(&rrfs);
- FD_SET(tmp->pipe[0], &rrfs);
-
-- if (!(t = select(FD_SETSIZE, &rrfs, NULL, NULL, &tv))) {
-+ t = select(FD_SETSIZE, &rrfs, NULL, NULL, &tv);
-+ if (!t) {
- chan_misdn_log(3, tmp->bc->port, "read Select Timed out\n");
- len = 160;
- }
-@@ -3151,7 +3838,7 @@
- {
- struct chan_list *ch;
- int i = 0;
--
-+
- if (!ast || !(ch = MISDN_ASTERISK_TECH_PVT(ast))) {
- return -1;
- }
-@@ -3160,12 +3847,12 @@
- chan_misdn_log(7, 0, "misdn_write: Returning because holded\n");
- return 0;
- }
--
-+
- if (!ch->bc ) {
- ast_log(LOG_WARNING, "private but no bc\n");
- return -1;
- }
--
-+
- if (ch->notxtone) {
- chan_misdn_log(7, ch->bc->port, "misdn_write: Returning because notxtone\n");
- return 0;
-@@ -3176,16 +3863,16 @@
- chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n");
- return 0;
- }
--
-+
- if (!(frame->subclass & prefformat)) {
- chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass);
- return 0;
- }
--
-
-+
- if (!frame->samples ) {
- chan_misdn_log(4, ch->bc->port, "misdn_write: zero write\n");
--
-+
- if (!strcmp(frame->src,"ast_prod")) {
- chan_misdn_log(1, ch->bc->port, "misdn_write: state (%s) prodded.\n", misdn_get_ch_state(ch));
-
-@@ -3203,7 +3890,7 @@
- chan_misdn_log(8, ch->bc->port, "misdn_write: no addr for bc dropping:%d\n", frame->samples);
- return 0;
- }
--
-+
- #ifdef MISDN_DEBUG
- {
- int i, max = 5 > frame->samples ? frame->samples : 5;
-@@ -3224,7 +3911,7 @@
- if (!ch->dropped_frame_cnt) {
- chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) dropping: %d frames addr:%x exten:%s cid:%s ch->state:%s bc_state:%d l3id:%x\n", frame->samples, ch->bc->addr, ast->exten, ast->cid.cid_num, misdn_get_ch_state( ch), ch->bc->bc_state, ch->bc->l3_id);
- }
--
-+
- if (++ch->dropped_frame_cnt > 100) {
- ch->dropped_frame_cnt = 0;
- chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) dropping: %d frames addr:%x dropped > 100 frames!\n", frame->samples, ch->bc->addr);
-@@ -3241,7 +3928,7 @@
- cb_log(0, ch->bc->port, "Misdn Jitterbuffer Overflow.\n");
- }
- }
--
-+
- } else {
- /*transmit without jitterbuffer*/
- i = misdn_lib_tx2misdn_frm(ch->bc, frame->data.ptr, frame->samples);
-@@ -3250,15 +3937,11 @@
- return 0;
- }
-
--
--
--
--static enum ast_bridge_result misdn_bridge (struct ast_channel *c0,
-- struct ast_channel *c1, int flags,
-- struct ast_frame **fo,
-- struct ast_channel **rc,
-- int timeoutms)
--
-+static enum ast_bridge_result misdn_bridge(struct ast_channel *c0,
-+ struct ast_channel *c1, int flags,
-+ struct ast_frame **fo,
-+ struct ast_channel **rc,
-+ int timeoutms)
- {
- struct chan_list *ch1, *ch2;
- struct ast_channel *carr[2], *who;
-@@ -3266,13 +3949,13 @@
- struct ast_frame *f;
- int p1_b, p2_b;
- int bridging;
--
-+
- ch1 = get_chan_by_ast(c0);
- ch2 = get_chan_by_ast(c1);
-
- carr[0] = c0;
- carr[1] = c1;
--
-+
- if (!(ch1 && ch2)) {
- return -1;
- }
-@@ -3294,8 +3977,12 @@
-
- ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
-
-- chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
--
-+ chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between \"%s\" <%s> and \"%s\" <%s>\n",
-+ ch1->bc->caller.name,
-+ ch1->bc->caller.number,
-+ ch2->bc->caller.name,
-+ ch2->bc->caller.number);
-+
- if (! (flags & AST_BRIDGE_DTMF_CHANNEL_0) ) {
- ch1->ignore_dtmf = 1;
- }
-@@ -3317,7 +4004,7 @@
- if (!f || f->frametype == AST_FRAME_CONTROL) {
- /* got hangup .. */
-
-- if (!f)
-+ if (!f)
- chan_misdn_log(4, ch1->bc->port, "Read Null Frame\n");
- else
- chan_misdn_log(4, ch1->bc->port, "Read Frame Control class:%d\n", f->subclass);
-@@ -3326,7 +4013,7 @@
- *rc = who;
- break;
- }
--
-+
- if ( f->frametype == AST_FRAME_DTMF ) {
- chan_misdn_log(1, 0, "Read DTMF %d from %s\n", f->subclass, who->exten);
-
-@@ -3334,16 +4021,16 @@
- *rc = who;
- break;
- }
--
-+
- #if 0
- if (f->frametype == AST_FRAME_VOICE) {
- chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
--
-+
- continue;
- }
- #endif
-
-- ast_write(who == c0 ? c1 : c0, f);
-+ ast_write((who == c0) ? c1 : c0, f);
- }
-
- chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid + 1);
-@@ -3371,11 +4058,11 @@
- chan_misdn_log(1, cl->bc->port, "Not sending Dialtone, because config wants it\n");
- return 0;
- }
--
-+
- chan_misdn_log(3, cl->bc->port, " --> Dial\n");
-
- cl->ts = ast_get_indication_tone(ast->zone, "dial");
--
-+
- if (cl->ts) {
- cl->notxtone = 0;
- cl->norxtone = 0;
-@@ -3429,7 +4116,7 @@
-
- cl->notxtone = 1;
- cl->norxtone = 1;
--
-+
- return 0;
- }
-
-@@ -3438,11 +4125,12 @@
- {
- struct chan_list *cl;
-
-- if (!(cl = ast_calloc(1, sizeof(*cl)))) {
-+ cl = ast_calloc(1, sizeof(*cl));
-+ if (!cl) {
- chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
- return NULL;
- }
--
-+
- cl->originator = orig;
- cl->need_queue_hangup = 1;
- cl->need_hangup = 1;
-@@ -3456,38 +4144,54 @@
- {
- struct ast_channel *tmp = NULL;
- char group[BUFFERSIZE + 1] = "";
-- char buf[128];
-- char *buf2 = ast_strdupa(data), *ext = NULL, *port_str;
-- char *tokb = NULL, *p = NULL;
-- int channel = 0, port = 0;
-+ char dial_str[128];
-+ char *dest_cp;
-+ char *p = NULL;
-+ int channel = 0;
-+ int port = 0;
- struct misdn_bchannel *newbc = NULL;
- int dec = 0;
-+ struct chan_list *cl;
-
-- struct chan_list *cl = init_chan_list(ORG_AST);
-+ AST_DECLARE_APP_ARGS(args,
-+ AST_APP_ARG(intf); /* interface token */
-+ AST_APP_ARG(ext); /* extension token */
-+ AST_APP_ARG(opts); /* options token */
-+ );
-
-- snprintf(buf, sizeof(buf), "%s/%s", misdn_type, (char*)data);
-+ snprintf(dial_str, sizeof(dial_str), "%s/%s", misdn_type, (char *) data);
-
-- port_str = strtok_r(buf2, "/", &tokb);
-+ /*
-+ * data is ---v
-+ * Dial(mISDN/g:group_name[/extension[/options]])
-+ * Dial(mISDN/port[:preselected_channel][/extension[/options]])
-+ *
-+ * The dial extension could be empty if you are using MISDN_KEYPAD
-+ * to control ISDN provider features.
-+ */
-+ dest_cp = ast_strdupa(data);
-+ AST_NONSTANDARD_APP_ARGS(args, dest_cp, '/');
-+ if (!args.ext) {
-+ args.ext = "";
-+ }
-
-- ext = strtok_r(NULL, "/", &tokb);
--
-- if (port_str) {
-- if (port_str[0] == 'g' && port_str[1] == ':' ) {
-+ if (!ast_strlen_zero(args.intf)) {
-+ if (args.intf[0] == 'g' && args.intf[1] == ':' ) {
- /* We make a group call lets checkout which ports are in my group */
-- port_str += 2;
-- ast_copy_string(group, port_str, sizeof(group));
-+ args.intf += 2;
-+ ast_copy_string(group, args.intf, sizeof(group));
- chan_misdn_log(2, 0, " --> Group Call group: %s\n", group);
-- } else if ((p = strchr(port_str, ':'))) {
-+ } else if ((p = strchr(args.intf, ':'))) {
- /* we have a preselected channel */
-- *p = 0;
-- channel = atoi(++p);
-- port = atoi(port_str);
-+ *p++ = 0;
-+ channel = atoi(p);
-+ port = atoi(args.intf);
- chan_misdn_log(2, port, " --> Call on preselected Channel (%d).\n", channel);
- } else {
-- port = atoi(port_str);
-+ port = atoi(args.intf);
- }
- } else {
-- ast_log(LOG_WARNING, " --> ! IND : CALL dad:%s WITHOUT PORT/Group, check extensions.conf\n", ext);
-+ ast_log(LOG_WARNING, " --> ! IND : Dial(%s) WITHOUT Port or Group, check extensions.conf\n", dial_str);
- return NULL;
- }
-
-@@ -3524,7 +4228,7 @@
- if (port >= port_start) {
- next_chan = 1;
- }
--
-+
- if (port <= port_start && next_chan) {
- int maxbchans=misdn_lib_get_maxchans(port);
- if (++robin_channel >= maxbchans) {
-@@ -3544,7 +4248,7 @@
- if (check && !port_up) {
- chan_misdn_log(1, port, "L1 is not Up on this Port\n");
- }
--
-+
- if (check && port_up < 0) {
- ast_log(LOG_WARNING, "This port (%d) is blocked\n", port);
- }
-@@ -3564,7 +4268,7 @@
- }
- }
- } while (!newbc && robin_channel != rr->channel);
-- } else {
-+ } else {
- for (port = misdn_cfg_get_next_port(0); port > 0;
- port = misdn_cfg_get_next_port(port)) {
-
-@@ -3580,17 +4284,18 @@
- chan_misdn_log(4, port, "portup:%d\n", port_up);
-
- if (port_up > 0) {
-- if ((newbc = misdn_lib_get_free_bc(port, 0, 0, dec))) {
-+ newbc = misdn_lib_get_free_bc(port, 0, 0, dec);
-+ if (newbc) {
- break;
- }
- }
- }
- }
- }
--
-+
- /* Group dial failed ?*/
- if (!newbc) {
-- ast_log(LOG_WARNING,
-+ ast_log(LOG_WARNING,
- "Could not Dial out on group '%s'.\n"
- "\tEither the L2 and L1 on all of these ports where DOWN (see 'show application misdn_check_l2l1')\n"
- "\tOr there was no free channel on none of the ports\n\n"
-@@ -3603,34 +4308,38 @@
- chan_misdn_log(1, port, " --> preselected_channel: %d\n", channel);
- }
- newbc = misdn_lib_get_free_bc(port, channel, 0, dec);
--
- if (!newbc) {
-- ast_log(LOG_WARNING, "Could not create channel on port:%d with extensions:%s\n", port, ext);
-+ ast_log(LOG_WARNING, "Could not create channel on port:%d for Dial(%s)\n", port, dial_str);
- return NULL;
- }
- }
--
-
-+
- /* create ast_channel and link all the objects together */
-+ cl = init_chan_list(ORG_AST);
-+ if (!cl) {
-+ ast_log(LOG_WARNING, "Could not create Asterisk channel for Dial(%s)\n", dial_str);
-+ return NULL;
-+ }
- cl->bc = newbc;
--
-- tmp = misdn_new(cl, AST_STATE_RESERVED, ext, NULL, format, port, channel);
-+
-+ tmp = misdn_new(cl, AST_STATE_RESERVED, args.ext, NULL, format, port, channel);
- if (!tmp) {
- ast_log(LOG_ERROR, "Could not create Asterisk object\n");
- return NULL;
- }
-
- cl->ast = tmp;
--
-+
- /* register chan in local list */
- cl_queue_chan(&cl_te, cl);
--
-+
- /* fill in the config into the objects */
-- read_config(cl, ORG_AST);
-+ read_config(cl);
-
- /* important */
- cl->need_hangup = 0;
--
-+
- return tmp;
- }
-
-@@ -3638,7 +4347,7 @@
- static int misdn_send_text(struct ast_channel *chan, const char *text)
- {
- struct chan_list *tmp = chan->tech_pvt;
--
-+
- if (tmp && tmp->bc) {
- ast_copy_string(tmp->bc->display, text, sizeof(tmp->bc->display));
- misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
-@@ -3646,7 +4355,7 @@
- ast_log(LOG_WARNING, "No chan_list but send_text request?\n");
- return -1;
- }
--
-+
- return 0;
- }
-
-@@ -3658,7 +4367,7 @@
- .send_digit_begin = misdn_digit_begin,
- .send_digit_end = misdn_digit_end,
- .call = misdn_call,
-- .bridge = misdn_bridge,
-+ .bridge = misdn_bridge,
- .hangup = misdn_hangup,
- .answer = misdn_answer,
- .read = misdn_read,
-@@ -3690,7 +4399,7 @@
-
- static int glob_channel = 0;
-
--static void update_name(struct ast_channel *tmp, int port, int c)
-+static void update_name(struct ast_channel *tmp, int port, int c)
- {
- int chan_offset = 0;
- int tmp_port = misdn_cfg_get_next_port(0);
-@@ -3699,7 +4408,7 @@
- if (tmp_port == port) {
- break;
- }
-- chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2;
-+ chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2;
- }
- if (c < 0) {
- c = 0;
-@@ -3737,7 +4446,7 @@
-
- tmp = ast_channel_alloc(1, state, cid_num, cid_name, "", exten, "", 0, "%s/%s%d-u%d", misdn_type, c ? "" : "tmp", chan_offset + c, glob_channel++);
- if (tmp) {
-- chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n", exten, callerid);
-+ chan_misdn_log(2, 0, " --> * NEW CHANNEL dialed:%s caller:%s\n", exten, callerid);
-
- tmp->nativeformats = prefformat;
-
-@@ -3745,7 +4454,7 @@
- tmp->rawreadformat = format;
- tmp->writeformat = format;
- tmp->rawwriteformat = format;
--
-+
- tmp->tech_pvt = chlist;
-
- misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
-@@ -3779,7 +4488,7 @@
- } else {
- chan_misdn_log(-1, 0, "Unable to allocate channel structure\n");
- }
--
-+
- return tmp;
- }
-
-@@ -3792,7 +4501,11 @@
- }
- }
-
-- chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n", bc->oad, bc->dad);
-+ chan_misdn_log(6, bc->port,
-+ "$$$ find_chan_by_bc: No channel found for dialed:%s caller:\"%s\" <%s>\n",
-+ bc->dialed.number,
-+ bc->caller.name,
-+ bc->caller.number);
-
- return NULL;
- }
-@@ -3806,7 +4519,7 @@
- }
- }
-
-- chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n", pid);
-+ chan_misdn_log(6, 0, "$$$ find_chan_by_pid: No channel found for pid:%d\n", pid);
-
- return NULL;
- }
-@@ -3819,21 +4532,29 @@
- return NULL;
- }
-
-- chan_misdn_log(6, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n", bc->channel, bc->oad, bc->dad);
-+ chan_misdn_log(6, bc->port, "$$$ find_holded: channel:%d dialed:%s caller:\"%s\" <%s>\n",
-+ bc->channel,
-+ bc->dialed.number,
-+ bc->caller.name,
-+ bc->caller.number);
- for (; help; help = help->next) {
- chan_misdn_log(4, bc->port, "$$$ find_holded: --> holded:%d channel:%d\n", help->state == MISDN_HOLDED, help->hold_info.channel);
-- if ((help->state == MISDN_HOLDED) &&
-+ if ((help->state == MISDN_HOLDED) &&
- (help->hold_info.port == bc->port)) {
- return help;
- }
- }
-- chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n", bc->oad, bc->dad);
-+ chan_misdn_log(6, bc->port,
-+ "$$$ find_holded: No channel found for dialed:%s caller:\"%s\" <%s>\n",
-+ bc->dialed.number,
-+ bc->caller.name,
-+ bc->caller.number);
-
- return NULL;
- }
-
-
--static struct chan_list *find_holded_l3(struct chan_list *list, unsigned long l3_id, int w)
-+static struct chan_list *find_holded_l3(struct chan_list *list, unsigned long l3_id, int w)
- {
- struct chan_list *help = list;
-
-@@ -3850,20 +4571,20 @@
- static void cl_queue_chan(struct chan_list **list, struct chan_list *chan)
- {
- chan_misdn_log(4, chan->bc ? chan->bc->port : 0, "* Queuing chan %p\n", chan);
--
-+
- ast_mutex_lock(&cl_te_lock);
- if (!*list) {
- *list = chan;
- } else {
- struct chan_list *help = *list;
-- for (; help->next; help = help->next);
-+ for (; help->next; help = help->next);
- help->next = chan;
- }
- chan->next = NULL;
- ast_mutex_unlock(&cl_te_lock);
- }
-
--static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan)
-+static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan)
- {
- struct chan_list *help;
-
-@@ -3879,13 +4600,13 @@
- ast_mutex_unlock(&cl_te_lock);
- return;
- }
--
-+
- if (*list == chan) {
- *list = (*list)->next;
- ast_mutex_unlock(&cl_te_lock);
- return;
- }
--
-+
- for (help = *list; help->next; help = help->next) {
- if (help->next == chan) {
- help->next = help->next->next;
-@@ -3893,7 +4614,7 @@
- return;
- }
- }
--
-+
- ast_mutex_unlock(&cl_te_lock);
- }
-
-@@ -3902,7 +4623,7 @@
-
- static int pbx_start_chan(struct chan_list *ch)
- {
-- int ret = ast_pbx_start(ch->ast);
-+ int ret = ast_pbx_start(ch->ast);
-
- ch->need_hangup = (ret >= 0) ? 0 : 1;
-
-@@ -3948,12 +4669,14 @@
- }
-
- /** Isdn asks us to release channel, pendant to misdn_hangup **/
--static void release_chan(struct misdn_bchannel *bc) {
-+static void release_chan(struct misdn_bchannel *bc)
-+{
- struct ast_channel *ast = NULL;
- struct chan_list *ch;
-
- ast_mutex_lock(&release_lock);
-- if (!(ch = find_chan_by_bc(cl_te, bc))) {
-+ ch = find_chan_by_bc(cl_te, bc);
-+ if (!ch) {
- chan_misdn_log(1, bc->port, "release_chan: Ch not found!\n");
- ast_mutex_unlock(&release_lock);
- return;
-@@ -3961,12 +4684,12 @@
-
- if (ch->ast) {
- ast = ch->ast;
-- }
-+ }
-
- chan_misdn_log(5, bc->port, "release_chan: bc with l3id: %x\n", bc->l3_id);
-
- /* releasing jitterbuffer */
-- if (ch->jb ) {
-+ if (ch->jb) {
- misdn_jb_destroy(ch->jb);
- ch->jb = NULL;
- } else {
-@@ -3994,7 +4717,14 @@
- close(ch->pipe[1]);
-
- if (ast && MISDN_ASTERISK_TECH_PVT(ast)) {
-- chan_misdn_log(1, bc->port, "* RELEASING CHANNEL pid:%d ctx:%s dad:%s oad:%s state: %s\n", bc ? bc->pid : -1, ast->context, ast->exten, ast->cid.cid_num, misdn_get_ch_state(ch));
-+ chan_misdn_log(1, bc->port,
-+ "* RELEASING CHANNEL pid:%d context:%s dialed:%s caller:\"%s\" <%s> state: %s\n",
-+ bc->pid,
-+ ast->context,
-+ ast->exten,
-+ ast->cid.cid_name ? ast->cid.cid_name : "",
-+ ast->cid.cid_num ? ast->cid.cid_num : "",
-+ misdn_get_ch_state(ch));
- chan_misdn_log(3, bc->port, " --> * State Down\n");
- MISDN_ASTERISK_TECH_PVT(ast) = NULL;
-
-@@ -4040,7 +4770,7 @@
-
- if (!ch->noautorespond_on_setup) {
- if (bc->nt) {
-- int ret;
-+ int ret;
- ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
- } else {
- int ret;
-@@ -4054,10 +4784,15 @@
- ch->state = MISDN_INCOMING_SETUP;
- }
-
-- chan_misdn_log(1, bc->port, "* Starting Ast ctx:%s dad:%s oad:%s with 's' extension\n", ast->context, ast->exten, ast->cid.cid_num);
--
-- strncpy(ast->exten, "s", 2);
--
-+ chan_misdn_log(1, bc->port,
-+ "* Starting Ast context:%s dialed:%s caller:\"%s\" <%s> with 's' extension\n",
-+ ast->context,
-+ ast->exten,
-+ ast->cid.cid_name ? ast->cid.cid_name : "",
-+ ast->cid.cid_num ? ast->cid.cid_num : "");
-+
-+ strcpy(ast->exten, "s");
-+
- if (pbx_start_chan(ch) < 0) {
- ast = NULL;
- hangup_chan(ch);
-@@ -4065,8 +4800,8 @@
-
- misdn_lib_send_event(bc, bc->nt ? EVENT_RELEASE_COMPLETE : EVENT_DISCONNECT);
- }
--
--
-+
-+
- while (!ast_strlen_zero(predial) ) {
- fr.frametype = AST_FRAME_DTMF;
- fr.subclass = *predial;
-@@ -4118,7 +4853,7 @@
- *
- chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Congestion pid:%d\n", bc ? bc->pid : -1);
- ch->state = MISDN_BUSY;
--
-+
- ast_queue_control(ast, AST_CONTROL_CONGESTION);
- */
- break;
-@@ -4133,11 +4868,11 @@
- }
-
- chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Busy pid:%d\n", bc ? bc->pid : -1);
--
-+
- ast_queue_control(ast, AST_CONTROL_BUSY);
--
-+
- ch->need_busy = 0;
--
-+
- break;
- }
- }
-@@ -4184,6 +4919,7 @@
- void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
- {
- char tmp[32];
-+
- chan_misdn_log(3, bc->port, " --> EXPORT_PID: pid:%d\n", bc->pid);
- snprintf(tmp, sizeof(tmp), "%d", bc->pid);
- pbx_builtin_setvar_helper(chan, "_MISDN_PID", tmp);
-@@ -4210,7 +4946,7 @@
- int add_in_calls(int port)
- {
- int max_in_calls;
--
-+
- misdn_cfg_get(port, MISDN_CFG_MAX_IN, &max_in_calls, sizeof(max_in_calls));
- misdn_in_calls[port]++;
-
-@@ -4218,14 +4954,14 @@
- ast_log(LOG_NOTICE, "Marking Incoming Call on port[%d]\n", port);
- return misdn_in_calls[port] - max_in_calls;
- }
--
-+
- return 0;
- }
-
- int add_out_calls(int port)
- {
- int max_out_calls;
--
-+
- misdn_cfg_get(port, MISDN_CFG_MAX_OUT, &max_out_calls, sizeof(max_out_calls));
-
- if (max_out_calls >= 0 && max_out_calls <= misdn_out_calls[port]) {
-@@ -4234,11 +4970,12 @@
- }
-
- misdn_out_calls[port]++;
--
-+
- return 0;
- }
-
--static void start_pbx(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan) {
-+static void start_pbx(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan)
-+{
- if (pbx_start_chan(ch) < 0) {
- hangup_chan(ch);
- chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
-@@ -4251,10 +4988,11 @@
- }
- }
-
--static void wait_for_digits(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan) {
-+static void wait_for_digits(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan)
-+{
- ch->state = MISDN_WAITING4DIGS;
- misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
-- if (bc->nt && !bc->dad[0]) {
-+ if (bc->nt && !bc->dialed.number[0]) {
- dialtone_indicate(ch);
- }
- }
-@@ -4267,20 +5005,27 @@
- cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
- {
- struct chan_list *ch = find_chan_by_bc(cl_te, bc);
--
-+
- if (event != EVENT_BCHAN_DATA && event != EVENT_TONE_GENERATE) { /* Debug Only Non-Bchan */
- int debuglevel = 1;
- if ( event == EVENT_CLEANUP && !user_data) {
- debuglevel = 5;
- }
-
-- chan_misdn_log(debuglevel, bc->port, "I IND :%s oad:%s dad:%s pid:%d state:%s\n", manager_isdn_get_info(event), bc->oad, bc->dad, bc->pid, ch ? misdn_get_ch_state(ch) : "none");
-+ chan_misdn_log(debuglevel, bc->port,
-+ "I IND :%s caller:\"%s\" <%s> dialed:%s pid:%d state:%s\n",
-+ manager_isdn_get_info(event),
-+ bc->caller.name,
-+ bc->caller.number,
-+ bc->dialed.number,
-+ bc->pid,
-+ ch ? misdn_get_ch_state(ch) : "none");
- if (debuglevel == 1) {
- misdn_lib_log_ies(bc);
- chan_misdn_log(4, bc->port, " --> bc_state:%s\n", bc_state2str(bc->bc_state));
- }
- }
--
-+
- if (!ch) {
- switch(event) {
- case EVENT_SETUP:
-@@ -4302,7 +5047,7 @@
- return -1;
- }
- }
--
-+
- if (ch) {
- switch (event) {
- case EVENT_TONE_GENERATE:
-@@ -4325,8 +5070,8 @@
- }
- }
- }
--
--
-+
-+
- switch (event) {
- case EVENT_PORT_ALARM:
- {
-@@ -4334,17 +5079,17 @@
- misdn_cfg_get(bc->port, MISDN_CFG_ALARM_BLOCK, &boa, sizeof(boa));
- if (boa) {
- cb_log(1, bc->port, " --> blocking\n");
-- misdn_lib_port_block(bc->port);
-+ misdn_lib_port_block(bc->port);
- }
- }
- break;
- case EVENT_BCHAN_ACTIVATED:
- break;
--
-+
- case EVENT_NEW_CHANNEL:
- update_name(ch->ast,bc->port,bc->channel);
- break;
--
-+
- case EVENT_NEW_L3ID:
- ch->l3id=bc->l3_id;
- ch->addr=bc->addr;
-@@ -4354,7 +5099,7 @@
- if (!ch) {
- ch = find_holded(cl_te,bc);
- }
--
-+
- if (!ch) {
- ast_log(LOG_WARNING, "NEW_BC without chan_list?\n");
- break;
-@@ -4364,7 +5109,7 @@
- ch->bc = (struct misdn_bchannel *)user_data;
- }
- break;
--
-+
- case EVENT_DTMF_TONE:
- {
- /* sending INFOS as DTMF-Frames :) */
-@@ -4380,7 +5125,7 @@
- fr.mallocd = 0;
- fr.offset = 0;
- fr.delivery = ast_tv(0,0);
--
-+
- if (!ch->ignore_dtmf) {
- chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
- ast_queue_frame(ch->ast, &fr);
-@@ -4391,12 +5136,12 @@
- break;
- case EVENT_STATUS:
- break;
--
-+
- case EVENT_INFORMATION:
- if (ch->state != MISDN_CONNECTED) {
- stop_indicate(ch);
- }
--
-+
- if (!ch->ast) {
- break;
- }
-@@ -4408,25 +5153,23 @@
- ast_copy_string(bc->info_dad, bc->keypad, sizeof(bc->info_dad));
- }
-
-- strncat(bc->dad, bc->info_dad, sizeof(bc->dad) - strlen(bc->dad) - 1);
-- ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
-+ strncat(bc->dialed.number, bc->info_dad, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
-+ ast_copy_string(ch->ast->exten, bc->dialed.number, sizeof(ch->ast->exten));
-
- /* Check for Pickup Request first */
- if (!strcmp(ch->ast->exten, ast_pickup_ext())) {
- if (ast_pickup_call(ch->ast)) {
- hangup_chan(ch);
- } else {
-- struct ast_channel *chan = ch->ast;
- ch->state = MISDN_CALLING_ACKNOWLEDGE;
-- ast_setstate(chan, AST_STATE_DOWN);
- hangup_chan(ch);
- ch->ast = NULL;
- break;
- }
- }
--
-- if (!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
-- if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) {
-+
-+ if (!ast_canmatch_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
-+ if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->caller.number)) {
- ast_log(LOG_WARNING, "Extension can never match, So jumping to 'i' extension. port(%d)\n", bc->port);
- strcpy(ch->ast->exten, "i");
-
-@@ -4454,13 +5197,13 @@
- ch->overlap_tv = ast_tvnow();
- ast_mutex_unlock(&ch->overlap_tv_lock);
- if (ch->overlap_dial_task == -1) {
-- ch->overlap_dial_task =
-+ ch->overlap_dial_task =
- misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
- }
- break;
- }
-
-- if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
-+ if (ast_exists_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
- ch->state = MISDN_DIALING;
- start_pbx(ch, bc, ch->ast);
- }
-@@ -4483,11 +5226,11 @@
- misdn_cfg_get(0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(digits));
- if (ch->state != MISDN_CONNECTED ) {
- if (digits) {
-- strncat(bc->dad, bc->info_dad, sizeof(bc->dad) - strlen(bc->dad) - 1);
-- ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
-+ strncat(bc->dialed.number, bc->info_dad, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
-+ ast_copy_string(ch->ast->exten, bc->dialed.number, sizeof(ch->ast->exten));
- ast_cdr_update(ch->ast);
- }
--
-+
- ast_queue_frame(ch->ast, &fr);
- }
- }
-@@ -4495,10 +5238,9 @@
- case EVENT_SETUP:
- {
- struct chan_list *ch = find_chan_by_bc(cl_te, bc);
-- int msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dad);
-+ int msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dialed.number);
- struct ast_channel *chan;
- int exceed;
-- int pres, screen;
- int ai;
- int im;
-
-@@ -4538,13 +5280,11 @@
- ch->bc = bc;
- ch->l3id = bc->l3_id;
- ch->addr = bc->addr;
-- ch->originator = ORG_MISDN;
-
-- chan = misdn_new(ch, AST_STATE_RESERVED, bc->dad, bc->oad, AST_FORMAT_ALAW, bc->port, bc->channel);
--
-+ chan = misdn_new(ch, AST_STATE_RESERVED, bc->dialed.number, bc->caller.number, AST_FORMAT_ALAW, bc->port, bc->channel);
- if (!chan) {
- misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
-- ast_log(LOG_ERROR, "cb_events: misdn_new failed !\n");
-+ ast_log(LOG_ERROR, "cb_events: misdn_new failed !\n");
- return 0;
- }
-
-@@ -4556,50 +5296,45 @@
- pbx_builtin_setvar_helper(chan, "MAX_OVERFLOW", tmp);
- }
-
-- read_config(ch, ORG_MISDN);
-+ read_config(ch);
-
- export_ch(chan, bc, ch);
-
- ch->ast->rings = 1;
- ast_setstate(ch->ast, AST_STATE_RINGING);
-
-- switch (bc->pres) {
-- case 1:
-- pres = AST_PRES_RESTRICTED;
-- chan_misdn_log(2, bc->port, " --> PRES: Restricted (1)\n");
-- break;
-- case 2:
-- pres = AST_PRES_UNAVAILABLE;
-- chan_misdn_log(2, bc->port, " --> PRES: Unavailable (2)\n");
-- break;
-- default:
-- pres = AST_PRES_ALLOWED;
-- chan_misdn_log(2, bc->port, " --> PRES: Allowed (%d)\n", bc->pres);
-- break;
-- }
-+ /* Update asterisk channel caller information */
-+ chan_misdn_log(2, bc->port, " --> TON: %s(%d)\n", misdn_to_str_ton(bc->caller.number_type), bc->caller.number_type);
-+ chan_misdn_log(2, bc->port, " --> PLAN: %s(%d)\n", misdn_to_str_plan(bc->caller.number_plan), bc->caller.number_plan);
-+ chan->cid.cid_ton = misdn_to_ast_ton(bc->caller.number_type)
-+ | misdn_to_ast_plan(bc->caller.number_plan);
-
-- switch (bc->screen) {
-- default:
-- case 0:
-- screen = AST_PRES_USER_NUMBER_UNSCREENED;
-- chan_misdn_log(2, bc->port, " --> SCREEN: Unscreened (%d)\n", bc->screen);
-- break;
-- case 1:
-- screen = AST_PRES_USER_NUMBER_PASSED_SCREEN;
-- chan_misdn_log(2, bc->port, " --> SCREEN: Passed screen (1)\n");
-- break;
-- case 2:
-- screen = AST_PRES_USER_NUMBER_FAILED_SCREEN;
-- chan_misdn_log(2, bc->port, " --> SCREEN: failed screen (2)\n");
-- break;
-- case 3:
-- screen = AST_PRES_NETWORK_NUMBER;
-- chan_misdn_log(2, bc->port, " --> SCREEN: Network Number (3)\n");
-- break;
-+ chan_misdn_log(2, bc->port, " --> PRES: %s(%d)\n", misdn_to_str_pres(bc->caller.presentation), bc->caller.presentation);
-+ chan_misdn_log(2, bc->port, " --> SCREEN: %s(%d)\n", misdn_to_str_screen(bc->caller.screening), bc->caller.screening);
-+ chan->cid.cid_pres = misdn_to_ast_pres(bc->caller.presentation)
-+ | misdn_to_ast_screen(bc->caller.screening);
-+
-+ ast_set_callerid(chan, bc->caller.number, NULL, bc->caller.number);
-+
-+ if (!ast_strlen_zero(bc->redirecting.from.number)) {
-+ struct ast_party_redirecting redirecting;
-+
-+ /* Add configured prefix to redirecting.from.number */
-+ misdn_add_number_prefix(bc->port, bc->redirecting.from.number_type, bc->redirecting.from.number, sizeof(bc->redirecting.from.number));
-+
-+ /* Update asterisk channel redirecting information */
-+ ast_party_redirecting_set_init(&redirecting, &chan->redirecting);
-+ redirecting.from.number = bc->redirecting.from.number;
-+ redirecting.from.number_type =
-+ misdn_to_ast_ton(bc->redirecting.from.number_type)
-+ | misdn_to_ast_plan(bc->redirecting.from.number_plan);
-+ redirecting.from.number_presentation =
-+ misdn_to_ast_pres(bc->redirecting.from.presentation)
-+ | misdn_to_ast_screen(bc->redirecting.from.screening);
-+ redirecting.reason = misdn_to_ast_reason(bc->redirecting.reason);
-+ ast_channel_set_redirecting(chan, &redirecting);
- }
-
-- chan->cid.cid_pres = pres | screen;
--
- pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
- chan->transfercapability = bc->capability;
-
-@@ -4628,7 +5363,7 @@
- break;
- }
- }
-- } /* end for */
-+ }
- if (i == ARRAY_LEN(allowed_bearers_array)) {
- /* We did not find the bearer capability */
- chan_misdn_log(0, bc->port, "Bearer capability not allowed: %s(%d)\n",
-@@ -4653,7 +5388,6 @@
- hangup_chan(ch);
- } else {
- ch->state = MISDN_CALLING_ACKNOWLEDGE;
-- ast_setstate(chan, AST_STATE_DOWN);
- hangup_chan(ch);
- ch->ast = NULL;
- break;
-@@ -4670,16 +5404,16 @@
- break;
- }
-
-- /* check if we should jump into s when we have no dad */
-+ /* check if we should jump into s when we have no dialed.number */
- misdn_cfg_get(bc->port, MISDN_CFG_IMMEDIATE, &im, sizeof(im));
-- if (im && ast_strlen_zero(bc->dad)) {
-+ if (im && ast_strlen_zero(bc->dialed.number)) {
- do_immediate_setup(bc, ch, chan);
- break;
- }
-
- chan_misdn_log(5, bc->port, "CONTEXT:%s\n", ch->context);
-- if (!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
-- if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) {
-+ if (!ast_canmatch_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
-+ if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->caller.number)) {
- ast_log(LOG_WARNING, "Extension can never match, So jumping to 'i' extension. port(%d)\n", bc->port);
- strcpy(ch->ast->exten, "i");
- misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
-@@ -4703,8 +5437,8 @@
- break;
- }
-
-- /* Whatever happens, when sending_complete is set or we are PTMP TE, we will definitely
-- * jump into the dialplan, when the dialed extension does not exist, the 's' extension
-+ /* Whatever happens, when sending_complete is set or we are PTMP TE, we will definitely
-+ * jump into the dialplan, when the dialed extension does not exist, the 's' extension
- * will be used by Asterisk automatically. */
- if (bc->sending_complete || (!bc->nt && !misdn_lib_is_ptp(bc->port))) {
- if (!ch->noautorespond_on_setup) {
-@@ -4719,17 +5453,17 @@
-
-
- /*
-- * When we are NT and overlapdial is set and if
-+ * When we are NT and overlapdial is set and if
- * the number is empty, we wait for the ISDN timeout
- * instead of our own timer.
- */
-- if (ch->overlap_dial && bc->nt && !bc->dad[0] ) {
-+ if (ch->overlap_dial && bc->nt && !bc->dialed.number[0] ) {
- wait_for_digits(ch, bc, chan);
- break;
- }
-
-- /*
-- * If overlapdial we will definitely send a SETUP_ACKNOWLEDGE and wait for more
-+ /*
-+ * If overlapdial we will definitely send a SETUP_ACKNOWLEDGE and wait for more
- * Infos with a Interdigit Timeout.
- * */
- if (ch->overlap_dial) {
-@@ -4739,16 +5473,16 @@
-
- wait_for_digits(ch, bc, chan);
- if (ch->overlap_dial_task == -1) {
-- ch->overlap_dial_task =
-+ ch->overlap_dial_task =
- misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
- }
- break;
- }
-
-- /* If the extension does not exist and we're not TE_PTMP we wait for more digits
-+ /* If the extension does not exist and we're not TE_PTMP we wait for more digits
- * without interdigit timeout.
- * */
-- if (!ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
-+ if (!ast_exists_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
- wait_for_digits(ch, bc, chan);
- break;
- }
-@@ -4756,29 +5490,30 @@
- /*
- * If the extension exists let's just jump into it.
- * */
-- if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
-+ if (ast_exists_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
- misdn_lib_send_event(bc, bc->need_more_infos ? EVENT_SETUP_ACKNOWLEDGE : EVENT_PROCEEDING);
- ch->state = MISDN_DIALING;
- start_pbx(ch, bc, chan);
- break;
- }
-+ break;
- }
-- break;
-
- case EVENT_SETUP_ACKNOWLEDGE:
- ch->state = MISDN_CALLING_ACKNOWLEDGE;
-
-- if (bc->channel)
-+ if (bc->channel) {
- update_name(ch->ast,bc->port,bc->channel);
--
-+ }
-+
- if (!ast_strlen_zero(bc->infos_pending)) {
- /* TX Pending Infos */
-- strncat(bc->dad, bc->infos_pending, sizeof(bc->dad) - strlen(bc->dad) - 1);
-+ strncat(bc->dialed.number, bc->infos_pending, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
-
- if (!ch->ast) {
- break;
- }
-- ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
-+ ast_copy_string(ch->ast->exten, bc->dialed.number, sizeof(ch->ast->exten));
- ast_copy_string(bc->info_dad, bc->infos_pending, sizeof(bc->info_dad));
- ast_copy_string(bc->infos_pending, "", sizeof(bc->infos_pending));
-
-@@ -4792,7 +5527,7 @@
- }
-
- ch->state = MISDN_PROCEEDING;
--
-+
- if (!ch->ast) {
- break;
- }
-@@ -4809,7 +5544,7 @@
- misdn_inband_avail(bc)) {
- start_bc_tones(ch);
- }
--
-+
- ch->state = MISDN_PROGRESS;
-
- if (!ch->ast) {
-@@ -4820,16 +5555,16 @@
- break;
- case EVENT_ALERTING:
- ch->state = MISDN_ALERTING;
--
-+
- if (!ch->ast) {
- break;
- }
-
- ast_queue_control(ch->ast, AST_CONTROL_RINGING);
- ast_setstate(ch->ast, AST_STATE_RINGING);
--
-+
- cb_log(7, bc->port, " --> Set State Ringing\n");
--
-+
- if (misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
- cb_log(1, bc->port, "Starting Tones, we have inband Data\n");
- start_bc_tones(ch);
-@@ -4843,38 +5578,41 @@
- }
- break;
- case EVENT_CONNECT:
-- {
-- struct ast_channel *bridged;
-+ {
-+ struct ast_party_connected_line connected;
-
-- /*we answer when we've got our very new L3 ID from the NT stack */
-- misdn_lib_send_event(bc, EVENT_CONNECT_ACKNOWLEDGE);
-+ /* we answer when we've got our very new L3 ID from the NT stack */
-+ misdn_lib_send_event(bc, EVENT_CONNECT_ACKNOWLEDGE);
-
-- if (!ch->ast) {
-- break;
-- }
-+ if (!ch->ast) {
-+ break;
-+ }
-
-- bridged = ast_bridged_channel(ch->ast);
-- stop_indicate(ch);
-+ stop_indicate(ch);
-
-- if (bridged && !strcasecmp(bridged->tech->type, "mISDN")) {
-- struct chan_list *bridged_ch = MISDN_ASTERISK_TECH_PVT(bridged);
-+ /* Add configured prefix to connected.number */
-+ misdn_add_number_prefix(bc->port, bc->connected.number_type, bc->connected.number, sizeof(bc->connected.number));
-
-- chan_misdn_log(1, bc->port, " --> copying cpndialplan:%d and cad:%s to the A-Channel\n", bc->cpnnumplan, bc->cad);
-- if (bridged_ch) {
-- bridged_ch->bc->cpnnumplan = bc->cpnnumplan;
-- ast_copy_string(bridged_ch->bc->cad, bc->cad, sizeof(bridged_ch->bc->cad));
-- }
-- }
-- }
-+ /* Update the connected line information on the other channel */
-+ ast_party_connected_line_init(&connected);
-+ connected.id.number = bc->connected.number;
-+ connected.id.number_type = misdn_to_ast_ton(bc->connected.number_type)
-+ | misdn_to_ast_plan(bc->connected.number_plan);
-+ connected.id.number_presentation = misdn_to_ast_pres(bc->connected.presentation)
-+ | misdn_to_ast_screen(bc->connected.screening);
-+ connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
-+ ast_channel_queue_connected_line_update(ch->ast, &connected);
-+
- ch->l3id = bc->l3_id;
- ch->addr = bc->addr;
-
- start_bc_tones(ch);
--
-+
- ch->state = MISDN_CONNECTED;
--
-+
- ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
- break;
-+ }
- case EVENT_CONNECT_ACKNOWLEDGE:
- ch->l3id = bc->l3_id;
- ch->addr = bc->addr;
-@@ -4896,7 +5634,7 @@
- alternative number, then play it instead of
- immediately releasing the call */
- chan_misdn_log(1, bc->port, " --> Inband Info Avail, not sending RELEASE\n");
--
-+
- ch->state = MISDN_DISCONNECTED;
- start_bc_tones(ch);
-
-@@ -4948,15 +5686,16 @@
- stop_bc_tones(ch);
- hangup_chan(ch);
-
-- if (ch)
-+ if (ch) {
- ch->state = MISDN_CLEANING;
-+ }
-
- release_chan(bc);
- break;
- case EVENT_BCHAN_ERROR:
- case EVENT_CLEANUP:
- stop_bc_tones(ch);
--
-+
- switch (ch->state) {
- case MISDN_CALLING:
- bc->cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
-@@ -4964,7 +5703,7 @@
- default:
- break;
- }
--
-+
- hangup_chan(ch);
- release_chan(bc);
- break;
-@@ -4997,23 +5736,23 @@
-
- res = generate(ast, tmp, tone_len, tone_len);
- ast->generatordata = tmp;
--
-+
- if (res) {
- ast_log(LOG_WARNING, "Auto-deactivating generator\n");
- ast_deactivate_generator(ast);
- } else {
- bc->tone_cnt = 0;
- }
-+ break;
- }
-- break;
--
- case EVENT_BCHAN_DATA:
- if (ch->bc->AOCD_need_export) {
- export_aoc_vars(ch->originator, ch->ast, ch->bc);
- }
- if (!misdn_cap_is_speech(ch->bc->capability)) {
- struct ast_frame frame;
-- /*In Data Modes we queue frames*/
-+
-+ /* In Data Modes we queue frames */
- frame.frametype = AST_FRAME_VOICE; /* we have no data frames yet */
- frame.subclass = AST_FORMAT_ALAW;
- frame.datalen = bc->bframe_len;
-@@ -5024,8 +5763,9 @@
- frame.src = NULL;
- frame.data.ptr = bc->bframe;
-
-- if (ch->ast)
-+ if (ch->ast) {
- ast_queue_frame(ch->ast, &frame);
-+ }
- } else {
- fd_set wrfs;
- struct timeval tv = { 0, 0 };
-@@ -5040,12 +5780,12 @@
- chan_misdn_log(9, bc->port, "Select Timed out\n");
- break;
- }
--
-+
- if (t < 0) {
- chan_misdn_log(-1, bc->port, "Select Error (err=%s)\n", strerror(errno));
- break;
- }
--
-+
- if (FD_ISSET(ch->pipe[1], &wrfs)) {
- chan_misdn_log(9, bc->port, "writing %d bytes to asterisk\n", bc->bframe_len);
- if (write(ch->pipe[1], bc->bframe, bc->bframe_len) <= 0) {
-@@ -5095,11 +5835,12 @@
- misdn_lib_send_event(bc, EVENT_RELEASE);
- }
- break;
-- case MISDN_CLEANING:
-+ case MISDN_CLEANING:
- chan_misdn_log(1, bc->port, " --> in state cleaning .. so ignoring, the stack should clean it for us\n");
- break;
- default:
- misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
-+ break;
- }
- break;
-
-@@ -5133,13 +5874,13 @@
- if (hold_ast) {
- ast_moh_stop(hold_ast);
- }
--
-+
- if (misdn_lib_send_event(bc, EVENT_RETRIEVE_ACKNOWLEDGE) < 0) {
- chan_misdn_log(4, bc->port, " --> RETRIEVE_ACK failed\n");
- misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
- }
-+ break;
- }
-- break;
- case EVENT_HOLD:
- {
- int hold_allowed;
-@@ -5157,7 +5898,7 @@
- chan_misdn_log(2, bc->port, "Bridge Partner is of type: %s\n", bridged->tech->type);
- ch->state = MISDN_HOLDED;
- ch->l3id = bc->l3_id;
--
-+
- misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE);
-
- /* XXX This should queue an AST_CONTROL_HOLD frame on this channel
-@@ -5172,11 +5913,11 @@
- misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
- chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
- }
-- }
- break;
-+ }
- case EVENT_FACILITY:
- print_facility(&(bc->fac_in), bc);
--
-+
- switch (bc->fac_in.Function) {
- #ifdef HAVE_MISDN_FAC_RESULT
- case Fac_RESULT:
-@@ -5190,7 +5931,7 @@
- ch_br = MISDN_ASTERISK_TECH_PVT(bridged);
- /*ch->state = MISDN_FACILITY_DEFLECTED;*/
- if (ch_br->bc) {
-- if (ast_exists_extension(bridged, ch->context, (char *)bc->fac_in.u.CDeflection.DeflectedToNumber, 1, bc->oad)) {
-+ if (ast_exists_extension(bridged, ch->context, (char *) bc->fac_in.u.CDeflection.DeflectedToNumber, 1, bc->caller.number)) {
- ch_br->state = MISDN_DIALING;
- if (pbx_start_chan(ch_br) < 0) {
- chan_misdn_log(-1, ch_br->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
-@@ -5199,7 +5940,7 @@
- }
- }
- misdn_lib_send_event(bc, EVENT_DISCONNECT);
-- }
-+ }
- break;
- case Fac_AOCDCurrency:
- if (ch) {
-@@ -5225,7 +5966,7 @@
- default:
- chan_misdn_log(0, bc->port," --> not yet handled: facility type:%d\n", bc->fac_in.Function);
- }
--
-+
- break;
- case EVENT_RESTART:
- if (!bc->dummy) {
-@@ -5237,7 +5978,7 @@
- chan_misdn_log(1, 0, "Got Unknown Event\n");
- break;
- }
--
-+
- return RESPONSE_OK;
- }
-
-@@ -5258,11 +5999,11 @@
- ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
-
- misdn_tasks_destroy();
--
-+
- if (!g_config_initialized) {
- return 0;
- }
--
-+
- ast_cli_unregister_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
-
- /* ast_unregister_application("misdn_crypt"); */
-@@ -5275,7 +6016,7 @@
- free_robin_list();
- misdn_cfg_destroy();
- misdn_lib_destroy();
--
-+
- if (misdn_debug) {
- ast_free(misdn_debug);
- }
-@@ -5283,7 +6024,7 @@
- ast_free(misdn_debug_only);
- }
- ast_free(misdn_ports);
--
-+
- return 0;
- }
-
-@@ -5301,18 +6042,18 @@
- };
-
- max_ports = misdn_lib_maxports_get();
--
-+
- if (max_ports <= 0) {
- ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
- return AST_MODULE_LOAD_DECLINE;
- }
--
-+
- if (misdn_cfg_init(max_ports, 0)) {
- ast_log(LOG_ERROR, "Unable to initialize misdn_config.\n");
- return AST_MODULE_LOAD_DECLINE;
- }
- g_config_initialized = 1;
--
-+
- misdn_debug = ast_malloc(sizeof(int) * (max_ports + 1));
- if (!misdn_debug) {
- ast_log(LOG_ERROR, "Out of memory for misdn_debug\n");
-@@ -5369,7 +6110,7 @@
- unload_module();
- return AST_MODULE_LOAD_DECLINE;
- }
--
-+
- ast_cli_register_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
-
- ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
-@@ -5400,7 +6141,7 @@
- " vt - Tx gain control, optarg is gain\n"
- );
-
--
-+
- ast_register_application("misdn_facility", misdn_facility_exec, "misdn_facility",
- "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
- "Sends the Facility Message FACILITY_TYPE with \n"
-@@ -5432,13 +6173,13 @@
- misdn_cfg_get(0, MISDN_GEN_TRACEFILE, global_tracefile, sizeof(global_tracefile));
-
- /* start the l1 watchers */
--
-+
- for (port = misdn_cfg_get_next_port(0); port >= 0; port = misdn_cfg_get_next_port(port)) {
- int l1timeout;
- misdn_cfg_get(port, MISDN_CFG_L1_TIMEOUT, &l1timeout, sizeof(l1timeout));
- if (l1timeout) {
- chan_misdn_log(4, 0, "Adding L1watcher task: port:%d timeout:%ds\n", port, l1timeout);
-- misdn_tasks_add(l1timeout * 1000, misdn_l1_task, &misdn_ports[port]);
-+ misdn_tasks_add(l1timeout * 1000, misdn_l1_task, &misdn_ports[port]);
- }
- }
-
-@@ -5462,19 +6203,20 @@
- {
- struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
- char *parse;
-+
- AST_DECLARE_APP_ARGS(args,
- AST_APP_ARG(facility_type);
- AST_APP_ARG(arg)[99];
- );
-
- chan_misdn_log(0, 0, "TYPE: %s\n", chan->tech->type);
--
-+
- if (strcasecmp(chan->tech->type, "mISDN")) {
- ast_log(LOG_WARNING, "misdn_facility makes only sense with chan_misdn channels!\n");
- return -1;
- }
--
-- if (ast_strlen_zero((char *)data)) {
-+
-+ if (ast_strlen_zero((char *) data)) {
- ast_log(LOG_WARNING, "misdn_facility requires arguments: facility_type[,<args>]\n");
- return -1;
- }
-@@ -5493,7 +6235,9 @@
- }
-
- if (strlen(args.arg[0]) >= sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber)) {
-- ast_log(LOG_WARNING, "Facility: Number argument too long (up to %d digits are allowed). Ignoring.\n", (int)sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber));
-+ ast_log(LOG_WARNING,
-+ "Facility: Number argument too long (up to %d digits are allowed). Ignoring.\n",
-+ (int) sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber));
- return 0;
- }
- ch->bc->fac_out.Function = Fac_CD;
-@@ -5517,11 +6261,11 @@
- int port_up;
-
- AST_DECLARE_APP_ARGS(args,
-- AST_APP_ARG(grouppar);
-- AST_APP_ARG(timeout);
-+ AST_APP_ARG(grouppar);
-+ AST_APP_ARG(timeout);
- );
-
-- if (ast_strlen_zero((char *)data)) {
-+ if (ast_strlen_zero((char *) data)) {
- ast_log(LOG_WARNING, "misdn_check_l2l1 Requires arguments\n");
- return -1;
- }
-@@ -5544,7 +6288,7 @@
- ast_copy_string(group, port_str, sizeof(group));
- chan_misdn_log(2, 0, "Checking Ports in group: %s\n", group);
-
-- for ( port = misdn_cfg_get_next_port(port);
-+ for (port = misdn_cfg_get_next_port(port);
- port > 0;
- port = misdn_cfg_get_next_port(port)) {
- char cfg_group[BUFFERSIZE + 1];
-@@ -5555,7 +6299,6 @@
-
- if (!strcasecmp(cfg_group, group)) {
- port_up = misdn_lib_port_up(port, 1);
--
- if (!port_up) {
- chan_misdn_log(2, 0, " --> port '%d'\n", port);
- misdn_lib_get_port_up(port);
-@@ -5595,7 +6338,7 @@
- ast_log(LOG_WARNING, "misdn_set_opt makes only sense with chan_misdn channels!\n");
- return -1;
- }
--
-+
- if (ast_strlen_zero((char *)data)) {
- ast_log(LOG_WARNING, "misdn_set_opt Requires arguments\n");
- return -1;
-@@ -5611,14 +6354,14 @@
- neglect = 1;
- tok++;
- }
--
-+
- switch(tok[0]) {
--
-+
- case 'd' :
- ast_copy_string(ch->bc->display, ++tok, sizeof(ch->bc->display));
- chan_misdn_log(1, ch->bc->port, "SETOPT: Display:%s\n", ch->bc->display);
- break;
--
-+
- case 'n':
- chan_misdn_log(1, ch->bc->port, "SETOPT: No DSP\n");
- ch->bc->nodsp = 1;
-@@ -5677,7 +6420,7 @@
- break;
- }
- break;
--
-+
- case 'c':
- keyidx = atoi(++tok);
- {
-@@ -5699,7 +6442,7 @@
- }
- case 'e':
- chan_misdn_log(1, ch->bc->port, "SETOPT: EchoCancel\n");
--
-+
- if (neglect) {
- chan_misdn_log(1, ch->bc->port, " --> disabled\n");
- #ifdef MISDN_1_2
-@@ -5719,11 +6462,11 @@
- }
- #endif
- }
--
-+
- break;
- case 'h':
- chan_misdn_log(1, ch->bc->port, "SETOPT: Digital\n");
--
-+
- if (strlen(tok) > 1 && tok[1] == '1') {
- chan_misdn_log(1, ch->bc->port, "SETOPT: HDLC \n");
- if (!ch->bc->hdlc) {
-@@ -5732,12 +6475,12 @@
- }
- ch->bc->capability = INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
- break;
--
-+
- case 's':
- chan_misdn_log(1, ch->bc->port, "SETOPT: Send DTMF\n");
- ch->bc->send_dtmf = 1;
- break;
--
-+
- case 'f':
- chan_misdn_log(1, ch->bc->port, "SETOPT: Faxdetect\n");
- ch->faxdetect = 1;
-@@ -5753,12 +6496,15 @@
- chan_misdn_log(1, ch->bc->port, "SETOPT: callerpres: %s\n", &tok[1]);
- /* CRICH: callingpres!!! */
- if (strstr(tok, "allowed")) {
-- ch->bc->pres = 0;
-+ ch->bc->presentation = 0;
-+ ch->bc->set_presentation = 1;
- } else if (strstr(tok, "restricted")) {
-- ch->bc->pres = 1;
-+ ch->bc->presentation = 1;
-+ ch->bc->set_presentation = 1;
- } else if (strstr(tok, "not_screened")) {
- chan_misdn_log(0, ch->bc->port, "SETOPT: callerpres: not_screened is deprecated\n");
-- ch->bc->pres = 1;
-+ ch->bc->presentation = 1;
-+ ch->bc->set_presentation = 1;
- }
- break;
- case 'i' :
-@@ -5791,19 +6537,19 @@
- ch->bc->nodsp = 1;
- ch->bc->nojitter = 1;
- }
--
-+
- return 0;
- }
-
-
--int chan_misdn_jb_empty ( struct misdn_bchannel *bc, char *buf, int len)
-+int chan_misdn_jb_empty ( struct misdn_bchannel *bc, char *buf, int len)
- {
- struct chan_list *ch = find_chan_by_bc(cl_te, bc);
--
-+
- if (ch && ch->jb) {
- return misdn_jb_empty(ch->jb, buf, len);
- }
--
-+
- return -1;
- }
-
-@@ -5860,7 +6606,7 @@
- void misdn_jb_destroy(struct misdn_jb *jb)
- {
- ast_mutex_destroy(&jb->mutexjb);
--
-+
- ast_free(jb->ok);
- ast_free(jb->samples);
- ast_free(jb);
-@@ -5877,10 +6623,10 @@
- }
-
- ast_mutex_lock(&jb->mutexjb);
--
-+
- wp = jb->wp;
- rp = jb->rp;
--
-+
- for (i = 0; i < len; i++) {
- jb->samples[wp] = data[i];
- jb->ok[wp] = 1;
-@@ -5924,7 +6670,7 @@
- jb->wp = wp;
-
- ast_mutex_unlock(&jb->mutexjb);
--
-+
- return 0;
- }
-
-@@ -5940,7 +6686,7 @@
- rp = jb->rp;
- wp = jb->wp;
-
-- if (jb->state_empty) {
-+ if (jb->state_empty) {
- for (i = 0; i < len; i++) {
- if (wp == rp) {
- jb->rp = rp;
-@@ -5976,16 +6722,10 @@
- return read;
- }
-
--
--
--
- /*******************************************************/
- /*************** JITTERBUFFER END *********************/
- /*******************************************************/
-
--
--
--
- static void chan_misdn_log(int level, int port, char *tmpl, ...)
- {
- va_list ap;
-@@ -6006,15 +6746,14 @@
-
- if (level == -1) {
- ast_log(LOG_WARNING, "%s", buf);
-+ } else if (misdn_debug_only[port] ?
-+ (level == 1 && misdn_debug[port]) || (level == misdn_debug[port])
-+ : level <= misdn_debug[port]) {
-
-- } else if (misdn_debug_only[port] ?
-- (level == 1 && misdn_debug[port]) || (level == misdn_debug[port])
-- : level <= misdn_debug[port]) {
--
- ast_console_puts(port_buf);
- ast_console_puts(buf);
- }
--
-+
- if ((level <= misdn_debug[0]) && !ast_strlen_zero(global_tracefile) ) {
- char ctimebuf[30];
- time_t tm = time(NULL);
-@@ -6022,20 +6761,21 @@
-
- FILE *fp = fopen(global_tracefile, "a+");
-
-- if ((p = strchr(tmp, '\n'))) {
-+ p = strchr(tmp, '\n');
-+ if (p) {
- *p = ':';
- }
--
-+
- if (!fp) {
- ast_console_puts("Error opening Tracefile: [ ");
- ast_console_puts(global_tracefile);
- ast_console_puts(" ] ");
--
-+
- ast_console_puts(strerror(errno));
- ast_console_puts("\n");
- return ;
- }
--
-+
- fputs(tmp, fp);
- fputs(" ", fp);
- fputs(port_buf, fp);
-Index: channels/chan_skinny.c
-===================================================================
---- a/channels/chan_skinny.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/channels/chan_skinny.c (.../trunk) (revision 186562)
-@@ -49,7 +49,7 @@
- #include "asterisk/pbx.h"
- #include "asterisk/sched.h"
- #include "asterisk/io.h"
--#include "asterisk/rtp.h"
-+#include "asterisk/rtp_engine.h"
- #include "asterisk/netsock.h"
- #include "asterisk/acl.h"
- #include "asterisk/callerid.h"
-@@ -1111,8 +1111,8 @@
- struct skinny_subchannel {
- ast_mutex_t lock;
- struct ast_channel *owner;
-- struct ast_rtp *rtp;
-- struct ast_rtp *vrtp;
-+ struct ast_rtp_instance *rtp;
-+ struct ast_rtp_instance *vrtp;
- unsigned int callid;
- /* time_t lastouttime; */ /* Unused */
- int progress;
-@@ -1347,7 +1347,7 @@
- .fixup = skinny_fixup,
- .send_digit_begin = skinny_senddigit_begin,
- .send_digit_end = skinny_senddigit_end,
-- .bridge = ast_rtp_bridge,
-+ .bridge = ast_rtp_instance_bridge,
- };
-
- static int skinny_extensionstate_cb(char *context, char* exten, int state, void *data);
-@@ -2516,6 +2516,43 @@
- return 0;
- }
-
-+static void update_connectedline(struct skinny_subchannel *sub, const void *data, size_t datalen)
-+{
-+ struct ast_channel *c = sub->owner;
-+ struct skinny_line *l = sub->parent;
-+ struct skinny_device *d = l->device;
-+
-+ if (ast_strlen_zero(c->cid.cid_num) || ast_strlen_zero(c->connected.id.number))
-+ return;
-+
-+ if (sub->owner->_state == AST_STATE_UP) {
-+ transmit_callstate(d, l->instance, SKINNY_CONNECTED, sub->callid);
-+ transmit_displaypromptstatus(d, "Connected", 0, l->instance, sub->callid);
-+ if (sub->outgoing)
-+ transmit_callinfo(d, c->connected.id.name, c->connected.id.number, l->cid_name, l->cid_num, l->instance, sub->callid, 1);
-+ else
-+ transmit_callinfo(d, l->cid_name, l->cid_num, c->connected.id.name, c->connected.id.number, l->instance, sub->callid, 2);
-+ } else {
-+ if (sub->outgoing) {
-+ transmit_callstate(d, l->instance, SKINNY_RINGIN, sub->callid);
-+ transmit_displaypromptstatus(d, "Ring-In", 0, l->instance, sub->callid);
-+ transmit_callinfo(d, c->connected.id.name, c->connected.id.number, l->cid_name, l->cid_num, l->instance, sub->callid, 1);
-+ } else {
-+ if (!sub->ringing) {
-+ transmit_callstate(d, l->instance, SKINNY_RINGOUT, sub->callid);
-+ transmit_displaypromptstatus(d, "Ring-Out", 0, l->instance, sub->callid);
-+ sub->ringing = 1;
-+ } else {
-+ transmit_callstate(d, l->instance, SKINNY_PROGRESS, sub->callid);
-+ transmit_displaypromptstatus(d, "Call Progress", 0, l->instance, sub->callid);
-+ sub->progress = 1;
-+ }
-+
-+ transmit_callinfo(d, l->cid_name, l->cid_num, c->connected.id.name, c->connected.id.number, l->instance, sub->callid, 2);
-+ }
-+ }
-+}
-+
- static void mwi_event_cb(const struct ast_event *event, void *userdata)
- {
- struct skinny_line *l = userdata;
-@@ -2557,46 +2594,48 @@
- /* I do not believe skinny can deal with video.
- Anyone know differently? */
- /* Yes, it can. Currently 7985 and Cisco VT Advantage do video. */
--static enum ast_rtp_get_result skinny_get_vrtp_peer(struct ast_channel *c, struct ast_rtp **rtp)
-+static enum ast_rtp_glue_result skinny_get_vrtp_peer(struct ast_channel *c, struct ast_rtp_instance **instance)
- {
- struct skinny_subchannel *sub = NULL;
-
- if (!(sub = c->tech_pvt) || !(sub->vrtp))
-- return AST_RTP_GET_FAILED;
-+ return AST_RTP_GLUE_RESULT_FORBID;
-
-- *rtp = sub->vrtp;
-+ ao2_ref(sub->vrtp, +1);
-+ *instance = sub->vrtp;
-
-- return AST_RTP_TRY_NATIVE;
-+ return AST_RTP_GLUE_RESULT_REMOTE;
- }
-
--static enum ast_rtp_get_result skinny_get_rtp_peer(struct ast_channel *c, struct ast_rtp **rtp)
-+static enum ast_rtp_glue_result skinny_get_rtp_peer(struct ast_channel *c, struct ast_rtp_instance **instance)
- {
- struct skinny_subchannel *sub = NULL;
- struct skinny_line *l;
-- enum ast_rtp_get_result res = AST_RTP_TRY_NATIVE;
-+ enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_REMOTE;
-
- if (skinnydebug)
- ast_verb(1, "skinny_get_rtp_peer() Channel = %s\n", c->name);
-
-
- if (!(sub = c->tech_pvt))
-- return AST_RTP_GET_FAILED;
-+ return AST_RTP_GLUE_RESULT_FORBID;
-
- ast_mutex_lock(&sub->lock);
-
- if (!(sub->rtp)){
- ast_mutex_unlock(&sub->lock);
-- return AST_RTP_GET_FAILED;
-+ return AST_RTP_GLUE_RESULT_FORBID;
- }
--
-- *rtp = sub->rtp;
-
-+ ao2_ref(sub->rtp, +1);
-+ *instance = sub->rtp;
-+
- l = sub->parent;
-
- if (!l->canreinvite || l->nat){
-- res = AST_RTP_TRY_PARTIAL;
-+ res = AST_RTP_GLUE_RESULT_LOCAL;
- if (skinnydebug)
-- ast_verb(1, "skinny_get_rtp_peer() Using AST_RTP_TRY_PARTIAL \n");
-+ ast_verb(1, "skinny_get_rtp_peer() Using AST_RTP_GLUE_RESULT_LOCAL \n");
- }
-
- ast_mutex_unlock(&sub->lock);
-@@ -2605,7 +2644,7 @@
-
- }
-
--static int skinny_set_rtp_peer(struct ast_channel *c, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active)
-+static int skinny_set_rtp_peer(struct ast_channel *c, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, int codecs, int nat_active)
- {
- struct skinny_subchannel *sub;
- struct skinny_line *l;
-@@ -2630,7 +2669,7 @@
- s = d->session;
-
- if (rtp){
-- ast_rtp_get_peer(rtp, &them);
-+ ast_rtp_instance_get_remote_address(rtp, &them);
-
- /* Shutdown any early-media or previous media on re-invite */
- if (!(req = req_alloc(sizeof(struct stop_media_transmission_message), STOP_MEDIA_TRANSMISSION_MESSAGE)))
-@@ -2654,7 +2693,7 @@
- req->data.startmedia.conferenceId = htolel(sub->callid);
- req->data.startmedia.passThruPartyId = htolel(sub->callid);
- if (!(l->canreinvite) || (l->nat)){
-- ast_rtp_get_us(rtp, &us);
-+ ast_rtp_instance_get_local_address(rtp, &us);
- req->data.startmedia.remoteIp = htolel(d->ourip.s_addr);
- req->data.startmedia.remotePort = htolel(ntohs(us.sin_port));
- } else {
-@@ -2675,11 +2714,11 @@
- return 0;
- }
-
--static struct ast_rtp_protocol skinny_rtp = {
-+static struct ast_rtp_glue skinny_rtp_glue = {
- .type = "Skinny",
- .get_rtp_info = skinny_get_rtp_peer,
- .get_vrtp_info = skinny_get_vrtp_peer,
-- .set_rtp_peer = skinny_set_rtp_peer,
-+ .update_peer = skinny_set_rtp_peer,
- };
-
- static char *handle_skinny_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-@@ -3559,29 +3598,36 @@
-
- ast_mutex_lock(&sub->lock);
- /* Allocate the RTP */
-- sub->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
-+ sub->rtp = ast_rtp_instance_new(NULL, sched, &bindaddr, NULL);
- if (hasvideo)
-- sub->vrtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
--
-+ sub->vrtp = ast_rtp_instance_new(NULL, sched, &bindaddr, NULL);
-+
-+ if (sub->rtp) {
-+ ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_RTCP, 1);
-+ }
-+ if (sub->vrtp) {
-+ ast_rtp_instance_set_prop(sub->vrtp, AST_RTP_PROPERTY_RTCP, 1);
-+ }
-+
- if (sub->rtp && sub->owner) {
-- ast_channel_set_fd(sub->owner, 0, ast_rtp_fd(sub->rtp));
-- ast_channel_set_fd(sub->owner, 1, ast_rtcp_fd(sub->rtp));
-+ ast_channel_set_fd(sub->owner, 0, ast_rtp_instance_fd(sub->rtp, 0));
-+ ast_channel_set_fd(sub->owner, 1, ast_rtp_instance_fd(sub->rtp, 1));
- }
- if (hasvideo && sub->vrtp && sub->owner) {
-- ast_channel_set_fd(sub->owner, 2, ast_rtp_fd(sub->vrtp));
-- ast_channel_set_fd(sub->owner, 3, ast_rtcp_fd(sub->vrtp));
-+ ast_channel_set_fd(sub->owner, 2, ast_rtp_instance_fd(sub->vrtp, 0));
-+ ast_channel_set_fd(sub->owner, 3, ast_rtp_instance_fd(sub->vrtp, 1));
- }
- if (sub->rtp) {
-- ast_rtp_setqos(sub->rtp, qos.tos_audio, qos.cos_audio, "Skinny RTP");
-- ast_rtp_setnat(sub->rtp, l->nat);
-+ ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "Skinny RTP");
-+ ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, l->nat);
- }
- if (sub->vrtp) {
-- ast_rtp_setqos(sub->vrtp, qos.tos_video, qos.cos_video, "Skinny VRTP");
-- ast_rtp_setnat(sub->vrtp, l->nat);
-+ ast_rtp_instance_set_qos(sub->vrtp, qos.tos_video, qos.cos_video, "Skinny VRTP");
-+ ast_rtp_instance_set_prop(sub->vrtp, AST_RTP_PROPERTY_NAT, l->nat);
- }
- /* Set Frame packetization */
- if (sub->rtp)
-- ast_rtp_codec_setpref(sub->rtp, &l->prefs);
-+ ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp, &l->prefs);
-
- /* Create the RTP connection */
- transmit_connect(d, sub);
-@@ -3601,6 +3647,8 @@
- l->hidecallerid ? "" : l->cid_num,
- l->hidecallerid ? "" : l->cid_name,
- c->cid.cid_ani ? NULL : l->cid_num);
-+ c->connected.id.number = ast_strdup(c->exten);
-+ c->connected.id.name = NULL;
- ast_setstate(c, AST_STATE_RING);
- if (!sub->rtp) {
- start_rtp(sub);
-@@ -3764,7 +3812,7 @@
- transmit_callstateonly(d, sub, SKINNY_RINGIN);
- transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGIN);
- transmit_displaypromptstatus(d, "Ring-In", 0, l->instance, sub->callid);
-- transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, l->cid_name, l->cid_num, l->instance, sub->callid, 1);
-+ transmit_callinfo(d, ast->connected.id.name, ast->connected.id.number, l->cid_name, l->cid_num, l->instance, sub->callid, 1);
- transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK);
- transmit_ringer_mode(d, SKINNY_RING_INSIDE);
-
-@@ -3852,7 +3900,7 @@
- sub->alreadygone = 0;
- sub->outgoing = 0;
- if (sub->rtp) {
-- ast_rtp_destroy(sub->rtp);
-+ ast_rtp_instance_destroy(sub->rtp);
- sub->rtp = NULL;
- }
- ast_mutex_unlock(&sub->lock);
-@@ -3891,7 +3939,7 @@
- /* order matters here...
- for some reason, transmit_callinfo must be before transmit_callstate,
- or you won't get keypad messages in some situations. */
-- transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, l->lastnumberdialed, l->lastnumberdialed, l->instance, sub->callid, 2);
-+ transmit_callinfo(d, ast->connected.id.name, ast->connected.id.number, l->lastnumberdialed, l->lastnumberdialed, l->instance, sub->callid, 2);
- transmit_callstateonly(d, sub, SKINNY_CONNECTED);
- transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_CONNECTED);
- transmit_dialednumber(d, l->lastnumberdialed, l->instance, sub->callid);
-@@ -3913,16 +3961,16 @@
-
- switch(ast->fdno) {
- case 0:
-- f = ast_rtp_read(sub->rtp); /* RTP Audio */
-+ f = ast_rtp_instance_read(sub->rtp, 0); /* RTP Audio */
- break;
- case 1:
-- f = ast_rtcp_read(sub->rtp); /* RTCP Control Channel */
-+ f = ast_rtp_instance_read(sub->rtp, 1); /* RTCP Control Channel */
- break;
- case 2:
-- f = ast_rtp_read(sub->vrtp); /* RTP Video */
-+ f = ast_rtp_instance_read(sub->vrtp, 0); /* RTP Video */
- break;
- case 3:
-- f = ast_rtcp_read(sub->vrtp); /* RTCP Control Channel for video */
-+ f = ast_rtp_instance_read(sub->vrtp, 1); /* RTCP Control Channel for video */
- break;
- #if 0
- case 5:
-@@ -3979,7 +4027,7 @@
- if (sub) {
- ast_mutex_lock(&sub->lock);
- if (sub->rtp) {
-- res = ast_rtp_write(sub->rtp, frame);
-+ res = ast_rtp_instance_write(sub->rtp, frame);
- }
- ast_mutex_unlock(&sub->lock);
- }
-@@ -4086,6 +4134,10 @@
- return "Unhold";
- case AST_CONTROL_SRCUPDATE:
- return "Media Source Update";
-+ case AST_CONTROL_CONNECTED_LINE:
-+ return "Connected Line";
-+ case AST_CONTROL_REDIRECTING:
-+ return "Redirecting";
- case -1:
- return "Stop tone";
- default:
-@@ -4193,7 +4245,7 @@
- transmit_callstateonly(d, sub, SKINNY_RINGOUT);
- transmit_dialednumber(d, l->lastnumberdialed, l->instance, sub->callid);
- transmit_displaypromptstatus(d, "Ring Out", 0, l->instance, sub->callid);
-- transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, l->lastnumberdialed, l->lastnumberdialed, l->instance, sub->callid, 2); /* 2 = outgoing from phone */
-+ transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, S_OR(ast->connected.id.name, l->lastnumberdialed), S_OR(ast->connected.id.number, l->lastnumberdialed), l->instance, sub->callid, 2); /* 2 = outgoing from phone */
- sub->ringing = 1;
- if (!d->earlyrtp) {
- break;
-@@ -4234,7 +4286,7 @@
- }
- transmit_callstateonly(d, sub, SKINNY_PROGRESS);
- transmit_displaypromptstatus(d, "Call Progress", 0, l->instance, sub->callid);
-- transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, l->lastnumberdialed, l->lastnumberdialed, l->instance, sub->callid, 2); /* 2 = outgoing from phone */
-+ transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, S_OR(ast->connected.id.name, l->lastnumberdialed), S_OR(ast->connected.id.number, l->lastnumberdialed), l->instance, sub->callid, 2); /* 2 = outgoing from phone */
- sub->progress = 1;
- if (!d->earlyrtp) {
- break;
-@@ -4253,8 +4305,11 @@
- case AST_CONTROL_PROCEEDING:
- break;
- case AST_CONTROL_SRCUPDATE:
-- ast_rtp_new_source(sub->rtp);
-+ ast_rtp_instance_new_source(sub->rtp);
- break;
-+ case AST_CONTROL_CONNECTED_LINE:
-+ update_connectedline(sub, data, datalen);
-+ break;
- default:
- ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
- return -1; /* Tell asterisk to provide inband signalling */
-@@ -4312,7 +4367,7 @@
- if (skinnydebug)
- ast_verb(1, "skinny_new: tmp->nativeformats=%d fmt=%d\n", tmp->nativeformats, fmt);
- if (sub->rtp) {
-- ast_channel_set_fd(tmp, 0, ast_rtp_fd(sub->rtp));
-+ ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(sub->rtp, 0));
- }
- if (state == AST_STATE_RING) {
- tmp->rings = 1;
-@@ -5537,8 +5592,8 @@
- l = sub->parent;
-
- if (sub->rtp) {
-- ast_rtp_set_peer(sub->rtp, &sin);
-- ast_rtp_get_us(sub->rtp, &us);
-+ ast_rtp_instance_set_remote_address(sub->rtp, &sin);
-+ ast_rtp_instance_get_local_address(sub->rtp, &us);
- } else {
- ast_log(LOG_ERROR, "No RTP structure, this is very bad\n");
- return 0;
-@@ -7289,7 +7344,7 @@
- return -1;
- }
-
-- ast_rtp_proto_register(&skinny_rtp);
-+ ast_rtp_glue_register(&skinny_rtp_glue);
- ast_cli_register_multiple(cli_skinny, ARRAY_LEN(cli_skinny));
-
- ast_manager_register2("SKINNYdevices", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_devices,
-@@ -7323,7 +7378,7 @@
- struct skinny_subchannel *sub;
- struct ast_context *con;
-
-- ast_rtp_proto_unregister(&skinny_rtp);
-+ ast_rtp_glue_unregister(&skinny_rtp_glue);
- ast_channel_unregister(&skinny_tech);
- ast_cli_unregister_multiple(cli_skinny, ARRAY_LEN(cli_skinny));
-
-Index: channels/chan_mgcp.c
-===================================================================
---- a/channels/chan_mgcp.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/channels/chan_mgcp.c (.../trunk) (revision 186562)
-@@ -52,7 +52,7 @@
- #include "asterisk/pbx.h"
- #include "asterisk/sched.h"
- #include "asterisk/io.h"
--#include "asterisk/rtp.h"
-+#include "asterisk/rtp_engine.h"
- #include "asterisk/acl.h"
- #include "asterisk/callerid.h"
- #include "asterisk/cli.h"
-@@ -282,7 +282,7 @@
- int id;
- struct ast_channel *owner;
- struct mgcp_endpoint *parent;
-- struct ast_rtp *rtp;
-+ struct ast_rtp_instance *rtp;
- struct sockaddr_in tmpdest;
- char txident[80]; /*! \todo FIXME txident is replaced by rqnt_ident in endpoint.
- This should be obsoleted */
-@@ -408,7 +408,7 @@
- static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone);
- static int transmit_modify_request(struct mgcp_subchannel *sub);
- static int transmit_notify_request_with_callerid(struct mgcp_subchannel *sub, char *tone, char *callernum, char *callername);
--static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp *rtp, int codecs);
-+static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp, int codecs);
- static int transmit_connection_del(struct mgcp_subchannel *sub);
- static int transmit_audit_endpoint(struct mgcp_endpoint *p);
- static void start_rtp(struct mgcp_subchannel *sub);
-@@ -447,7 +447,7 @@
- .fixup = mgcp_fixup,
- .send_digit_begin = mgcp_senddigit_begin,
- .send_digit_end = mgcp_senddigit_end,
-- .bridge = ast_rtp_bridge,
-+ .bridge = ast_rtp_instance_bridge,
- };
-
- static void mwi_event_cb(const struct ast_event *event, void *userdata)
-@@ -472,7 +472,6 @@
- event = ast_event_get_cached(AST_EVENT_MWI,
- AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mbox,
- AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, cntx,
-- AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
- AST_EVENT_IE_END);
-
- if (event) {
-@@ -504,7 +503,7 @@
- sub->alreadygone = 0;
- memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
- if (sub->rtp) {
-- ast_rtp_destroy(sub->rtp);
-+ ast_rtp_instance_destroy(sub->rtp);
- sub->rtp = NULL;
- }
- dump_cmd_queues(NULL, sub); /* SC */
-@@ -916,7 +915,7 @@
- transmit_modify_request(sub->next);
- }
-
-- transmit_notify_request_with_callerid(sub, tone, ast->cid.cid_num, ast->cid.cid_name);
-+ transmit_notify_request_with_callerid(sub, tone, ast->connected.id.number, ast->connected.id.name);
- ast_setstate(ast, AST_STATE_RINGING);
-
- if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) {
-@@ -1004,7 +1003,7 @@
- /* Reset temporary destination */
- memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
- if (sub->rtp) {
-- ast_rtp_destroy(sub->rtp);
-+ ast_rtp_instance_destroy(sub->rtp);
- sub->rtp = NULL;
- }
-
-@@ -1204,7 +1203,7 @@
- /* Retrieve audio/etc from channel. Assumes sub->lock is already held. */
- struct ast_frame *f;
-
-- f = ast_rtp_read(sub->rtp);
-+ f = ast_rtp_instance_read(sub->rtp, 0);
- /* Don't send RFC2833 if we're not supposed to */
- if (f && (f->frametype == AST_FRAME_DTMF) && !(sub->parent->dtmfmode & MGCP_DTMF_RFC2833))
- return &ast_null_frame;
-@@ -1262,7 +1261,7 @@
- ast_mutex_lock(&sub->lock);
- if ((sub->parent->sub == sub) || !sub->parent->singlepath) {
- if (sub->rtp) {
-- res = ast_rtp_write(sub->rtp, frame);
-+ res = ast_rtp_instance_write(sub->rtp, frame);
- }
- }
- ast_mutex_unlock(&sub->lock);
-@@ -1298,7 +1297,7 @@
- res = -1; /* Let asterisk play inband indications */
- } else if (p->dtmfmode & MGCP_DTMF_RFC2833) {
- ast_log(LOG_DEBUG, "Sending DTMF using RFC2833");
-- ast_rtp_senddigit_begin(sub->rtp, digit);
-+ ast_rtp_instance_dtmf_begin(sub->rtp, digit);
- } else {
- ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode);
- }
-@@ -1325,7 +1324,7 @@
- tmp[2] = digit;
- tmp[3] = '\0';
- transmit_notify_request(sub, tmp);
-- ast_rtp_senddigit_end(sub->rtp, digit);
-+ ast_rtp_instance_dtmf_end(sub->rtp, digit);
- } else {
- ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode);
- }
-@@ -1454,7 +1453,7 @@
- ast_moh_stop(ast);
- break;
- case AST_CONTROL_SRCUPDATE:
-- ast_rtp_new_source(sub->rtp);
-+ ast_rtp_instance_new_source(sub->rtp);
- break;
- case -1:
- transmit_notify_request(sub, "");
-@@ -1482,7 +1481,7 @@
- fmt = ast_best_codec(tmp->nativeformats);
- ast_string_field_build(tmp, name, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id);
- if (sub->rtp)
-- ast_channel_set_fd(tmp, 0, ast_rtp_fd(sub->rtp));
-+ ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(sub->rtp, 0));
- if (i->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)) {
- i->dsp = ast_dsp_new();
- ast_dsp_set_features(i->dsp, DSP_FEATURE_DIGIT_DETECT);
-@@ -1875,12 +1874,12 @@
- sin.sin_family = AF_INET;
- memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
- sin.sin_port = htons(portno);
-- ast_rtp_set_peer(sub->rtp, &sin);
-+ ast_rtp_instance_set_remote_address(sub->rtp, &sin);
- #if 0
- printf("Peer RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
- #endif
- /* Scan through the RTP payload types specified in a "m=" line: */
-- ast_rtp_pt_clear(sub->rtp);
-+ ast_rtp_codecs_payloads_clear(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp);
- codecs = ast_strdupa(m + len);
- while (!ast_strlen_zero(codecs)) {
- if (sscanf(codecs, "%d%n", &codec, &len) != 1) {
-@@ -1889,7 +1888,7 @@
- ast_log(LOG_WARNING, "Error in codec string '%s' at '%s'\n", m, codecs);
- return -1;
- }
-- ast_rtp_set_m_type(sub->rtp, codec);
-+ ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp, codec);
- codec_count++;
- codecs += len;
- }
-@@ -1902,11 +1901,11 @@
- if (sscanf(a, "rtpmap: %u %[^/]/", &codec, mimeSubtype) != 2)
- continue;
- /* Note: should really look at the 'freq' and '#chans' params too */
-- ast_rtp_set_rtpmap_type(sub->rtp, codec, "audio", mimeSubtype, 0);
-+ ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp, codec, "audio", mimeSubtype, 0);
- }
-
- /* Now gather all of the codecs that were asked for: */
-- ast_rtp_get_current_formats(sub->rtp, &peercapability, &peerNonCodecCapability);
-+ ast_rtp_codecs_payload_formats(ast_rtp_instance_get_codecs(sub->rtp), &peercapability, &peerNonCodecCapability);
- p->capability = capability & peercapability;
- if (mgcpdebug) {
- ast_verbose("Capabilities: us - %d, them - %d, combined - %d\n",
-@@ -2044,7 +2043,7 @@
- }
-
-
--static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struct ast_rtp *rtp)
-+static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp)
- {
- int len;
- int codec;
-@@ -2067,9 +2066,9 @@
- ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n");
- return -1;
- }
-- ast_rtp_get_us(sub->rtp, &sin);
-+ ast_rtp_instance_get_local_address(sub->rtp, &sin);
- if (rtp) {
-- ast_rtp_get_peer(rtp, &dest);
-+ ast_rtp_instance_get_remote_address(sub->rtp, &dest);
- } else {
- if (sub->tmpdest.sin_addr.s_addr) {
- dest.sin_addr = sub->tmpdest.sin_addr;
-@@ -2095,11 +2094,11 @@
- if (mgcpdebug) {
- ast_verbose("Answering with capability %d\n", x);
- }
-- codec = ast_rtp_lookup_code(sub->rtp, 1, x);
-+ codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, x);
- if (codec > -1) {
- snprintf(costr, sizeof(costr), " %d", codec);
- strncat(m, costr, sizeof(m) - strlen(m) - 1);
-- snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(1, x, 0));
-+ snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype2(1, x, 0));
- strncat(a, costr, sizeof(a) - strlen(a) - 1);
- }
- }
-@@ -2109,11 +2108,11 @@
- if (mgcpdebug) {
- ast_verbose("Answering with non-codec capability %d\n", x);
- }
-- codec = ast_rtp_lookup_code(sub->rtp, 0, x);
-+ codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 0, x);
- if (codec > -1) {
- snprintf(costr, sizeof(costr), " %d", codec);
- strncat(m, costr, sizeof(m) - strlen(m) - 1);
-- snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(0, x, 0));
-+ snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype2(0, x, 0));
- strncat(a, costr, sizeof(a) - strlen(a) - 1);
- if (x == AST_RTP_DTMF) {
- /* Indicate we support DTMF... Not sure about 16,
-@@ -2137,7 +2136,7 @@
- return 0;
- }
-
--static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp *rtp, int codecs)
-+static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp, int codecs)
- {
- struct mgcp_request resp;
- char local[256];
-@@ -2148,13 +2147,13 @@
- if (ast_strlen_zero(sub->cxident) && rtp) {
- /* We don't have a CXident yet, store the destination and
- wait a bit */
-- ast_rtp_get_peer(rtp, &sub->tmpdest);
-+ ast_rtp_instance_get_remote_address(rtp, &sub->tmpdest);
- return 0;
- }
- ast_copy_string(local, "p:20", sizeof(local));
- for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) {
- if (p->capability & x) {
-- snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x, 0));
-+ snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, x, 0));
- strncat(local, tmp, sizeof(local) - strlen(local) - 1);
- }
- }
-@@ -2173,7 +2172,7 @@
- return send_request(p, sub, &resp, oseq); /* SC */
- }
-
--static int transmit_connect_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp *rtp)
-+static int transmit_connect_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp)
- {
- struct mgcp_request resp;
- char local[256];
-@@ -2184,7 +2183,7 @@
- ast_copy_string(local, "p:20", sizeof(local));
- for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) {
- if (p->capability & x) {
-- snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x, 0));
-+ snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, x, 0));
- strncat(local, tmp, sizeof(local) - strlen(local) - 1);
- }
- }
-@@ -2612,21 +2611,17 @@
- ast_mutex_lock(&sub->lock);
- /* check again to be on the safe side */
- if (sub->rtp) {
-- ast_rtp_destroy(sub->rtp);
-+ ast_rtp_instance_destroy(sub->rtp);
- sub->rtp = NULL;
- }
- /* Allocate the RTP now */
-- sub->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
-+ sub->rtp = ast_rtp_instance_new(NULL, sched, &bindaddr, NULL);
- if (sub->rtp && sub->owner)
-- ast_channel_set_fd(sub->owner, 0, ast_rtp_fd(sub->rtp));
-+ ast_channel_set_fd(sub->owner, 0, ast_rtp_instance_fd(sub->rtp, 0));
- if (sub->rtp) {
-- ast_rtp_setqos(sub->rtp, qos.tos_audio, qos.cos_audio, "MGCP RTP");
-- ast_rtp_setnat(sub->rtp, sub->nat);
-+ ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "MGCP RTP");
-+ ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, sub->nat);
- }
--#if 0
-- ast_rtp_set_callback(p->rtp, rtpready);
-- ast_rtp_set_data(p->rtp, p);
--#endif
- /* Make a call*ID */
- snprintf(sub->callid, sizeof(sub->callid), "%08lx%s", ast_random(), sub->txident);
- /* Transmit the connection create */
-@@ -3941,22 +3936,22 @@
- return (gw_reload ? NULL : gw);
- }
-
--static enum ast_rtp_get_result mgcp_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
-+static enum ast_rtp_glue_result mgcp_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
- {
- struct mgcp_subchannel *sub = NULL;
-
- if (!(sub = chan->tech_pvt) || !(sub->rtp))
-- return AST_RTP_GET_FAILED;
-+ return AST_RTP_GLUE_RESULT_FORBID;
-
-- *rtp = sub->rtp;
-+ *instance = sub->rtp ? ao2_ref(sub->rtp, +1), sub->rtp : NULL;
-
- if (sub->parent->canreinvite)
-- return AST_RTP_TRY_NATIVE;
-+ return AST_RTP_GLUE_RESULT_REMOTE;
- else
-- return AST_RTP_TRY_PARTIAL;
-+ return AST_RTP_GLUE_RESULT_LOCAL;
- }
-
--static int mgcp_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active)
-+static int mgcp_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, int codecs, int nat_active)
- {
- /* XXX Is there such thing as video support with MGCP? XXX */
- struct mgcp_subchannel *sub;
-@@ -3968,10 +3963,10 @@
- return -1;
- }
-
--static struct ast_rtp_protocol mgcp_rtp = {
-+static struct ast_rtp_glue mgcp_rtp_glue = {
- .type = "MGCP",
- .get_rtp_info = mgcp_get_rtp_peer,
-- .set_rtp_peer = mgcp_set_rtp_peer,
-+ .update_peer = mgcp_set_rtp_peer,
- };
-
- static void destroy_endpoint(struct mgcp_endpoint *e)
-@@ -3985,7 +3980,7 @@
- transmit_connection_del(sub);
- }
- if (sub->rtp) {
-- ast_rtp_destroy(sub->rtp);
-+ ast_rtp_instance_destroy(sub->rtp);
- sub->rtp = NULL;
- }
- memset(sub->magic, 0, sizeof(sub->magic));
-@@ -4277,7 +4272,7 @@
- return AST_MODULE_LOAD_FAILURE;
- }
-
-- ast_rtp_proto_register(&mgcp_rtp);
-+ ast_rtp_glue_register(&mgcp_rtp_glue);
- ast_cli_register_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry));
-
- /* And start the monitor for the first time */
-@@ -4380,7 +4375,7 @@
- }
-
- close(mgcpsock);
-- ast_rtp_proto_unregister(&mgcp_rtp);
-+ ast_rtp_glue_unregister(&mgcp_rtp_glue);
- ast_cli_unregister_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry));
- sched_context_destroy(sched);
-
-Index: channels/chan_unistim.c
-===================================================================
---- a/channels/chan_unistim.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/channels/chan_unistim.c (.../trunk) (revision 186562)
-@@ -60,7 +60,7 @@
- #include "asterisk/module.h"
- #include "asterisk/pbx.h"
- #include "asterisk/event.h"
--#include "asterisk/rtp.h"
-+#include "asterisk/rtp_engine.h"
- #include "asterisk/netsock.h"
- #include "asterisk/acl.h"
- #include "asterisk/callerid.h"
-@@ -365,7 +365,7 @@
- /*! Unistim line */
- struct unistim_line *parent;
- /*! RTP handle */
-- struct ast_rtp *rtp;
-+ struct ast_rtp_instance *rtp;
- int alreadygone;
- char ringvolume;
- char ringstyle;
-@@ -711,7 +711,7 @@
- .send_digit_begin = unistim_senddigit_begin,
- .send_digit_end = unistim_senddigit_end,
- .send_text = unistim_sendtext,
--/* .bridge = ast_rtp_bridge, */
-+ .bridge = ast_rtp_instance_bridge,
- };
-
- static void display_last_error(const char *sz_msg)
-@@ -1854,7 +1854,7 @@
- static void swap_subs(struct unistim_line *p, int a, int b)
- {
- /* struct ast_channel *towner; */
-- struct ast_rtp *rtp;
-+ struct ast_rtp_instance *rtp;
- int fds;
-
- if (unistimdebug)
-@@ -2056,30 +2056,29 @@
- /* Allocate the RTP */
- if (unistimdebug)
- ast_verb(0, "Starting RTP. Bind on %s\n", ast_inet_ntoa(sout.sin_addr));
-- sub->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, sout.sin_addr);
-+ sub->rtp = ast_rtp_instance_new(NULL, sched, &sout, NULL);
- if (!sub->rtp) {
- ast_log(LOG_WARNING, "Unable to create RTP session: %s binaddr=%s\n",
- strerror(errno), ast_inet_ntoa(sout.sin_addr));
- ast_mutex_unlock(&sub->lock);
- return;
- }
-- if (sub->rtp && sub->owner) {
-- sub->owner->fds[0] = ast_rtp_fd(sub->rtp);
-- sub->owner->fds[1] = ast_rtcp_fd(sub->rtp);
-+ ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_RTCP, 1);
-+ if (sub->owner) {
-+ sub->owner->fds[0] = ast_rtp_instance_fd(sub->rtp, 0);
-+ sub->owner->fds[1] = ast_rtp_instance_fd(sub->rtp, 1);
- }
-- if (sub->rtp) {
-- ast_rtp_setqos(sub->rtp, qos.tos_audio, qos.cos_audio, "UNISTIM RTP");
-- ast_rtp_setnat(sub->rtp, sub->parent->parent->nat);
-- }
-+ ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "UNISTIM RTP");
-+ ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, sub->parent->parent->nat);
-
- /* Create the RTP connection */
-- ast_rtp_get_us(sub->rtp, &us);
-+ ast_rtp_instance_get_local_address(sub->rtp, &us);
- sin.sin_family = AF_INET;
- /* Setting up RTP for our side */
- memcpy(&sin.sin_addr, &sub->parent->parent->session->sin.sin_addr,
- sizeof(sin.sin_addr));
- sin.sin_port = htons(sub->parent->parent->rtp_port);
-- ast_rtp_set_peer(sub->rtp, &sin);
-+ ast_rtp_instance_set_remote_address(sub->rtp, &sin);
- if (!(sub->owner->nativeformats & sub->owner->readformat)) {
- int fmt;
- fmt = ast_best_codec(sub->owner->nativeformats);
-@@ -2091,7 +2090,7 @@
- sub->owner->readformat = fmt;
- sub->owner->writeformat = fmt;
- }
-- codec = ast_rtp_lookup_code(sub->rtp, 1, sub->owner->readformat);
-+ codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, sub->owner->readformat);
- /* Setting up RTP of the phone */
- if (public_ip.sin_family == 0) /* NAT IP override ? */
- memcpy(&public, &us, sizeof(public)); /* No defined, using IP from recvmsg */
-@@ -3672,16 +3671,16 @@
- Sendicon(TEXT_LINE0, FAV_ICON_NONE, session);
-
- if (sub->owner) {
-- if (sub->owner->cid.cid_num) {
-- send_text(TEXT_LINE1, TEXT_NORMAL, session, sub->owner->cid.cid_num);
-- change_callerid(session, 0, sub->owner->cid.cid_num);
-+ if (sub->owner->connected.id.number) {
-+ send_text(TEXT_LINE1, TEXT_NORMAL, session, sub->owner->connected.id.number);
-+ change_callerid(session, 0, sub->owner->connected.id.number);
- } else {
- send_text(TEXT_LINE1, TEXT_NORMAL, session, DEFAULTCALLERID);
- change_callerid(session, 0, DEFAULTCALLERID);
- }
-- if (sub->owner->cid.cid_name) {
-- send_text(TEXT_LINE0, TEXT_NORMAL, session, sub->owner->cid.cid_name);
-- change_callerid(session, 1, sub->owner->cid.cid_name);
-+ if (sub->owner->connected.id.name) {
-+ send_text(TEXT_LINE0, TEXT_NORMAL, session, sub->owner->connected.id.name);
-+ change_callerid(session, 1, sub->owner->connected.id.name);
- } else {
- send_text(TEXT_LINE0, TEXT_NORMAL, session, DEFAULTCALLERNAME);
- change_callerid(session, 1, DEFAULTCALLERNAME);
-@@ -3724,7 +3723,7 @@
- if (sub->rtp) {
- if (unistimdebug)
- ast_verb(0, "Destroying RTP session\n");
-- ast_rtp_destroy(sub->rtp);
-+ ast_rtp_instance_destroy(sub->rtp);
- sub->rtp = NULL;
- }
- return 0;
-@@ -3769,7 +3768,7 @@
- if (sub->rtp) {
- if (unistimdebug)
- ast_verb(0, "Destroying RTP session\n");
-- ast_rtp_destroy(sub->rtp);
-+ ast_rtp_instance_destroy(sub->rtp);
- sub->rtp = NULL;
- }
- return 0;
-@@ -3794,7 +3793,7 @@
- if (sub->rtp) {
- if (unistimdebug)
- ast_verb(0, "Destroying RTP session\n");
-- ast_rtp_destroy(sub->rtp);
-+ ast_rtp_instance_destroy(sub->rtp);
- sub->rtp = NULL;
- } else if (unistimdebug)
- ast_verb(0, "No RTP session to destroy\n");
-@@ -3921,10 +3920,10 @@
-
- switch (ast->fdno) {
- case 0:
-- f = ast_rtp_read(sub->rtp); /* RTP Audio */
-+ f = ast_rtp_instance_read(sub->rtp, 0); /* RTP Audio */
- break;
- case 1:
-- f = ast_rtcp_read(sub->rtp); /* RTCP Control Channel */
-+ f = ast_rtp_instance_read(sub->rtp, 1); /* RTCP Control Channel */
- break;
- default:
- f = &ast_null_frame;
-@@ -3990,7 +3989,7 @@
- if (sub) {
- ast_mutex_lock(&sub->lock);
- if (sub->rtp) {
-- res = ast_rtp_write(sub->rtp, frame);
-+ res = ast_rtp_instance_write(sub->rtp, frame);
- }
- ast_mutex_unlock(&sub->lock);
- }
-@@ -4391,7 +4390,6 @@
- event = ast_event_get_cached(AST_EVENT_MWI,
- AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
- AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
-- AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
- AST_EVENT_IE_END);
-
- if (event) {
-@@ -4456,8 +4454,8 @@
- if ((sub->rtp) && (sub->subtype == 0)) {
- if (unistimdebug)
- ast_verb(0, "New unistim channel with a previous rtp handle ?\n");
-- tmp->fds[0] = ast_rtp_fd(sub->rtp);
-- tmp->fds[1] = ast_rtcp_fd(sub->rtp);
-+ tmp->fds[0] = ast_rtp_instance_fd(sub->rtp, 0);
-+ tmp->fds[1] = ast_rtp_instance_fd(sub->rtp, 1);
- }
- if (sub->rtp)
- ast_jb_configure(tmp, &global_jbconf);
-@@ -5527,51 +5525,19 @@
- return 0;
- }
-
--static enum ast_rtp_get_result unistim_get_vrtp_peer(struct ast_channel *chan,
-- struct ast_rtp **rtp)
-+static enum ast_rtp_glue_result unistim_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
- {
-- return AST_RTP_TRY_NATIVE;
--}
-+ struct unistim_subchannel *sub = chan->tech_pvt;
-
--static enum ast_rtp_get_result unistim_get_rtp_peer(struct ast_channel *chan,
-- struct ast_rtp **rtp)
--{
-- struct unistim_subchannel *sub;
-- enum ast_rtp_get_result res = AST_RTP_GET_FAILED;
-+ ao2_ref(sub->rtp, +1);
-+ *instance = sub->rtp;
-
-- if (unistimdebug)
-- ast_verb(0, "unistim_get_rtp_peer called\n");
--
-- sub = chan->tech_pvt;
-- if (sub && sub->rtp) {
-- *rtp = sub->rtp;
-- res = AST_RTP_TRY_NATIVE;
-- }
--
-- return res;
-+ return AST_RTP_GLUE_RESULT_LOCAL;
- }
-
--static int unistim_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp,
-- struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active)
--{
-- struct unistim_subchannel *sub;
--
-- if (unistimdebug)
-- ast_verb(0, "unistim_set_rtp_peer called\n");
--
-- sub = chan->tech_pvt;
--
-- if (sub)
-- return 0;
--
-- return -1;
--}
--
--static struct ast_rtp_protocol unistim_rtp = {
-+static struct ast_rtp_glue unistim_rtp_glue = {
- .type = channel_type,
- .get_rtp_info = unistim_get_rtp_peer,
-- .get_vrtp_info = unistim_get_vrtp_peer,
-- .set_rtp_peer = unistim_set_rtp_peer,
- };
-
- /*--- load_module: PBX load module - initialization ---*/
-@@ -5604,7 +5570,7 @@
- goto chanreg_failed;
- }
-
-- ast_rtp_proto_register(&unistim_rtp);
-+ ast_rtp_glue_register(&unistim_rtp_glue);
-
- ast_cli_register_multiple(unistim_cli, ARRAY_LEN(unistim_cli));
-
-@@ -5635,7 +5601,7 @@
- ast_cli_unregister_multiple(unistim_cli, ARRAY_LEN(unistim_cli));
-
- ast_channel_unregister(&unistim_tech);
-- ast_rtp_proto_unregister(&unistim_rtp);
-+ ast_rtp_glue_unregister(&unistim_rtp_glue);
-
- ast_mutex_lock(&monlock);
- if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
-Index: channels/chan_local.c
-===================================================================
---- a/channels/chan_local.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/channels/chan_local.c (.../trunk) (revision 186562)
-@@ -39,7 +39,6 @@
- #include "asterisk/pbx.h"
- #include "asterisk/sched.h"
- #include "asterisk/io.h"
--#include "asterisk/rtp.h"
- #include "asterisk/acl.h"
- #include "asterisk/callerid.h"
- #include "asterisk/file.h"
-@@ -407,6 +406,37 @@
- ast_moh_start(ast, data, NULL);
- } else if (condition == AST_CONTROL_UNHOLD) {
- ast_moh_stop(ast);
-+ } else if (condition == AST_CONTROL_CONNECTED_LINE || condition == AST_CONTROL_REDIRECTING) {
-+ struct ast_channel *this_channel;
-+ struct ast_channel *the_other_channel;
-+ /* A connected line update frame may only contain a partial amount of data, such
-+ * as just a source, or just a ton, and not the full amount of information. However,
-+ * the collected information is all stored in the outgoing channel's connectedline
-+ * structure, so when receiving a connected line update on an outgoing local channel,
-+ * we need to transmit the collected connected line information instead of whatever
-+ * happens to be in this control frame. The same applies for redirecting information, which
-+ * is why it is handled here as well.*/
-+ isoutbound = IS_OUTBOUND(ast, p);
-+ if (isoutbound) {
-+ this_channel = p->chan;
-+ the_other_channel = p->owner;
-+ } else {
-+ this_channel = p->owner;
-+ the_other_channel = p->chan;
-+ }
-+ if (the_other_channel) {
-+ unsigned char frame_data[1024];
-+ if (condition == AST_CONTROL_CONNECTED_LINE) {
-+ f.datalen = ast_connected_line_build_data(frame_data, sizeof(frame_data), &this_channel->connected);
-+ } else {
-+ f.datalen = ast_redirecting_build_data(frame_data, sizeof(frame_data), &this_channel->redirecting);
-+ }
-+ f.subclass = condition;
-+ f.data.ptr = frame_data;
-+ if (!(res = local_queue_frame(p, isoutbound, &f, ast, 1))) {
-+ ast_mutex_unlock(&p->lock);
-+ }
-+ }
- } else {
- /* Queue up a frame representing the indication as a control frame */
- ast_mutex_lock(&p->lock);
-@@ -510,22 +540,45 @@
-
- if (!p)
- return -1;
--
-- ast_mutex_lock(&p->lock);
-
-+ /* If you value your sanity, please don't look at this code */
-+start_over:
-+ while (ast_channel_trylock(p->chan)) {
-+ ast_channel_unlock(p->owner);
-+ usleep(1);
-+ ast_channel_lock(p->owner);
-+ }
-+
-+ /* p->owner and p->chan are locked now. Let's get p locked */
-+ if (ast_mutex_trylock(&p->lock)) {
-+ /* @#$&$@ */
-+ ast_channel_unlock(p->chan);
-+ ast_channel_unlock(p->owner);
-+ usleep(1);
-+ ast_channel_lock(p->owner);
-+ goto start_over;
-+ }
-+
- /*
- * Note that cid_num and cid_name aren't passed in the ast_channel_alloc
- * call, so it's done here instead.
-+ *
-+ * All these failure points just return -1. The individual strings will
-+ * be cleared when we destroy the channel.
- */
-- p->chan->cid.cid_dnid = ast_strdup(p->owner->cid.cid_dnid);
-- p->chan->cid.cid_num = ast_strdup(p->owner->cid.cid_num);
-- p->chan->cid.cid_name = ast_strdup(p->owner->cid.cid_name);
-- p->chan->cid.cid_rdnis = ast_strdup(p->owner->cid.cid_rdnis);
-- p->chan->cid.cid_ani = ast_strdup(p->owner->cid.cid_ani);
-- p->chan->cid.cid_pres = p->owner->cid.cid_pres;
-- p->chan->cid.cid_ani2 = p->owner->cid.cid_ani2;
-- p->chan->cid.cid_ton = p->owner->cid.cid_ton;
-+ if (!(p->chan->cid.cid_rdnis = ast_strdup(p->owner->cid.cid_rdnis))) {
-+ return -1;
-+ }
-+ ast_party_redirecting_copy(&p->chan->redirecting, &p->owner->redirecting);
-+
-+ if (!(p->chan->cid.cid_dnid = ast_strdup(p->owner->cid.cid_dnid))) {
-+ return -1;
-+ }
- p->chan->cid.cid_tns = p->owner->cid.cid_tns;
-+
-+ ast_connected_line_copy_to_caller(&p->chan->cid, &p->owner->connected);
-+ ast_connected_line_copy_from_caller(&p->chan->connected, &p->owner->cid);
-+
- ast_string_field_set(p->chan, language, p->owner->language);
- ast_string_field_set(p->chan, accountcode, p->owner->accountcode);
- ast_string_field_set(p->chan, musicclass, p->owner->musicclass);
-@@ -561,6 +614,7 @@
- ast_set_flag(p, LOCAL_LAUNCHED_PBX);
-
- ast_mutex_unlock(&p->lock);
-+ ast_channel_unlock(p->chan);
- return res;
- }
-
-Index: channels/chan_bridge.c
-===================================================================
---- a/channels/chan_bridge.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/channels/chan_bridge.c (.../trunk) (revision 186562)
-@@ -39,7 +39,6 @@
- #include "asterisk/pbx.h"
- #include "asterisk/sched.h"
- #include "asterisk/io.h"
--#include "asterisk/rtp.h"
- #include "asterisk/acl.h"
- #include "asterisk/callerid.h"
- #include "asterisk/file.h"
-Index: channels/misdn/isdn_msg_parser.c
-===================================================================
---- a/channels/misdn/isdn_msg_parser.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/channels/misdn/isdn_msg_parser.c (.../trunk) (revision 186562)
-@@ -11,7 +11,7 @@
- * the GNU General Public License
- */
-
--/*! \file
-+/*! \file
- * \brief Interface to mISDN - message parser
- * \author Christian Richter <crich@beronet.com>
- */
-@@ -25,21 +25,57 @@
-
- #include "ie.c"
-
-+/*!
-+ * \internal
-+ * \brief Build the name, number, name/number display message string
-+ *
-+ * \param display Display buffer to fill in
-+ * \param display_length Length of the display buffer to fill in
-+ * \param display_format Display format enumeration
-+ * \param name Name string to use
-+ * \param number Number string to use
-+ *
-+ * \return Nothing
-+ */
-+static void build_display_str(char *display, size_t display_length, int display_format, const char *name, const char *number)
-+{
-+ display[0] = 0;
-+ switch (display_format) {
-+ default:
-+ case 0: /* none */
-+ break;
-
-+ case 1: /* name */
-+ snprintf(display, display_length, "%s", name);
-+ break;
-+
-+ case 2: /* number */
-+ snprintf(display, display_length, "%s", number);
-+ break;
-+
-+ case 3: /* both */
-+ if (name[0] || number[0]) {
-+ snprintf(display, display_length, "\"%s\" <%s>", name, number);
-+ }
-+ break;
-+ }
-+}
-+
-+
- static void set_channel(struct misdn_bchannel *bc, int channel)
- {
-
- cb_log(3,bc->port,"set_channel: bc->channel:%d channel:%d\n", bc->channel, channel);
--
--
-+
-+
- if (channel==0xff) {
- /* any channel */
- channel=-1;
- }
--
-+
- /* ALERT: is that everytime true ? */
- if (channel > 0 && bc->nt ) {
--
-+
- if (bc->channel && ( bc->channel != 0xff) ) {
- cb_log(0,bc->port,"We already have a channel (%d)\n", bc->channel);
- } else {
-@@ -47,179 +83,191 @@
- cb_event(EVENT_NEW_CHANNEL,bc,NULL);
- }
- }
--
-+
- if (channel > 0 && !bc->nt ) {
- bc->channel = channel;
- cb_event(EVENT_NEW_CHANNEL,bc,NULL);
- }
- }
-
--static void parse_proceeding (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
-+static void parse_proceeding (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- CALL_PROCEEDING_t *proceeding=(CALL_PROCEEDING_t*)((unsigned long)msg->data+ HEADER_LEN);
- //struct misdn_stack *stack=get_stack_by_bc(bc);
--
-+
- {
- int exclusive, channel;
- dec_ie_channel_id(proceeding->CHANNEL_ID, (Q931_info_t *)proceeding, &exclusive, &channel, nt,bc);
-
- set_channel(bc,channel);
--
-+
- }
--
-+
- dec_ie_progress(proceeding->PROGRESS, (Q931_info_t *)proceeding, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
--
--
--#ifdef DEBUG
-- printf("Parsing PROCEEDING Msg\n");
-+
-+
-+#ifdef DEBUG
-+ printf("Parsing PROCEEDING Msg\n");
- #endif
- }
- static msg_t *build_proceeding (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- CALL_PROCEEDING_t *proceeding;
-- msg_t *msg =(msg_t*)create_l3msg(CC_PROCEEDING | REQUEST, MT_CALL_PROCEEDING, bc?bc->l3_id:-1, sizeof(CALL_PROCEEDING_t) ,nt);
--
-+ msg_t *msg =(msg_t*)create_l3msg(CC_PROCEEDING | REQUEST, MT_CALL_PROCEEDING, bc?bc->l3_id:-1, sizeof(CALL_PROCEEDING_t) ,nt);
-+
- proceeding=(CALL_PROCEEDING_t*)((msg->data+HEADER_LEN));
-
- enc_ie_channel_id(&proceeding->CHANNEL_ID, msg, 1,bc->channel, nt,bc);
--
-- if (nt)
-+
-+ if (nt)
- enc_ie_progress(&proceeding->PROGRESS, msg, 0, nt?1:5, 8, nt,bc);
--
-
--#ifdef DEBUG
-- printf("Building PROCEEDING Msg\n");
-+
-+#ifdef DEBUG
-+ printf("Building PROCEEDING Msg\n");
- #endif
-- return msg;
-+ return msg;
- }
-
--static void parse_alerting (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
-+static void parse_alerting (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
- {
-- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
-+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- ALERTING_t *alerting=(ALERTING_t*)((unsigned long)(msg->data+HEADER_LEN));
- //Q931_info_t *qi=(Q931_info_t*)(msg->data+HEADER_LEN);
--
-+
- dec_ie_progress(alerting->PROGRESS, (Q931_info_t *)alerting, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
--
--#ifdef DEBUG
-- printf("Parsing ALERTING Msg\n");
-+
-+#ifdef DEBUG
-+ printf("Parsing ALERTING Msg\n");
- #endif
-
--
-+
- }
-
--static msg_t *build_alerting (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
-+static msg_t *build_alerting (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- ALERTING_t *alerting;
-- msg_t *msg =(msg_t*)create_l3msg(CC_ALERTING | REQUEST, MT_ALERTING, bc?bc->l3_id:-1, sizeof(ALERTING_t) ,nt);
--
-- alerting=(ALERTING_t*)((msg->data+HEADER_LEN));
--
-+ msg_t *msg =(msg_t*)create_l3msg(CC_ALERTING | REQUEST, MT_ALERTING, bc?bc->l3_id:-1, sizeof(ALERTING_t) ,nt);
-+
-+ alerting=(ALERTING_t*)((msg->data+HEADER_LEN));
-+
- enc_ie_channel_id(&alerting->CHANNEL_ID, msg, 1,bc->channel, nt,bc);
--
-- if (nt)
-+
-+ if (nt)
- enc_ie_progress(&alerting->PROGRESS, msg, 0, nt?1:5, 8, nt,bc);
--#ifdef DEBUG
-- printf("Building ALERTING Msg\n");
-+#ifdef DEBUG
-+ printf("Building ALERTING Msg\n");
- #endif
-- return msg;
-+ return msg;
- }
-
-
--static void parse_progress (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
-+static void parse_progress (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
-- PROGRESS_t *progress=(PROGRESS_t*)((unsigned long)(msg->data+HEADER_LEN));
-- //Q931_info_t *qi=(Q931_info_t*)(msg->data+HEADER_LEN);
--
-+ PROGRESS_t *progress=(PROGRESS_t*)((unsigned long)(msg->data+HEADER_LEN));
-+ //Q931_info_t *qi=(Q931_info_t*)(msg->data+HEADER_LEN);
-+
- dec_ie_progress(progress->PROGRESS, (Q931_info_t *)progress, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
--
--#ifdef DEBUG
-- printf("Parsing PROGRESS Msg\n");
-+
-+#ifdef DEBUG
-+ printf("Parsing PROGRESS Msg\n");
- #endif
- }
-
--static msg_t *build_progress (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
-+static msg_t *build_progress (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- PROGRESS_t *progress;
-- msg_t *msg =(msg_t*)create_l3msg(CC_PROGRESS | REQUEST, MT_PROGRESS, bc?bc->l3_id:-1, sizeof(PROGRESS_t) ,nt);
--
-- progress=(PROGRESS_t*)((msg->data+HEADER_LEN));
-+ msg_t *msg =(msg_t*)create_l3msg(CC_PROGRESS | REQUEST, MT_PROGRESS, bc?bc->l3_id:-1, sizeof(PROGRESS_t) ,nt);
-
--#ifdef DEBUG
-- printf("Building PROGRESS Msg\n");
-+ progress=(PROGRESS_t*)((msg->data+HEADER_LEN));
-+
-+#ifdef DEBUG
-+ printf("Building PROGRESS Msg\n");
- #endif
-- return msg;
-+ return msg;
- }
-
--static void parse_setup (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
--{
-+static void parse_setup (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
-+{
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- SETUP_t *setup= (SETUP_t*)((unsigned long)msg->data+HEADER_LEN);
- Q931_info_t *qi=(Q931_info_t*)((unsigned long)msg->data+HEADER_LEN);
-+ int type;
-+ int plan;
-+ int present;
-+ int screen;
-+ int reason;
-
--#ifdef DEBUG
-- printf("Parsing SETUP Msg\n");
-+#ifdef DEBUG
-+ printf("Parsing SETUP Msg\n");
- #endif
-- {
-- int type,plan,present, screen;
-- char id[32];
-- dec_ie_calling_pn(setup->CALLING_PN, qi, &type, &plan, &present, &screen, id, sizeof(id)-1, nt,bc);
-
-- bc->onumplan=type;
-- strcpy(bc->oad, id);
-- switch (present) {
-- case 0:
-- bc->pres=0; /* screened */
-- break;
-- case 1:
-- bc->pres=1; /* not screened */
-- break;
-- default:
-- bc->pres=0;
-- }
-- switch (screen) {
-- case 0:
-- break;
-- default:
-- ;
-- }
-+ dec_ie_calling_pn(setup->CALLING_PN, qi, &type, &plan, &present, &screen, bc->caller.number, sizeof(bc->caller.number) - 1, nt, bc);
-+ bc->caller.number_type = type;
-+ bc->caller.number_plan = plan;
-+ switch (present) {
-+ default:
-+ case 0:
-+ bc->caller.presentation = 0; /* presentation allowed */
-+ break;
-+ case 1:
-+ bc->caller.presentation = 1; /* presentation restricted */
-+ break;
-+ case 2:
-+ bc->caller.presentation = 2; /* Number not available */
-+ break;
- }
-- {
-- int type, plan;
-- char number[32];
-- dec_ie_called_pn(setup->CALLED_PN, (Q931_info_t *)setup, &type, &plan, number, sizeof(number)-1, nt,bc);
-- strcpy(bc->dad, number);
-- bc->dnumplan=type;
-+ if (0 <= screen) {
-+ bc->caller.screening = screen;
-+ } else {
-+ bc->caller.screening = 0; /* Unscreened */
- }
-- {
-- char keypad[32];
-- dec_ie_keypad(setup->KEYPAD, (Q931_info_t *)setup, keypad, sizeof(keypad)-1, nt,bc);
-- strcpy(bc->keypad, keypad);
-- }
-
-- {
-- dec_ie_complete(setup->COMPLETE, (Q931_info_t *)setup, &bc->sending_complete, nt,bc);
--
-+ dec_ie_called_pn(setup->CALLED_PN, (Q931_info_t *) setup, &type, &plan, bc->dialed.number, sizeof(bc->dialed.number) - 1, nt, bc);
-+ bc->dialed.number_type = type;
-+ bc->dialed.number_plan = plan;
-+
-+ dec_ie_keypad(setup->KEYPAD, (Q931_info_t *) setup, bc->keypad, sizeof(bc->keypad) - 1, nt, bc);
-+
-+ dec_ie_complete(setup->COMPLETE, (Q931_info_t *) setup, &bc->sending_complete, nt, bc);
-+
-+ dec_ie_redir_nr(setup->REDIR_NR, (Q931_info_t *) setup, &type, &plan, &present, &screen, &reason, bc->redirecting.from.number, sizeof(bc->redirecting.from.number) - 1, nt, bc);
-+ bc->redirecting.from.number_type = type;
-+ bc->redirecting.from.number_plan = plan;
-+ switch (present) {
-+ default:
-+ case 0:
-+ bc->redirecting.from.presentation = 0; /* presentation allowed */
-+ break;
-+ case 1:
-+ bc->redirecting.from.presentation = 1; /* presentation restricted */
-+ break;
-+ case 2:
-+ bc->redirecting.from.presentation = 2; /* Number not available */
-+ break;
- }
--
-- {
-- int type, plan, present, screen, reason;
-- char id[32];
-- dec_ie_redir_nr(setup->REDIR_NR, (Q931_info_t *)setup, &type, &plan, &present, &screen, &reason, id, sizeof(id)-1, nt,bc);
--
-- strcpy(bc->rad, id);
-- bc->rnumplan=type;
-+ if (0 <= screen) {
-+ bc->redirecting.from.screening = screen;
-+ } else {
-+ bc->redirecting.from.screening = 0; /* Unscreened */
- }
-+ if (0 <= reason) {
-+ bc->redirecting.reason = reason;
-+ } else {
-+ bc->redirecting.reason = mISDN_REDIRECTING_REASON_UNKNOWN;
-+ }
-+
- {
- int coding, capability, mode, rate, multi, user, async, urate, stopbits, dbits, parity;
-+
- dec_ie_bearer(setup->BEARER, (Q931_info_t *)setup, &coding, &capability, &mode, &rate, &multi, &user, &async, &urate, &stopbits, &dbits, &parity, nt,bc);
- switch (capability) {
-- case -1: bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
-+ case -1: bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
- break;
- case 0: bc->capability=INFO_CAPABILITY_SPEECH;
- break;
-@@ -228,7 +276,7 @@
- case 8: bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
- bc->user1 = user;
- bc->urate = urate;
--
-+
- bc->rate = rate;
- bc->mode = mode;
- break;
-@@ -237,7 +285,7 @@
- default:
- break;
- }
--
-+
- switch(user) {
- case 2:
- bc->law=INFO_CODEC_ULAW;
-@@ -247,15 +295,15 @@
- break;
- default:
- bc->law=INFO_CODEC_ALAW;
--
-+
- }
--
-- bc->capability=capability;
-+
-+ bc->capability=capability;
- }
- {
- int exclusive, channel;
- dec_ie_channel_id(setup->CHANNEL_ID, (Q931_info_t *)setup, &exclusive, &channel, nt,bc);
--
-+
- set_channel(bc,channel);
- }
-
-@@ -266,55 +314,63 @@
- else
- cb_log(1,bc->port,"NO USERUESRINFO\n");
- }
--
-+
- dec_ie_progress(setup->PROGRESS, (Q931_info_t *)setup, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
--
-+
- }
-
--#define ANY_CHANNEL 0xff /* IE attribut for 'any channel' */
--static msg_t *build_setup (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
-+#define ANY_CHANNEL 0xff /* IE attribute for 'any channel' */
-+static msg_t *build_setup (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- SETUP_t *setup;
-- msg_t *msg =(msg_t*)create_l3msg(CC_SETUP | REQUEST, MT_SETUP, bc?bc->l3_id:-1, sizeof(SETUP_t) ,nt);
--
-- setup=(SETUP_t*)((msg->data+HEADER_LEN));
--
-+ msg_t *msg =(msg_t*)create_l3msg(CC_SETUP | REQUEST, MT_SETUP, bc?bc->l3_id:-1, sizeof(SETUP_t) ,nt);
-+
-+ setup=(SETUP_t*)((msg->data+HEADER_LEN));
-+
- if (bc->channel == 0 || bc->channel == ANY_CHANNEL || bc->channel==-1)
- enc_ie_channel_id(&setup->CHANNEL_ID, msg, 0, bc->channel, nt,bc);
-- else
-+ else
- enc_ie_channel_id(&setup->CHANNEL_ID, msg, 1, bc->channel, nt,bc);
--
--
-- {
-- int type=bc->onumplan,plan=1,present=bc->pres,screen=bc->screen;
-- enc_ie_calling_pn(&setup->CALLING_PN, msg, type, plan, present,
-- screen, bc->oad, nt, bc);
-+
-+
-+ enc_ie_calling_pn(&setup->CALLING_PN, msg, bc->caller.number_type, bc->caller.number_plan,
-+ bc->caller.presentation, bc->caller.screening, bc->caller.number, nt, bc);
-+
-+ if (bc->dialed.number[0]) {
-+ enc_ie_called_pn(&setup->CALLED_PN, msg, bc->dialed.number_type, bc->dialed.number_plan, bc->dialed.number, nt, bc);
- }
--
-- {
-- if (bc->dad[0])
-- enc_ie_called_pn(&setup->CALLED_PN, msg, bc->dnumplan, 1, bc->dad, nt,bc);
-+
-+ if (bc->redirecting.from.number[0]) {
-+ enc_ie_redir_nr(&setup->REDIR_NR, msg, bc->redirecting.from.number_type, bc->redirecting.from.number_plan,
-+ bc->redirecting.from.presentation, bc->redirecting.from.screening, bc->redirecting.reason,
-+ bc->redirecting.from.number, nt, bc);
- }
-
-- {
-- if (bc->rad[0])
-- enc_ie_redir_nr(&setup->REDIR_NR, msg, 1, 1, bc->pres, bc->screen, 0, bc->rad, nt,bc);
-+ if (bc->keypad[0]) {
-+ enc_ie_keypad(&setup->KEYPAD, msg, bc->keypad, nt,bc);
- }
-
-- {
-- if (bc->keypad[0])
-- enc_ie_keypad(&setup->KEYPAD, msg, bc->keypad, nt,bc);
-- }
--
--
-+
-+
- if (*bc->display) {
-- enc_ie_display(&setup->DISPLAY, msg, bc->display, nt,bc);
-+ enc_ie_display(&setup->DISPLAY, msg, bc->display, nt, bc);
-+ } else if (nt && bc->caller.presentation == 0) {
-+ char display[sizeof(bc->display)];
-+
-+ /* Presentation is allowed */
-+ build_display_str(display, sizeof(display), bc->display_setup, bc->caller.name, bc->caller.number);
-+ if (display[0]) {
-+ enc_ie_display(&setup->DISPLAY, msg, display, nt, bc);
-+ }
- }
--
-+
- {
-- int coding=0, capability, mode=0 /* 2 for packet ! */
-- ,user, rate=0x10;
-+ int coding = 0;
-+ int capability;
-+ int mode = 0; /* 2 for packet! */
-+ int user;
-+ int rate = 0x10;
-
- switch (bc->law) {
- case INFO_CODEC_ULAW: user=2;
-@@ -324,7 +380,7 @@
- default:
- user=3;
- }
--
-+
- switch (bc->capability) {
- case INFO_CAPABILITY_SPEECH: capability = 0;
- break;
-@@ -337,81 +393,108 @@
- user=-1;
- break;
- default:
-- capability=bc->capability;
-+ capability=bc->capability;
- }
--
--
--
-+
- enc_ie_bearer(&setup->BEARER, msg, coding, capability, mode, rate, -1, user, nt,bc);
- }
-
- if (bc->sending_complete) {
- enc_ie_complete(&setup->COMPLETE,msg, bc->sending_complete, nt, bc);
- }
--
-+
- if (bc->uulen) {
- int protocol=4;
- enc_ie_useruser(&setup->USER_USER, msg, protocol, bc->uu, bc->uulen, nt,bc);
- cb_log(1,bc->port,"ENCODING USERUESRINFO:%s\n",bc->uu);
- }
-
--#ifdef DEBUG
-- printf("Building SETUP Msg\n");
-+#ifdef DEBUG
-+ printf("Building SETUP Msg\n");
- #endif
-- return msg;
-+ return msg;
- }
-
--static void parse_connect (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
-+static void parse_connect (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- CONNECT_t *connect=(CONNECT_t*)((unsigned long)(msg->data+HEADER_LEN));
--
-- int plan,pres,screen;
--
-+ int type;
-+ int plan;
-+ int pres;
-+ int screen;
-+
- bc->ces = connect->ces;
-- bc->ces = connect->ces;
-
- dec_ie_progress(connect->PROGRESS, (Q931_info_t *)connect, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
-
-- dec_ie_connected_pn(connect->CONNECT_PN,(Q931_info_t *)connect, &bc->cpnnumplan, &plan, &pres, &screen, bc->cad, 31, nt, bc);
-+ dec_ie_connected_pn(connect->CONNECT_PN, (Q931_info_t *) connect, &type, &plan,
-+ &pres, &screen, bc->connected.number, sizeof(bc->connected.number) - 1, nt, bc);
-+ bc->connected.number_type = type;
-+ bc->connected.number_plan = plan;
-+ switch (pres) {
-+ default:
-+ case 0:
-+ bc->connected.presentation = 0; /* presentation allowed */
-+ break;
-+ case 1:
-+ bc->connected.presentation = 1; /* presentation restricted */
-+ break;
-+ case 2:
-+ bc->connected.presentation = 2; /* Number not available */
-+ break;
-+ }
-+ if (0 <= screen) {
-+ bc->connected.screening = screen;
-+ } else {
-+ bc->connected.screening = 0; /* Unscreened */
-+ }
-
- /*
- cb_log(1,bc->port,"CONNETED PN: %s cpn_dialplan:%d\n", connected_pn, type);
- */
--
--#ifdef DEBUG
-- printf("Parsing CONNECT Msg\n");
-+
-+#ifdef DEBUG
-+ printf("Parsing CONNECT Msg\n");
- #endif
- }
-
--static msg_t *build_connect (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
-+static msg_t *build_connect (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- CONNECT_t *connect;
-- msg_t *msg =(msg_t*)create_l3msg(CC_CONNECT | REQUEST, MT_CONNECT, bc?bc->l3_id:-1, sizeof(CONNECT_t) ,nt);
--
-+ msg_t *msg =(msg_t*)create_l3msg(CC_CONNECT | REQUEST, MT_CONNECT, bc?bc->l3_id:-1, sizeof(CONNECT_t) ,nt);
-+
- cb_log(6,bc->port,"BUILD_CONNECT: bc:%p bc->l3id:%d, nt:%d\n",bc,bc->l3_id,nt);
-
-- connect=(CONNECT_t*)((msg->data+HEADER_LEN));
-+ connect=(CONNECT_t*)((msg->data+HEADER_LEN));
-
- if (nt) {
- time_t now;
- time(&now);
- enc_ie_date(&connect->DATE, msg, now, nt,bc);
- }
--
-- {
-- int type=bc->cpnnumplan, plan=1, present=2, screen=0;
-- enc_ie_connected_pn(&connect->CONNECT_PN, msg, type,plan, present, screen, bc->cad, nt , bc);
-+
-+ enc_ie_connected_pn(&connect->CONNECT_PN, msg, bc->connected.number_type, bc->connected.number_plan,
-+ bc->connected.presentation, bc->connected.screening, bc->connected.number, nt, bc);
-+
-+ if (nt && bc->connected.presentation == 0) {
-+ char display[sizeof(bc->display)];
-+
-+ /* Presentation is allowed */
-+ build_display_str(display, sizeof(display), bc->display_connected, bc->connected.name, bc->connected.number);
-+ if (display[0]) {
-+ enc_ie_display(&connect->DISPLAY, msg, display, nt, bc);
-+ }
- }
-
--#ifdef DEBUG
-- printf("Building CONNECT Msg\n");
-+#ifdef DEBUG
-+ printf("Building CONNECT Msg\n");
- #endif
-- return msg;
-+ return msg;
- }
-
--static void parse_setup_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
-+static void parse_setup_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- SETUP_ACKNOWLEDGE_t *setup_acknowledge=(SETUP_ACKNOWLEDGE_t*)((unsigned long)(msg->data+HEADER_LEN));
-@@ -423,384 +506,384 @@
-
- set_channel(bc, channel);
- }
--
-+
- dec_ie_progress(setup_acknowledge->PROGRESS, (Q931_info_t *)setup_acknowledge, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
--#ifdef DEBUG
-- printf("Parsing SETUP_ACKNOWLEDGE Msg\n");
-+#ifdef DEBUG
-+ printf("Parsing SETUP_ACKNOWLEDGE Msg\n");
- #endif
-
--
-+
- }
-
--static msg_t *build_setup_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
-+static msg_t *build_setup_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- SETUP_ACKNOWLEDGE_t *setup_acknowledge;
-- msg_t *msg =(msg_t*)create_l3msg(CC_SETUP_ACKNOWLEDGE | REQUEST, MT_SETUP_ACKNOWLEDGE, bc?bc->l3_id:-1, sizeof(SETUP_ACKNOWLEDGE_t) ,nt);
--
-- setup_acknowledge=(SETUP_ACKNOWLEDGE_t*)((msg->data+HEADER_LEN));
--
-+ msg_t *msg =(msg_t*)create_l3msg(CC_SETUP_ACKNOWLEDGE | REQUEST, MT_SETUP_ACKNOWLEDGE, bc?bc->l3_id:-1, sizeof(SETUP_ACKNOWLEDGE_t) ,nt);
-+
-+ setup_acknowledge=(SETUP_ACKNOWLEDGE_t*)((msg->data+HEADER_LEN));
-+
- enc_ie_channel_id(&setup_acknowledge->CHANNEL_ID, msg, 1,bc->channel, nt,bc);
--
-- if (nt)
-+
-+ if (nt)
- enc_ie_progress(&setup_acknowledge->PROGRESS, msg, 0, nt?1:5, 8, nt,bc);
--
--#ifdef DEBUG
-- printf("Building SETUP_ACKNOWLEDGE Msg\n");
-+
-+#ifdef DEBUG
-+ printf("Building SETUP_ACKNOWLEDGE Msg\n");
- #endif
-- return msg;
-+ return msg;
- }
-
--static void parse_connect_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
-+static void parse_connect_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
- {
--#ifdef DEBUG
-- printf("Parsing CONNECT_ACKNOWLEDGE Msg\n");
-+#ifdef DEBUG
-+ printf("Parsing CONNECT_ACKNOWLEDGE Msg\n");
- #endif
-
--
-+
- }
-
--static msg_t *build_connect_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
-+static msg_t *build_connect_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- CONNECT_ACKNOWLEDGE_t *connect_acknowledge;
-- msg_t *msg =(msg_t*)create_l3msg(CC_CONNECT | RESPONSE, MT_CONNECT, bc?bc->l3_id:-1, sizeof(CONNECT_ACKNOWLEDGE_t) ,nt);
--
-- connect_acknowledge=(CONNECT_ACKNOWLEDGE_t*)((msg->data+HEADER_LEN));
--
-+ msg_t *msg =(msg_t*)create_l3msg(CC_CONNECT | RESPONSE, MT_CONNECT, bc?bc->l3_id:-1, sizeof(CONNECT_ACKNOWLEDGE_t) ,nt);
-+
-+ connect_acknowledge=(CONNECT_ACKNOWLEDGE_t*)((msg->data+HEADER_LEN));
-+
- enc_ie_channel_id(&connect_acknowledge->CHANNEL_ID, msg, 1, bc->channel, nt,bc);
--
--#ifdef DEBUG
-- printf("Building CONNECT_ACKNOWLEDGE Msg\n");
-+
-+#ifdef DEBUG
-+ printf("Building CONNECT_ACKNOWLEDGE Msg\n");
- #endif
-- return msg;
-+ return msg;
- }
-
--static void parse_user_information (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
-+static void parse_user_information (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
- {
--#ifdef DEBUG
-- printf("Parsing USER_INFORMATION Msg\n");
-+#ifdef DEBUG
-+ printf("Parsing USER_INFORMATION Msg\n");
- #endif
-
--
-+
- }
-
--static msg_t *build_user_information (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
-+static msg_t *build_user_information (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- USER_INFORMATION_t *user_information;
-- msg_t *msg =(msg_t*)create_l3msg(CC_USER_INFORMATION | REQUEST, MT_USER_INFORMATION, bc?bc->l3_id:-1, sizeof(USER_INFORMATION_t) ,nt);
--
-- user_information=(USER_INFORMATION_t*)((msg->data+HEADER_LEN));
-+ msg_t *msg =(msg_t*)create_l3msg(CC_USER_INFORMATION | REQUEST, MT_USER_INFORMATION, bc?bc->l3_id:-1, sizeof(USER_INFORMATION_t) ,nt);
-
--#ifdef DEBUG
-- printf("Building USER_INFORMATION Msg\n");
-+ user_information=(USER_INFORMATION_t*)((msg->data+HEADER_LEN));
-+
-+#ifdef DEBUG
-+ printf("Building USER_INFORMATION Msg\n");
- #endif
-- return msg;
-+ return msg;
- }
-
--static void parse_suspend_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
-+static void parse_suspend_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
- {
--#ifdef DEBUG
-- printf("Parsing SUSPEND_REJECT Msg\n");
-+#ifdef DEBUG
-+ printf("Parsing SUSPEND_REJECT Msg\n");
- #endif
-
--
-+
- }
-
--static msg_t *build_suspend_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
-+static msg_t *build_suspend_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- SUSPEND_REJECT_t *suspend_reject;
-- msg_t *msg =(msg_t*)create_l3msg(CC_SUSPEND_REJECT | REQUEST, MT_SUSPEND_REJECT, bc?bc->l3_id:-1, sizeof(SUSPEND_REJECT_t) ,nt);
--
-- suspend_reject=(SUSPEND_REJECT_t*)((msg->data+HEADER_LEN));
-+ msg_t *msg =(msg_t*)create_l3msg(CC_SUSPEND_REJECT | REQUEST, MT_SUSPEND_REJECT, bc?bc->l3_id:-1, sizeof(SUSPEND_REJECT_t) ,nt);
-
--#ifdef DEBUG
-- printf("Building SUSPEND_REJECT Msg\n");
-+ suspend_reject=(SUSPEND_REJECT_t*)((msg->data+HEADER_LEN));
-+
-+#ifdef DEBUG
-+ printf("Building SUSPEND_REJECT Msg\n");
- #endif
-- return msg;
-+ return msg;
- }
-
--static void parse_resume_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
-+static void parse_resume_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
- {
--#ifdef DEBUG
-- printf("Parsing RESUME_REJECT Msg\n");
-+#ifdef DEBUG
-+ printf("Parsing RESUME_REJECT Msg\n");
- #endif
-
--
-+
- }
-
--static msg_t *build_resume_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
-+static msg_t *build_resume_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- RESUME_REJECT_t *resume_reject;
-- msg_t *msg =(msg_t*)create_l3msg(CC_RESUME_REJECT | REQUEST, MT_RESUME_REJECT, bc?bc->l3_id:-1, sizeof(RESUME_REJECT_t) ,nt);
--
-- resume_reject=(RESUME_REJECT_t*)((msg->data+HEADER_LEN));
-+ msg_t *msg =(msg_t*)create_l3msg(CC_RESUME_REJECT | REQUEST, MT_RESUME_REJECT, bc?bc->l3_id:-1, sizeof(RESUME_REJECT_t) ,nt);
-
--#ifdef DEBUG
-- printf("Building RESUME_REJECT Msg\n");
-+ resume_reject=(RESUME_REJECT_t*)((msg->data+HEADER_LEN));
-+
-+#ifdef DEBUG
-+ printf("Building RESUME_REJECT Msg\n");
- #endif
-- return msg;
-+ return msg;
- }
-
--static void parse_hold (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
-+static void parse_hold (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
- {
--#ifdef DEBUG
-- printf("Parsing HOLD Msg\n");
-+#ifdef DEBUG
-+ printf("Parsing HOLD Msg\n");
- #endif
-
--
-+
- }
-
--static msg_t *build_hold (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
-+static msg_t *build_hold (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- HOLD_t *hold;
-- msg_t *msg =(msg_t*)create_l3msg(CC_HOLD | REQUEST, MT_HOLD, bc?bc->l3_id:-1, sizeof(HOLD_t) ,nt);
--
-- hold=(HOLD_t*)((msg->data+HEADER_LEN));
-+ msg_t *msg =(msg_t*)create_l3msg(CC_HOLD | REQUEST, MT_HOLD, bc?bc->l3_id:-1, sizeof(HOLD_t) ,nt);
-
--#ifdef DEBUG
-- printf("Building HOLD Msg\n");
-+ hold=(HOLD_t*)((msg->data+HEADER_LEN));
-+
-+#ifdef DEBUG
-+ printf("Building HOLD Msg\n");
- #endif
-- return msg;
-+ return msg;
- }
-
--static void parse_suspend (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
-+static void parse_suspend (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
- {
--#ifdef DEBUG
-- printf("Parsing SUSPEND Msg\n");
-+#ifdef DEBUG
-+ printf("Parsing SUSPEND Msg\n");
- #endif
-
--
-+
- }
-
--static msg_t *build_suspend (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
-+static msg_t *build_suspend (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- SUSPEND_t *suspend;
-- msg_t *msg =(msg_t*)create_l3msg(CC_SUSPEND | REQUEST, MT_SUSPEND, bc?bc->l3_id:-1, sizeof(SUSPEND_t) ,nt);
--
-- suspend=(SUSPEND_t*)((msg->data+HEADER_LEN));
-+ msg_t *msg =(msg_t*)create_l3msg(CC_SUSPEND | REQUEST, MT_SUSPEND, bc?bc->l3_id:-1, sizeof(SUSPEND_t) ,nt);
-
--#ifdef DEBUG
-- printf("Building SUSPEND Msg\n");
-+ suspend=(SUSPEND_t*)((msg->data+HEADER_LEN));
-+
-+#ifdef DEBUG
-+ printf("Building SUSPEND Msg\n");
- #endif
-- return msg;
-+ return msg;
- }
-
--static void parse_resume (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
-+static void parse_resume (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
- {
--#ifdef DEBUG
-- printf("Parsing RESUME Msg\n");
-+#ifdef DEBUG
-+ printf("Parsing RESUME Msg\n");
- #endif
-
--
-+
- }
-
--static msg_t *build_resume (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
-+static msg_t *build_resume (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- RESUME_t *resume;
-- msg_t *msg =(msg_t*)create_l3msg(CC_RESUME | REQUEST, MT_RESUME, bc?bc->l3_id:-1, sizeof(RESUME_t) ,nt);
--
-- resume=(RESUME_t*)((msg->data+HEADER_LEN));
-+ msg_t *msg =(msg_t*)create_l3msg(CC_RESUME | REQUEST, MT_RESUME, bc?bc->l3_id:-1, sizeof(RESUME_t) ,nt);
-
--#ifdef DEBUG
-- printf("Building RESUME Msg\n");
-+ resume=(RESUME_t*)((msg->data+HEADER_LEN));
-+
-+#ifdef DEBUG
-+ printf("Building RESUME Msg\n");
- #endif
-- return msg;
-+ return msg;
- }
-
--static void parse_hold_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
-+static void parse_hold_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
- {
--#ifdef DEBUG
-- printf("Parsing HOLD_ACKNOWLEDGE Msg\n");
-+#ifdef DEBUG
-+ printf("Parsing HOLD_ACKNOWLEDGE Msg\n");
- #endif
-
--
-+
- }
-
--static msg_t *build_hold_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
-+static msg_t *build_hold_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- HOLD_ACKNOWLEDGE_t *hold_acknowledge;
-- msg_t *msg =(msg_t*)create_l3msg(CC_HOLD_ACKNOWLEDGE | REQUEST, MT_HOLD_ACKNOWLEDGE, bc?bc->l3_id:-1, sizeof(HOLD_ACKNOWLEDGE_t) ,nt);
--
-- hold_acknowledge=(HOLD_ACKNOWLEDGE_t*)((msg->data+HEADER_LEN));
-+ msg_t *msg =(msg_t*)create_l3msg(CC_HOLD_ACKNOWLEDGE | REQUEST, MT_HOLD_ACKNOWLEDGE, bc?bc->l3_id:-1, sizeof(HOLD_ACKNOWLEDGE_t) ,nt);
-
--#ifdef DEBUG
-- printf("Building HOLD_ACKNOWLEDGE Msg\n");
-+ hold_acknowledge=(HOLD_ACKNOWLEDGE_t*)((msg->data+HEADER_LEN));
-+
-+#ifdef DEBUG
-+ printf("Building HOLD_ACKNOWLEDGE Msg\n");
- #endif
-- return msg;
-+ return msg;
- }
-
--static void parse_suspend_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
-+static void parse_suspend_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
- {
--#ifdef DEBUG
-- printf("Parsing SUSPEND_ACKNOWLEDGE Msg\n");
-+#ifdef DEBUG
-+ printf("Parsing SUSPEND_ACKNOWLEDGE Msg\n");
- #endif
-
--
-+
- }
-
--static msg_t *build_suspend_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
-+static msg_t *build_suspend_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- SUSPEND_ACKNOWLEDGE_t *suspend_acknowledge;
-- msg_t *msg =(msg_t*)create_l3msg(CC_SUSPEND_ACKNOWLEDGE | REQUEST, MT_SUSPEND_ACKNOWLEDGE, bc?bc->l3_id:-1, sizeof(SUSPEND_ACKNOWLEDGE_t) ,nt);
--
-- suspend_acknowledge=(SUSPEND_ACKNOWLEDGE_t*)((msg->data+HEADER_LEN));
-+ msg_t *msg =(msg_t*)create_l3msg(CC_SUSPEND_ACKNOWLEDGE | REQUEST, MT_SUSPEND_ACKNOWLEDGE, bc?bc->l3_id:-1, sizeof(SUSPEND_ACKNOWLEDGE_t) ,nt);
-
--#ifdef DEBUG
-- printf("Building SUSPEND_ACKNOWLEDGE Msg\n");
-+ suspend_acknowledge=(SUSPEND_ACKNOWLEDGE_t*)((msg->data+HEADER_LEN));
-+
-+#ifdef DEBUG
-+ printf("Building SUSPEND_ACKNOWLEDGE Msg\n");
- #endif
-- return msg;
-+ return msg;
- }
-
--static void parse_resume_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
-+static void parse_resume_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
- {
--#ifdef DEBUG
-- printf("Parsing RESUME_ACKNOWLEDGE Msg\n");
-+#ifdef DEBUG
-+ printf("Parsing RESUME_ACKNOWLEDGE Msg\n");
- #endif
-
--
-+
- }
-
--static msg_t *build_resume_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
-+static msg_t *build_resume_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- RESUME_ACKNOWLEDGE_t *resume_acknowledge;
-- msg_t *msg =(msg_t*)create_l3msg(CC_RESUME_ACKNOWLEDGE | REQUEST, MT_RESUME_ACKNOWLEDGE, bc?bc->l3_id:-1, sizeof(RESUME_ACKNOWLEDGE_t) ,nt);
--
-- resume_acknowledge=(RESUME_ACKNOWLEDGE_t*)((msg->data+HEADER_LEN));
-+ msg_t *msg =(msg_t*)create_l3msg(CC_RESUME_ACKNOWLEDGE | REQUEST, MT_RESUME_ACKNOWLEDGE, bc?bc->l3_id:-1, sizeof(RESUME_ACKNOWLEDGE_t) ,nt);
-
--#ifdef DEBUG
-- printf("Building RESUME_ACKNOWLEDGE Msg\n");
-+ resume_acknowledge=(RESUME_ACKNOWLEDGE_t*)((msg->data+HEADER_LEN));
-+
-+#ifdef DEBUG
-+ printf("Building RESUME_ACKNOWLEDGE Msg\n");
- #endif
-- return msg;
-+ return msg;
- }
-
--static void parse_hold_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
-+static void parse_hold_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
- {
--#ifdef DEBUG
-- printf("Parsing HOLD_REJECT Msg\n");
-+#ifdef DEBUG
-+ printf("Parsing HOLD_REJECT Msg\n");
- #endif
-
--
-+
- }
-
--static msg_t *build_hold_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
-+static msg_t *build_hold_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- HOLD_REJECT_t *hold_reject;
-- msg_t *msg =(msg_t*)create_l3msg(CC_HOLD_REJECT | REQUEST, MT_HOLD_REJECT, bc?bc->l3_id:-1, sizeof(HOLD_REJECT_t) ,nt);
--
-- hold_reject=(HOLD_REJECT_t*)((msg->data+HEADER_LEN));
-+ msg_t *msg =(msg_t*)create_l3msg(CC_HOLD_REJECT | REQUEST, MT_HOLD_REJECT, bc?bc->l3_id:-1, sizeof(HOLD_REJECT_t) ,nt);
-
--#ifdef DEBUG
-- printf("Building HOLD_REJECT Msg\n");
-+ hold_reject=(HOLD_REJECT_t*)((msg->data+HEADER_LEN));
-+
-+#ifdef DEBUG
-+ printf("Building HOLD_REJECT Msg\n");
- #endif
-- return msg;
-+ return msg;
- }
-
--static void parse_retrieve (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
-+static void parse_retrieve (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
- {
--#ifdef DEBUG
-- printf("Parsing RETRIEVE Msg\n");
-+#ifdef DEBUG
-+ printf("Parsing RETRIEVE Msg\n");
- #endif
-
--
-+
- }
-
--static msg_t *build_retrieve (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
-+static msg_t *build_retrieve (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- RETRIEVE_t *retrieve;
-- msg_t *msg =(msg_t*)create_l3msg(CC_RETRIEVE | REQUEST, MT_RETRIEVE, bc?bc->l3_id:-1, sizeof(RETRIEVE_t) ,nt);
--
-- retrieve=(RETRIEVE_t*)((msg->data+HEADER_LEN));
-+ msg_t *msg =(msg_t*)create_l3msg(CC_RETRIEVE | REQUEST, MT_RETRIEVE, bc?bc->l3_id:-1, sizeof(RETRIEVE_t) ,nt);
-
--#ifdef DEBUG
-- printf("Building RETRIEVE Msg\n");
-+ retrieve=(RETRIEVE_t*)((msg->data+HEADER_LEN));
-+
-+#ifdef DEBUG
-+ printf("Building RETRIEVE Msg\n");
- #endif
-- return msg;
-+ return msg;
- }
-
--static void parse_retrieve_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
-+static void parse_retrieve_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
- {
--#ifdef DEBUG
-- printf("Parsing RETRIEVE_ACKNOWLEDGE Msg\n");
-+#ifdef DEBUG
-+ printf("Parsing RETRIEVE_ACKNOWLEDGE Msg\n");
- #endif
-
--
-+
- }
-
--static msg_t *build_retrieve_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
-+static msg_t *build_retrieve_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- RETRIEVE_ACKNOWLEDGE_t *retrieve_acknowledge;
-- msg_t *msg =(msg_t*)create_l3msg(CC_RETRIEVE_ACKNOWLEDGE | REQUEST, MT_RETRIEVE_ACKNOWLEDGE, bc?bc->l3_id:-1, sizeof(RETRIEVE_ACKNOWLEDGE_t) ,nt);
--
-- retrieve_acknowledge=(RETRIEVE_ACKNOWLEDGE_t*)((msg->data+HEADER_LEN));
-+ msg_t *msg =(msg_t*)create_l3msg(CC_RETRIEVE_ACKNOWLEDGE | REQUEST, MT_RETRIEVE_ACKNOWLEDGE, bc?bc->l3_id:-1, sizeof(RETRIEVE_ACKNOWLEDGE_t) ,nt);
-
-+ retrieve_acknowledge=(RETRIEVE_ACKNOWLEDGE_t*)((msg->data+HEADER_LEN));
-+
- enc_ie_channel_id(&retrieve_acknowledge->CHANNEL_ID, msg, 1, bc->channel, nt,bc);
--#ifdef DEBUG
-- printf("Building RETRIEVE_ACKNOWLEDGE Msg\n");
-+#ifdef DEBUG
-+ printf("Building RETRIEVE_ACKNOWLEDGE Msg\n");
- #endif
-- return msg;
-+ return msg;
- }
-
--static void parse_retrieve_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
-+static void parse_retrieve_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
- {
--#ifdef DEBUG
-- printf("Parsing RETRIEVE_REJECT Msg\n");
-+#ifdef DEBUG
-+ printf("Parsing RETRIEVE_REJECT Msg\n");
- #endif
-
--
-+
- }
-
--static msg_t *build_retrieve_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
-+static msg_t *build_retrieve_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- RETRIEVE_REJECT_t *retrieve_reject;
-- msg_t *msg =(msg_t*)create_l3msg(CC_RETRIEVE_REJECT | REQUEST, MT_RETRIEVE_REJECT, bc?bc->l3_id:-1, sizeof(RETRIEVE_REJECT_t) ,nt);
--
-- retrieve_reject=(RETRIEVE_REJECT_t*)((msg->data+HEADER_LEN));
-+ msg_t *msg =(msg_t*)create_l3msg(CC_RETRIEVE_REJECT | REQUEST, MT_RETRIEVE_REJECT, bc?bc->l3_id:-1, sizeof(RETRIEVE_REJECT_t) ,nt);
-
--#ifdef DEBUG
-- printf("Building RETRIEVE_REJECT Msg\n");
-+ retrieve_reject=(RETRIEVE_REJECT_t*)((msg->data+HEADER_LEN));
-+
-+#ifdef DEBUG
-+ printf("Building RETRIEVE_REJECT Msg\n");
- #endif
-- return msg;
-+ return msg;
- }
-
--static void parse_disconnect (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
-+static void parse_disconnect (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- DISCONNECT_t *disconnect=(DISCONNECT_t*)((unsigned long)(msg->data+HEADER_LEN));
- int location;
-- int cause;
-+ int cause;
- dec_ie_cause(disconnect->CAUSE, (Q931_info_t *)(disconnect), &location, &cause, nt,bc);
- if (cause>0) bc->cause=cause;
-
- dec_ie_progress(disconnect->PROGRESS, (Q931_info_t *)disconnect, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
--#ifdef DEBUG
-- printf("Parsing DISCONNECT Msg\n");
-+#ifdef DEBUG
-+ printf("Parsing DISCONNECT Msg\n");
- #endif
-
--
-+
- }
-
--static msg_t *build_disconnect (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
-+static msg_t *build_disconnect (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- DISCONNECT_t *disconnect;
-- msg_t *msg =(msg_t*)create_l3msg(CC_DISCONNECT | REQUEST, MT_DISCONNECT, bc?bc->l3_id:-1, sizeof(DISCONNECT_t) ,nt);
--
-- disconnect=(DISCONNECT_t*)((msg->data+HEADER_LEN));
--
-+ msg_t *msg =(msg_t*)create_l3msg(CC_DISCONNECT | REQUEST, MT_DISCONNECT, bc?bc->l3_id:-1, sizeof(DISCONNECT_t) ,nt);
-+
-+ disconnect=(DISCONNECT_t*)((msg->data+HEADER_LEN));
-+
- enc_ie_cause(&disconnect->CAUSE, msg, (nt)?1:0, bc->out_cause,nt,bc);
- if (nt) enc_ie_progress(&disconnect->PROGRESS, msg, 0, nt?1:5, 8 ,nt,bc);
-
-@@ -809,42 +892,42 @@
- enc_ie_useruser(&disconnect->USER_USER, msg, protocol, bc->uu, bc->uulen, nt,bc);
- cb_log(1,bc->port,"ENCODING USERUESRINFO:%s\n",bc->uu);
- }
--
--#ifdef DEBUG
-- printf("Building DISCONNECT Msg\n");
-+
-+#ifdef DEBUG
-+ printf("Building DISCONNECT Msg\n");
- #endif
-- return msg;
-+ return msg;
- }
-
--static void parse_restart (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
-+static void parse_restart (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- RESTART_t *restart=(RESTART_t*)((unsigned long)(msg->data+HEADER_LEN));
-
- struct misdn_stack *stack=get_stack_by_bc(bc);
--
--#ifdef DEBUG
-+
-+#ifdef DEBUG
- printf("Parsing RESTART Msg\n");
- #endif
--
-+
- {
- int exclusive;
- dec_ie_channel_id(restart->CHANNEL_ID, (Q931_info_t *)restart, &exclusive, &bc->restart_channel, nt,bc);
- cb_log(3, stack->port, "CC_RESTART Request on channel:%d on this port.\n", bc->restart_channel);
- }
--
-+
- }
-
--static msg_t *build_restart (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
-+static msg_t *build_restart (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- RESTART_t *restart;
-- msg_t *msg =(msg_t*)create_l3msg(CC_RESTART | REQUEST, MT_RESTART, bc?bc->l3_id:-1, sizeof(RESTART_t) ,nt);
--
-- restart=(RESTART_t*)((msg->data+HEADER_LEN));
-+ msg_t *msg =(msg_t*)create_l3msg(CC_RESTART | REQUEST, MT_RESTART, bc?bc->l3_id:-1, sizeof(RESTART_t) ,nt);
-
--#ifdef DEBUG
-- printf("Building RESTART Msg\n");
-+ restart=(RESTART_t*)((msg->data+HEADER_LEN));
-+
-+#ifdef DEBUG
-+ printf("Building RESTART Msg\n");
- #endif
-
- if (bc->channel > 0) {
-@@ -855,33 +938,33 @@
- }
-
- cb_log(0,bc->port, "Restarting channel %d\n", bc->channel);
-- return msg;
-+ return msg;
- }
-
--static void parse_release (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
-+static void parse_release (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- RELEASE_t *release=(RELEASE_t*)((unsigned long)(msg->data+HEADER_LEN));
- int location;
- int cause;
--
-+
- dec_ie_cause(release->CAUSE, (Q931_info_t *)(release), &location, &cause, nt,bc);
- if (cause>0) bc->cause=cause;
--#ifdef DEBUG
-- printf("Parsing RELEASE Msg\n");
-+#ifdef DEBUG
-+ printf("Parsing RELEASE Msg\n");
- #endif
-
--
-+
- }
-
--static msg_t *build_release (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
-+static msg_t *build_release (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- RELEASE_t *release;
-- msg_t *msg =(msg_t*)create_l3msg(CC_RELEASE | REQUEST, MT_RELEASE, bc?bc->l3_id:-1, sizeof(RELEASE_t) ,nt);
--
-- release=(RELEASE_t*)((msg->data+HEADER_LEN));
--
-+ msg_t *msg =(msg_t*)create_l3msg(CC_RELEASE | REQUEST, MT_RELEASE, bc?bc->l3_id:-1, sizeof(RELEASE_t) ,nt);
-+
-+ release=(RELEASE_t*)((msg->data+HEADER_LEN));
-+
- if (bc->out_cause>= 0)
- enc_ie_cause(&release->CAUSE, msg, nt?1:0, bc->out_cause, nt,bc);
-
-@@ -890,14 +973,14 @@
- enc_ie_useruser(&release->USER_USER, msg, protocol, bc->uu, bc->uulen, nt,bc);
- cb_log(1,bc->port,"ENCODING USERUESRINFO:%s\n",bc->uu);
- }
--
--#ifdef DEBUG
-- printf("Building RELEASE Msg\n");
-+
-+#ifdef DEBUG
-+ printf("Building RELEASE Msg\n");
- #endif
-- return msg;
-+ return msg;
- }
-
--static void parse_release_complete (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
-+static void parse_release_complete (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- RELEASE_COMPLETE_t *release_complete=(RELEASE_COMPLETE_t*)((unsigned long)(msg->data+HEADER_LEN));
-@@ -926,19 +1009,19 @@
- dec_ie_cause(release_complete->CAUSE, (Q931_info_t *)(release_complete), &location, &cause, nt,bc);
- if (cause>0) bc->cause=cause;
-
--#ifdef DEBUG
-- printf("Parsing RELEASE_COMPLETE Msg\n");
-+#ifdef DEBUG
-+ printf("Parsing RELEASE_COMPLETE Msg\n");
- #endif
- }
-
--static msg_t *build_release_complete (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
-+static msg_t *build_release_complete (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- RELEASE_COMPLETE_t *release_complete;
-- msg_t *msg =(msg_t*)create_l3msg(CC_RELEASE_COMPLETE | REQUEST, MT_RELEASE_COMPLETE, bc?bc->l3_id:-1, sizeof(RELEASE_COMPLETE_t) ,nt);
--
-- release_complete=(RELEASE_COMPLETE_t*)((msg->data+HEADER_LEN));
--
-+ msg_t *msg =(msg_t*)create_l3msg(CC_RELEASE_COMPLETE | REQUEST, MT_RELEASE_COMPLETE, bc?bc->l3_id:-1, sizeof(RELEASE_COMPLETE_t) ,nt);
-+
-+ release_complete=(RELEASE_COMPLETE_t*)((msg->data+HEADER_LEN));
-+
- enc_ie_cause(&release_complete->CAUSE, msg, nt?1:0, bc->out_cause, nt,bc);
-
- if (bc->uulen) {
-@@ -946,23 +1029,23 @@
- enc_ie_useruser(&release_complete->USER_USER, msg, protocol, bc->uu, bc->uulen, nt,bc);
- cb_log(1,bc->port,"ENCODING USERUESRINFO:%s\n",bc->uu);
- }
--
--#ifdef DEBUG
-- printf("Building RELEASE_COMPLETE Msg\n");
-+
-+#ifdef DEBUG
-+ printf("Building RELEASE_COMPLETE Msg\n");
- #endif
-- return msg;
-+ return msg;
- }
-
--static void parse_facility (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
-+static void parse_facility (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt ? mISDNUSER_HEAD_SIZE : mISDN_HEADER_LEN;
-- FACILITY_t *facility = (FACILITY_t*)(msg->data+HEADER_LEN);
-- Q931_info_t *qi = (Q931_info_t*)(msg->data+HEADER_LEN);
-+ FACILITY_t *facility = (FACILITY_t*)(msg->data+HEADER_LEN);
-+ Q931_info_t *qi = (Q931_info_t*)(msg->data+HEADER_LEN);
- unsigned char *p = NULL;
- int err;
-
--#ifdef DEBUG
-- printf("Parsing FACILITY Msg\n");
-+#ifdef DEBUG
-+ printf("Parsing FACILITY Msg\n");
- #endif
-
- if (!bc->nt) {
-@@ -973,31 +1056,37 @@
- }
- if (!p)
- return;
--
-+
- err = decodeFac(p, &(bc->fac_in));
- if (err) {
- cb_log(5, bc->port, "Decoding FACILITY failed! (%d)\n", err);
- }
- }
-
--static msg_t *build_facility (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
-+static msg_t *build_facility (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
- {
-- int len,
-- HEADER_LEN = nt ? mISDNUSER_HEAD_SIZE : mISDN_HEADER_LEN;
-- unsigned char *ie_fac,
-- fac_tmp[256];
-- msg_t *msg =(msg_t*)create_l3msg(CC_FACILITY | REQUEST, MT_FACILITY, bc?bc->l3_id:-1, sizeof(FACILITY_t) ,nt);
-- FACILITY_t *facility = (FACILITY_t*)(msg->data+HEADER_LEN);
-+ int len;
-+ int HEADER_LEN;
-+ unsigned char *ie_fac;
-+ unsigned char fac_tmp[256];
-+ msg_t *msg;
-+ FACILITY_t *facility;
- Q931_info_t *qi;
-
--#ifdef DEBUG
-- printf("Building FACILITY Msg\n");
-+#ifdef DEBUG
-+ printf("Building FACILITY Msg\n");
- #endif
--
-+
- len = encodeFac(fac_tmp, &(bc->fac_out));
-- if (len <= 0)
-+ if (len <= 0) {
-+ /* mISDN does not know how to build the requested facility structure */
- return NULL;
-+ }
-
-+ msg = (msg_t *) create_l3msg(CC_FACILITY | REQUEST, MT_FACILITY, bc ? bc->l3_id : -1, sizeof(FACILITY_t), nt);
-+ HEADER_LEN = nt ? mISDNUSER_HEAD_SIZE : mISDN_HEADER_LEN;
-+ facility = (FACILITY_t *) (msg->data + HEADER_LEN);
-+
- ie_fac = msg_put(msg, len);
- if (bc->nt) {
- facility->FACILITY = ie_fac + 1;
-@@ -1009,147 +1098,144 @@
- memcpy(ie_fac, fac_tmp, len);
-
- if (*bc->display) {
-+#ifdef DEBUG
- printf("Sending %s as Display\n", bc->display);
-+#endif
- enc_ie_display(&facility->DISPLAY, msg, bc->display, nt,bc);
- }
-
-- return msg;
-+ return msg;
- }
-
--static void parse_notify (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
-+static void parse_notify (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
- {
--#ifdef DEBUG
-- printf("Parsing NOTIFY Msg\n");
-+#ifdef DEBUG
-+ printf("Parsing NOTIFY Msg\n");
- #endif
- }
-
--static msg_t *build_notify (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
-+static msg_t *build_notify (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- NOTIFY_t *notify;
-- msg_t *msg =(msg_t*)create_l3msg(CC_NOTIFY | REQUEST, MT_NOTIFY, bc?bc->l3_id:-1, sizeof(NOTIFY_t) ,nt);
--
-- notify=(NOTIFY_t*)((msg->data+HEADER_LEN));
-+ msg_t *msg =(msg_t*)create_l3msg(CC_NOTIFY | REQUEST, MT_NOTIFY, bc?bc->l3_id:-1, sizeof(NOTIFY_t) ,nt);
-
--#ifdef DEBUG
-- printf("Building NOTIFY Msg\n");
-+ notify=(NOTIFY_t*)((msg->data+HEADER_LEN));
-+
-+#ifdef DEBUG
-+ printf("Building NOTIFY Msg\n");
- #endif
-- return msg;
-+ return msg;
- }
-
--static void parse_status_enquiry (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
-+static void parse_status_enquiry (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
- {
--#ifdef DEBUG
-- printf("Parsing STATUS_ENQUIRY Msg\n");
-+#ifdef DEBUG
-+ printf("Parsing STATUS_ENQUIRY Msg\n");
- #endif
- }
-
--static msg_t *build_status_enquiry (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
-+static msg_t *build_status_enquiry (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- STATUS_ENQUIRY_t *status_enquiry;
-- msg_t *msg =(msg_t*)create_l3msg(CC_STATUS_ENQUIRY | REQUEST, MT_STATUS_ENQUIRY, bc?bc->l3_id:-1, sizeof(STATUS_ENQUIRY_t) ,nt);
--
-- status_enquiry=(STATUS_ENQUIRY_t*)((msg->data+HEADER_LEN));
-+ msg_t *msg =(msg_t*)create_l3msg(CC_STATUS_ENQUIRY | REQUEST, MT_STATUS_ENQUIRY, bc?bc->l3_id:-1, sizeof(STATUS_ENQUIRY_t) ,nt);
-
--#ifdef DEBUG
-- printf("Building STATUS_ENQUIRY Msg\n");
-+ status_enquiry=(STATUS_ENQUIRY_t*)((msg->data+HEADER_LEN));
-+
-+#ifdef DEBUG
-+ printf("Building STATUS_ENQUIRY Msg\n");
- #endif
-- return msg;
-+ return msg;
- }
-
--static void parse_information (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
-+static void parse_information (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- INFORMATION_t *information=(INFORMATION_t*)((unsigned long)(msg->data+HEADER_LEN));
-- {
-- int type, plan;
-- char number[32];
-- char keypad[32];
-- dec_ie_called_pn(information->CALLED_PN, (Q931_info_t *)information, &type, &plan, number, sizeof(number)-1, nt, bc);
-- dec_ie_keypad(information->KEYPAD, (Q931_info_t *)information, keypad, sizeof(keypad)-1, nt, bc);
-- strcpy(bc->info_dad, number);
-- strcpy(bc->keypad,keypad);
-- }
--#ifdef DEBUG
-- printf("Parsing INFORMATION Msg\n");
-+ int type, plan;
-+
-+ dec_ie_called_pn(information->CALLED_PN, (Q931_info_t *) information, &type, &plan, bc->info_dad, sizeof(bc->info_dad) - 1, nt, bc);
-+ dec_ie_keypad(information->KEYPAD, (Q931_info_t *) information, bc->keypad, sizeof(bc->keypad) - 1, nt, bc);
-+
-+#ifdef DEBUG
-+ printf("Parsing INFORMATION Msg\n");
- #endif
- }
-
--static msg_t *build_information (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
-+static msg_t *build_information (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- INFORMATION_t *information;
-- msg_t *msg =(msg_t*)create_l3msg(CC_INFORMATION | REQUEST, MT_INFORMATION, bc?bc->l3_id:-1, sizeof(INFORMATION_t) ,nt);
--
-- information=(INFORMATION_t*)((msg->data+HEADER_LEN));
--
-- {
-- enc_ie_called_pn(&information->CALLED_PN, msg, 0, 1, bc->info_dad, nt,bc);
-- }
-+ msg_t *msg =(msg_t*)create_l3msg(CC_INFORMATION | REQUEST, MT_INFORMATION, bc?bc->l3_id:-1, sizeof(INFORMATION_t) ,nt);
-
-+ information=(INFORMATION_t*)((msg->data+HEADER_LEN));
-+
-+ enc_ie_called_pn(&information->CALLED_PN, msg, 0, 1, bc->info_dad, nt,bc);
-+
- {
- if (*bc->display) {
-+#ifdef DEBUG
- printf("Sending %s as Display\n", bc->display);
-+#endif
- enc_ie_display(&information->DISPLAY, msg, bc->display, nt,bc);
- }
- }
--
--#ifdef DEBUG
-- printf("Building INFORMATION Msg\n");
-+
-+#ifdef DEBUG
-+ printf("Building INFORMATION Msg\n");
- #endif
-- return msg;
-+ return msg;
- }
-
--static void parse_status (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
-+static void parse_status (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- STATUS_t *status=(STATUS_t*)((unsigned long)(msg->data+HEADER_LEN));
- int location;
- int cause;
--
-+
- dec_ie_cause(status->CAUSE, (Q931_info_t *)(status), &location, &cause, nt,bc);
- if (cause>0) bc->cause=cause;
-- ;
-
--#ifdef DEBUG
-- printf("Parsing STATUS Msg\n");
-+#ifdef DEBUG
-+ printf("Parsing STATUS Msg\n");
- #endif
- }
-
--static msg_t *build_status (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
-+static msg_t *build_status (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- STATUS_t *status;
-- msg_t *msg =(msg_t*)create_l3msg(CC_STATUS | REQUEST, MT_STATUS, bc?bc->l3_id:-1, sizeof(STATUS_t) ,nt);
--
-- status=(STATUS_t*)((msg->data+HEADER_LEN));
-+ msg_t *msg =(msg_t*)create_l3msg(CC_STATUS | REQUEST, MT_STATUS, bc?bc->l3_id:-1, sizeof(STATUS_t) ,nt);
-
--#ifdef DEBUG
-- printf("Building STATUS Msg\n");
-+ status=(STATUS_t*)((msg->data+HEADER_LEN));
-+
-+#ifdef DEBUG
-+ printf("Building STATUS Msg\n");
- #endif
-- return msg;
-+ return msg;
- }
-
--static void parse_timeout (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
-+static void parse_timeout (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
- {
--#ifdef DEBUG
-- printf("Parsing STATUS Msg\n");
--#endif
-+#ifdef DEBUG
-+ printf("Parsing STATUS Msg\n");
-+#endif
- }
-
--static msg_t *build_timeout (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
-+static msg_t *build_timeout (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
- {
- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
- STATUS_t *status;
-- msg_t *msg =(msg_t*)create_l3msg(CC_STATUS | REQUEST, MT_STATUS, bc?bc->l3_id:-1, sizeof(STATUS_t) ,nt);
--
-- status=(STATUS_t*)((msg->data+HEADER_LEN));
-+ msg_t *msg =(msg_t*)create_l3msg(CC_STATUS | REQUEST, MT_STATUS, bc?bc->l3_id:-1, sizeof(STATUS_t) ,nt);
-
--#ifdef DEBUG
-- printf("Building STATUS Msg\n");
-+ status=(STATUS_t*)((msg->data+HEADER_LEN));
-+
-+#ifdef DEBUG
-+ printf("Building STATUS Msg\n");
- #endif
-- return msg;
-+ return msg;
- }
-
-
-@@ -1161,97 +1247,40 @@
- /** Msg Array **/
-
- struct isdn_msg msgs_g[] = {
-- {CC_PROCEEDING,L3,EVENT_PROCEEDING,
-- parse_proceeding,build_proceeding,
-- "PROCEEDING"},
-- {CC_ALERTING,L3,EVENT_ALERTING,
-- parse_alerting,build_alerting,
-- "ALERTING"},
-- {CC_PROGRESS,L3,EVENT_PROGRESS,
-- parse_progress,build_progress,
-- "PROGRESS"},
-- {CC_SETUP,L3,EVENT_SETUP,
-- parse_setup,build_setup,
-- "SETUP"},
-- {CC_CONNECT,L3,EVENT_CONNECT,
-- parse_connect,build_connect,
-- "CONNECT"},
-- {CC_SETUP_ACKNOWLEDGE,L3,EVENT_SETUP_ACKNOWLEDGE,
-- parse_setup_acknowledge,build_setup_acknowledge,
-- "SETUP_ACKNOWLEDGE"},
-- {CC_CONNECT_ACKNOWLEDGE ,L3,EVENT_CONNECT_ACKNOWLEDGE ,
-- parse_connect_acknowledge ,build_connect_acknowledge,
-- "CONNECT_ACKNOWLEDGE "},
-- {CC_USER_INFORMATION,L3,EVENT_USER_INFORMATION,
-- parse_user_information,build_user_information,
-- "USER_INFORMATION"},
-- {CC_SUSPEND_REJECT,L3,EVENT_SUSPEND_REJECT,
-- parse_suspend_reject,build_suspend_reject,
-- "SUSPEND_REJECT"},
-- {CC_RESUME_REJECT,L3,EVENT_RESUME_REJECT,
-- parse_resume_reject,build_resume_reject,
-- "RESUME_REJECT"},
-- {CC_HOLD,L3,EVENT_HOLD,
-- parse_hold,build_hold,
-- "HOLD"},
-- {CC_SUSPEND,L3,EVENT_SUSPEND,
-- parse_suspend,build_suspend,
-- "SUSPEND"},
-- {CC_RESUME,L3,EVENT_RESUME,
-- parse_resume,build_resume,
-- "RESUME"},
-- {CC_HOLD_ACKNOWLEDGE,L3,EVENT_HOLD_ACKNOWLEDGE,
-- parse_hold_acknowledge,build_hold_acknowledge,
-- "HOLD_ACKNOWLEDGE"},
-- {CC_SUSPEND_ACKNOWLEDGE,L3,EVENT_SUSPEND_ACKNOWLEDGE,
-- parse_suspend_acknowledge,build_suspend_acknowledge,
-- "SUSPEND_ACKNOWLEDGE"},
-- {CC_RESUME_ACKNOWLEDGE,L3,EVENT_RESUME_ACKNOWLEDGE,
-- parse_resume_acknowledge,build_resume_acknowledge,
-- "RESUME_ACKNOWLEDGE"},
-- {CC_HOLD_REJECT,L3,EVENT_HOLD_REJECT,
-- parse_hold_reject,build_hold_reject,
-- "HOLD_REJECT"},
-- {CC_RETRIEVE,L3,EVENT_RETRIEVE,
-- parse_retrieve,build_retrieve,
-- "RETRIEVE"},
-- {CC_RETRIEVE_ACKNOWLEDGE,L3,EVENT_RETRIEVE_ACKNOWLEDGE,
-- parse_retrieve_acknowledge,build_retrieve_acknowledge,
-- "RETRIEVE_ACKNOWLEDGE"},
-- {CC_RETRIEVE_REJECT,L3,EVENT_RETRIEVE_REJECT,
-- parse_retrieve_reject,build_retrieve_reject,
-- "RETRIEVE_REJECT"},
-- {CC_DISCONNECT,L3,EVENT_DISCONNECT,
-- parse_disconnect,build_disconnect,
-- "DISCONNECT"},
-- {CC_RESTART,L3,EVENT_RESTART,
-- parse_restart,build_restart,
-- "RESTART"},
-- {CC_RELEASE,L3,EVENT_RELEASE,
-- parse_release,build_release,
-- "RELEASE"},
-- {CC_RELEASE_COMPLETE,L3,EVENT_RELEASE_COMPLETE,
-- parse_release_complete,build_release_complete,
-- "RELEASE_COMPLETE"},
-- {CC_FACILITY,L3,EVENT_FACILITY,
-- parse_facility,build_facility,
-- "FACILITY"},
-- {CC_NOTIFY,L3,EVENT_NOTIFY,
-- parse_notify,build_notify,
-- "NOTIFY"},
-- {CC_STATUS_ENQUIRY,L3,EVENT_STATUS_ENQUIRY,
-- parse_status_enquiry,build_status_enquiry,
-- "STATUS_ENQUIRY"},
-- {CC_INFORMATION,L3,EVENT_INFORMATION,
-- parse_information,build_information,
-- "INFORMATION"},
-- {CC_STATUS,L3,EVENT_STATUS,
-- parse_status,build_status,
-- "STATUS"},
-- {CC_TIMEOUT,L3,EVENT_TIMEOUT,
-- parse_timeout,build_timeout,
-- "TIMEOUT"},
-- {0,0,0,NULL,NULL,NULL}
-+/* *INDENT-OFF* */
-+ /* misdn_msg, event, msg_parser, msg_builder, info */
-+ { CC_PROCEEDING, EVENT_PROCEEDING, parse_proceeding, build_proceeding, "PROCEEDING" },
-+ { CC_ALERTING, EVENT_ALERTING, parse_alerting, build_alerting, "ALERTING" },
-+ { CC_PROGRESS, EVENT_PROGRESS, parse_progress, build_progress, "PROGRESS" },
-+ { CC_SETUP, EVENT_SETUP, parse_setup, build_setup, "SETUP" },
-+ { CC_CONNECT, EVENT_CONNECT, parse_connect, build_connect, "CONNECT" },
-+ { CC_SETUP_ACKNOWLEDGE, EVENT_SETUP_ACKNOWLEDGE, parse_setup_acknowledge, build_setup_acknowledge, "SETUP_ACKNOWLEDGE" },
-+ { CC_CONNECT_ACKNOWLEDGE, EVENT_CONNECT_ACKNOWLEDGE, parse_connect_acknowledge, build_connect_acknowledge, "CONNECT_ACKNOWLEDGE " },
-+ { CC_USER_INFORMATION, EVENT_USER_INFORMATION, parse_user_information, build_user_information, "USER_INFORMATION" },
-+ { CC_SUSPEND_REJECT, EVENT_SUSPEND_REJECT, parse_suspend_reject, build_suspend_reject, "SUSPEND_REJECT" },
-+ { CC_RESUME_REJECT, EVENT_RESUME_REJECT, parse_resume_reject, build_resume_reject, "RESUME_REJECT" },
-+ { CC_HOLD, EVENT_HOLD, parse_hold, build_hold, "HOLD" },
-+ { CC_SUSPEND, EVENT_SUSPEND, parse_suspend, build_suspend, "SUSPEND" },
-+ { CC_RESUME, EVENT_RESUME, parse_resume, build_resume, "RESUME" },
-+ { CC_HOLD_ACKNOWLEDGE, EVENT_HOLD_ACKNOWLEDGE, parse_hold_acknowledge, build_hold_acknowledge, "HOLD_ACKNOWLEDGE" },
-+ { CC_SUSPEND_ACKNOWLEDGE, EVENT_SUSPEND_ACKNOWLEDGE, parse_suspend_acknowledge, build_suspend_acknowledge, "SUSPEND_ACKNOWLEDGE" },
-+ { CC_RESUME_ACKNOWLEDGE, EVENT_RESUME_ACKNOWLEDGE, parse_resume_acknowledge, build_resume_acknowledge, "RESUME_ACKNOWLEDGE" },
-+ { CC_HOLD_REJECT, EVENT_HOLD_REJECT, parse_hold_reject, build_hold_reject, "HOLD_REJECT" },
-+ { CC_RETRIEVE, EVENT_RETRIEVE, parse_retrieve, build_retrieve, "RETRIEVE" },
-+ { CC_RETRIEVE_ACKNOWLEDGE, EVENT_RETRIEVE_ACKNOWLEDGE, parse_retrieve_acknowledge, build_retrieve_acknowledge, "RETRIEVE_ACKNOWLEDGE" },
-+ { CC_RETRIEVE_REJECT, EVENT_RETRIEVE_REJECT, parse_retrieve_reject, build_retrieve_reject, "RETRIEVE_REJECT" },
-+ { CC_DISCONNECT, EVENT_DISCONNECT, parse_disconnect, build_disconnect, "DISCONNECT" },
-+ { CC_RESTART, EVENT_RESTART, parse_restart, build_restart, "RESTART" },
-+ { CC_RELEASE, EVENT_RELEASE, parse_release, build_release, "RELEASE" },
-+ { CC_RELEASE_COMPLETE, EVENT_RELEASE_COMPLETE, parse_release_complete, build_release_complete, "RELEASE_COMPLETE" },
-+ { CC_FACILITY, EVENT_FACILITY, parse_facility, build_facility, "FACILITY" },
-+ { CC_NOTIFY, EVENT_NOTIFY, parse_notify, build_notify, "NOTIFY" },
-+ { CC_STATUS_ENQUIRY, EVENT_STATUS_ENQUIRY, parse_status_enquiry, build_status_enquiry, "STATUS_ENQUIRY" },
-+ { CC_INFORMATION, EVENT_INFORMATION, parse_information, build_information, "INFORMATION" },
-+ { CC_STATUS, EVENT_STATUS, parse_status, build_status, "STATUS" },
-+ { CC_TIMEOUT, EVENT_TIMEOUT, parse_timeout, build_timeout, "TIMEOUT" },
-+ { 0, 0, NULL, NULL, NULL }
-+/* *INDENT-ON* */
- };
-
- #define msgs_max (sizeof(msgs_g)/sizeof(struct isdn_msg))
-@@ -1263,15 +1292,15 @@
-
- if (nt){
- mISDNuser_head_t *hh = (mISDNuser_head_t*)msg->data;
--
-+
- for (i=0; i< msgs_max -1; i++) {
- if ( (hh->prim&COMMAND_MASK)==(msgs[i].misdn_msg&COMMAND_MASK)) return i;
- }
--
-+
- } else {
- iframe_t *frm = (iframe_t*)msg->data;
--
-- for (i=0; i< msgs_max -1; i++)
-+
-+ for (i=0; i< msgs_max -1; i++)
- if ( (frm->prim&COMMAND_MASK)==(msgs[i].misdn_msg&COMMAND_MASK)) return i;
- }
-
-@@ -1281,11 +1310,11 @@
- int isdn_msg_get_index_by_event(struct isdn_msg msgs[], enum event_e event, int nt)
- {
- int i;
-- for (i=0; i< msgs_max; i++)
-+ for (i=0; i< msgs_max; i++)
- if ( event == msgs[i].event) return i;
-
- cb_log(10,0, "get_index: event not found!\n");
--
-+
- return -1;
- }
-
-@@ -1318,9 +1347,9 @@
- char * isdn_get_info(struct isdn_msg msgs[], enum event_e event, int nt)
- {
- int i=isdn_msg_get_index_by_event(msgs, event, nt);
--
-+
- if(i>=0) return msgs[i].info;
--
-+
- if (event == EVENT_CLEANUP) return EVENT_CLEAN_INFO;
- if (event == EVENT_DTMF_TONE) return EVENT_DTMF_TONE_INFO;
- if (event == EVENT_NEW_L3ID) return EVENT_NEW_L3ID_INFO;
-@@ -1331,7 +1360,7 @@
- if (event == EVENT_TONE_GENERATE) return EVENT_TONE_GENERATE_INFO;
- if (event == EVENT_PORT_ALARM) return EVENT_PORT_ALARM_INFO;
- if (event == EVENT_BCHAN_ERROR) return EVENT_BCHAN_ERROR_INFO;
--
-+
- return NULL;
- }
-
-@@ -1348,6 +1377,6 @@
- {
- int i=isdn_msg_get_index_by_event(msgs, event, nt);
- if(i<0) return NULL;
--
-+
- return msgs[i].msg_builder(msgs, bc, nt);
- }
-Index: channels/misdn/portinfo.c
-===================================================================
---- a/channels/misdn/portinfo.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/channels/misdn/portinfo.c (.../trunk) (revision 186562)
-@@ -1,4 +1,4 @@
--/*! \file
-+/*! \file
- * \brief Interface to mISDN - port info
- * \author Christian Richter <crich@beronet.com>
- */
-Index: channels/misdn/isdn_lib.c
-===================================================================
---- a/channels/misdn/isdn_lib.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/channels/misdn/isdn_lib.c (.../trunk) (revision 186562)
-@@ -11,7 +11,7 @@
- * the GNU General Public License
- */
-
--/*! \file
-+/*! \file
- * \brief Interface to mISDN
- * \author Christian Richter <crich@beronet.com>
- */
-@@ -33,7 +33,7 @@
- int (*cb_jb_empty)(struct misdn_bchannel *bc, char *buffer, int len);
-
-
--/*
-+/*
- * Define ARRAY_LEN() because I cannot
- * #include "asterisk/utils.h"
- */
-@@ -62,7 +62,7 @@
- return stack->pri;
- }
- }
--
-+
- return -1;
- }
-
-@@ -74,15 +74,15 @@
- return stack->nt;
- }
- }
--
-+
- return -1;
- }
-
--void misdn_make_dummy(struct misdn_bchannel *dummybc, int port, int l3id, int nt, int channel)
-+void misdn_make_dummy(struct misdn_bchannel *dummybc, int port, int l3id, int nt, int channel)
- {
- memset (dummybc,0,sizeof(struct misdn_bchannel));
- dummybc->port=port;
-- if (l3id==0)
-+ if (l3id==0)
- dummybc->l3_id = MISDN_ID_DUMMY;
- else
- dummybc->l3_id=l3id;
-@@ -119,7 +119,7 @@
- }
-
- int misdn_lib_is_port_blocked(int port)
--{
-+{
- struct misdn_stack *stack=get_misdn_stack();
- for ( ; stack; stack=stack->next) {
- if (stack->port == port) {
-@@ -138,12 +138,12 @@
- return -1;
- }
-
--int misdn_lib_get_maxchans(int port)
-+int misdn_lib_get_maxchans(int port)
- {
- struct misdn_stack *stack=get_misdn_stack();
- for ( ; stack; stack=stack->next) {
- if (stack->port == port) {
-- if (stack->pri)
-+ if (stack->pri)
- return 30;
- else
- return 2;
-@@ -159,7 +159,7 @@
-
- if (!bc)
- return NULL;
--
-+
- for ( ; stack; stack = stack->next) {
- if (bc->port == stack->port)
- return stack;
-@@ -171,19 +171,24 @@
-
- void get_show_stack_details(int port, char *buf)
- {
-- struct misdn_stack *stack=get_misdn_stack();
--
-- for ( ; stack; stack=stack->next) {
-- if (stack->port == port) break;
-+ struct misdn_stack *stack = get_misdn_stack();
-+
-+ for (; stack; stack = stack->next) {
-+ if (stack->port == port) {
-+ break;
-+ }
- }
--
-+
- if (stack) {
-- sprintf(buf, "* Port %d Type %s Prot. %s L2Link %s L1Link:%s Blocked:%d",
-- stack->port, stack->nt ? "NT" : "TE", stack->ptp ? "PTP" : "PMP",
-- stack->l2link ? "UP" : "DOWN", stack->l1link ? "UP" : "DOWN",
-+ sprintf(buf, "* Port %2d Type %s Prot. %s L2Link %s L1Link:%s Blocked:%d",
-+ stack->port,
-+ stack->nt ? "NT" : "TE",
-+ stack->ptp ? "PTP" : "PMP",
-+ stack->l2link ? "UP " : "DOWN",
-+ stack->l1link ? "UP " : "DOWN",
- stack->blocked);
- } else {
-- buf[0]=0;
-+ buf[0] = 0;
- }
- }
-
-@@ -219,10 +224,10 @@
- void *user_data;
-
- msg_queue_t upqueue;
-- msg_queue_t activatequeue;
--
-+ msg_queue_t activatequeue;
-+
- sem_t new_msg;
--
-+
- struct misdn_stack *stack_list;
- } ;
-
-@@ -248,7 +253,7 @@
- int misdn_lib_port_restart(int port);
- int misdn_lib_pid_restart(int pid);
-
--extern struct isdn_msg msgs_g[];
-+extern struct isdn_msg msgs_g[];
-
- #define ISDN_PID_L3_B_USER 0x430000ff
- #define ISDN_PID_L4_B_USER 0x440000ff
-@@ -304,7 +309,7 @@
- "Res Digital",
- "Unknown Bearer"
- };
--
-+
- switch (cap) {
- case INFO_CAPABILITY_SPEECH:
- return bearers[0];
-@@ -330,7 +335,7 @@
- static void init_flip_bits(void)
- {
- int i,k;
--
-+
- for (i = 0 ; i < 256 ; i++) {
- unsigned char sample = 0 ;
- for (k = 0; k<8; k++) {
-@@ -344,11 +349,11 @@
- {
- int i;
- char * start = buf;
--
-+
- for (i = 0 ; i < len; i++) {
- buf[i] = flip_table[(unsigned char)buf[i]];
- }
--
-+
- return start;
- }
-
-@@ -359,13 +364,13 @@
- {
- int i = 0;
- msg_t *dmsg;
--
-+
- while(i < 10)
- {
- dmsg = prep_l3data_msg(prim, dinfo, size, 256, NULL);
- if (dmsg)
- return(dmsg);
--
-+
- if (!i)
- printf("cannot allocate memory, trying again...\n");
- i++;
-@@ -383,10 +388,10 @@
- msg_t *dmsg;
- Q931_info_t *qi;
- iframe_t *frm;
--
-+
- if (!ntmode)
- size = sizeof(Q931_info_t)+2;
--
-+
- while(i < 10) {
- if (ntmode) {
- dmsg = prep_l3data_msg(prim, dinfo, size, 256, NULL);
-@@ -406,7 +411,7 @@
- return(dmsg);
- }
- }
--
-+
- if (!i) printf("cannot allocate memory, trying again...\n");
- i++;
- usleep(300000);
-@@ -425,11 +430,11 @@
- cb_log(0,bc->port,"send_msg: IEK!! no stack\n ");
- return -1;
- }
--
-+
- frm->addr = (stack->upper_id | FLG_MSG_DOWN);
- frm->dinfo = bc->l3_id;
- frm->len = (dmsg->len) - mISDN_HEADER_LEN;
--
-+
- cb_log(4,stack->port,"Sending msg, prim:%x addr:%x dinfo:%x\n",frm->prim,frm->addr,frm->dinfo);
-
- mISDN_write(midev, dmsg->data, dmsg->len, TIMEOUT_1SEC);
-@@ -457,7 +462,7 @@
- /* We have opted to never receive any available inband recorded messages */
- return 0;
- }
--
-+
- switch (bc->progress_indicator) {
- case INFO_PI_INBAND_AVAILABLE:
- case INFO_PI_CALL_NOT_E2E_ISDN:
-@@ -505,7 +510,7 @@
- cb_log(0,stack->port,"couldn't set channel %d in\n", channel );
- return -1;
- }
--
-+
- return 0;
- }
-
-@@ -517,9 +522,9 @@
- int chan=0;
- int bnums = stack->pri ? stack->b_num : stack->b_num - 1;
-
-- if (bc->channel_found)
-+ if (bc->channel_found)
- return 0;
--
-+
- bc->channel_found=1;
-
- cb_log(5,stack->port,"find_free_chan: req_chan:%d\n",channel);
-@@ -528,7 +533,7 @@
- cb_log(0, stack->port, " !! out of bound call to find_free_chan_in_stack! (ch:%d)\n", channel);
- return 0;
- }
--
-+
- channel--;
-
- if (dec) {
-@@ -558,7 +563,7 @@
- dump_chan_list(stack);
- bc->out_cause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION;
- return -1;
-- }
-+ }
-
- if (set_chan_in_stack(stack, chan)<0) {
- cb_log (0, stack->port, "Channel Already in use:%d\n", chan);
-@@ -576,8 +581,8 @@
- cb_log(0,stack?stack->port:0, "empty_chan_in_stack: cannot empty channel %d\n",channel);
- return -1;
- }
--
-- cb_log (4, stack?stack->port:0, "empty_chan_in_stack: %d\n",channel);
-+
-+ cb_log (4, stack?stack->port:0, "empty_chan_in_stack: %d\n",channel);
- stack->channels[channel-1] = 0;
- dump_chan_list(stack);
- return 0;
-@@ -585,7 +590,7 @@
-
- char *bc_state2str(enum bchannel_state state) {
- int i;
--
-+
- struct bchan_state_s {
- char *n;
- enum bchannel_state s;
-@@ -604,7 +609,7 @@
- {"BCHAN_CLEAN_REQUEST", BCHAN_CLEAN_REQUEST},
- {"BCHAN_ERROR", BCHAN_ERROR}
- };
--
-+
- for (i=0; i< sizeof(states)/sizeof(struct bchan_state_s); i++)
- if ( states[i].s == state)
- return states[i].n;
-@@ -618,7 +623,7 @@
- bc->l3_id,
- bc_state2str(bc->bc_state),
- bc_state2str(state) );
--
-+
- switch (state) {
- case BCHAN_ACTIVATED:
- if (bc->next_bc_state == BCHAN_BRIDGED) {
-@@ -644,6 +649,29 @@
-
- static void empty_bc(struct misdn_bchannel *bc)
- {
-+ bc->caller.presentation = 0; /* allowed */
-+ bc->caller.number_plan = NUMPLAN_ISDN;
-+ bc->caller.number_type = NUMTYPE_UNKNOWN;
-+ bc->caller.name[0] = 0;
-+ bc->caller.number[0] = 0;
-+ bc->caller.subaddress[0] = 0;
-+
-+ bc->connected.presentation = 0; /* allowed */
-+ bc->connected.number_plan = NUMPLAN_ISDN;
-+ bc->connected.number_type = NUMTYPE_UNKNOWN;
-+ bc->connected.name[0] = 0;
-+ bc->connected.number[0] = 0;
-+ bc->connected.subaddress[0] = 0;
-+
-+ bc->redirecting.from.presentation = 0; /* allowed */
-+ bc->redirecting.from.number_plan = NUMPLAN_ISDN;
-+ bc->redirecting.from.number_type = NUMTYPE_UNKNOWN;
-+ bc->redirecting.from.name[0] = 0;
-+ bc->redirecting.from.number[0] = 0;
-+ bc->redirecting.from.subaddress[0] = 0;
-+
-+ bc->redirecting.reason = mISDN_REDIRECTING_REASON_UNKNOWN;
-+
- bc->dummy=0;
-
- bc->bframe_len=0;
-@@ -656,38 +684,32 @@
- bc->sending_complete = 0;
-
- bc->restart_channel=0;
--
-+
- bc->conf_id = 0;
-
- bc->need_more_infos = 0;
--
-+
- bc->send_dtmf=0;
- bc->nodsp=0;
- bc->nojitter=0;
-
- bc->time_usec=0;
--
-+
- bc->rxgain=0;
- bc->txgain=0;
-
- bc->crypt=0;
- bc->curptx=0; bc->curprx=0;
--
-+
- bc->crypt_key[0] = 0;
--
-+
- bc->generate_tone=0;
- bc->tone_cnt=0;
--
-- bc->dnumplan=NUMPLAN_UNKNOWN;
-- bc->onumplan=NUMPLAN_UNKNOWN;
-- bc->rnumplan=NUMPLAN_UNKNOWN;
-- bc->cpnnumplan=NUMPLAN_UNKNOWN;
--
-
- bc->active = 0;
-
- bc->early_bconnect = 1;
--
-+
- #ifdef MISDN_1_2
- *bc->pipeline = 0;
- #else
-@@ -698,17 +720,22 @@
- bc->AOCD_need_export = 0;
-
- bc->orig=0;
--
-+
- bc->cause = AST_CAUSE_NORMAL_CLEARING;
- bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
-- bc->pres = 0; /* allowed */
--
-+
-+ bc->display_connected = 0; /* none */
-+ bc->display_setup = 0; /* none */
-+
-+ bc->presentation = 0; /* allowed */
-+ bc->set_presentation = 0;
-+
- bc->evq=EVENT_NOTHING;
-
- bc->progress_coding=0;
- bc->progress_location=0;
- bc->progress_indicator=0;
--
-+
- /** Set Default Bearer Caps **/
- bc->capability=INFO_CAPABILITY_SPEECH;
- bc->law=INFO_CODEC_ALAW;
-@@ -716,24 +743,23 @@
- bc->rate=0x10;
- bc->user1=0;
- bc->urate=0;
--
-+
- bc->hdlc=0;
--
--
-+
-+ bc->dialed.number_plan = NUMPLAN_ISDN;
-+ bc->dialed.number_type = NUMTYPE_UNKNOWN;
-+ bc->dialed.number[0] = 0;
-+ bc->dialed.subaddress[0] = 0;
-+
- bc->info_dad[0] = 0;
- bc->display[0] = 0;
- bc->infos_pending[0] = 0;
-- bc->cad[0] = 0;
-- bc->oad[0] = 0;
-- bc->dad[0] = 0;
-- bc->rad[0] = 0;
-- bc->orig_dad[0] = 0;
- bc->uu[0]=0;
- bc->uulen=0;
--
-+
- bc->fac_in.Function = Fac_None;
- bc->fac_out.Function = Fac_None;
--
-+
- bc->te_choose_channel = 0;
- bc->channel_found= 0;
-
-@@ -748,32 +774,32 @@
- struct misdn_stack * stack;
-
- cb_log(3, bc?bc->port:0, "$$$ CLEANUP CALLED pid:%d\n", bc?bc->pid:-1);
--
-+
- if (!bc ) return -1;
- stack=get_stack_by_bc(bc);
--
-+
- if (!stack) return -1;
--
-+
- switch (bc->bc_state ) {
- case BCHAN_CLEANED:
- cb_log(5, stack->port, "$$$ Already cleaned up bc with stid :%x\n", bc->b_stid);
- return -1;
--
-+
- default:
- break;
- }
--
-+
- cb_log(2, stack->port, "$$$ Cleaning up bc with stid :%x pid:%d\n", bc->b_stid, bc->pid);
--
-+
- manager_ec_disable(bc);
-
- manager_bchannel_deactivate(bc);
-
- mISDN_write_frame(stack->midev, buff, bc->layer_id|FLG_MSG_TARGET|FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
--
-+
- bc->b_stid = 0;
- bc_state_change(bc, BCHAN_CLEANED);
--
-+
- return ret;
- }
-
-@@ -785,14 +811,14 @@
-
- for (i=0; i<=stack->b_num; i++) {
- if (global_state == MISDN_INITIALIZED) {
-- cb_event(EVENT_CLEANUP, &stack->bc[i], NULL);
-+ cb_event(EVENT_CLEANUP, &stack->bc[i], NULL);
- empty_chan_in_stack(stack,i+1);
- empty_bc(&stack->bc[i]);
- clean_up_bc(&stack->bc[i]);
- stack->bc[i].in_use = 0;
- }
--
-- }
-+
-+ }
- }
-
- static int new_te_id = 0;
-@@ -801,9 +827,9 @@
-
- static int misdn_lib_get_l1_down(struct misdn_stack *stack)
- {
-- /* Pull Up L1 */
-+ /* Pull Up L1 */
- iframe_t act;
-- act.prim = PH_DEACTIVATE | REQUEST;
-+ act.prim = PH_DEACTIVATE | REQUEST;
- act.addr = stack->lower_id|FLG_MSG_DOWN;
- act.dinfo = 0;
- act.len = 0;
-@@ -815,38 +841,38 @@
-
- static int misdn_lib_get_l2_down(struct misdn_stack *stack)
- {
--
-+
- if (stack->ptp && (stack->nt) ) {
- msg_t *dmsg;
- /* L2 */
- dmsg = create_l2msg(DL_RELEASE| REQUEST, 0, 0);
--
-+
- if (stack->nst.manager_l3(&stack->nst, dmsg))
- free_msg(dmsg);
--
-+
- } else {
- iframe_t act;
--
-+
- act.prim = DL_RELEASE| REQUEST;
- act.addr = (stack->upper_id |FLG_MSG_DOWN) ;
--
-+
- act.dinfo = 0;
- act.len = 0;
- return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
- }
--
-+
- return 0;
- }
-
-
- static int misdn_lib_get_l1_up(struct misdn_stack *stack)
- {
-- /* Pull Up L1 */
-+ /* Pull Up L1 */
- iframe_t act;
-- act.prim = PH_ACTIVATE | REQUEST;
-+ act.prim = PH_ACTIVATE | REQUEST;
- act.addr = (stack->upper_id | FLG_MSG_DOWN) ;
-
--
-+
- act.dinfo = 0;
- act.len = 0;
-
-@@ -856,26 +882,26 @@
-
- int misdn_lib_get_l2_up(struct misdn_stack *stack)
- {
--
-+
- if (stack->ptp && (stack->nt) ) {
- msg_t *dmsg;
- /* L2 */
- dmsg = create_l2msg(DL_ESTABLISH | REQUEST, 0, 0);
--
-+
- if (stack->nst.manager_l3(&stack->nst, dmsg))
- free_msg(dmsg);
--
-+
- } else {
- iframe_t act;
--
-+
- act.prim = DL_ESTABLISH | REQUEST;
- act.addr = (stack->upper_id |FLG_MSG_DOWN) ;
--
-+
- act.dinfo = 0;
- act.len = 0;
- return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
- }
--
-+
- return 0;
- }
-
-@@ -883,10 +909,10 @@
- static int misdn_lib_get_l2_te_ptp_up(struct misdn_stack *stack)
- {
- iframe_t act;
--
-+
- act.prim = DL_ESTABLISH | REQUEST;
- act.addr = (stack->upper_id & ~LAYER_ID_MASK) | 3 | FLG_MSG_DOWN;
--
-+
- act.dinfo = 0;
- act.len = 0;
- return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
-@@ -897,14 +923,14 @@
- static int misdn_lib_get_short_status(struct misdn_stack *stack)
- {
- iframe_t act;
--
--
-- act.prim = MGR_SHORTSTATUS | REQUEST;
--
-+
-+
-+ act.prim = MGR_SHORTSTATUS | REQUEST;
-+
- act.addr = (stack->upper_id | MSG_BROADCAST) ;
-
- act.dinfo = SSTATUS_BROADCAST_BIT | SSTATUS_ALL;
--
-+
- act.len = 0;
- return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
- }
-@@ -929,7 +955,7 @@
- if (stack->procids[proc_id] == 0) {
- break;
- }
-- } /* end for */
-+ }
- if (proc_id == MAXPROCS) {
- cb_log(0, stack->port, "Couldn't Create New ProcId.\n");
- return -1;
-@@ -941,7 +967,7 @@
- bc->l3_id = l3_id;
- cb_log(3, stack->port, " --> new_l3id %x\n", l3_id);
- } else {
-- if (stack->ptp || bc->te_choose_channel) {
-+ if ((stack->pri && stack->ptp) || bc->te_choose_channel) {
- /* we know exactly which channels are in use */
- if (find_free_chan_in_stack(stack, bc, bc->channel_preselected ? bc->channel : 0, bc->dec) < 0) {
- return -1;
-@@ -996,7 +1022,7 @@
- cb_log(0, bc->port, "setup_bc: NO STACK FOUND!!\n");
- return -1;
- }
--
-+
- midev = stack->midev;
- channel = bc->channel - 1 - (bc->channel > 16);
- b_stid = stack->b_stids[channel >= 0 ? channel : 0];
-@@ -1008,9 +1034,9 @@
- cb_log(4, stack->port, "$$$ bc already setup stid :%x (state:%s)\n", b_stid, bc_state2str(bc->bc_state) );
- return -1;
- }
--
-+
- cb_log(5, stack->port, "$$$ Setting up bc with stid :%x\n", b_stid);
--
-+
- /*check if the b_stid is already initialized*/
- for (i=0; i <= stack->b_num; i++) {
- if (stack->bc[i].b_stid == b_stid) {
-@@ -1018,10 +1044,10 @@
- return -1;
- }
- }
--
-+
- if (b_stid <= 0) {
- cb_log(0, stack->port," -- Stid <=0 at the moment in channel:%d\n",channel);
--
-+
- bc_state_change(bc,BCHAN_ERROR);
- return 1;
- }
-@@ -1031,10 +1057,10 @@
- {
- layer_info_t li;
- memset(&li, 0, sizeof(li));
--
-+
- li.object_id = -1;
- li.extentions = 0;
--
-+
- li.st = bc->b_stid; /* given idx */
-
-
-@@ -1044,18 +1070,18 @@
- #endif
- if ( bc->hdlc || bc->nodsp) {
- cb_log(4, stack->port,"setup_bc: without dsp\n");
-- {
-+ {
- int l = sizeof(li.name);
- strncpy(li.name, "B L3", l);
- li.name[l-1] = 0;
- }
- li.pid.layermask = ISDN_LAYER((3));
- li.pid.protocol[3] = ISDN_PID_L3_B_USER;
--
-+
- bc->layer=3;
- } else {
- cb_log(4, stack->port,"setup_bc: with dsp\n");
-- {
-+ {
- int l = sizeof(li.name);
- strncpy(li.name, "B L4", l);
- li.name[l-1] = 0;
-@@ -1064,8 +1090,8 @@
- li.pid.protocol[4] = ISDN_PID_L4_B_USER;
-
- bc->layer=4;
-- }
--
-+ }
-+
- ret = mISDN_new_layer(midev, &li);
- if (ret ) {
- cb_log(0, stack->port,"New Layer Err: %d %s\n",ret,strerror(errno));
-@@ -1073,23 +1099,23 @@
- bc_state_change(bc,BCHAN_ERROR);
- return(-EINVAL);
- }
--
-+
- bc->layer_id = li.id;
- }
--
-+
- memset(&pid, 0, sizeof(pid));
--
--
--
-+
-+
-+
- cb_log(4, stack->port," --> Channel is %d\n", bc->channel);
--
-+
- if (bc->nodsp) {
- cb_log(2, stack->port," --> TRANSPARENT Mode (no DSP, no HDLC)\n");
- pid.protocol[1] = ISDN_PID_L1_B_64TRANS;
- pid.protocol[2] = ISDN_PID_L2_B_TRANS;
- pid.protocol[3] = ISDN_PID_L3_B_USER;
- pid.layermask = ISDN_LAYER((1)) | ISDN_LAYER((2)) | ISDN_LAYER((3));
--
-+
- } else if ( bc->hdlc ) {
- cb_log(2, stack->port," --> HDLC Mode\n");
- pid.protocol[1] = ISDN_PID_L1_B_64HDLC ;
-@@ -1103,16 +1129,16 @@
- pid.protocol[3] = ISDN_PID_L3_B_DSP;
- pid.protocol[4] = ISDN_PID_L4_B_USER;
- pid.layermask = ISDN_LAYER((1)) | ISDN_LAYER((2)) | ISDN_LAYER((3)) | ISDN_LAYER((4));
--
-- }
-
-+ }
-+
- ret = mISDN_set_stack(midev, bc->b_stid, &pid);
-
- if (ret){
- cb_log(0, stack->port,"$$$ Set Stack Err: %d %s\n",ret,strerror(errno));
--
-+
- mISDN_write_frame(midev, buff, bc->layer_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
--
-+
- bc_state_change(bc,BCHAN_ERROR);
- cb_event(EVENT_BCHAN_ERROR, bc, glob_mgr->user_data);
- return(-EINVAL);
-@@ -1123,7 +1149,7 @@
- if (ret) {
- cb_log(0, stack->port,"$$$ Set StackIND Err: %d %s\n",ret,strerror(errno));
- mISDN_write_frame(midev, buff, bc->layer_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
--
-+
- bc_state_change(bc,BCHAN_ERROR);
- cb_event(EVENT_BCHAN_ERROR, bc, glob_mgr->user_data);
- return(-EINVAL);
-@@ -1136,14 +1162,14 @@
- if (!bc->addr) {
- cb_log(0, stack->port,"$$$ Get Layerid Err: %d %s\n",ret,strerror(errno));
- mISDN_write_frame(midev, buff, bc->layer_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
--
-+
- bc_state_change(bc,BCHAN_ERROR);
- cb_event(EVENT_BCHAN_ERROR, bc, glob_mgr->user_data);
- return (-EINVAL);
- }
-
- manager_bchannel_activate(bc);
--
-+
- bc_state_change(bc,BCHAN_ACTIVATED);
-
- return 0;
-@@ -1157,11 +1183,11 @@
- unsigned char buff[1025] = "";
- iframe_t *frm = (iframe_t *)buff;
- int ret;
--
-+
- if (!bc) return -1;
--
-+
- cb_log(8, port, "Init.BC %d.\n",bidx);
--
-+
- memset(bc, 0,sizeof(struct misdn_bchannel));
-
- bc->send_lock=malloc(sizeof(struct send_lock));
-@@ -1169,40 +1195,40 @@
- return -1;
- }
- pthread_mutex_init(&bc->send_lock->lock, NULL);
--
-+
- if (msn) {
- int l = sizeof(bc->msn);
- strncpy(bc->msn,msn, l);
- bc->msn[l-1] = 0;
- }
--
--
-+
-+
- empty_bc(bc);
- bc_state_change(bc, BCHAN_CLEANED);
--
-+
- bc->port=stack->port;
- bc->nt=stack->nt?1:0;
- bc->pri=stack->pri;
--
-+
- {
- ibuffer_t* ibuf= init_ibuffer(MISDN_IBUF_SIZE);
-
- if (!ibuf) return -1;
--
-+
- clear_ibuffer( ibuf);
--
-+
- ibuf->rsem=malloc(sizeof(sem_t));
- if (!ibuf->rsem) {
- return -1;
- }
--
-+
- bc->astbuf=ibuf;
-
- if (sem_init(ibuf->rsem,1,0)<0)
- sem_init(ibuf->rsem,0,0);
--
-+
- }
--
-+
- {
- stack_info_t *stinf;
- ret = mISDN_get_stack_info(midev, stack->port, buff, sizeof(buff));
-@@ -1210,12 +1236,12 @@
- cb_log(0, port, "%s: Cannot get stack info for this port. (ret=%d)\n", __FUNCTION__, ret);
- return -1;
- }
--
-+
- stinf = (stack_info_t *)&frm->data.p;
--
-+
- cb_log(8, port, " --> Child %x\n",stinf->child[bidx]);
- }
--
-+
- return 0;
- }
-
-@@ -1227,7 +1253,7 @@
- unsigned char buff[1025];
- iframe_t *frm = (iframe_t *)buff;
- stack_info_t *stinf;
-- int i;
-+ int i;
- layer_info_t li;
-
- struct misdn_stack *stack = malloc(sizeof(struct misdn_stack));
-@@ -1235,28 +1261,28 @@
-
-
- cb_log(8, port, "Init. Stack.\n");
--
-+
- memset(stack,0,sizeof(struct misdn_stack));
--
-+
- for (i=0; i<MAX_BCHANS + 1; i++ ) stack->channels[i]=0;
--
-+
- stack->port=port;
- stack->midev=midev;
- stack->ptp=ptp;
--
-+
- stack->holding=NULL;
- stack->pri=0;
--
-+
- msg_queue_init(&stack->downqueue);
- msg_queue_init(&stack->upqueue);
--
-+
- /* query port's requirements */
- ret = mISDN_get_stack_info(midev, port, buff, sizeof(buff));
- if (ret < 0) {
- cb_log(0, port, "%s: Cannot get stack info for this port. (ret=%d)\n", __FUNCTION__, ret);
- return(NULL);
- }
--
-+
- stinf = (stack_info_t *)&frm->data.p;
-
- stack->d_stid = stinf->id;
-@@ -1264,7 +1290,7 @@
-
- for (i=0; i<=stinf->childcnt; i++)
- stack->b_stids[i] = stinf->child[i];
--
-+
- switch(stinf->pid.protocol[0] & ~ISDN_PID_FEATURE_MASK) {
- case ISDN_PID_L0_TE_S0:
- stack->nt=0;
-@@ -1283,7 +1309,7 @@
- cb_log(8, port, "TE S2M Stack\n");
- stack->nt=1;
- stack->pri=1;
--
-+
- break;
- default:
- cb_log(0, port, "this is a unknown port type 0x%08x\n", stinf->pid.protocol[0]);
-@@ -1291,19 +1317,19 @@
- }
-
- if (!stack->nt) {
-- if (stinf->pid.protocol[2] & ISDN_PID_L2_DF_PTP ) {
-+ if (stinf->pid.protocol[2] & ISDN_PID_L2_DF_PTP ) {
- stack->ptp = 1;
- } else {
- stack->ptp = 0;
- }
- }
--
-+
- {
- int ret;
- int nt=stack->nt;
-
- cb_log(8, port, "Init. Stack.\n");
--
-+
- memset(&li, 0, sizeof(li));
- {
- int l = sizeof(li.name);
-@@ -1315,15 +1341,15 @@
- li.pid.protocol[nt?2:4] = nt?ISDN_PID_L2_LAPD_NET:ISDN_PID_L4_CAPI20;
- li.pid.layermask = ISDN_LAYER((nt?2:4));
- li.st = stack->d_stid;
--
--
-+
-+
- ret = mISDN_new_layer(midev, &li);
- if (ret) {
- cb_log(0, port, "%s: Cannot add layer %d to this port.\n", __FUNCTION__, nt?2:4);
- return(NULL);
- }
--
--
-+
-+
- stack->upper_id = li.id;
- ret = mISDN_register_layer(midev, stack->d_stid, stack->upper_id);
- if (ret)
-@@ -1331,52 +1357,52 @@
- cb_log(0,port,"Cannot register layer %d of this port.\n", nt?2:4);
- return(NULL);
- }
--
-- stack->lower_id = mISDN_get_layerid(midev, stack->d_stid, nt?1:3);
-+
-+ stack->lower_id = mISDN_get_layerid(midev, stack->d_stid, nt?1:3);
- if (stack->lower_id < 0) {
- cb_log(0, port, "%s: Cannot get layer(%d) id of this port.\n", __FUNCTION__, nt?1:3);
- return(NULL);
- }
--
-+
- stack->upper_id = mISDN_get_layerid(midev, stack->d_stid, nt?2:4);
- if (stack->upper_id < 0) {
- cb_log(0, port, "%s: Cannot get layer(%d) id of this port.\n", __FUNCTION__, 2);
- return(NULL);
- }
--
-+
- cb_log(8, port, "NT Stacks upper_id %x\n",stack->upper_id);
--
--
-+
-+
- /* create nst (nt-mode only) */
- if (nt) {
--
-+
- memset(&stack->nst, 0, sizeof(net_stack_t));
- memset(&stack->mgr, 0, sizeof(manager_t));
--
-+
- stack->mgr.nst = &stack->nst;
- stack->nst.manager = &stack->mgr;
--
-+
- stack->nst.l3_manager = handle_event_nt;
- stack->nst.device = midev;
- stack->nst.cardnr = port;
- stack->nst.d_stid = stack->d_stid;
--
-+
- stack->nst.feature = FEATURE_NET_HOLD;
- if (stack->ptp)
- stack->nst.feature |= FEATURE_NET_PTP;
- if (stack->pri)
- stack->nst.feature |= FEATURE_NET_CRLEN2 | FEATURE_NET_EXTCID;
--
-+
- stack->nst.l1_id = stack->lower_id;
- stack->nst.l2_id = stack->upper_id;
--
-+
- msg_queue_init(&stack->nst.down_queue);
--
-+
- Isdnl2Init(&stack->nst);
- Isdnl3Init(&stack->nst);
--
-- }
--
-+
-+ }
-+
- if (!stack->nt) {
- /*assume L1 is up, we'll get DEACTIVATES soon, for non
- * up L1s*/
-@@ -1384,7 +1410,7 @@
- }
- stack->l1link=0;
- stack->l2link=0;
--#if 0
-+#if 0
- if (!stack->nt) {
- misdn_lib_get_short_status(stack);
- } else {
-@@ -1396,12 +1422,12 @@
-
- misdn_lib_get_short_status(stack);
- misdn_lib_get_l1_up(stack);
-- misdn_lib_get_l2_up(stack);
--
-+ misdn_lib_get_l2_up(stack);
-+
- }
-
- cb_log(8,0,"stack_init: port:%d lowerId:%x upperId:%x\n",stack->port,stack->lower_id, stack->upper_id);
--
-+
- return stack;
- }
-
-@@ -1415,11 +1441,11 @@
- cleanup_Isdnl2(&stack->nst);
- cleanup_Isdnl3(&stack->nst);
- }
--
-- if (stack->lower_id)
-+
-+ if (stack->lower_id)
- mISDN_write_frame(stack->midev, buf, stack->lower_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
-
-- if (stack->upper_id)
-+ if (stack->upper_id)
- mISDN_write_frame(stack->midev, buf, stack->upper_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
- }
-
-@@ -1427,14 +1453,14 @@
- static struct misdn_stack * find_stack_by_addr(int addr)
- {
- struct misdn_stack *stack;
--
-+
- for (stack=glob_mgr->stack_list;
- stack;
- stack=stack->next) {
- if ( (stack->upper_id&STACK_ID_MASK) == (addr&STACK_ID_MASK)) return stack;
-
- }
--
-+
- return NULL;
- }
-
-@@ -1442,24 +1468,24 @@
- static struct misdn_stack * find_stack_by_port(int port)
- {
- struct misdn_stack *stack;
--
-+
- for (stack=glob_mgr->stack_list;
- stack;
-- stack=stack->next)
-+ stack=stack->next)
- if (stack->port == port) return stack;
--
-+
- return NULL;
- }
-
- static struct misdn_stack * find_stack_by_mgr(manager_t* mgr_nt)
- {
- struct misdn_stack *stack;
--
-+
- for (stack=glob_mgr->stack_list;
- stack;
-- stack=stack->next)
-+ stack=stack->next)
- if ( &stack->mgr == mgr_nt) return stack;
--
-+
- return NULL;
- }
-
-@@ -1506,7 +1532,7 @@
- }
- }
- }
--
-+
- return NULL;
- }
-
-@@ -1514,7 +1540,7 @@
- {
- struct misdn_stack* stack;
- int i;
--
-+
- for (stack=glob_mgr->stack_list;
- stack;
- stack=stack->next) {
-@@ -1533,14 +1559,14 @@
- struct misdn_stack* stack=find_stack_by_port(port);
- int i;
-
-- if (!stack) return NULL;
--
-+ if (!stack) return NULL;
-+
- for (i=0; i<=stack->b_num; i++) {
- if ( stack->bc[i].channel== channel ) {
- return &stack->bc[i];
- }
- }
--
-+
- return NULL;
- }
-
-@@ -1551,16 +1577,23 @@
- static int handle_event ( struct misdn_bchannel *bc, enum event_e event, iframe_t *frm)
- {
- struct misdn_stack *stack=get_stack_by_bc(bc);
--
-+
- if (!stack->nt) {
--
-+
- switch (event) {
-
- case EVENT_CONNECT_ACKNOWLEDGE:
- setup_bc(bc);
-
- if ( *bc->crypt_key ) {
-- cb_log(4, stack->port, "ENABLING BLOWFISH channel:%d oad%d:%s dad%d:%s\n", bc->channel, bc->onumplan,bc->oad, bc->dnumplan,bc->dad);
-+ cb_log(4, stack->port,
-+ "ENABLING BLOWFISH channel:%d caller%d:\"%s\" <%s> dialed%d:%s\n",
-+ bc->channel,
-+ bc->caller.number_type,
-+ bc->caller.name,
-+ bc->caller.number,
-+ bc->dialed.number_type,
-+ bc->dialed.number);
- manager_ph_control_block(bc, BF_ENABLE_KEY, bc->crypt_key, strlen(bc->crypt_key) );
- }
-
-@@ -1582,7 +1615,14 @@
- case EVENT_CONNECT:
-
- if ( *bc->crypt_key ) {
-- cb_log(4, stack->port, "ENABLING BLOWFISH channel:%d oad%d:%s dad%d:%s\n", bc->channel, bc->onumplan,bc->oad, bc->dnumplan,bc->dad);
-+ cb_log(4, stack->port,
-+ "ENABLING BLOWFISH channel:%d caller%d:\"%s\" <%s> dialed%d:%s\n",
-+ bc->channel,
-+ bc->caller.number_type,
-+ bc->caller.name,
-+ bc->caller.number,
-+ bc->dialed.number_type,
-+ bc->dialed.number);
- manager_ph_control_block(bc, BF_ENABLE_KEY, bc->crypt_key, strlen(bc->crypt_key) );
- }
- case EVENT_ALERTING:
-@@ -1602,12 +1642,12 @@
-
- if (!bc->channel)
- cb_log(0, stack->port, "Any Channel Requested, but we have no more!!\n");
-- else
-+ else
- cb_log(0, stack->port, "Requested Channel Already in Use releasing this call with cause 34!!!!\n");
-
- /* when the channel is already in use, we can't
-- * simply clear it, we need to make sure that
-- * it will still be marked as in_use in the
-+ * simply clear it, we need to make sure that
-+ * it will still be marked as in_use in the
- * available channels list.*/
- bc->channel=0;
-
-@@ -1626,7 +1666,7 @@
- break;
- }
- } else { /** NT MODE **/
--
-+
- }
- return 0;
- }
-@@ -1636,7 +1676,7 @@
- struct misdn_bchannel *bc;
-
- if (!stack) return -1;
--
-+
- switch (frm->prim) {
- case CC_NEW_CR|INDICATION:
- cb_log(7, stack->port, " --> lib: NEW_CR Ind with l3id:%x on this port.\n",frm->dinfo);
-@@ -1646,7 +1686,7 @@
- cb_log(0, stack->port, " --> !! lib: No free channel!\n");
- return -1;
- }
--
-+
- cb_log(7, stack->port, " --> new_process: New L3Id: %x\n",frm->dinfo);
- bc->l3_id=frm->dinfo;
- return 1;
-@@ -1663,14 +1703,14 @@
- {
- struct misdn_bchannel *bc=find_bc_by_l3id(stack, frm->dinfo);
- struct misdn_bchannel dummybc;
--
-+
- if (!bc) {
- cb_log(4, stack->port, " --> Didn't find BC so temporarily creating dummy BC (l3id:%x) on this port.\n", frm->dinfo);
- misdn_make_dummy(&dummybc, stack->port, frm->dinfo, stack->nt, 0);
--
-- bc=&dummybc;
-+
-+ bc=&dummybc;
- }
--
-+
- if (bc) {
- int channel = bc->channel;
- cb_log(4, stack->port, " --> lib: CLEANING UP l3id: %x\n",frm->dinfo);
-@@ -1698,15 +1738,15 @@
- }
- }
- else {
-- if (stack->nt)
-+ if (stack->nt)
- cb_log(4, stack->port, "BC with dinfo: %x not found.. (prim was %x and addr %x)\n",frm->dinfo, frm->prim, frm->addr);
- }
--
-+
- return 1;
- }
- break;
- }
--
-+
- return 0;
- }
-
-@@ -1720,10 +1760,10 @@
- cb_log(1,0,"misdn_release: No Stack found\n");
- return;
- }
--
-- if (bc->channel>0)
-+
-+ if (bc->channel>0)
- empty_chan_in_stack(stack,bc->channel);
--
-+
- empty_bc(bc);
- clean_up_bc(bc);
- bc->in_use=0;
-@@ -1732,21 +1772,21 @@
-
-
-
--int misdn_lib_get_port_up (int port)
--{ /* Pull Up L1 */
-+int misdn_lib_get_port_up (int port)
-+{ /* Pull Up L1 */
- struct misdn_stack *stack;
--
-+
- for (stack=glob_mgr->stack_list;
- stack;
- stack=stack->next) {
--
-+
- if (stack->port == port) {
-
- if (!stack->l1link)
- misdn_lib_get_l1_up(stack);
- if (!stack->l2link)
- misdn_lib_get_l2_up(stack);
--
-+
- return 0;
- }
- }
-@@ -1754,8 +1794,8 @@
- }
-
-
--int misdn_lib_get_port_down (int port)
--{ /* Pull Down L1 */
-+int misdn_lib_get_port_down (int port)
-+{ /* Pull Down L1 */
- struct misdn_stack *stack;
- for (stack=glob_mgr->stack_list;
- stack;
-@@ -1778,7 +1818,7 @@
- for (stack=glob_mgr->stack_list;
- stack;
- stack=stack->next) {
--
-+
- if (stack->port == port) {
-
- if (stack->blocked) {
-@@ -1805,7 +1845,7 @@
- }
- }
- }
--
-+
- return -1;
- }
-
-@@ -1825,7 +1865,7 @@
- if (!bc) {
- cb_log(4, stack->port, " --> Didn't find BC so temporarily creating dummy BC (l3id:%x) on this port.\n", hh->dinfo);
- misdn_make_dummy(&dummybc, stack->port, hh->dinfo, stack->nt, 0);
-- bc=&dummybc;
-+ bc=&dummybc;
- }
-
- if (bc) {
-@@ -1858,7 +1898,7 @@
-
- hh=(mISDNuser_head_t*)msg->data;
- port=stack->port;
--
-+
- cb_log(5, stack->port, " --> lib: prim %x dinfo %x\n",hh->prim, hh->dinfo);
- {
- switch(hh->prim){
-@@ -1873,7 +1913,7 @@
- frm.addr=stack->upper_id | FLG_MSG_DOWN;
-
- frm.prim = CC_NEW_CR|INDICATION;
--
-+
- if (handle_cr( stack, &frm)< 0) {
- msg_t *dmsg;
- cb_log(4, stack->port, "Patch from MEIDANIS:Sending RELEASE_COMPLETE %x (No free Chan for you..)\n", hh->dinfo);
-@@ -1882,7 +1922,7 @@
- free_msg(msg);
- return 0;
- }
--
-+
- bc = find_bc_by_l3id(stack, hh->dinfo);
- hold_bc = stack_holder_find(stack, bc->l3_id);
- cb_log(4, stack->port, "bc_l3id:%x holded_bc_l3id:%x\n",bc->l3_id, hold_bc->l3_id);
-@@ -1898,17 +1938,17 @@
- bc->holded=0;
- bc->b_stid=0;
- }
--
-+
- }
--
-+
- break;
--
-+
- case CC_SETUP|CONFIRM:
- {
- struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo);
- int l3id = *((int *)(((u_char *)msg->data)+ mISDNUSER_HEAD_SIZE));
- cb_log(4, stack->port, " --> lib: Event_ind:SETUP CONFIRM [NT] : new L3ID is %x\n",l3id );
--
-+
- if (!bc) { cb_log(4, stack->port, "Bc Not found (after SETUP CONFIRM)\n"); return 0; }
- cb_log (2,bc->port,"I IND :CC_SETUP|CONFIRM: old l3id:%x new l3id:%x\n", bc->l3_id, l3id);
- bc->l3_id=l3id;
-@@ -1916,11 +1956,11 @@
- }
- free_msg(msg);
- return 0;
--
-+
- case CC_SETUP|INDICATION:
- {
- struct misdn_bchannel* bc=misdn_lib_get_free_bc(stack->port, 0, 1, 0);
-- if (!bc)
-+ if (!bc)
- ERR_NO_CHANNEL:
- {
- msg_t *dmsg;
-@@ -1930,7 +1970,7 @@
- free_msg(msg);
- return 0;
- }
--
-+
- cb_log(4, stack->port, " --> new_process: New L3Id: %x\n",hh->dinfo);
- bc->l3_id=hh->dinfo;
- }
-@@ -1938,11 +1978,11 @@
-
- case CC_CONNECT_ACKNOWLEDGE|INDICATION:
- break;
--
-+
- case CC_ALERTING|INDICATION:
- case CC_PROCEEDING|INDICATION:
- case CC_SETUP_ACKNOWLEDGE|INDICATION:
-- if(!stack->ptp) break;
-+ if(!stack->ptp) break;
- case CC_CONNECT|INDICATION:
- break;
- case CC_DISCONNECT|INDICATION:
-@@ -1950,22 +1990,22 @@
- struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo);
- if (!bc) {
- bc=find_bc_by_masked_l3id(stack, hh->dinfo, 0xffff0000);
-- if (bc) {
-+ if (bc) {
- int myprocid=bc->l3_id&0x0000ffff;
- hh->dinfo=(hh->dinfo&0xffff0000)|myprocid;
- cb_log(3,stack->port,"Reject dinfo: %x cause:%d\n",hh->dinfo,bc->cause);
-- reject=1;
-+ reject=1;
- }
- }
- }
- break;
--
-+
- case CC_FACILITY|INDICATION:
- {
- struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo);
- if (!bc) {
- bc=find_bc_by_masked_l3id(stack, hh->dinfo, 0xffff0000);
-- if (bc) {
-+ if (bc) {
- int myprocid=bc->l3_id&0x0000ffff;
- hh->dinfo=(hh->dinfo&0xffff0000)|myprocid;
- cb_log(4,bc->port,"Repaired reject Bug, new dinfo: %x\n",hh->dinfo);
-@@ -1973,7 +2013,7 @@
- }
- }
- break;
--
-+
- case CC_RELEASE_COMPLETE|INDICATION:
- break;
-
-@@ -1994,13 +2034,13 @@
- {
- struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo);
-
-- if (bc) {
-+ if (bc) {
- cb_log(1, stack->port, "CC_RELEASE|CONFIRM (l3id:%x), sending RELEASE_COMPLETE\n", hh->dinfo);
- misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
- }
- }
- break;
--
-+
- case CC_RELEASE|INDICATION:
- break;
-
-@@ -2009,7 +2049,7 @@
- free_msg(msg);
- return 0 ;
- break;
--
-+
- case CC_NEW_CR|INDICATION:
- /* Got New CR for bchan, for now I handle this one in */
- /* connect_ack, Need to be changed */
-@@ -2022,36 +2062,36 @@
- stack->procids[bc->l3_id&0xff] = 0 ;
- }
- cb_log(4, stack->port, "lib: Event_ind:CC_NEW_CR : very new L3ID is %x\n",l3id );
--
-+
- bc->l3_id =l3id;
- cb_event(EVENT_NEW_L3ID, bc, glob_mgr->user_data);
--
-+
- free_msg(msg);
- return 0;
- }
--
-+
- case DL_ESTABLISH | INDICATION:
- case DL_ESTABLISH | CONFIRM:
- {
- cb_log(3, stack->port, "%% GOT L2 Activate Info.\n");
--
-+
- if (stack->ptp && stack->l2link) {
- cb_log(0, stack->port, "%% GOT L2 Activate Info. but we're activated already.. this l2 is faulty, blocking port\n");
- cb_event(EVENT_PORT_ALARM, &stack->bc[0], glob_mgr->user_data);
- }
-
- if (stack->ptp && !stack->restart_sent) {
-- /* make sure we restart the interface of the
-+ /* make sure we restart the interface of the
- * other side */
- stack->restart_sent=1;
- misdn_lib_send_restart(stack->port, -1);
-
- }
--
-+
- /* when we get the L2 UP, the L1 is UP definitely too*/
- stack->l2link = 1;
- stack->l2upcnt=0;
--
-+
- free_msg(msg);
- return 0;
- }
-@@ -2075,10 +2115,10 @@
- stack->l2upcnt++;
- }
- }
--
-- } else
-+
-+ } else
- cb_log(3, stack->port, "%% GOT L2 DeActivate Info.\n");
--
-+
- stack->l2link = 0;
- free_msg(msg);
- return 0;
-@@ -2086,37 +2126,37 @@
- break;
- }
- }
--
-+
- {
- /* Parse Events and fire_up to App. */
- struct misdn_bchannel *bc;
- struct misdn_bchannel dummybc;
--
-+
- enum event_e event = isdn_msg_get_event(msgs_g, msg, 1);
--
-+
- bc=find_bc_by_l3id(stack, hh->dinfo);
--
-+
- if (!bc) {
- cb_log(4, stack->port, " --> Didn't find BC so temporarily creating dummy BC (l3id:%x).\n", hh->dinfo);
- misdn_make_dummy(&dummybc, stack->port, hh->dinfo, stack->nt, 0);
-- bc=&dummybc;
-+ bc=&dummybc;
- }
- if (bc ) {
- isdn_msg_parse_event(msgs_g,msg,bc, 1);
-
- switch (event) {
- case EVENT_SETUP:
-- if (bc->channel<=0 || bc->channel==0xff)
-+ if (bc->channel<=0 || bc->channel==0xff)
- bc->channel=0;
--
-- if (find_free_chan_in_stack(stack,bc, bc->channel,0)<0)
-+
-+ if (find_free_chan_in_stack(stack,bc, bc->channel,0)<0)
- goto ERR_NO_CHANNEL;
- break;
- case EVENT_RELEASE:
- case EVENT_RELEASE_COMPLETE:
- {
- int channel=bc->channel;
-- int tmpcause=bc->cause;
-+ int tmpcause=bc->cause;
- empty_bc(bc);
- bc->cause=tmpcause;
- clean_up_bc(bc);
-@@ -2130,7 +2170,7 @@
- default:
- break;
- }
--
-+
- if(!isdn_get_info(msgs_g,event,1)) {
- cb_log(4, stack->port, "Unknown Event Ind: prim %x dinfo %x\n",hh->prim, hh->dinfo);
- } else {
-@@ -2161,8 +2201,8 @@
- static int handle_timers(msg_t* msg)
- {
- iframe_t *frm= (iframe_t*)msg->data;
-- struct misdn_stack *stack;
--
-+ struct misdn_stack *stack;
-+
- /* Timer Stuff */
- switch (frm->prim) {
- case MGR_INITTIMER | CONFIRM:
-@@ -2172,17 +2212,17 @@
- free_msg(msg);
- return(1);
- }
--
--
--
-+
-+
-+
- if (frm->prim==(MGR_TIMER | INDICATION) ) {
- for (stack = glob_mgr->stack_list;
- stack;
- stack = stack->next) {
- itimer_t *it;
--
-+
- if (!stack->nt) continue;
--
-+
- it = stack->nst.tlist;
- /* find timer */
- for(it=stack->nst.tlist;
-@@ -2201,12 +2241,12 @@
- return 1;
- }
- }
--
-+
- cb_log(0, 0, "Timer Msg without Timer ??\n");
- free_msg(msg);
- return 1;
- }
--
-+
- return 0;
- }
-
-@@ -2226,23 +2266,23 @@
- static int do_tone(struct misdn_bchannel *bc, int len)
- {
- bc->tone_cnt=len;
--
-+
- if (bc->generate_tone) {
- cb_event(EVENT_TONE_GENERATE, bc, glob_mgr->user_data);
--
-+
- if ( !bc->nojitter ) {
- misdn_tx_jitter(bc,len);
- }
--
-+
- return 1;
- }
--
-+
- return 0;
- }
-
-
- #ifdef MISDN_SAVE_DATA
--static void misdn_save_data(int id, char *p1, int l1, char *p2, int l2)
-+static void misdn_save_data(int id, char *p1, int l1, char *p2, int l2)
- {
- char n1[32],n2[32];
- FILE *rx, *tx;
-@@ -2250,17 +2290,17 @@
- sprintf(n1,"/tmp/misdn-rx-%d.raw",id);
- sprintf(n2,"/tmp/misdn-tx-%d.raw",id);
-
-- rx = fopen(n1,"a+");
-+ rx = fopen(n1,"a+");
- tx = fopen(n2,"a+");
-
- if (!rx || !tx) {
- cb_log(0,0,"Couldn't open files: %s\n",strerror(errno));
- return ;
- }
--
-+
- fwrite(p1,1,l1,rx);
- fwrite(p2,1,l2,tx);
--
-+
- fclose(rx);
- fclose(tx);
-
-@@ -2273,25 +2313,25 @@
- char *data=&buf[mISDN_HEADER_LEN];
- iframe_t *txfrm= (iframe_t*)buf;
- int jlen, r;
--
-+
- jlen=cb_jb_empty(bc,data,len);
--
-+
- if (jlen) {
- #ifdef MISDN_SAVE_DATA
- misdn_save_data((bc->port*100+bc->channel), data, jlen, bc->bframe, bc->bframe_len);
- #endif
- flip_buf_bits( data, jlen);
--
-+
- if (jlen < len) {
- cb_log(7,bc->port,"Jitterbuffer Underrun.\n");
- }
--
-+
- txfrm->prim = DL_DATA|REQUEST;
--
-+
- txfrm->dinfo = 0;
--
-+
- txfrm->addr = bc->addr|FLG_MSG_DOWN; /* | IF_DOWN; */
--
-+
- txfrm->len =jlen;
- cb_log(9, bc->port, "Transmitting %d samples 2 misdn\n", txfrm->len);
-
-@@ -2332,25 +2372,25 @@
- iframe_t *frm= (iframe_t*)msg->data;
- struct misdn_bchannel *bc=find_bc_by_addr(frm->addr);
- struct misdn_stack *stack;
--
-+
- if (!bc) {
- cb_log(1,0,"handle_bchan: BC not found for prim:%x with addr:%x dinfo:%x\n", frm->prim, frm->addr, frm->dinfo);
- return 0 ;
- }
--
-+
- stack = get_stack_by_bc(bc);
--
-+
- if (!stack) {
- cb_log(0, bc->port,"handle_bchan: STACK not found for prim:%x with addr:%x dinfo:%x\n", frm->prim, frm->addr, frm->dinfo);
- return 0;
- }
--
-+
- switch (frm->prim) {
-
- case MGR_SETSTACK| CONFIRM:
- cb_log(3, stack->port, "BCHAN: MGR_SETSTACK|CONFIRM pid:%d\n",bc->pid);
- break;
--
-+
- case MGR_SETSTACK| INDICATION:
- cb_log(3, stack->port, "BCHAN: MGR_SETSTACK|IND pid:%d\n",bc->pid);
- break;
-@@ -2363,9 +2403,9 @@
- usleep(1000);
- goto AGAIN;
- }
--
-+
- cb_log(0,stack->port,"$$$ Get Layer (%d) Id Error: %s\n",bc->layer,strerror(errno));
--
-+
- /* we kill the channel later, when we received some
- data. */
- bc->addr= frm->addr;
-@@ -2373,12 +2413,12 @@
- cb_log(0, stack->port,"$$$ bc->addr <0 Error:%s\n",strerror(errno));
- bc->addr=0;
- }
--
-+
- cb_log(4, stack->port," --> Got Adr %x\n", bc->addr);
-
- free_msg(msg);
--
--
-+
-+
- switch(bc->bc_state) {
- case BCHAN_SETUP:
- bc_state_change(bc,BCHAN_SETUPED);
-@@ -2395,31 +2435,31 @@
- case MGR_DELLAYER| INDICATION:
- cb_log(3, stack->port, "BCHAN: MGR_DELLAYER|IND pid:%d\n",bc->pid);
- break;
--
-+
- case MGR_DELLAYER| CONFIRM:
- cb_log(3, stack->port, "BCHAN: MGR_DELLAYER|CNF pid:%d\n",bc->pid);
--
-+
- bc->pid=0;
- bc->addr=0;
--
-+
- free_msg(msg);
- return 1;
--
-+
- case PH_ACTIVATE | INDICATION:
- case DL_ESTABLISH | INDICATION:
- cb_log(3, stack->port, "BCHAN: ACT Ind pid:%d\n", bc->pid);
-
- free_msg(msg);
-- return 1;
-+ return 1;
-
- case PH_ACTIVATE | CONFIRM:
- case DL_ESTABLISH | CONFIRM:
--
-+
- cb_log(3, stack->port, "BCHAN: bchan ACT Confirm pid:%d\n",bc->pid);
- free_msg(msg);
--
-- return 1;
-
-+ return 1;
-+
- case DL_ESTABLISH | REQUEST:
- {
- char buf[128];
-@@ -2435,33 +2475,40 @@
- }
- free_msg(msg);
- return 1;
--
-+
- case PH_DEACTIVATE | INDICATION:
- case DL_RELEASE | INDICATION:
- cb_log (3, stack->port, "BCHAN: DeACT Ind pid:%d\n",bc->pid);
--
-+
- free_msg(msg);
- return 1;
--
-+
- case PH_DEACTIVATE | CONFIRM:
- case DL_RELEASE | CONFIRM:
- cb_log(3, stack->port, "BCHAN: DeACT Conf pid:%d\n",bc->pid);
--
-+
- free_msg(msg);
- return 1;
--
-+
- case PH_CONTROL|INDICATION:
- {
- unsigned int *cont = (unsigned int *) &frm->data.p;
--
-- cb_log(4, stack->port, "PH_CONTROL: channel:%d oad%d:%s dad%d:%s \n", bc->channel, bc->onumplan,bc->oad, bc->dnumplan,bc->dad);
-
-+ cb_log(4, stack->port,
-+ "PH_CONTROL: channel:%d caller%d:\"%s\" <%s> dialed%d:%s \n",
-+ bc->channel,
-+ bc->caller.number_type,
-+ bc->caller.name,
-+ bc->caller.number,
-+ bc->dialed.number_type,
-+ bc->dialed.number);
-+
- if ((*cont & ~DTMF_TONE_MASK) == DTMF_TONE_VAL) {
- int dtmf = *cont & DTMF_TONE_MASK;
- cb_log(4, stack->port, " --> DTMF TONE: %c\n",dtmf);
- bc->dtmf=dtmf;
- cb_event(EVENT_DTMF_TONE, bc, glob_mgr->user_data);
--
-+
- free_msg(msg);
- return 1;
- }
-@@ -2482,11 +2529,11 @@
- case DL_DATA|REQUEST:
- cb_log(0, stack->port, "DL_DATA REQUEST \n");
- do_tone(bc, 64);
--
-+
- free_msg(msg);
- return 1;
--
--
-+
-+
- case PH_DATA|INDICATION:
- case DL_DATA|INDICATION:
- {
-@@ -2494,10 +2541,10 @@
- bc->bframe_len = frm->len;
-
- /** Anyway flip the bufbits **/
-- if ( misdn_cap_is_speech(bc->capability) )
-+ if ( misdn_cap_is_speech(bc->capability) )
- flip_buf_bits(bc->bframe, bc->bframe_len);
--
-
-+
- if (!bc->bframe_len) {
- cb_log(2, stack->port, "DL_DATA INDICATION bc->addr:%x frm->addr:%x\n", bc->addr, frm->addr);
- free_msg(msg);
-@@ -2509,12 +2556,12 @@
- free_msg(msg);
- return 1;
- }
--
-+
- #if MISDN_DEBUG
- cb_log(0, stack->port, "DL_DATA INDICATION Len %d\n", frm->len);
-
- #endif
--
-+
- if ( (bc->bc_state == BCHAN_ACTIVATED) && frm->len > 0) {
- int t;
-
-@@ -2528,7 +2575,7 @@
- #endif
- if ( !t ) {
- int i;
--
-+
- if ( misdn_cap_is_speech(bc->capability)) {
- if ( !bc->nojitter ) {
- #ifdef MISDN_B_DEBUG
-@@ -2541,15 +2588,15 @@
- }
- }
-
--#ifdef MISDN_B_DEBUG
-+#ifdef MISDN_B_DEBUG
- cb_log(0,bc->port,"EVENT_B_DATA START\n");
- #endif
--
-+
- i = cb_event(EVENT_BCHAN_DATA, bc, glob_mgr->user_data);
--#ifdef MISDN_B_DEBUG
-+#ifdef MISDN_B_DEBUG
- cb_log(0,bc->port,"EVENT_B_DATA STOP\n");
- #endif
--
-+
- if (i<0) {
- cb_log(10,stack->port,"cb_event returned <0\n");
- /*clean_up_bc(bc);*/
-@@ -2582,7 +2629,7 @@
- #endif
- break;
- }
--
-+
- return 0;
- }
-
-@@ -2596,29 +2643,29 @@
-
- stack=find_stack_by_addr( frm->addr );
-
--
--
-+
-+
- if (!stack || !stack->nt) {
- return 0;
- }
-
--
-+
- if ((err=stack->nst.l1_l2(&stack->nst,msg))) {
--
-+
- if (nt_err_cnt > 0 ) {
- if (nt_err_cnt < 100) {
-- nt_err_cnt++;
-+ nt_err_cnt++;
- cb_log(0, stack->port, "NT Stack sends us error: %d \n", err);
- } else if (nt_err_cnt < 105){
- cb_log(0, stack->port, "NT Stack sends us error: %d over 100 times, so I'll stop this message\n", err);
-- nt_err_cnt = - 1;
-+ nt_err_cnt = - 1;
- }
- }
- free_msg(msg);
- return 1;
--
-+
- }
--
-+
- return 1;
- }
-
-@@ -2626,13 +2673,13 @@
- static int handle_frm(msg_t *msg)
- {
- iframe_t *frm = (iframe_t*) msg->data;
--
-+
- struct misdn_stack *stack=find_stack_by_addr(frm->addr);
-
- if (!stack || stack->nt) {
- return 0;
- }
--
-+
- cb_log(4,stack?stack->port:0,"handle_frm: frm->addr:%x frm->prim:%x\n",frm->addr,frm->prim);
-
- {
-@@ -2650,7 +2697,7 @@
- free_msg(msg);
- return 1;
- }
--
-+
- bc=find_bc_by_l3id(stack, frm->dinfo);
-
- if (!bc && (frm->prim==(CC_RESTART|CONFIRM)) ) {
-@@ -2670,15 +2717,15 @@
- return 1;
- }
-
--
-+
- handle_frm_bc:
- if (bc ) {
- enum event_e event = isdn_msg_get_event(msgs_g, msg, 0);
- enum event_response_e response=RESPONSE_OK;
- int ret;
--
-+
- isdn_msg_parse_event(msgs_g,msg,bc, 0);
--
-+
- /** Preprocess some Events **/
- ret = handle_event(bc, event, frm);
- if (ret<0) {
-@@ -2688,8 +2735,8 @@
- }
- /* shoot up event to App: */
- cb_log(5, stack->port, "lib Got Prim: Addr %x prim %x dinfo %x\n",frm->addr, frm->prim, frm->dinfo);
--
-- if(!isdn_get_info(msgs_g,event,0))
-+
-+ if(!isdn_get_info(msgs_g,event,0))
- cb_log(0, stack->port, "Unknown Event Ind: Addr:%x prim %x dinfo %x\n",frm->addr, frm->prim, frm->dinfo);
- else
- response=cb_event(event, bc, glob_mgr->user_data);
-@@ -2698,13 +2745,13 @@
- switch (response) {
- case RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE:
-
-- cb_log(0, stack->port, "TOTALLY IGNORING SETUP\n");
--
-+ cb_log(0, stack->port, "TOTALLY IGNORING SETUP\n");
-+
- break;
- case RESPONSE_IGNORE_SETUP:
- /* I think we should send CC_RELEASE_CR, but am not sure*/
- bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
--
-+
- case RESPONSE_RELEASE_SETUP:
- misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
- if (bc->channel>0)
-@@ -2718,7 +2765,7 @@
- case RESPONSE_OK:
- cb_log(4, stack->port, "GOT SETUP OK\n");
-
--
-+
- break;
- default:
- break;
-@@ -2728,13 +2775,13 @@
- if (event == EVENT_RELEASE_COMPLETE) {
- /* release bchannel only after we've announced the RELEASE_COMPLETE */
- int channel=bc->channel;
-- int tmpcause=bc->cause;
-- int tmp_out_cause=bc->out_cause;
-+ int tmpcause=bc->cause;
-+ int tmp_out_cause=bc->out_cause;
- empty_bc(bc);
- bc->cause=tmpcause;
- bc->out_cause=tmp_out_cause;
- clean_up_bc(bc);
--
-+
- if (tmpcause == AST_CAUSE_REQUESTED_CHAN_UNAVAIL) {
- cb_log(0,stack->port,"**** Received CAUSE:%d, so not cleaning up channel %d\n", AST_CAUSE_REQUESTED_CHAN_UNAVAIL, channel);
- cb_log(0,stack->port,"**** This channel is now no longer available,\nplease try to restart it with 'misdn send restart <port> <channel>'\n");
-@@ -2755,11 +2802,11 @@
-
- cb_log(5, stack->port, "Freeing Msg on prim:%x \n",frm->prim);
-
--
-+
- free_msg(msg);
- return 1;
- #endif
--
-+
- } else {
- struct misdn_bchannel dummybc;
- if (frm->prim!=(CC_FACILITY|INDICATION))
-@@ -2770,7 +2817,7 @@
- memset (&dummybc,0,sizeof(dummybc));
- dummybc.port=stack->port;
- dummybc.l3_id=frm->dinfo;
-- bc=&dummybc;
-+ bc=&dummybc;
- goto handle_frm_bc;
- }
- }
-@@ -2785,7 +2832,7 @@
- iframe_t *frm = (iframe_t*) msg->data;
- struct misdn_stack *stack = find_stack_by_addr(frm->addr);
- int i ;
--
-+
- if (!stack) return 0 ;
-
- switch (frm->prim) {
-@@ -2793,9 +2840,9 @@
- case PH_ACTIVATE | INDICATION:
- cb_log (3, stack->port, "L1: PH L1Link Up!\n");
- stack->l1link=1;
--
-+
- if (stack->nt) {
--
-+
- if (stack->nst.l1_l2(&stack->nst, msg))
- free_msg(msg);
-
-@@ -2804,14 +2851,14 @@
- } else {
- free_msg(msg);
- }
--
-+
- for (i=0;i<=stack->b_num; i++) {
- if (stack->bc[i].evq != EVENT_NOTHING) {
- cb_log(4, stack->port, "Firing Queued Event %s because L1 got up\n", isdn_get_info(msgs_g, stack->bc[i].evq, 0));
- misdn_lib_send_event(&stack->bc[i],stack->bc[i].evq);
- stack->bc[i].evq=EVENT_NOTHING;
- }
--
-+
- }
- return 1;
-
-@@ -2819,16 +2866,16 @@
- free_msg(msg);
- cb_log(3,stack->port,"L1: PH_ACTIVATE|REQUEST \n");
- return 1;
--
-+
- case PH_DEACTIVATE | REQUEST:
- free_msg(msg);
- cb_log(3,stack->port,"L1: PH_DEACTIVATE|REQUEST \n");
- return 1;
--
-+
- case PH_DEACTIVATE | CONFIRM:
- case PH_DEACTIVATE | INDICATION:
- cb_log (3, stack->port, "L1: PH L1Link Down! \n");
--
-+
- #if 0
- for (i=0; i<=stack->b_num; i++) {
- if (global_state == MISDN_INITIALIZED) {
-@@ -2836,19 +2883,19 @@
- }
- }
- #endif
--
-+
- if (stack->nt) {
- if (stack->nst.l1_l2(&stack->nst, msg))
- free_msg(msg);
- } else {
- free_msg(msg);
- }
--
-+
- stack->l1link=0;
- stack->l2link=0;
- return 1;
- }
--
-+
- return 0;
- }
-
-@@ -2857,11 +2904,11 @@
- iframe_t *frm = (iframe_t*) msg->data;
-
- struct misdn_stack *stack = find_stack_by_addr(frm->addr);
--
-+
- if (!stack) {
- return 0 ;
- }
--
-+
- switch(frm->prim) {
-
- case DL_ESTABLISH | REQUEST:
-@@ -2870,13 +2917,13 @@
- case DL_RELEASE | REQUEST:
- cb_log(1,stack->port,"DL_RELEASE|REQUEST \n");
- return 1;
--
-+
- case DL_ESTABLISH | INDICATION:
- case DL_ESTABLISH | CONFIRM:
- {
- cb_log (3, stack->port, "L2: L2Link Up! \n");
- if (stack->ptp && stack->l2link) {
-- cb_log (-1, stack->port, "L2: L2Link Up! but it's already UP.. must be faulty, blocking port\n");
-+ cb_log (-1, stack->port, "L2: L2Link Up! but it's already UP.. must be faulty, blocking port\n");
- cb_event(EVENT_PORT_ALARM, &stack->bc[0], glob_mgr->user_data);
- }
- stack->l2link=1;
-@@ -2884,13 +2931,13 @@
- return 1;
- }
- break;
--
-+
- case DL_RELEASE | INDICATION:
- case DL_RELEASE | CONFIRM:
- {
- cb_log (3, stack->port, "L2: L2Link Down! \n");
- stack->l2link=0;
--
-+
- free_msg(msg);
- return 1;
- }
-@@ -2909,9 +2956,9 @@
- free_msg(msg);
- return 1;
- }
--
-+
- stack = find_stack_by_addr(frm->addr);
--
-+
- if (!stack) {
- if (frm->prim == (MGR_DELLAYER|CONFIRM)) {
- cb_log(2, 0, "MGMT: DELLAYER|CONFIRM Addr: %x !\n",
-@@ -2919,20 +2966,20 @@
- free_msg(msg);
- return 1;
- }
--
-+
- return 0;
- }
--
-+
- switch(frm->prim) {
- case MGR_SHORTSTATUS | INDICATION:
- case MGR_SHORTSTATUS | CONFIRM:
- cb_log(5, 0, "MGMT: Short status dinfo %x\n",frm->dinfo);
--
-+
- switch (frm->dinfo) {
- case SSTATUS_L1_ACTIVATED:
- cb_log(3, 0, "MGMT: SSTATUS: L1_ACTIVATED \n");
- stack->l1link=1;
--
-+
- break;
- case SSTATUS_L1_DEACTIVATED:
- cb_log(3, 0, "MGMT: SSTATUS: L1_DEACTIVATED \n");
-@@ -2946,16 +2993,16 @@
- cb_log(3, stack->port, "MGMT: SSTATUS: L2_ESTABLISH \n");
- stack->l2link=1;
- break;
--
-+
- case SSTATUS_L2_RELEASED:
- cb_log(3, stack->port, "MGMT: SSTATUS: L2_RELEASED \n");
- stack->l2link=0;
- break;
- }
--
-+
- free_msg(msg);
- return 1;
--
-+
- case MGR_SETSTACK | INDICATION:
- cb_log(4, stack->port, "MGMT: SETSTACK|IND dinfo %x\n",frm->dinfo);
- free_msg(msg);
-@@ -2964,21 +3011,21 @@
- cb_log(4, stack->port, "MGMT: DELLAYER|CNF dinfo %x\n",frm->dinfo) ;
- free_msg(msg);
- return 1;
--
-+
- }
--
-+
- /*
- if ( (frm->prim & 0x0f0000) == 0x0f0000) {
- cb_log(5, 0, "$$$ MGMT FRAME: prim %x addr %x dinfo %x\n",frm->prim, frm->addr, frm->dinfo) ;
- free_msg(msg);
- return 1;
- } */
--
-+
- return 0;
- }
-
-
--static msg_t *fetch_msg(int midev)
-+static msg_t *fetch_msg(int midev)
- {
- msg_t *msg=alloc_msg(MAX_MSG_SIZE);
- int r;
-@@ -2991,7 +3038,7 @@
- AGAIN:
- r=mISDN_read(midev,msg->data,MAX_MSG_SIZE, TIMEOUT_10SEC);
- msg->len=r;
--
-+
- if (r==0) {
- free_msg(msg); /* danger, cause usually freeing in main_loop */
- cb_log(6,0,"Got empty Msg..\n");
-@@ -3005,8 +3052,8 @@
- usleep(5000);
- goto AGAIN;
- }
--
-- cb_log(0,0,"mISDN_read returned :%d error:%s (%d)\n",r,strerror(errno),errno);
-+
-+ cb_log(0,0,"mISDN_read returned :%d error:%s (%d)\n",r,strerror(errno),errno);
- }
-
- #if 0
-@@ -3024,12 +3071,12 @@
- ;
-
- if (stack) {
-- cb_log(4, port, "Checking L1 State\n");
-+ cb_log(4, port, "Checking L1 State\n");
- if (!stack->l1link) {
-- cb_log(4, port, "L1 State Down, trying to get it up again\n");
-+ cb_log(4, port, "L1 State Down, trying to get it up again\n");
- misdn_lib_get_short_status(stack);
-- misdn_lib_get_l1_up(stack);
-- misdn_lib_get_l2_up(stack);
-+ misdn_lib_get_l1_up(stack);
-+ misdn_lib_get_l2_up(stack);
- }
- }
- }
-@@ -3041,19 +3088,19 @@
- int zero_frm=0 , fff_frm=0 ;
- int midev= mgr->midev;
- int port=0;
--
-+
- while (1) {
-- msg_t *msg = fetch_msg(midev);
-+ msg_t *msg = fetch_msg(midev);
- iframe_t *frm;
--
--
-+
-+
- if (!msg) continue;
--
-+
- frm = (iframe_t*) msg->data;
--
-+
- /** When we make a call from NT2Ast we get these frames **/
- if (frm->len == 0 && frm->addr == 0 && frm->dinfo == 0 && frm->prim == 0 ) {
-- zero_frm++;
-+ zero_frm++;
- free_msg(msg);
- continue;
- } else {
-@@ -3062,10 +3109,10 @@
- zero_frm = 0 ;
- }
- }
--
-+
- /** I get this sometimes after setup_bc **/
- if (frm->len == 0 && frm->dinfo == 0 && frm->prim == 0xffffffff ) {
-- fff_frm++;
-+ fff_frm++;
- free_msg(msg);
- continue;
- } else {
-@@ -3074,7 +3121,7 @@
- fff_frm = 0 ;
- }
- }
--
-+
- manager_isdn_handler(frm, msg);
- }
-
-@@ -3090,24 +3137,24 @@
- int ret;
-
- if (midev<=0) return midev;
--
-+
- /* create entity for layer 3 TE-mode */
- mISDN_write_frame(midev, buff, 0, MGR_NEWENTITY | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
- ret = mISDN_read_frame(midev, frm, sizeof(iframe_t), 0, MGR_NEWENTITY | CONFIRM, TIMEOUT_1SEC);
--
-+
- if (ret < mISDN_HEADER_LEN) {
- noentity:
- fprintf(stderr, "cannot request MGR_NEWENTITY from mISDN: %s\n",strerror(errno));
- exit(-1);
- }
--
-+
- entity = frm->dinfo & 0xffff ;
--
-+
- if (!entity)
- goto noentity;
-
- return midev;
--
-+
- }
-
- void te_lib_destroy(int midev)
-@@ -3131,14 +3178,14 @@
- {
- struct misdn_stack *stack;
- int i;
--
-+
- for (stack=glob_mgr->stack_list;
- stack;
- stack=stack->next) {
- for (i=0; i<=stack->b_num; i++)
- if (stack->bc[i].pid == pid) return &stack->bc[i];
- }
--
-+
- return NULL;
- }
-
-@@ -3159,12 +3206,12 @@
- cb_log(2,bc->port, "channel with stid:%x for one second still in use! (n:%d lu:%d)\n", bc->b_stid, (int) now.tv_sec, (int) bc->last_used.tv_sec);
- return 1;
- }
--
-
-+
- cb_log(3,bc->port, "channel with stid:%x not in use!\n", bc->b_stid);
- return 0;
- }
--
-+
- cb_log(2,bc->port, "channel with stid:%x in use!\n", bc->b_stid);
- return 1;
- }
-@@ -3194,7 +3241,7 @@
- {
- struct misdn_stack *stack;
- int i;
--
-+
- if (channel < 0 || channel > MAX_BCHANS) {
- cb_log(0,port,"Requested channel out of bounds (%d)\n",channel);
- return NULL;
-@@ -3203,7 +3250,7 @@
- usleep(1000);
-
- for (stack=glob_mgr->stack_list; stack; stack=stack->next) {
--
-+
- if (stack->port == port) {
- int maxnum;
-
-@@ -3211,12 +3258,12 @@
- cb_log(0,port,"Port is blocked\n");
- return NULL;
- }
--
-+
- if (channel > 0) {
- if (channel <= stack->b_num) {
- for (i = 0; i < stack->b_num; i++) {
- if ( stack->bc[i].channel == channel) {
-- if (test_inuse(&stack->bc[i])) {
-+ if (test_inuse(&stack->bc[i])) {
- cb_log(0,port,"Requested channel:%d on port:%d is already in use\n",channel, port);
- return NULL;
-
-@@ -3240,7 +3287,7 @@
- /* 3. channel on bri means CW*/
- if (!stack->pri && i==stack->b_num)
- stack->bc[i].cw=1;
--
-+
- prepare_bc(&stack->bc[i], channel);
- stack->bc[i].dec=1;
- return &stack->bc[i];
-@@ -3268,10 +3315,6 @@
- return NULL;
- }
-
--
--
--
--/* ******************************************************************* */
- /*!
- * \internal
- * \brief Convert the facility function enum value into a string.
-@@ -3280,36 +3323,30 @@
- */
- static const char *fac2str(enum FacFunction facility)
- {
-- static const struct {
-- enum FacFunction facility;
-+ static const struct {
-+ enum FacFunction facility;
- char *name;
- } arr[] = {
- /* *INDENT-OFF* */
- { Fac_None, "Fac_None" },
-- { Fac_GetSupportedServices, "Fac_GetSupportedServices" },
-- { Fac_Listen, "Fac_Listen" },
-- { Fac_Suspend, "Fac_Suspend" },
-- { Fac_Resume, "Fac_Resume" },
- { Fac_CFActivate, "Fac_CFActivate" },
- { Fac_CFDeactivate, "Fac_CFDeactivate" },
-- { Fac_CFInterrogateParameters, "Fac_CFInterrogateParameters" },
-- { Fac_CFInterrogateNumbers, "Fac_CFInterrogateNumbers" },
- { Fac_CD, "Fac_CD" },
- { Fac_AOCDCurrency, "Fac_AOCDCurrency" },
- { Fac_AOCDChargingUnit, "Fac_AOCDChargingUnit" },
- /* *INDENT-ON* */
- };
--
-+
- unsigned index;
--
-+
- for (index = 0; index < ARRAY_LEN(arr); ++index) {
- if (arr[index].facility == facility) {
- return arr[index].name;
- }
-- } /* end for */
-+ }
-
- return "unknown";
--} /* end fac2str() */
-+}
-
- void misdn_lib_log_ies(struct misdn_bchannel *bc)
- {
-@@ -3321,27 +3358,57 @@
-
- if (!stack) return;
-
-- cb_log(2, stack->port, " --> channel:%d mode:%s cause:%d ocause:%d rad:%s cad:%s\n", bc->channel, stack->nt?"NT":"TE", bc->cause, bc->out_cause, bc->rad, bc->cad);
--
- cb_log(2, stack->port,
-- " --> info_dad:%s onumplan:%c dnumplan:%c rnumplan:%c cpnnumplan:%c\n",
-- bc->info_dad,
-- bc->onumplan>=0?'0'+bc->onumplan:' ',
-- bc->dnumplan>=0?'0'+bc->dnumplan:' ',
-- bc->rnumplan>=0?'0'+bc->rnumplan:' ',
-- bc->cpnnumplan>=0?'0'+bc->cpnnumplan:' '
-- );
--
-+ " --> channel:%d mode:%s cause:%d ocause:%d\n",
-+ bc->channel,
-+ stack->nt ? "NT" : "TE",
-+ bc->cause,
-+ bc->out_cause);
-+
-+ cb_log(2, stack->port,
-+ " --> info_dad:%s dialed numtype:%d plan:%d\n",
-+ bc->info_dad,
-+ bc->dialed.number_type,
-+ bc->dialed.number_plan);
-+
-+ cb_log(2, stack->port,
-+ " --> caller:\"%s\" <%s> type:%d plan:%d pres:%d screen:%d\n",
-+ bc->caller.name,
-+ bc->caller.number,
-+ bc->caller.number_type,
-+ bc->caller.number_plan,
-+ bc->caller.presentation,
-+ bc->caller.screening);
-+
-+ cb_log(2, stack->port,
-+ " --> redirecting:\"%s\" <%s> type:%d plan:%d pres:%d screen:%d reason:%d\n",
-+ bc->redirecting.from.name,
-+ bc->redirecting.from.number,
-+ bc->redirecting.from.number_type,
-+ bc->redirecting.from.number_plan,
-+ bc->redirecting.from.presentation,
-+ bc->redirecting.from.screening,
-+ bc->redirecting.reason);
-+
-+ cb_log(2, stack->port,
-+ " --> connected:\"%s\" <%s> type:%d plan:%d pres:%d screen:%d\n",
-+ bc->connected.name,
-+ bc->connected.number,
-+ bc->connected.number_type,
-+ bc->connected.number_plan,
-+ bc->connected.presentation,
-+ bc->connected.screening);
-+
- cb_log(3, stack->port, " --> caps:%s pi:%x keypad:%s sending_complete:%d\n", bearer2str(bc->capability),bc->progress_indicator, bc->keypad, bc->sending_complete);
-- cb_log(4, stack->port, " --> screen:%d --> pres:%d\n",
-- bc->screen, bc->pres);
--
-+
-+ cb_log(4, stack->port, " --> set_pres:%d pres:%d\n", bc->set_presentation, bc->presentation);
-+
- cb_log(4, stack->port, " --> addr:%x l3id:%x b_stid:%x layer_id:%x\n", bc->addr, bc->l3_id, bc->b_stid, bc->layer_id);
--
-+
- cb_log(4, stack->port, " --> facility:%s out_facility:%s\n",fac2str(bc->fac_in.Function),fac2str(bc->fac_out.Function));
-
- cb_log(5, stack->port, " --> urate:%d rate:%d mode:%d user1:%d\n", bc->urate, bc->rate, bc->mode,bc->user1);
--
-+
- cb_log(5, stack->port, " --> bc:%p h:%d sh:%d\n", bc, bc->holded, bc->stack_holder);
- }
-
-@@ -3364,19 +3431,24 @@
-
- int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event )
- {
-- msg_t *msg;
-+ msg_t *msg;
- int retval=0;
- struct misdn_stack *stack;
--
-+
- if (!bc) RETURN(-1,OUT_POST_UNLOCK);
--
-+
- stack = get_stack_by_bc(bc);
--
-+
- if (!stack) {
-- cb_log(0,bc->port,"SENDEVENT: no Stack for event:%s oad:%s dad:%s \n", isdn_get_info(msgs_g, event, 0), bc->oad, bc->dad);
-+ cb_log(0,bc->port,
-+ "SENDEVENT: no Stack for event:%s caller:\"%s\" <%s> dialed:%s \n",
-+ isdn_get_info(msgs_g, event, 0),
-+ bc->caller.name,
-+ bc->caller.number,
-+ bc->dialed.number);
- RETURN(-1,OUT);
- }
--
-+
- misdn_send_lock(bc);
-
-
-@@ -3389,11 +3461,17 @@
- misdn_lib_get_l1_up(stack);
- RETURN(0,OUT);
- }
--
-- cb_log(1, stack->port, "I SEND:%s oad:%s dad:%s pid:%d\n", isdn_get_info(msgs_g, event, 0), bc->oad, bc->dad, bc->pid);
-+
-+ cb_log(1, stack->port,
-+ "I SEND:%s caller:\"%s\" <%s> dialed:%s pid:%d\n",
-+ isdn_get_info(msgs_g, event, 0),
-+ bc->caller.name,
-+ bc->caller.number,
-+ bc->dialed.number,
-+ bc->pid);
- cb_log(4, stack->port, " --> bc_state:%s\n",bc_state2str(bc->bc_state));
- misdn_lib_log_ies(bc);
--
-+
- switch (event) {
- case EVENT_SETUP:
- if (create_process(glob_mgr->midev, bc)<0) {
-@@ -3431,19 +3509,26 @@
- if (misdn_cap_is_speech(bc->capability)) {
- if ((event==EVENT_CONNECT)||(event==EVENT_RETRIEVE_ACKNOWLEDGE)) {
- if ( *bc->crypt_key ) {
-- cb_log(4, stack->port, " --> ENABLING BLOWFISH channel:%d oad%d:%s dad%d:%s \n", bc->channel, bc->onumplan,bc->oad, bc->dnumplan,bc->dad);
--
-+ cb_log(4, stack->port,
-+ " --> ENABLING BLOWFISH channel:%d caller%d:\"%s\" <%s> dialed%d:%s\n",
-+ bc->channel,
-+ bc->caller.number_type,
-+ bc->caller.name,
-+ bc->caller.number,
-+ bc->dialed.number_type,
-+ bc->dialed.number);
-+
- manager_ph_control_block(bc, BF_ENABLE_KEY, bc->crypt_key, strlen(bc->crypt_key) );
- }
--
-+
- if (!bc->nodsp) manager_ph_control(bc, DTMF_TONE_START, 0);
- manager_ec_enable(bc);
--
-+
- if (bc->txgain != 0) {
- cb_log(4, stack->port, "--> Changing txgain to %d\n", bc->txgain);
- manager_ph_control(bc, VOL_CHANGE_TX, bc->txgain);
- }
--
-+
- if ( bc->rxgain != 0 ) {
- cb_log(4, stack->port, "--> Changing rxgain to %d\n", bc->rxgain);
- manager_ph_control(bc, VOL_CHANGE_RX, bc->rxgain);
-@@ -3466,7 +3551,7 @@
- bc_state_change(holded_bc,BCHAN_CLEANED);
-
- stack_holder_add(stack,holded_bc);
--
-+
- /*kill the bridge and clean the bchannel*/
- if (stack->nt) {
- int channel;
-@@ -3481,7 +3566,7 @@
- misdn_split_conf(bc2,bc->conf_id);
- }
- }
--
-+
- channel = bc->channel;
-
- empty_bc(bc);
-@@ -3490,9 +3575,9 @@
- if (channel>0)
- empty_chan_in_stack(stack,channel);
-
-- bc->in_use=0;
-+ bc->in_use=0;
- }
--
-+
- }
- break;
-
-@@ -3502,7 +3587,7 @@
- cb_log(0,bc->port," --> we have already send Disconnect\n");
- RETURN(-1,OUT);
- }
--
-+
- bc->need_disconnect=0;
- break;
- case EVENT_RELEASE:
-@@ -3526,30 +3611,30 @@
- /*create cleanup in TE*/
- int channel=bc->channel;
-
-- int tmpcause=bc->cause;
-- int tmp_out_cause=bc->out_cause;
-+ int tmpcause=bc->cause;
-+ int tmp_out_cause=bc->out_cause;
- empty_bc(bc);
- bc->cause=tmpcause;
- bc->out_cause=tmp_out_cause;
- clean_up_bc(bc);
--
-+
- if (channel>0)
- empty_chan_in_stack(stack,channel);
--
-+
- bc->in_use=0;
- }
- break;
--
-+
- case EVENT_CONNECT_ACKNOWLEDGE:
-
- if ( bc->nt || misdn_cap_is_speech(bc->capability)) {
- int retval=setup_bc(bc);
- if (retval == -EINVAL){
- cb_log(0,bc->port,"send_event: setup_bc failed\n");
--
-+
- }
- }
--
-+
- if (misdn_cap_is_speech(bc->capability)) {
- if ( !bc->nodsp) manager_ph_control(bc, DTMF_TONE_START, 0);
- manager_ec_enable(bc);
-@@ -3564,21 +3649,32 @@
- }
- }
- break;
--
-+
- default:
- break;
- }
--
-+
- /* Later we should think about sending bchannel data directly to misdn. */
- msg = isdn_msg_build_event(msgs_g, bc, event, stack->nt);
-- msg_queue_tail(&stack->downqueue, msg);
-- sem_post(&glob_mgr->new_msg);
--
-+ if (!msg) {
-+ /*
-+ * The message was not built.
-+ *
-+ * NOTE: The only time that the message will fail to build
-+ * is because the requested FACILITY message is not supported.
-+ * A failed malloc() results in exit() being called.
-+ */
-+ RETURN(-1, OUT);
-+ } else {
-+ msg_queue_tail(&stack->downqueue, msg);
-+ sem_post(&glob_mgr->new_msg);
-+ }
-+
- OUT:
- misdn_send_unlock(bc);
-
- OUT_POST_UNLOCK:
-- return retval;
-+ return retval;
- }
-
-
-@@ -3596,12 +3692,12 @@
- cb_log(0,0,"mISDN Msg without Address pr:%x dinfo:%x (already more than 100 of them)\n",frm->prim,frm->dinfo);
- cnt=0;
- }
--
-+
- free_msg(msg);
- return 1;
--
-+
- }
--
-+
- switch (frm->prim) {
- case MGR_SETSTACK|INDICATION:
- return handle_bchan(msg);
-@@ -3609,7 +3705,7 @@
-
- case MGR_SETSTACK|CONFIRM:
- case MGR_CLEARSTACK|CONFIRM:
-- free_msg(msg) ;
-+ free_msg(msg) ;
- return 1;
- break;
-
-@@ -3630,13 +3726,13 @@
- struct misdn_bchannel *bc;
-
- /*we flush the read buffer here*/
--
-+
- cb_log(9,0,"BCHAN DATA without BC: addr:%x port:%d channel:%d\n",frm->addr, port,channel);
--
-- free_msg(msg);
-+
-+ free_msg(msg);
- return 1;
--
--
-+
-+
- bc = find_bc_by_channel(port, channel);
-
- if (!bc) {
-@@ -3647,7 +3743,7 @@
- free_msg(msg);
- return 1;
- }
--
-+
- cb_log(0,0," --> bc not found by channel\n");
- if (stack->l2link)
- misdn_lib_get_l2_down(stack);
-@@ -3658,7 +3754,7 @@
- free_msg(msg);
- return 1;
- }
--
-+
- cb_log(3,port," --> BC in state:%s\n", bc_state2str(bc->bc_state));
- }
- }
-@@ -3673,7 +3769,7 @@
- struct misdn_stack *stack;
- stack=find_stack_by_addr( frm->addr );
-
--
-+
- if (!stack) {
- return 0;
- }
-@@ -3685,7 +3781,7 @@
- #endif
-
- int manager_isdn_handler(iframe_t *frm ,msg_t *msg)
--{
-+{
-
- if (frm->dinfo==0xffffffff && frm->prim==(PH_DATA|CONFIRM)) {
- cb_log(0,0,"SERIOUS BUG, dinfo == 0xffffffff, prim == PH_DATA | CONFIRM !!!!\n");
-@@ -3696,35 +3792,35 @@
- if (handle_bchan(msg)) {
- return 0 ;
- }
--
-+
- if (unhandled_bmsg_count==1000) {
-- cb_log(0, 0, "received 1k Unhandled Bchannel Messages: prim %x len %d from addr %x, dinfo %x on this port.\n",frm->prim, frm->len, frm->addr, frm->dinfo);
-+ cb_log(0, 0, "received 1k Unhandled Bchannel Messages: prim %x len %d from addr %x, dinfo %x on this port.\n",frm->prim, frm->len, frm->addr, frm->dinfo);
- unhandled_bmsg_count=0;
- }
-
- unhandled_bmsg_count++;
- free_msg(msg);
- return 0;
-- }
-+ }
-
- #ifdef RECV_FRM_SYSLOG_DEBUG
- syslog(LOG_NOTICE,"mISDN recv: P(%02d): ADDR:%x PRIM:%x DINFO:%x\n",stack->port, frm->addr, frm->prim, frm->dinfo);
- #endif
-
-- if (handle_timers(msg))
-+ if (handle_timers(msg))
- return 0 ;
-
--
-- if (handle_mgmt(msg))
-- return 0 ;
--
-- if (handle_l2(msg))
-+
-+ if (handle_mgmt(msg))
- return 0 ;
-
-+ if (handle_l2(msg))
-+ return 0 ;
-+
- /* Its important to handle l1 AFTER l2 */
-- if (handle_l1(msg))
-+ if (handle_l1(msg))
- return 0 ;
--
-+
- if (handle_frm_nt(msg)) {
- return 0;
- }
-@@ -3737,10 +3833,10 @@
- return 0 ;
- }
-
-- cb_log(0, 0, "Unhandled Message: prim %x len %d from addr %x, dinfo %x on this port.\n",frm->prim, frm->len, frm->addr, frm->dinfo);
-+ cb_log(0, 0, "Unhandled Message: prim %x len %d from addr %x, dinfo %x on this port.\n",frm->prim, frm->len, frm->addr, frm->dinfo);
- free_msg(msg);
--
-
-+
- return 0;
- }
-
-@@ -3768,16 +3864,16 @@
-
- frm->dinfo = 0;
- frm->len = 0;
--
-+
- msg_queue_tail(&glob_mgr->activatequeue, msg);
- sem_post(&glob_mgr->new_msg);
-
--
-- return 0;
-+
-+ return 0;
- }
-
-
--int queue_cleanup_bc(struct misdn_bchannel *bc)
-+int queue_cleanup_bc(struct misdn_bchannel *bc)
- {
- msg_t *msg=alloc_msg(MAX_MSG_SIZE);
- iframe_t *frm;
-@@ -3794,15 +3890,15 @@
-
- frm->dinfo = bc->port;
- frm->len = 0;
--
-+
- msg_queue_tail(&glob_mgr->activatequeue, msg);
- sem_post(&glob_mgr->new_msg);
-
-- return 0;
-+ return 0;
-
- }
-
--int misdn_lib_pid_restart(int pid)
-+int misdn_lib_pid_restart(int pid)
- {
- struct misdn_bchannel *bc=manager_find_bc_by_pid(pid);
-
-@@ -3819,7 +3915,7 @@
- struct misdn_bchannel dummybc;
- /*default is all channels*/
- cb_log(0, port, "Sending Restarts on this port.\n");
--
-+
- misdn_make_dummy(&dummybc, stack->port, MISDN_ID_GLOBAL, stack->nt, 0);
-
- /*default is all channels*/
-@@ -3855,11 +3951,11 @@
- int misdn_lib_port_restart(int port)
- {
- struct misdn_stack *stack=find_stack_by_port(port);
--
-+
- cb_log(0, port, "Restarting this port.\n");
- if (stack) {
- cb_log(0, port, "Stack:%p\n",stack);
--
-+
- clear_l3(stack);
- {
- msg_t *msg=alloc_msg(MAX_MSG_SIZE);
-@@ -3869,7 +3965,7 @@
- cb_log(0, port, "port_restart: alloc_msg failed\n");
- return -1;
- }
--
-+
- frm=(iframe_t*)msg->data;
- /* we must activate if we are deactivated */
- /* activate bchannel */
-@@ -3884,7 +3980,7 @@
-
- if (stack->nt)
- misdn_lib_reinit_nt_stack(stack->port);
--
-+
- }
-
- return 0;
-@@ -3892,25 +3988,25 @@
-
-
-
--static sem_t handler_started;
-+static sem_t handler_started;
-
- /* This is a thread */
- static void manager_event_handler(void *arg)
- {
-- sem_post(&handler_started);
-+ sem_post(&handler_started);
- while (1) {
- struct misdn_stack *stack;
- msg_t *msg;
--
-+
- /** wait for events **/
- sem_wait(&glob_mgr->new_msg);
--
-+
- for (msg=msg_dequeue(&glob_mgr->activatequeue);
- msg;
- msg=msg_dequeue(&glob_mgr->activatequeue)
- )
- {
--
-+
- iframe_t *frm = (iframe_t*) msg->data ;
-
- switch ( frm->prim) {
-@@ -3925,7 +4021,7 @@
- free_msg(msg);
- break;
- }
--
-+
- bc = find_bc_by_l3id(stack, frm->addr);
- if (bc) {
- cb_log(1,bc->port,"CLEARSTACK queued, cleaning up\n");
-@@ -3934,7 +4030,7 @@
- cb_log(0,stack->port,"bc could not be cleaned correctly !! addr [%x]\n",frm->addr);
- }
- }
-- free_msg(msg);
-+ free_msg(msg);
- break;
- case MGR_SETSTACK | REQUEST :
- /* Warning: memory leak here if we get this message */
-@@ -3947,10 +4043,10 @@
-
- for (stack=glob_mgr->stack_list;
- stack;
-- stack=stack->next ) {
-+ stack=stack->next ) {
-
- while ( (msg=msg_dequeue(&stack->upqueue)) ) {
-- /** Handle L2/3 Signalling after bchans **/
-+ /** Handle L2/3 Signalling after bchans **/
- if (!handle_frm_nt(msg)) {
- /* Maybe it's TE */
- if (!handle_frm(msg)) {
-@@ -3960,16 +4056,16 @@
- }
- }
-
-- /* Here we should check if we really want to
-- send all the messages we've queued, lets
-- assume we've queued a Disconnect, but
-+ /* Here we should check if we really want to
-+ send all the messages we've queued, lets
-+ assume we've queued a Disconnect, but
- received it already from the other side!*/
--
-+
- while ( (msg=msg_dequeue(&stack->downqueue)) ) {
- if (stack->nt ) {
- if (stack->nst.manager_l3(&stack->nst, msg))
- cb_log(0, stack->port, "Error@ Sending Message in NT-Stack.\n");
--
-+
- } else {
- iframe_t *frm = (iframe_t *)msg->data;
- struct misdn_bchannel *bc = find_bc_by_l3id(stack, frm->dinfo);
-@@ -3998,14 +4094,14 @@
-
- int i = mISDN_open();
- int max=0;
--
-+
- if (i<0)
- return -1;
-
- max = mISDN_get_stack_count(i);
--
-+
- mISDN_close(i);
--
-+
- return max;
- }
-
-@@ -4022,12 +4118,12 @@
- #endif
- }
-
--void misdn_lib_nt_debug_init( int flags, char *file )
-+void misdn_lib_nt_debug_init( int flags, char *file )
- {
- static int init=0;
- char *f;
--
-- if (!flags)
-+
-+ if (!flags)
- f=NULL;
- else
- f=file;
-@@ -4048,50 +4144,50 @@
- char plist[1024];
- int midev;
- int port_count=0;
--
-+
- cb_log = iface->cb_log;
- cb_event = iface->cb_event;
- cb_jb_empty = iface->cb_jb_empty;
--
-+
- glob_mgr = mgr;
--
-+
- msg_init();
-
- misdn_lib_nt_debug_init(0,NULL);
--
-+
- if (!portlist || (*portlist == 0) ) return 1;
--
-+
- init_flip_bits();
--
-+
- {
- strncpy(plist,portlist, 1024);
- plist[1023] = 0;
- }
--
-+
- memcpy(tone_425_flip,tone_425,TONE_425_SIZE);
- flip_buf_bits(tone_425_flip,TONE_425_SIZE);
-
- memcpy(tone_silence_flip,tone_SILENCE,TONE_SILENCE_SIZE);
- flip_buf_bits(tone_silence_flip,TONE_SILENCE_SIZE);
--
-+
- midev=te_lib_init();
- mgr->midev=midev;
-
- port_count=mISDN_get_stack_count(midev);
--
-+
- msg_queue_init(&mgr->activatequeue);
--
-+
- if (sem_init(&mgr->new_msg, 1, 0)<0)
- sem_init(&mgr->new_msg, 0, 0);
--
-+
- for (tok=strtok_r(plist," ,",&tokb );
-- tok;
-+ tok;
- tok=strtok_r(NULL," ,",&tokb)) {
- int port = atoi(tok);
- struct misdn_stack *stack;
- static int first=1;
- int ptp=0;
--
-+
- if (strstr(tok, "ptp"))
- ptp=1;
-
-@@ -4100,12 +4196,12 @@
- exit(1);
- }
- stack=stack_init(midev, port, ptp);
--
-+
- if (!stack) {
- perror("stack_init");
- exit(1);
- }
--
-+
- {
- int i;
- for(i=0;i<=stack->b_num; i++) {
-@@ -4122,30 +4218,30 @@
- first=0;
- continue;
- }
--
-+
- if (stack) {
- struct misdn_stack * help;
-- for ( help=mgr->stack_list; help; help=help->next )
-+ for ( help=mgr->stack_list; help; help=help->next )
- if (help->next == NULL) break;
- help->next=stack;
- }
--
-+
- }
--
-+
- if (sem_init(&handler_started, 1, 0)<0)
- sem_init(&handler_started, 0, 0);
--
-+
- cb_log(8, 0, "Starting Event Handler\n");
- pthread_create( &mgr->event_handler_thread, NULL,(void*)manager_event_handler, mgr);
--
-+
- sem_wait(&handler_started) ;
- cb_log(8, 0, "Starting Event Catcher\n");
- pthread_create( &mgr->event_thread, NULL, (void*)misdn_lib_isdn_event_catcher, mgr);
--
-+
- cb_log(8, 0, "Event Catcher started\n");
-
-- global_state= MISDN_INITIALIZED;
--
-+ global_state= MISDN_INITIALIZED;
-+
- return (mgr == NULL);
- }
-
-@@ -4153,7 +4249,7 @@
- {
- struct misdn_stack *help;
- int i;
--
-+
- for ( help=glob_mgr->stack_list; help; help=help->next ) {
- for(i=0;i<=help->b_num; i++) {
- char buf[1024];
-@@ -4163,21 +4259,21 @@
- cb_log (1, help->port, "Destroying this port.\n");
- stack_destroy(help);
- }
--
-+
- if (global_state == MISDN_INITIALIZED) {
- cb_log(4, 0, "Killing Handler Thread\n");
- if ( pthread_cancel(glob_mgr->event_handler_thread) == 0 ) {
- cb_log(4, 0, "Joining Handler Thread\n");
- pthread_join(glob_mgr->event_handler_thread, NULL);
- }
--
-+
- cb_log(4, 0, "Killing Main Thread\n");
- if ( pthread_cancel(glob_mgr->event_thread) == 0 ) {
- cb_log(4, 0, "Joining Main Thread\n");
- pthread_join(glob_mgr->event_thread, NULL);
- }
- }
--
-+
- cb_log(1, 0, "Closing mISDN device\n");
- te_lib_destroy(glob_mgr->midev);
- }
-@@ -4197,12 +4293,12 @@
- cb_log(0, bc->port, "bchannel_activate: Stack not found !");
- return ;
- }
--
-+
- /* we must activate if we are deactivated */
- clear_ibuffer(bc->astbuf);
--
-+
- cb_log(5, stack->port, "$$$ Bchan Activated addr %x\n", bc->addr);
--
-+
- mISDN_write_frame(stack->midev, buf, bc->addr | FLG_MSG_DOWN, DL_ESTABLISH | REQUEST, 0,0, NULL, TIMEOUT_1SEC);
-
- return ;
-@@ -4213,7 +4309,7 @@
- {
- struct misdn_stack *stack=get_stack_by_bc(bc);
- iframe_t dact;
-- char buf[128];
-+ char buf[128];
-
- switch (bc->bc_state) {
- case BCHAN_ACTIVATED:
-@@ -4226,11 +4322,11 @@
- return ;
-
- }
--
-+
- cb_log(5, stack->port, "$$$ Bchan deActivated addr %x\n", bc->addr);
--
-+
- bc->generate_tone=0;
--
-+
- dact.prim = DL_RELEASE | REQUEST;
- dact.addr = bc->addr | FLG_MSG_DOWN;
- dact.dinfo = 0;
-@@ -4238,9 +4334,9 @@
- mISDN_write_frame(stack->midev, buf, bc->addr | FLG_MSG_DOWN, DL_RELEASE|REQUEST,0,0,NULL, TIMEOUT_1SEC);
-
- clear_ibuffer(bc->astbuf);
--
-+
- bc_state_change(bc,BCHAN_RELEASE);
--
-+
- return;
- }
-
-@@ -4260,19 +4356,19 @@
- cb_log(3, bc->port, "BC not yet activated (state:%s)\n",bc_state2str(bc->bc_state));
- return -1;
- }
--
-+
- frm->prim = DL_DATA|REQUEST;
- frm->dinfo = 0;
- frm->addr = bc->addr | FLG_MSG_DOWN ;
--
-+
- frm->len = len;
- memcpy(&buf[mISDN_HEADER_LEN], data,len);
--
-- if ( misdn_cap_is_speech(bc->capability) )
-+
-+ if ( misdn_cap_is_speech(bc->capability) )
- flip_buf_bits( &buf[mISDN_HEADER_LEN], len);
- else
- cb_log(6, stack->port, "Writing %d data bytes\n",len);
--
-+
- cb_log(9, stack->port, "Writing %d bytes 2 mISDN\n",len);
- r=mISDN_write(stack->midev, buf, frm->len + mISDN_HEADER_LEN, TIMEOUT_INFINIT);
- return 0;
-@@ -4289,9 +4385,9 @@
- iframe_t *ctrl = (iframe_t *)buffer; /* preload data */
- unsigned int *d = (unsigned int*)&ctrl->data.p;
- /*struct misdn_stack *stack=get_stack_by_bc(bc);*/
--
-+
- cb_log(4,bc->port,"ph_control: c1:%x c2:%x\n",c1,c2);
--
-+
- ctrl->prim = PH_CONTROL | REQUEST;
- ctrl->addr = bc->addr | FLG_MSG_DOWN;
- ctrl->dinfo = 0;
-@@ -4340,7 +4436,7 @@
- iframe_t *ctrl = (iframe_t *)buffer;
- unsigned int *d = (unsigned int *)&ctrl->data.p;
- /*struct misdn_stack *stack=get_stack_by_bc(bc);*/
--
-+
- ctrl->prim = PH_CONTROL | REQUEST;
- ctrl->addr = bc->addr | FLG_MSG_DOWN;
- ctrl->dinfo = 0;
-@@ -4356,13 +4452,13 @@
- void manager_clean_bc(struct misdn_bchannel *bc )
- {
- struct misdn_stack *stack=get_stack_by_bc(bc);
--
-+
- if (bc->channel>0)
- empty_chan_in_stack(stack, bc->channel);
- empty_bc(bc);
- bc->in_use=0;
-
-- cb_event(EVENT_CLEANUP, bc, NULL);
-+ cb_event(EVENT_CLEANUP, bc, NULL);
- }
-
-
-@@ -4370,15 +4466,15 @@
- {
- struct misdn_bchannel *help;
- cb_log(4,stack->port, "*HOLDER: add %x\n",holder->l3_id);
--
-+
- holder->stack_holder=1;
- holder->next=NULL;
--
-+
- if (!stack->holding) {
- stack->holding = holder;
- return;
- }
--
-+
- for (help=stack->holding;
- help;
- help=help->next) {
-@@ -4387,7 +4483,7 @@
- break;
- }
- }
--
-+
- }
-
- void stack_holder_remove(struct misdn_stack *stack, struct misdn_bchannel *holder)
-@@ -4395,17 +4491,17 @@
- struct misdn_bchannel *h1;
-
- if (!holder->stack_holder) return;
--
-+
- holder->stack_holder=0;
--
-+
- cb_log(4,stack->port, "*HOLDER: remove %x\n",holder->l3_id);
- if (!stack || ! stack->holding) return;
--
-+
- if (holder == stack->holding) {
- stack->holding = stack->holding->next;
- return;
- }
--
-+
- for (h1=stack->holding;
- h1;
- h1=h1->next) {
-@@ -4421,9 +4517,9 @@
- struct misdn_bchannel *help;
-
- cb_log(4,stack?stack->port:0, "*HOLDER: find_bychan %c\n", chan);
--
-+
- if (!stack) return NULL;
--
-+
- for (help=stack->holding;
- help;
- help=help->next) {
-@@ -4443,9 +4539,9 @@
- struct misdn_bchannel *help;
-
- cb_log(4,stack?stack->port:0, "*HOLDER: find %lx\n",l3id);
--
-+
- if (!stack) return NULL;
--
-+
- for (help=stack->holding;
- help;
- help=help->next) {
-@@ -4461,34 +4557,34 @@
-
-
-
--void misdn_lib_send_tone(struct misdn_bchannel *bc, enum tone_e tone)
-+void misdn_lib_send_tone(struct misdn_bchannel *bc, enum tone_e tone)
- {
- char buf[mISDN_HEADER_LEN + 128] = "";
- iframe_t *frm = (iframe_t*)buf;
-
- switch(tone) {
- case TONE_DIAL:
-- manager_ph_control(bc, TONE_PATT_ON, TONE_GERMAN_DIALTONE);
-+ manager_ph_control(bc, TONE_PATT_ON, TONE_GERMAN_DIALTONE);
- break;
--
-+
- case TONE_ALERTING:
-- manager_ph_control(bc, TONE_PATT_ON, TONE_GERMAN_RINGING);
-+ manager_ph_control(bc, TONE_PATT_ON, TONE_GERMAN_RINGING);
- break;
--
-+
- case TONE_HANGUP:
-- manager_ph_control(bc, TONE_PATT_ON, TONE_GERMAN_HANGUP);
-+ manager_ph_control(bc, TONE_PATT_ON, TONE_GERMAN_HANGUP);
- break;
-
- case TONE_NONE:
- default:
-- manager_ph_control(bc, TONE_PATT_OFF, TONE_GERMAN_HANGUP);
-+ manager_ph_control(bc, TONE_PATT_OFF, TONE_GERMAN_HANGUP);
- }
-
- frm->prim=DL_DATA|REQUEST;
- frm->addr=bc->addr|FLG_MSG_DOWN;
- frm->dinfo=0;
- frm->len=128;
--
-+
- mISDN_write(glob_mgr->midev, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
- }
-
-@@ -4496,7 +4592,7 @@
- void manager_ec_enable(struct misdn_bchannel *bc)
- {
- struct misdn_stack *stack=get_stack_by_bc(bc);
--
-+
- cb_log(4, stack?stack->port:0,"ec_enable\n");
-
- if (!misdn_cap_is_speech(bc->capability)) {
-@@ -4513,7 +4609,7 @@
-
- if (bc->ec_enable) {
- cb_log(3, stack?stack->port:0,"Sending Control ECHOCAN_ON taps:%d\n",bc->ec_deftaps);
--
-+
- switch (bc->ec_deftaps) {
- case 4:
- case 8:
-@@ -4530,10 +4626,10 @@
- cb_log(0, stack->port, "Taps should be power of 2\n");
- bc->ec_deftaps=128;
- }
--
-+
- ec_arr[0]=bc->ec_deftaps;
- ec_arr[1]=0;
--
-+
- manager_ph_control_block(bc, ECHOCAN_ON, ec_arr, sizeof(ec_arr));
- }
- #endif
-@@ -4545,7 +4641,7 @@
- void manager_ec_disable(struct misdn_bchannel *bc)
- {
- struct misdn_stack *stack=get_stack_by_bc(bc);
--
-+
- cb_log(4, stack?stack->port:0," --> ec_disable\n");
-
- if (!misdn_cap_is_speech(bc->capability)) {
-@@ -4600,10 +4696,10 @@
-
- cb_log(4, bc1->port, "I Send: BRIDGE from:%d to:%d\n",bc1->port,bc2->port);
-
-- for (bc=bc_list; *bc; bc++) {
-+ for (bc=bc_list; *bc; bc++) {
- (*bc)->conf_id=conf_id;
- cb_log(4, (*bc)->port, " --> bc_addr:%x\n",(*bc)->addr);
--
-+
- switch((*bc)->bc_state) {
- case BCHAN_ACTIVATED:
- misdn_join_conf(*bc,conf_id);
-@@ -4622,15 +4718,15 @@
- bc1,bc2,NULL
- };
- struct misdn_bchannel **bc;
--
-- for (bc=bc_list; *bc; bc++) {
-+
-+ for (bc=bc_list; *bc; bc++) {
- if ( (*bc)->bc_state == BCHAN_BRIDGED){
- misdn_split_conf( *bc, (*bc)->conf_id);
- } else {
- cb_log( 2, (*bc)->port, "BC not bridged (state:%s) so not splitting it\n",bc_state2str((*bc)->bc_state));
- }
- }
--
-+
- }
-
-
-@@ -4646,37 +4742,37 @@
- void misdn_lib_reinit_nt_stack(int port)
- {
- struct misdn_stack *stack=find_stack_by_port(port);
--
-+
- if (stack) {
- stack->l2link=0;
- stack->blocked=0;
--
-+
- cleanup_Isdnl3(&stack->nst);
- cleanup_Isdnl2(&stack->nst);
-
-
- memset(&stack->nst, 0, sizeof(net_stack_t));
- memset(&stack->mgr, 0, sizeof(manager_t));
--
-+
- stack->mgr.nst = &stack->nst;
- stack->nst.manager = &stack->mgr;
--
-+
- stack->nst.l3_manager = handle_event_nt;
- stack->nst.device = glob_mgr->midev;
- stack->nst.cardnr = port;
- stack->nst.d_stid = stack->d_stid;
--
-+
- stack->nst.feature = FEATURE_NET_HOLD;
- if (stack->ptp)
- stack->nst.feature |= FEATURE_NET_PTP;
- if (stack->pri)
- stack->nst.feature |= FEATURE_NET_CRLEN2 | FEATURE_NET_EXTCID;
--
-+
- stack->nst.l1_id = stack->lower_id;
- stack->nst.l2_id = stack->upper_id;
--
-+
- msg_queue_init(&stack->nst.down_queue);
--
-+
- Isdnl2Init(&stack->nst);
- Isdnl3Init(&stack->nst);
-
-Index: channels/misdn/isdn_lib_intern.h
-===================================================================
---- a/channels/misdn/isdn_lib_intern.h (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/channels/misdn/isdn_lib_intern.h (.../trunk) (revision 186562)
-@@ -41,7 +41,6 @@
- struct isdn_msg {
- unsigned long misdn_msg;
-
-- enum layer_e layer;
- enum event_e event;
-
- void (*msg_parser)(struct isdn_msg *msgs, msg_t *msg, struct misdn_bchannel *bc, int nt);
-Index: channels/misdn/isdn_lib.h
-===================================================================
---- a/channels/misdn/isdn_lib.h (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/channels/misdn/isdn_lib.h (.../trunk) (revision 186562)
-@@ -96,15 +96,23 @@
- ENOCHAN=1
- };
-
--
- enum mISDN_NUMBER_PLAN {
-- NUMPLAN_UNINITIALIZED=-1,
-- NUMPLAN_INTERNATIONAL=0x1,
-- NUMPLAN_NATIONAL=0x2,
-- NUMPLAN_SUBSCRIBER=0x4,
-- NUMPLAN_UNKNOWN=0x0
-+ NUMPLAN_UNKNOWN = 0x0,
-+ NUMPLAN_ISDN = 0x1, /* ISDN/Telephony numbering plan E.164 */
-+ NUMPLAN_DATA = 0x3, /* Data numbering plan X.121 */
-+ NUMPLAN_TELEX = 0x4, /* Telex numbering plan F.69 */
-+ NUMPLAN_NATIONAL = 0x8,
-+ NUMPLAN_PRIVATE = 0x9
- };
-
-+enum mISDN_NUMBER_TYPE {
-+ NUMTYPE_UNKNOWN = 0x0,
-+ NUMTYPE_INTERNATIONAL = 0x1,
-+ NUMTYPE_NATIONAL = 0x2,
-+ NUMTYPE_NETWORK_SPECIFIC = 0x3,
-+ NUMTYPE_SUBSCRIBER = 0x4,
-+ NUMTYPE_ABBREVIATED = 0x5
-+};
-
- enum event_response_e {
- RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE,
-@@ -189,6 +197,19 @@
- INFO_PI_INTERWORKING_NO_RELEASE_POST_ANSWER =0x13
- };
-
-+/*!
-+ * \brief Q.931 encoded redirecting reason
-+ */
-+enum mISDN_REDIRECTING_REASON {
-+ mISDN_REDIRECTING_REASON_UNKNOWN = 0x0,
-+ mISDN_REDIRECTING_REASON_CALL_FWD_BUSY = 0x1, /* Call forwarding busy or called DTE busy */
-+ mISDN_REDIRECTING_REASON_NO_REPLY = 0x2, /* Call forwarding no reply */
-+ mISDN_REDIRECTING_REASON_DEFLECTION = 0x4, /* Call deflection */
-+ mISDN_REDIRECTING_REASON_OUT_OF_ORDER = 0x9, /* Called DTE out of order */
-+ mISDN_REDIRECTING_REASON_CALL_FWD_DTE = 0xA, /* Call forwarding by the called DTE */
-+ mISDN_REDIRECTING_REASON_CALL_FWD = 0xF /* Call forwarding unconditional or systematic call redirection */
-+};
-+
- enum { /*CODECS*/
- INFO_CODEC_ULAW=2,
- INFO_CODEC_ALAW=3
-@@ -202,12 +223,81 @@
- UNKNOWN
- };
-
-+/* Maximum phone number (address) length plus null terminator */
-+#define MISDN_MAX_NUMBER_LEN (31 + 1)
-
-+/* Maximum name length plus null terminator (From ECMA-164) */
-+#define MISDN_MAX_NAME_LEN (50 + 1)
-
-+/* Maximum subaddress length plus null terminator */
-+#define MISDN_MAX_SUBADDRESS_LEN (23 + 1)
-+
-+/* Maximum keypad facility content length plus null terminator */
-+#define MISDN_MAX_KEYPAD_LEN (31 + 1)
-+
-+/*! \brief Connected-Line/Calling/Redirecting ID info struct */
-+struct misdn_party_id {
-+ /*! \brief Number presentation restriction code
-+ * 0=Allowed, 1=Restricted, 2=Unavailable
-+ */
-+ int presentation;
-+
-+ /*! \brief Number screening code
-+ * 0=Unscreened, 1=Passed Screen, 2=Failed Screen, 3=Network Number
-+ */
-+ int screening;
-+
-+ /*! \brief Type-of-number in ISDN terms for the number */
-+ enum mISDN_NUMBER_TYPE number_type;
-+
-+ /*! \brief Type-of-number numbering plan. */
-+ enum mISDN_NUMBER_PLAN number_plan;
-+
-+ /*! \brief Subscriber Name
-+ * \note The name is currently obtained from Asterisk for
-+ * potential use in display ie's since basic ISDN does
-+ * not support names directly.
-+ */
-+ char name[MISDN_MAX_NAME_LEN];
-+
-+ /*! \brief Phone number (Address) */
-+ char number[MISDN_MAX_NUMBER_LEN];
-+
-+ /*! \brief Subaddress number */
-+ char subaddress[MISDN_MAX_SUBADDRESS_LEN];
-+};
-+
-+/*! \brief Redirecting information struct */
-+struct misdn_party_redirecting {
-+ /*! \brief Who is redirecting the call (Sent to the party the call is redirected toward) */
-+ struct misdn_party_id from;
-+
-+ /*! \brief Reason a call is being redirected (Q.931 field value) */
-+ enum mISDN_REDIRECTING_REASON reason;
-+};
-+
-+
-+/*! \brief B channel control structure */
- struct misdn_bchannel {
- /*! \brief B channel send locking structure */
- struct send_lock *send_lock;
-
-+ /*! \brief Originating/Caller ID information struct
-+ * \note The number_type element is set to "localdialplan" in /etc/asterisk/misdn.conf for outgoing calls
-+ * \note The number element can be set to "callerid" in /etc/asterisk/misdn.conf for outgoing calls
-+ */
-+ struct misdn_party_id caller;
-+
-+ /*! \brief Connected-Party/Connected-Line ID information struct
-+ * \note The number_type element is set to "cpndialplan" in /etc/asterisk/misdn.conf for outgoing calls
-+ */
-+ struct misdn_party_id connected;
-+
-+ /*! \brief Redirecting information struct (Where a call diversion or transfer was invoked)
-+ * \note The redirecting subaddress is not defined in Q.931 so it is not used.
-+ */
-+ struct misdn_party_redirecting redirecting;
-+
- /*! \brief TRUE if this is a dummy BC record */
- int dummy;
-
-@@ -326,26 +416,6 @@
- /*! \brief TRUE if we will not use the jitter buffer system */
- int nojitter;
-
-- /*! \brief Type-of-number in ISDN terms for the dialed/called number
-- * \note This value is set to "dialplan" in /etc/asterisk/misdn.conf for outgoing calls
-- */
-- enum mISDN_NUMBER_PLAN dnumplan;
--
-- /*! \brief Type-of-number in ISDN terms for the redirecting number which a call diversion or transfer was invoked.
-- * \note Collected from the incoming SETUP message but not used.
-- */
-- enum mISDN_NUMBER_PLAN rnumplan;
--
-- /*! \brief Type-of-number in ISDN terms for the originating/calling number (Caller-ID)
-- * \note This value is set to "localdialplan" in /etc/asterisk/misdn.conf for outgoing calls
-- */
-- enum mISDN_NUMBER_PLAN onumplan;
--
-- /*! \brief Type-of-number in ISDN terms for the connected party number
-- * \note This value is set to "cpndialplan" in /etc/asterisk/misdn.conf for outgoing calls
-- */
-- enum mISDN_NUMBER_PLAN cpnnumplan;
--
- /*! \brief Progress Indicator IE coding standard field.
- * \note Collected from the incoming messages but not used.
- */
-@@ -421,16 +491,38 @@
- */
- int stack_holder;
-
-- /*! \brief Caller ID presentation restriction code
-+ /*!
-+ * \brief Put a display ie in the CONNECT message
-+ * \details
-+ * Put a display ie in the CONNECT message containing the following
-+ * information if it is available (nt port only):
-+ * 0 - Do not put the connected line information in the display ie.
-+ * 1 - Put the available connected line name in the display ie.
-+ * 2 - Put the available connected line number in the display ie.
-+ * 3 - Put the available connected line name and number in the display ie.
-+ */
-+ int display_connected;
-+
-+ /*!
-+ * \brief Put a display ie in the SETUP message
-+ * \details
-+ * Put a display ie in the SETUP message containing the following
-+ * information if it is available (nt port only):
-+ * 0 - Do not put the caller information in the display ie.
-+ * 1 - Put the available caller name in the display ie.
-+ * 2 - Put the available caller number in the display ie.
-+ * 3 - Put the available caller name and number in the display ie.
-+ */
-+ int display_setup;
-+
-+ /*! \brief User set presentation restriction code
- * 0=Allowed, 1=Restricted, 2=Unavailable
- * \note It is settable by the misdn_set_opt() application.
- */
-- int pres;
-+ int presentation;
-
-- /*! \brief Caller ID screening code
-- * 0=Unscreened, 1=Passed Screen, 2=Failed Screen, 3=Network Number
-- */
-- int screen;
-+ /*! \brief TRUE if the user set the presentation restriction code */
-+ int set_presentation;
-
- /*! \brief SETUP message bearer capability field code value */
- int capability;
-@@ -462,6 +554,23 @@
- int hdlc;
- /* V110 */
-
-+ /*! \brief Dialed/Called information struct */
-+ struct {
-+ /*! \brief Type-of-number in ISDN terms for the dialed/called number
-+ * \note This value is set to "dialplan" in /etc/asterisk/misdn.conf for outgoing calls
-+ */
-+ enum mISDN_NUMBER_TYPE number_type;
-+
-+ /*! \brief Type-of-number numbering plan. */
-+ enum mISDN_NUMBER_PLAN number_plan;
-+
-+ /*! \brief Dialed/Called Phone Number (Address) */
-+ char number[MISDN_MAX_NUMBER_LEN];
-+
-+ /*! \brief Dialed/Called Subaddress number */
-+ char subaddress[MISDN_MAX_SUBADDRESS_LEN];
-+ } dialed;
-+
- /*! \brief Display message that can be displayed by the user phone.
- * \note Maximum displayable length is 34 or 82 octets.
- * It is also settable by the misdn_set_opt() application.
-@@ -469,39 +578,20 @@
- char display[84];
-
- /*! \brief Not used. Contents are setup but not used. */
-- char msn[32];
-+ char msn[MISDN_MAX_NUMBER_LEN];
-
-- /*! \brief Originating/Calling Phone Number (Address)
-- * \note This value can be set to "callerid" in /etc/asterisk/misdn.conf for outgoing calls
-- */
-- char oad[32];
--
-- /*! \brief Redirecting Phone Number (Address) where a call diversion or transfer was invoked */
-- char rad[32];
--
-- /*! \brief Dialed/Called Phone Number (Address) */
-- char dad[32];
--
-- /*! \brief Connected Party/Line Phone Number (Address) */
-- char cad[32];
--
-- /*! \brief Original Dialed/Called Phone Number (Address) before national/international dialing prefix added.
-- * \note Not used. Contents are setup but not used.
-- */
-- char orig_dad[32];
--
- /*! \brief Q.931 Keypad Facility IE contents
- * \note Contents exported and imported to Asterisk variable MISDN_KEYPAD
- */
-- char keypad[32];
-+ char keypad[MISDN_MAX_KEYPAD_LEN];
-
- /*! \brief Current overlap dialing digits to/from INFORMATION messages */
-- char info_dad[64];
-+ char info_dad[MISDN_MAX_NUMBER_LEN];
-
- /*! \brief Collected digits to go into info_dad[] while waiting for a SETUP_ACKNOWLEDGE to come in. */
-- char infos_pending[64];
-+ char infos_pending[MISDN_MAX_NUMBER_LEN];
-
--/* unsigned char info_keypad[32]; */
-+/* unsigned char info_keypad[MISDN_MAX_KEYPAD_LEN]; */
- /* unsigned char clisub[24]; */
- /* unsigned char cldsub[24]; */
-
-Index: channels/misdn/Makefile
-===================================================================
---- a/channels/misdn/Makefile (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/channels/misdn/Makefile (.../trunk) (revision 186562)
-@@ -13,5 +13,5 @@
- portinfo: portinfo.o
- $(CC) -o $@ $^ -lisdnnet -lmISDN -lpthread
-
--clean:
-+clean:
- rm -rf *.a *.o *.so portinfo *.i
-Index: channels/misdn/chan_misdn_config.h
-===================================================================
---- a/channels/misdn/chan_misdn_config.h (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/channels/misdn/chan_misdn_config.h (.../trunk) (revision 186562)
-@@ -11,7 +11,7 @@
- * the GNU General Public License
- */
-
--/*! \file
-+/*! \file
- * \brief Interface to mISDN - Config
- * \author Christian Richter <crich@beronet.com>
- */
-@@ -46,10 +46,16 @@
- MISDN_CFG_DIALPLAN, /* int */
- MISDN_CFG_LOCALDIALPLAN, /* int */
- MISDN_CFG_CPNDIALPLAN, /* int */
-- MISDN_CFG_NATPREFIX, /* char[] */
-- MISDN_CFG_INTERNATPREFIX, /* char[] */
-+ MISDN_CFG_TON_PREFIX_UNKNOWN, /* char[] */
-+ MISDN_CFG_TON_PREFIX_INTERNATIONAL, /* char[] */
-+ MISDN_CFG_TON_PREFIX_NATIONAL, /* char[] */
-+ MISDN_CFG_TON_PREFIX_NETWORK_SPECIFIC,/* char[] */
-+ MISDN_CFG_TON_PREFIX_SUBSCRIBER, /* char[] */
-+ MISDN_CFG_TON_PREFIX_ABBREVIATED, /* char[] */
- MISDN_CFG_PRES, /* int */
- MISDN_CFG_SCREEN, /* int */
-+ MISDN_CFG_DISPLAY_CONNECTED, /* int */
-+ MISDN_CFG_DISPLAY_SETUP, /* int */
- MISDN_CFG_ALWAYS_IMMEDIATE, /* int (bool) */
- MISDN_CFG_NODIALTONE, /* int (bool) */
- MISDN_CFG_IMMEDIATE, /* int (bool) */
-@@ -89,7 +95,7 @@
- MISDN_CFG_FAXDETECT_TIMEOUT, /* int */
- MISDN_CFG_PTP, /* int (bool) */
- MISDN_CFG_LAST,
--
-+
- /* general config items */
- MISDN_GEN_FIRST,
- #ifndef MISDN_1_2
-@@ -116,14 +122,14 @@
- };
-
- /* you must call misdn_cfg_init before any other function of this header file */
--int misdn_cfg_init(int max_ports, int reload);
-+int misdn_cfg_init(int max_ports, int reload);
- void misdn_cfg_reload(void);
- void misdn_cfg_destroy(void);
-
- void misdn_cfg_update_ptp( void );
-
--/* if you requst a general config element, the port value is ignored. if the requested
-- * value is not available, or the buffer is too small, the buffer will be nulled (in
-+/* if you requst a general config element, the port value is ignored. if the requested
-+ * value is not available, or the buffer is too small, the buffer will be nulled (in
- * case of a char* only its first byte will be nulled). */
- void misdn_cfg_get(int port, enum misdn_cfg_elements elem, void* buf, int bufsize);
-
-Index: channels/misdn/ie.c
-===================================================================
---- a/channels/misdn/ie.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/channels/misdn/ie.c (.../trunk) (revision 186562)
-@@ -15,7 +15,7 @@
- * the GNU General Public License
- */
-
--/*! \file
-+/*! \file
- * \brief Interface to mISDN
- * \author Christian Richter <crich@beronet.com>
- */
-@@ -153,7 +153,7 @@
- p[4+(multi>=0)] = 0xa0 + user;
- }
-
--static void dec_ie_bearer(unsigned char *p, Q931_info_t *qi, int *coding, int *capability, int *mode, int *rate, int *multi, int *user,
-+static void dec_ie_bearer(unsigned char *p, Q931_info_t *qi, int *coding, int *capability, int *mode, int *rate, int *multi, int *user,
- int *async, int *urate, int *stopbits, int *dbits, int *parity, int nt, struct misdn_bchannel *bc)
- {
- int octet;
-@@ -168,13 +168,13 @@
- *stopbits = -1;
- *dbits = -1;
- *parity = -1;
--
-+
- if (!nt)
- {
- p = NULL;
- #ifdef LLC_SUPPORT
- if (qi->QI_ELEMENT(llc)) {
--
-+
- p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(llc) + 1;
- }
- #endif
-@@ -189,7 +189,7 @@
- printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
- return;
- }
--
-+
- *coding = (p[1]&0x60) >> 5;
- *capability = p[1] & 0x1f;
- octet = 2;
-@@ -221,7 +221,7 @@
-
- if (p[0] <= octet)
- goto done;
--
-+
- if (p[octet++] & 0x80)
- goto l2;
-
-@@ -231,7 +231,7 @@
-
- if (p[0] <= octet)
- goto done;
--
-+
- if (p[octet++] & 0x80)
- goto l2;
-
-@@ -239,7 +239,7 @@
-
- if (p[0] <= octet)
- goto done;
--
-+
- if (p[octet++] & 0x80)
- goto l2;
-
-@@ -247,20 +247,20 @@
-
- if (p[0] <= octet)
- goto done;
--
-+
- if (!p[octet++] & 0x80)
- goto l2;
-
- /* Wheee. V.110 speed information */
-
- *stopbits = (p[octet] & 0x60) >> 5;
-- *dbits = (p[octet] & 0x18) >> 3;
-+ *dbits = (p[octet] & 0x18) >> 3;
- *parity = p[octet] & 7;
-
- octet++;
- }
- l2: /* Nobody seems to want the rest so we don't bother (yet) */
-- done:
-+ done:
- if (MISDN_IE_DEBG) printf(" coding=%d capability=%d mode=%d rate=%d multi=%d user=%d async=%d urate=%d stopbits=%d dbits=%d parity=%d\n", *coding, *capability, *mode, *rate, *multi, *user, *async, *urate, *stopbits, *dbits, *parity);
- }
-
-@@ -292,7 +292,7 @@
- if (MISDN_IE_DEBG) printf(debug+(i*3), " %02x", callid[i]);
- i++;
- }
--
-+
- if (MISDN_IE_DEBG) printf(" callid%s\n", debug);
-
- l = callid_len;
-@@ -338,7 +338,7 @@
- if (MISDN_IE_DEBG) printf(debug+(i*3), " %02x", callid[i]);
- i++;
- }
--
-+
- if (MISDN_IE_DEBG) printf(" callid%s\n", debug);
- }
- #endif
-@@ -501,7 +501,7 @@
- } else
- {
- strnncpy(number, (char *)p+2, p[0]-1, number_len);
-- /* SPECIAL workarround for IBT software bug */
-+ /* SPECIAL workarround for IBT software bug */
- /* if (number[0]==0x80) */
- /* strcpy((char *)number, (char *)number+1); */
- }
-@@ -691,7 +691,7 @@
- int l;
- struct misdn_stack *stack=get_stack_by_bc(bc);
- int pri = stack->pri;
--
-+
- if (exclusive<0 || exclusive>1)
- {
- printf("%s: ERROR: exclusive(%d) is out of range.\n", __FUNCTION__, exclusive);
-@@ -707,8 +707,8 @@
- }
-
- /* if (MISDN_IE_DEBG) printf(" exclusive=%d channel=%d\n", exclusive, channel); */
--
-
-+
- if (!pri)
- {
- /* BRI */
-@@ -1086,7 +1086,7 @@
- *location = -1;
- //*progress = -1;
- *progress = 0;
--
-+
- if (!nt)
- {
- p = NULL;
-@@ -1350,7 +1350,7 @@
- if (MISDN_IE_DEBG) sprintf(debug+(i*3), " %02x", user[i]);
- i++;
- }
--
-+
- if (MISDN_IE_DEBG) printf(" protocol=%d user-user%s\n", protocol, debug);
-
- l = user_len+1;
-@@ -1397,7 +1397,7 @@
- i++;
- }
- debug[i*3] = '\0';
--
-+
- if (MISDN_IE_DEBG) printf(" protocol=%d user-user%s\n", *protocol, debug);
- }
- #endif
-Index: channels/chan_gtalk.c
-===================================================================
---- a/channels/chan_gtalk.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/channels/chan_gtalk.c (.../trunk) (revision 186562)
-@@ -52,7 +52,8 @@
- #include "asterisk/pbx.h"
- #include "asterisk/sched.h"
- #include "asterisk/io.h"
--#include "asterisk/rtp.h"
-+#include "asterisk/rtp_engine.h"
-+#include "asterisk/stun.h"
- #include "asterisk/acl.h"
- #include "asterisk/callerid.h"
- #include "asterisk/file.h"
-@@ -112,8 +113,8 @@
- char cid_name[80]; /*!< Caller ID name */
- char exten[80]; /*!< Called extension */
- struct ast_channel *owner; /*!< Master Channel */
-- struct ast_rtp *rtp; /*!< RTP audio session */
-- struct ast_rtp *vrtp; /*!< RTP video session */
-+ struct ast_rtp_instance *rtp; /*!< RTP audio session */
-+ struct ast_rtp_instance *vrtp; /*!< RTP video session */
- int jointcapability; /*!< Supported capability at both ends (codecs ) */
- int peercapability;
- struct gtalk_pvt *next; /* Next entity */
-@@ -183,11 +184,6 @@
- static struct gtalk_pvt *gtalk_alloc(struct gtalk *client, const char *us, const char *them, const char *sid);
- static char *gtalk_do_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
- static char *gtalk_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
--/*----- RTP interface functions */
--static int gtalk_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp,
-- struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active);
--static enum ast_rtp_get_result gtalk_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp);
--static int gtalk_get_codec(struct ast_channel *chan);
-
- /*! \brief PBX interface structure for channel registration */
- static const struct ast_channel_tech gtalk_tech = {
-@@ -197,7 +193,7 @@
- .requester = gtalk_request,
- .send_digit_begin = gtalk_digit_begin,
- .send_digit_end = gtalk_digit_end,
-- .bridge = ast_rtp_bridge,
-+ .bridge = ast_rtp_instance_bridge,
- .call = gtalk_call,
- .hangup = gtalk_hangup,
- .answer = gtalk_answer,
-@@ -216,14 +212,6 @@
- static struct io_context *io; /*!< The IO context */
- static struct in_addr __ourip;
-
--/*! \brief RTP driver interface */
--static struct ast_rtp_protocol gtalk_rtp = {
-- type: "Gtalk",
-- get_rtp_info: gtalk_get_rtp_peer,
-- set_rtp_peer: gtalk_set_rtp_peer,
-- get_codec: gtalk_get_codec,
--};
--
- static struct ast_cli_entry gtalk_cli[] = {
- AST_CLI_DEFINE(gtalk_do_reload, "Reload GoogleTalk configuration"),
- AST_CLI_DEFINE(gtalk_show_channels, "Show GoogleTalk channels"),
-@@ -371,7 +359,7 @@
- iks_insert_node(dcodecs, payload_gsm);
- res++;
- }
-- ast_rtp_lookup_code(p->rtp, 1, codec);
-+
- return res;
- }
-
-@@ -523,18 +511,19 @@
- return res;
- }
-
--static enum ast_rtp_get_result gtalk_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
-+static enum ast_rtp_glue_result gtalk_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
- {
- struct gtalk_pvt *p = chan->tech_pvt;
-- enum ast_rtp_get_result res = AST_RTP_GET_FAILED;
-+ enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_FORBID;
-
- if (!p)
- return res;
-
- ast_mutex_lock(&p->lock);
- if (p->rtp){
-- *rtp = p->rtp;
-- res = AST_RTP_TRY_PARTIAL;
-+ ao2_ref(p->rtp, +1);
-+ *instance = p->rtp;
-+ res = AST_RTP_GLUE_RESULT_LOCAL;
- }
- ast_mutex_unlock(&p->lock);
-
-@@ -547,7 +536,7 @@
- return p->peercapability;
- }
-
--static int gtalk_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active)
-+static int gtalk_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, int codecs, int nat_active)
- {
- struct gtalk_pvt *p;
-
-@@ -567,6 +556,13 @@
- return 0;
- }
-
-+static struct ast_rtp_glue gtalk_rtp_glue = {
-+ .type = "Gtalk",
-+ .get_rtp_info = gtalk_get_rtp_peer,
-+ .get_codec = gtalk_get_codec,
-+ .update_peer = gtalk_set_rtp_peer,
-+};
-+
- static int gtalk_response(struct gtalk *client, char *from, ikspak *pak, const char *reasonstr, const char *reasonstr2)
- {
- iks *response = NULL, *error = NULL, *reason = NULL;
-@@ -615,15 +611,15 @@
- }
-
- /* codec points to the first <payload-type/> tag */
-- codec = iks_child(iks_child(iks_child(pak->x)));
-+ codec = iks_first_tag(iks_first_tag(iks_first_tag(pak->x)));
- while (codec) {
-- ast_rtp_set_m_type(tmp->rtp, atoi(iks_find_attrib(codec, "id")));
-- ast_rtp_set_rtpmap_type(tmp->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0);
-- codec = iks_next(codec);
-+ ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(tmp->rtp), tmp->rtp, atoi(iks_find_attrib(codec, "id")));
-+ ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(tmp->rtp), tmp->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0);
-+ codec = iks_next_tag(codec);
- }
-
- /* Now gather all of the codecs that we are asked for */
-- ast_rtp_get_current_formats(tmp->rtp, &tmp->peercapability, &peernoncodeccapability);
-+ ast_rtp_codecs_payload_formats(ast_rtp_instance_get_codecs(tmp->rtp), &tmp->peercapability, &peernoncodeccapability);
-
- /* at this point, we received an awser from the remote Gtalk client,
- which allows us to compare capabilities */
-@@ -810,7 +806,7 @@
- goto safeout;
- }
-
-- ast_rtp_get_us(p->rtp, &sin);
-+ ast_rtp_instance_get_local_address(p->rtp, &sin);
- ast_find_ourip(&us, bindaddr);
- if (!strcmp(ast_inet_ntoa(us), "127.0.0.1")) {
- ast_log(LOG_WARNING, "Found a loopback IP on the system, check your network configuration or set the bindaddr attribute.");
-@@ -951,8 +947,9 @@
- tmp->initiator = 1;
- }
- /* clear codecs */
-- tmp->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
-- ast_rtp_pt_clear(tmp->rtp);
-+ tmp->rtp = ast_rtp_instance_new(NULL, sched, &bindaddr, NULL);
-+ ast_rtp_instance_set_prop(tmp->rtp, AST_RTP_PROPERTY_RTCP, 1);
-+ ast_rtp_codecs_payloads_clear(ast_rtp_instance_get_codecs(tmp->rtp), tmp->rtp);
-
- /* add user configured codec capabilites */
- if (client->capability)
-@@ -1014,20 +1011,20 @@
-
- /* Set Frame packetization */
- if (i->rtp)
-- ast_rtp_codec_setpref(i->rtp, &i->prefs);
-+ ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(i->rtp), i->rtp, &i->prefs);
-
- tmp->nativeformats = ast_codec_choose(&i->prefs, what, 1) | (i->jointcapability & AST_FORMAT_VIDEO_MASK);
- fmt = ast_best_codec(tmp->nativeformats);
-
- if (i->rtp) {
-- ast_rtp_setstun(i->rtp, 1);
-- ast_channel_set_fd(tmp, 0, ast_rtp_fd(i->rtp));
-- ast_channel_set_fd(tmp, 1, ast_rtcp_fd(i->rtp));
-+ ast_rtp_instance_set_prop(i->rtp, AST_RTP_PROPERTY_STUN, 1);
-+ ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(i->rtp, 0));
-+ ast_channel_set_fd(tmp, 1, ast_rtp_instance_fd(i->rtp, 1));
- }
- if (i->vrtp) {
-- ast_rtp_setstun(i->rtp, 1);
-- ast_channel_set_fd(tmp, 2, ast_rtp_fd(i->vrtp));
-- ast_channel_set_fd(tmp, 3, ast_rtcp_fd(i->vrtp));
-+ ast_rtp_instance_set_prop(i->vrtp, AST_RTP_PROPERTY_STUN, 1);
-+ ast_channel_set_fd(tmp, 2, ast_rtp_instance_fd(i->vrtp, 0));
-+ ast_channel_set_fd(tmp, 3, ast_rtp_instance_fd(i->vrtp, 1));
- }
- if (state == AST_STATE_RING)
- tmp->rings = 1;
-@@ -1142,9 +1139,9 @@
- if (p->owner)
- ast_log(LOG_WARNING, "Uh oh, there's an owner, this is going to be messy.\n");
- if (p->rtp)
-- ast_rtp_destroy(p->rtp);
-+ ast_rtp_instance_destroy(p->rtp);
- if (p->vrtp)
-- ast_rtp_destroy(p->vrtp);
-+ ast_rtp_instance_destroy(p->vrtp);
- gtalk_free_candidates(p->theircandidates);
- ast_free(p);
- }
-@@ -1204,16 +1201,16 @@
- }
-
- /* codec points to the first <payload-type/> tag */
-- codec = iks_child(iks_child(iks_child(pak->x)));
-+ codec = iks_first_tag(iks_first_tag(iks_first_tag(pak->x)));
-
- while (codec) {
-- ast_rtp_set_m_type(p->rtp, atoi(iks_find_attrib(codec, "id")));
-- ast_rtp_set_rtpmap_type(p->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0);
-- codec = iks_next(codec);
-+ ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id")));
-+ ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0);
-+ codec = iks_next_tag(codec);
- }
-
- /* Now gather all of the codecs that we are asked for */
-- ast_rtp_get_current_formats(p->rtp, &p->peercapability, &peernoncodeccapability);
-+ ast_rtp_codecs_payload_formats(ast_rtp_instance_get_codecs(p->rtp), &p->peercapability, &peernoncodeccapability);
- p->jointcapability = p->capability & p->peercapability;
- ast_mutex_unlock(&p->lock);
-
-@@ -1277,16 +1274,16 @@
- p->ourcandidates->username);
-
- /* Find out the result of the STUN */
-- ast_rtp_get_peer(p->rtp, &aux);
-+ ast_rtp_instance_get_remote_address(p->rtp, &aux);
-
- /* If the STUN result is different from the IP of the hostname,
- lock on the stun IP of the hostname advertised by the
- remote client */
- if (aux.sin_addr.s_addr &&
- aux.sin_addr.s_addr != sin.sin_addr.s_addr)
-- ast_rtp_stun_request(p->rtp, &aux, username);
-+ ast_rtp_instance_stun_request(p->rtp, &aux, username);
- else
-- ast_rtp_stun_request(p->rtp, &sin, username);
-+ ast_rtp_instance_stun_request(p->rtp, &sin, username);
-
- if (aux.sin_addr.s_addr) {
- ast_debug(4, "Receiving RTP traffic from IP %s, matches with remote candidate's IP %s\n", ast_inet_ntoa(aux.sin_addr), tmp->ip);
-@@ -1323,11 +1320,11 @@
- traversenodes = pak->query;
- while(traversenodes) {
- if(!strcasecmp(iks_name(traversenodes), "session")) {
-- traversenodes = iks_child(traversenodes);
-+ traversenodes = iks_first_tag(traversenodes);
- continue;
- }
- if(!strcasecmp(iks_name(traversenodes), "transport")) {
-- traversenodes = iks_child(traversenodes);
-+ traversenodes = iks_first_tag(traversenodes);
- continue;
- }
- if(!strcasecmp(iks_name(traversenodes), "candidate")) {
-@@ -1366,7 +1363,7 @@
- gtalk_update_stun(p->parent, p);
- newcandidate = NULL;
- }
-- traversenodes = iks_next(traversenodes);
-+ traversenodes = iks_next_tag(traversenodes);
- }
-
- receipt = iks_new("iq");
-@@ -1387,7 +1384,7 @@
-
- if (!p->rtp)
- return &ast_null_frame;
-- f = ast_rtp_read(p->rtp);
-+ f = ast_rtp_instance_read(p->rtp, 0);
- gtalk_update_stun(p->parent, p);
- if (p->owner) {
- /* We already hold the channel lock */
-@@ -1438,7 +1435,7 @@
- if (p) {
- ast_mutex_lock(&p->lock);
- if (p->rtp) {
-- res = ast_rtp_write(p->rtp, frame);
-+ res = ast_rtp_instance_write(p->rtp, frame);
- }
- ast_mutex_unlock(&p->lock);
- }
-@@ -1447,7 +1444,7 @@
- if (p) {
- ast_mutex_lock(&p->lock);
- if (p->vrtp) {
-- res = ast_rtp_write(p->vrtp, frame);
-+ res = ast_rtp_instance_write(p->vrtp, frame);
- }
- ast_mutex_unlock(&p->lock);
- }
-@@ -2062,7 +2059,7 @@
- return 0;
- }
-
-- ast_rtp_proto_register(&gtalk_rtp);
-+ ast_rtp_glue_register(&gtalk_rtp_glue);
- ast_cli_register_multiple(gtalk_cli, ARRAY_LEN(gtalk_cli));
-
- /* Make sure we can register our channel type */
-@@ -2086,7 +2083,7 @@
- ast_cli_unregister_multiple(gtalk_cli, ARRAY_LEN(gtalk_cli));
- /* First, take us out of the channel loop */
- ast_channel_unregister(&gtalk_tech);
-- ast_rtp_proto_unregister(&gtalk_rtp);
-+ ast_rtp_glue_unregister(&gtalk_rtp_glue);
-
- if (!ast_mutex_lock(&gtalklock)) {
- /* Hangup all interfaces if they have an owner */
-Index: configure.ac
-===================================================================
---- a/configure.ac (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/configure.ac (.../trunk) (revision 186562)
-@@ -609,8 +609,6 @@
- AC_MSG_RESULT(no)
- )
-
--AST_C_DEFINE_CHECK([RTLD_NOLOAD], [RTLD_NOLOAD], [dlfcn.h])
--
- AST_C_DEFINE_CHECK([IP_MTU_DISCOVER], [IP_MTU_DISCOVER], [netinet/in.h])
-
- AC_CHECK_HEADER([libkern/OSAtomic.h],
-Index: apps/app_senddtmf.c
-===================================================================
---- a/apps/app_senddtmf.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/apps/app_senddtmf.c (.../trunk) (revision 186562)
-@@ -106,7 +106,7 @@
- astman_send_error(s, m, "Channel not specified");
- return 0;
- }
-- if (!digit) {
-+ if (ast_strlen_zero(digit)) {
- astman_send_error(s, m, "No digit specified");
- ast_channel_unlock(chan);
- return 0;
-Index: apps/app_test.c
-===================================================================
---- a/apps/app_test.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/apps/app_test.c (.../trunk) (revision 186562)
-@@ -132,7 +132,7 @@
- return (noise / samples);
- }
-
--static int sendnoise(struct ast_channel *chan, int ms)
-+static int sendnoise(struct ast_channel *chan, int ms)
- {
- int res;
- res = ast_tonepair_start(chan, 1537, 2195, ms, 8192);
-@@ -140,7 +140,7 @@
- res = ast_waitfordigit(chan, ms);
- ast_tonepair_stop(chan);
- }
-- return res;
-+ return res;
- }
-
- static int testclient_exec(struct ast_channel *chan, void *data)
-@@ -150,41 +150,41 @@
- char fn[80];
- char serverver[80];
- FILE *f;
--
-+
- /* Check for test id */
- if (ast_strlen_zero(testid)) {
- ast_log(LOG_WARNING, "TestClient requires an argument - the test id\n");
- return -1;
- }
--
-+
- if (chan->_state != AST_STATE_UP)
- res = ast_answer(chan);
--
-+
- /* Wait a few just to be sure things get started */
- res = ast_safe_sleep(chan, 3000);
- /* Transmit client version */
- if (!res)
- res = ast_dtmf_stream(chan, NULL, "8378*1#", 0, 0);
- ast_debug(1, "Transmit client version\n");
--
-+
- /* Read server version */
- ast_debug(1, "Read server version\n");
-- if (!res)
-+ if (!res)
- res = ast_app_getdata(chan, NULL, serverver, sizeof(serverver) - 1, 0);
- if (res > 0)
- res = 0;
- ast_debug(1, "server version: %s\n", serverver);
--
-+
- if (res > 0)
- res = 0;
-
- if (!res)
- res = ast_safe_sleep(chan, 1000);
- /* Send test id */
-- if (!res)
-- res = ast_dtmf_stream(chan, NULL, testid, 0, 0);
-- if (!res)
-- res = ast_dtmf_stream(chan, NULL, "#", 0, 0);
-+ if (!res)
-+ res = ast_dtmf_stream(chan, NULL, testid, 0, 0);
-+ if (!res)
-+ res = ast_dtmf_stream(chan, NULL, "#", 0, 0);
- ast_debug(1, "send test identifier: %s\n", testid);
-
- if ((res >=0) && (!ast_strlen_zero(testid))) {
-@@ -198,7 +198,7 @@
- fprintf(f, "CLIENTTEST ID: %s\n", testid);
- fprintf(f, "ANSWER: PASS\n");
- res = 0;
--
-+
- if (!res) {
- /* Step 1: Wait for "1" */
- ast_debug(1, "TestClient: 2. Wait DTMF 1\n");
-@@ -209,8 +209,9 @@
- else
- res = -1;
- }
-- if (!res)
-+ if (!res) {
- res = ast_safe_sleep(chan, 1000);
-+ }
- if (!res) {
- /* Step 2: Send "2" */
- ast_debug(1, "TestClient: 2. Send DTMF 2\n");
-@@ -226,7 +227,7 @@
- fprintf(f, "WAIT 1 SEC: %s\n", (res < 0) ? "FAIL" : "PASS");
- if (res > 0)
- res = 0;
-- }
-+ }
- if (!res) {
- /* Step 4: Measure noise */
- ast_debug(1, "TestClient: 4. Measure noise\n");
-@@ -272,7 +273,7 @@
- }
- if (!res) {
- /* Step 9: Measure noise */
-- ast_debug(1, "TestClient: 6. Measure tone\n");
-+ ast_debug(1, "TestClient: 9. Measure tone\n");
- res = measurenoise(chan, 4000, "TestClient");
- fprintf(f, "MEASURETONE: %s (%d)\n", (res < 0) ? "FAIL" : "PASS", res);
- if (res > 0)
-@@ -280,7 +281,7 @@
- }
- if (!res) {
- /* Step 10: Send "7" */
-- ast_debug(1, "TestClient: 7. Send DTMF 7\n");
-+ ast_debug(1, "TestClient: 10. Send DTMF 7\n");
- res = ast_dtmf_stream(chan, NULL, "7", 0, 0);
- fprintf(f, "SEND DTMF 7: %s\n", (res < 0) ? "FAIL" : "PASS");
- if (res > 0)
-@@ -297,6 +298,9 @@
- res = -1;
- }
- if (!res) {
-+ res = ast_safe_sleep(chan, 1000);
-+ }
-+ if (!res) {
- /* Step 12: Hangup! */
- ast_debug(1, "TestClient: 12. Hangup\n");
- }
-@@ -324,7 +328,7 @@
- res = ast_answer(chan);
- /* Read version */
- ast_debug(1, "Read client version\n");
-- if (!res)
-+ if (!res)
- res = ast_app_getdata(chan, NULL, testid, sizeof(testid) - 1, 0);
- if (res > 0)
- res = 0;
-@@ -338,8 +342,8 @@
- if (res > 0)
- res = 0;
-
-- if (!res)
-- res = ast_app_getdata(chan, NULL, testid, sizeof(testid) - 1, 0);
-+ if (!res)
-+ res = ast_app_getdata(chan, NULL, testid, sizeof(testid) - 1, 0);
- ast_debug(1, "read test identifier: %s\n", testid);
- /* Check for sneakyness */
- if (strchr(testid, '/'))
-@@ -391,7 +395,6 @@
- if (res > 0)
- res = 0;
- }
--
- if (!res) {
- /* Step 5: Wait one second */
- ast_debug(1, "TestServer: 5. Wait one second\n");
-@@ -400,7 +403,6 @@
- if (res > 0)
- res = 0;
- }
--
- if (!res) {
- /* Step 6: Measure noise */
- ast_debug(1, "TestServer: 6. Measure tone\n");
-@@ -409,7 +411,6 @@
- if (res > 0)
- res = 0;
- }
--
- if (!res) {
- /* Step 7: Send "5" */
- ast_debug(1, "TestServer: 7. Send DTMF 5\n");
-@@ -418,14 +419,13 @@
- if (res > 0)
- res = 0;
- }
--
- if (!res) {
- /* Step 8: Transmit tone noise */
- ast_debug(1, "TestServer: 8. Transmit tone\n");
- res = sendnoise(chan, 6000);
- fprintf(f, "SENDTONE: %s\n", (res < 0) ? "FAIL" : "PASS");
- }
--
-+
- if (!res || (res == '7')) {
- /* Step 9: Wait for "7" */
- ast_debug(1, "TestServer: 9. Wait DTMF 7\n");
-@@ -437,8 +437,9 @@
- else
- res = -1;
- }
-- if (!res)
-+ if (!res) {
- res = ast_safe_sleep(chan, 1000);
-+ }
- if (!res) {
- /* Step 10: Send "8" */
- ast_debug(1, "TestServer: 10. Send DTMF 8\n");
-@@ -474,7 +475,7 @@
- res = ast_unregister_application(testc_app);
- res |= ast_unregister_application(tests_app);
-
-- return res;
-+ return res;
- }
-
- static int load_module(void)
-Index: apps/app_ices.c
-===================================================================
---- a/apps/app_ices.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/apps/app_ices.c (.../trunk) (revision 186562)
-@@ -58,7 +58,7 @@
- <description>
- <para>Streams to an icecast server using ices (available separately).
- A configuration file must be supplied for ices (see contrib/asterisk-ices.xml).</para>
-- <note><para>ICES version 2 cient and server required.</para></note>
-+ <note><para>ICES version 2 client and server required.</para></note>
- </description>
- </application>
-
-Index: apps/app_directed_pickup.c
-===================================================================
---- a/apps/app_directed_pickup.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/apps/app_directed_pickup.c (.../trunk) (revision 186562)
-@@ -40,6 +40,7 @@
- #include "asterisk/lock.h"
- #include "asterisk/app.h"
- #include "asterisk/features.h"
-+#include "asterisk/callerid.h"
-
- #define PICKUPMARK "PICKUPMARK"
-
-@@ -91,9 +92,21 @@
- static int pickup_do(struct ast_channel *chan, struct ast_channel *target)
- {
- int res = 0;
-+ struct ast_party_connected_line connected_caller;
-
- ast_debug(1, "Call pickup on '%s' by '%s'\n", target->name, chan->name);
-
-+ connected_caller = target->connected;
-+ connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
-+ ast_channel_update_connected_line(chan, &connected_caller);
-+
-+ ast_channel_lock(chan);
-+ ast_connected_line_copy_from_caller(&connected_caller, &chan->cid);
-+ ast_channel_unlock(chan);
-+ connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
-+ ast_channel_queue_connected_line_update(chan, &connected_caller);
-+ ast_party_connected_line_free(&connected_caller);
-+
- if ((res = ast_answer(chan))) {
- ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
- return -1;
-Index: apps/app_minivm.c
-===================================================================
---- a/apps/app_minivm.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/apps/app_minivm.c (.../trunk) (revision 186562)
-@@ -1177,7 +1177,7 @@
- }
- ast_debug(4, "Fromstring now: %s\n", ast_strlen_zero(passdata) ? "-default-" : passdata);
-
-- fprintf(p, "Message-ID: <Asterisk-%d-%s-%d-%s>\n", (unsigned int)rand(), vmu->username, (int)getpid(), who);
-+ fprintf(p, "Message-ID: <Asterisk-%d-%s-%d-%s>\n", (unsigned int)ast_random(), vmu->username, (int)getpid(), who);
- len_passdata = strlen(vmu->fullname) * 2 + 3;
- passdata2 = alloca(len_passdata);
- if (!ast_strlen_zero(vmu->email))
-@@ -1210,7 +1210,7 @@
- fprintf(p, "MIME-Version: 1.0\n");
-
- /* Something unique. */
-- snprintf(bound, sizeof(bound), "voicemail_%s%d%d", vmu->username, (int)getpid(), (unsigned int)rand());
-+ snprintf(bound, sizeof(bound), "voicemail_%s%d%d", vmu->username, (int)getpid(), (unsigned int)ast_random());
-
- fprintf(p, "Content-Type: multipart/mixed; boundary=\"%s\"\n\n\n", bound);
-
-@@ -1785,13 +1785,10 @@
- AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, (new+urgent),
- AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, old,
- AST_EVENT_IE_END))) {
-- return;
-+ return;
- }
-
-- ast_event_queue_and_cache(event,
-- AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR,
-- AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR,
-- AST_EVENT_IE_END);
-+ ast_event_queue_and_cache(event);
- }
-
- /*! \brief Send MWI using interal Asterisk event subsystem */
-Index: apps/app_dumpchan.c
-===================================================================
---- a/apps/app_dumpchan.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/apps/app_dumpchan.c (.../trunk) (revision 186562)
-@@ -149,7 +149,7 @@
-
- static int dumpchan_exec(struct ast_channel *chan, void *data)
- {
-- struct ast_str *vars = ast_str_thread_get(&global_app_buf, 16);
-+ struct ast_str *vars = ast_str_thread_get(&ast_str_thread_global_buf, 16);
- char info[1024];
- int level = 0;
- static char *line = "================================================================================";
-Index: apps/app_voicemail.c
-===================================================================
---- a/apps/app_voicemail.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/apps/app_voicemail.c (.../trunk) (revision 186562)
-@@ -325,7 +325,7 @@
- static char *get_header_by_tag(char *header, char *tag, char *buf, size_t len);
- static void vm_imap_delete(int msgnum, struct ast_vm_user *vmu);
- static char *get_user_by_mailbox(char *mailbox, char *buf, size_t len);
--static struct vm_state *get_vm_state_by_imapuser(char *user, int interactive);
-+static struct vm_state *get_vm_state_by_imapuser(const char *user, int interactive);
- static struct vm_state *get_vm_state_by_mailbox(const char *mailbox, const char *context, int interactive);
- static struct vm_state *create_vm_state_from_user(struct ast_vm_user *vmu);
- static void vmstate_insert(struct vm_state *vms);
-@@ -518,11 +518,6 @@
- Spanish also uses:
- \arg \b vm-youhaveno
-
--Ukrainian requires the following additional soundfile:
--\arg \b vm-nove 'nove'
--\arg \b vm-stare 'stare'
--\arg \b digits/ua/1e 'odne'
--
- Italian requires the following additional soundfile:
-
- For vm_intro_it:
-@@ -809,7 +804,7 @@
- static int vm_tempgreeting(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain);
- static int vm_play_folder_name(struct ast_channel *chan, char *mbox);
- static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int msgnum, long duration, char *fmt, char *cidnum, char *cidname, const char *flag);
--static void make_email_file(FILE *p, char *srcemail, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, char *cidnum, char *cidname, char *attach, char *attach2, char *format, int duration, int attach_user_voicemail, struct ast_channel *chan, const char *category, int imap, const char *flag);
-+static void make_email_file(FILE *p, char *srcemail, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, char *attach, char *attach2, char *format, int duration, int attach_user_voicemail, struct ast_channel *chan, const char *category, int imap, const char *flag);
- static void apply_options(struct ast_vm_user *vmu, const char *options);
- static int add_email_attachment(FILE *p, struct ast_vm_user *vmu, char *format, char *attach, char *greeting_attachment, char *mailbox, char *bound, char *filename, int last, int msgnum);
- static int is_valid_dtmf(const char *key);
-@@ -1916,9 +1911,9 @@
- }
- imap_delete_old_greeting(fn, vms);
- }
--
-- make_email_file(p, myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL), fn, introfn, fmt, duration, 1, chan, NULL, 1, flag);
-- /* read mail file to memory */
-+
-+ make_email_file(p, myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, "INBOX", S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL), fn, introfn, fmt, duration, 1, chan, NULL, 1, flag);
-+ /* read mail file to memory */
- len = ftell(p);
- rewind(p);
- if (!(buf = ast_malloc(len + 1))) {
-@@ -2299,22 +2294,14 @@
-
- static void update_messages_by_imapuser(const char *user, unsigned long number)
- {
-- struct vmstate *vlist = NULL;
-+ struct vm_state *vms = get_vm_state_by_imapuser(user, 1);
-
-- AST_LIST_LOCK(&vmstates);
-- AST_LIST_TRAVERSE(&vmstates, vlist, list) {
-- if (!vlist->vms) {
-- ast_debug(3, "error: vms is NULL for %s\n", user);
-- continue;
-- }
-- if (!vlist->vms->imapuser) {
-- ast_debug(3, "error: imapuser is NULL for %s\n", user);
-- continue;
-- }
-- ast_debug(3, "saving mailbox message number %lu as message %d. Interactive set to %d\n", number, vlist->vms->vmArrayIndex, vlist->vms->interactive);
-- vlist->vms->msgArray[vlist->vms->vmArrayIndex++] = number;
-+ if (!vms && !(vms = get_vm_state_by_imapuser(user, 0))) {
-+ return;
- }
-- AST_LIST_UNLOCK(&vmstates);
-+
-+ ast_debug(3, "saving mailbox message number %lu as message %d. Interactive set to %d\n", number, vms->vmArrayIndex, vms->interactive);
-+ vms->msgArray[vms->vmArrayIndex++] = number;
- }
-
- void mm_searched(MAILSTREAM *stream, unsigned long number)
-@@ -2605,7 +2592,7 @@
- return vms_p;
- }
-
--static struct vm_state *get_vm_state_by_imapuser(char *user, int interactive)
-+static struct vm_state *get_vm_state_by_imapuser(const char *user, int interactive)
- {
- struct vmstate *vlist = NULL;
-
-@@ -3856,9 +3843,16 @@
- return 1;
- }
-
--static void prep_email_sub_vars(struct ast_channel *ast, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, char *cidnum, char *cidname, char *dur, char *date, char *passdata, size_t passdatasize, const char *category, const char *flag)
-+static void prep_email_sub_vars(struct ast_channel *ast, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, char *dur, char *date, char *passdata, size_t passdatasize, const char *category, const char *flag)
- {
- char callerid[256];
-+ char fromdir[256], fromfile[256];
-+ struct ast_config *msg_cfg;
-+ const char *origcallerid, *origtime;
-+ char origcidname[80], origcidnum[80], origdate[80];
-+ int inttime;
-+ struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
-+
- /* Prepare variables for substitution in email body and subject */
- pbx_builtin_setvar_helper(ast, "VM_NAME", vmu->fullname);
- pbx_builtin_setvar_helper(ast, "VM_DUR", dur);
-@@ -3873,6 +3867,35 @@
- pbx_builtin_setvar_helper(ast, "VM_DATE", date);
- pbx_builtin_setvar_helper(ast, "VM_CATEGORY", category ? ast_strdupa(category) : "no category");
- pbx_builtin_setvar_helper(ast, "VM_FLAG", flag);
-+
-+ /* Retrieve info from VM attribute file */
-+ make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, fromfolder);
-+ make_file(fromfile, sizeof(fromfile), fromdir, msgnum - 1);
-+ if (strlen(fromfile) < sizeof(fromfile) - 5) {
-+ strcat(fromfile, ".txt");
-+ }
-+ if (!(msg_cfg = ast_config_load(fromfile, config_flags))) {
-+ if (option_debug > 0) {
-+ ast_log(LOG_DEBUG, "Config load for message text file '%s' failed\n", fromfile);
-+ }
-+ return;
-+ }
-+
-+ if ((origcallerid = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
-+ pbx_builtin_setvar_helper(ast, "ORIG_VM_CALLERID", origcallerid);
-+ ast_callerid_split(origcallerid, origcidname, sizeof(origcidname), origcidnum, sizeof(origcidnum));
-+ pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNAME", origcidname);
-+ pbx_builtin_setvar_helper(ast, "ORIG_VM_CIDNUM", origcidnum);
-+ }
-+
-+ if ((origtime = ast_variable_retrieve(msg_cfg, "message", "origtime")) && sscanf(origtime, "%d", &inttime) == 1) {
-+ struct timeval tv = { inttime, };
-+ struct ast_tm tm;
-+ ast_localtime(&tv, &tm, NULL);
-+ ast_strftime(origdate, sizeof(origdate), emaildateformat, &tm);
-+ pbx_builtin_setvar_helper(ast, "ORIG_VM_DATE", origdate);
-+ }
-+ ast_config_destroy(msg_cfg);
- }
-
- /*!
-@@ -4006,7 +4029,7 @@
- *
- * The email body, and base 64 encoded attachement (if any) are stored to the file identified by *p. This method does not actually send the email. That is done by invoking the configure 'mailcmd' and piping this generated file into it, or with the sendemail() function.
- */
--static void make_email_file(FILE *p, char *srcemail, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, char *cidnum, char *cidname, char *attach, char *attach2, char *format, int duration, int attach_user_voicemail, struct ast_channel *chan, const char *category, int imap, const char *flag)
-+static void make_email_file(FILE *p, char *srcemail, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, char *attach, char *attach2, char *format, int duration, int attach_user_voicemail, struct ast_channel *chan, const char *category, int imap, const char *flag)
- {
- char date[256];
- char host[MAXHOSTNAMELEN] = "";
-@@ -4066,7 +4089,7 @@
- if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Substitution/voicemail"))) {
- char *ptr;
- memset(passdata2, 0, len_passdata2);
-- prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, enc_cidnum, enc_cidname, dur, date, passdata2, len_passdata2, category, flag);
-+ prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, passdata2, len_passdata2, category, flag);
- pbx_substitute_variables_helper(ast, fromstring, passdata2, len_passdata2);
- len_passdata = strlen(passdata2) * 3 + 300;
- passdata = alloca(len_passdata);
-@@ -4117,7 +4140,7 @@
- }
-
- memset(passdata, 0, len_passdata);
-- prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, cidnum, cidname, dur, date, passdata, len_passdata, category, flag);
-+ prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, passdata, len_passdata, category, flag);
- pbx_substitute_variables_helper(ast, e_subj, passdata, len_passdata);
- if (check_mime(passdata)) {
- int first_line = 1;
-@@ -4203,17 +4226,57 @@
- int vmlen = strlen(e_body) * 3 + 200;
- passdata = alloca(vmlen);
- memset(passdata, 0, vmlen);
-- prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, cidnum, cidname, dur, date, passdata, vmlen, category, flag);
-+ prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, passdata, vmlen, category, flag);
- pbx_substitute_variables_helper(ast, e_body, passdata, vmlen);
- fprintf(p, "%s" ENDL, passdata);
- ast_channel_free(ast);
- } else
- ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
-- } else if (msgnum > -1){
-- fprintf(p, "Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just left a %s long %s message (number %d)" ENDL
-- "in mailbox %s from %s, on %s so you might" ENDL
-- "want to check it when you get a chance. Thanks!" ENDL ENDL "\t\t\t\t--Asterisk" ENDL ENDL, vmu->fullname,
-- dur, flag, msgnum + 1, mailbox, (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")), date);
-+ } else if (msgnum > -1) {
-+ if (strcmp(vmu->mailbox, mailbox)) {
-+ /* Forwarded type */
-+ struct ast_config *msg_cfg;
-+ const char *v;
-+ int inttime;
-+ char fromdir[256], fromfile[256], origdate[80] = "", origcallerid[80] = "";
-+ struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
-+ /* Retrieve info from VM attribute file */
-+ make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, fromfolder);
-+ make_file(fromfile, sizeof(fromfile), fromdir, msgnum);
-+ if (strlen(fromfile) < sizeof(fromfile) - 5) {
-+ strcat(fromfile, ".txt");
-+ }
-+ if ((msg_cfg = ast_config_load(fromfile, config_flags))) {
-+ if ((v = ast_variable_retrieve(msg_cfg, "message", "callerid"))) {
-+ ast_copy_string(origcallerid, v, sizeof(origcallerid));
-+ }
-+
-+ /* You might be tempted to do origdate, except that a) it's in the wrong
-+ * format, and b) it's missing for IMAP recordings. */
-+ if ((v = ast_variable_retrieve(msg_cfg, "message", "origtime")) && sscanf(v, "%d", &inttime) == 1) {
-+ struct timeval tv = { inttime, };
-+ struct ast_tm tm;
-+ ast_localtime(&tv, &tm, NULL);
-+ ast_strftime(origdate, sizeof(origdate), emaildateformat, &tm);
-+ }
-+ fprintf(p, "Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just forwarded"
-+ " a %s long message (number %d)" ENDL "in mailbox %s from %s, on %s" ENDL
-+ "(originally sent by %s on %s)" ENDL "so you might want to check it when you get a"
-+ " chance. Thanks!" ENDL ENDL "\t\t\t\t--Asterisk" ENDL ENDL, vmu->fullname, dur,
-+ msgnum + 1, mailbox, (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")),
-+ date, origcallerid, origdate);
-+ ast_config_destroy(msg_cfg);
-+ } else {
-+ goto plain_message;
-+ }
-+ } else {
-+plain_message:
-+ fprintf(p, "Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just left a "
-+ "%s long message (number %d)" ENDL "in mailbox %s from %s, on %s so you might" ENDL
-+ "want to check it when you get a chance. Thanks!" ENDL ENDL "\t\t\t\t--Asterisk"
-+ ENDL ENDL, vmu->fullname, dur, msgnum + 1, mailbox,
-+ (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")), date);
-+ }
- } else {
- fprintf(p, "This message is to let you know that your greeting was changed on %s." ENDL
- "Please do not delete this message, lest your greeting vanish with it." ENDL ENDL, date);
-@@ -4288,7 +4351,7 @@
- }
- #undef ENDL
-
--static int sendmail(char *srcemail, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, char *cidnum, char *cidname, char *attach, char *attach2, char *format, int duration, int attach_user_voicemail, struct ast_channel *chan, const char *category, const char *flag)
-+static int sendmail(char *srcemail, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, char *attach, char *attach2, char *format, int duration, int attach_user_voicemail, struct ast_channel *chan, const char *category, const char *flag)
- {
- FILE *p=NULL;
- char tmp[80] = "/tmp/astmail-XXXXXX";
-@@ -4307,7 +4370,7 @@
- ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
- return -1;
- } else {
-- make_email_file(p, srcemail, vmu, msgnum, context, mailbox, cidnum, cidname, attach, attach2, format, duration, attach_user_voicemail, chan, category, 0, flag);
-+ make_email_file(p, srcemail, vmu, msgnum, context, mailbox, fromfolder, cidnum, cidname, attach, attach2, format, duration, attach_user_voicemail, chan, category, 0, flag);
- fclose(p);
- snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
- ast_safe_system(tmp2);
-@@ -4316,7 +4379,7 @@
- return 0;
- }
-
--static int sendpage(char *srcemail, char *pager, int msgnum, char *context, char *mailbox, char *cidnum, char *cidname, int duration, struct ast_vm_user *vmu, const char *category, const char *flag)
-+static int sendpage(char *srcemail, char *pager, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, int duration, struct ast_vm_user *vmu, const char *category, const char *flag)
- {
- char date[256];
- char host[MAXHOSTNAMELEN] = "";
-@@ -4347,7 +4410,7 @@
- int vmlen = strlen(fromstring)*3 + 200;
- passdata = alloca(vmlen);
- memset(passdata, 0, vmlen);
-- prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, cidnum, cidname, dur, date, passdata, vmlen, category, flag);
-+ prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, passdata, vmlen, category, flag);
- pbx_substitute_variables_helper(ast, pagerfromstring, passdata, vmlen);
- fprintf(p, "From: %s <%s>\n", passdata, who);
- ast_channel_free(ast);
-@@ -4363,7 +4426,7 @@
- int vmlen = strlen(pagersubject) * 3 + 200;
- passdata = alloca(vmlen);
- memset(passdata, 0, vmlen);
-- prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, cidnum, cidname, dur, date, passdata, vmlen, category, flag);
-+ prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, passdata, vmlen, category, flag);
- pbx_substitute_variables_helper(ast, pagersubject, passdata, vmlen);
- fprintf(p, "Subject: %s\n\n", passdata);
- ast_channel_free(ast);
-@@ -4385,7 +4448,7 @@
- int vmlen = strlen(pagerbody) * 3 + 200;
- passdata = alloca(vmlen);
- memset(passdata, 0, vmlen);
-- prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, cidnum, cidname, dur, date, passdata, vmlen, category, flag);
-+ prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, passdata, vmlen, category, flag);
- pbx_substitute_variables_helper(ast, pagerbody, passdata, vmlen);
- fprintf(p, "%s\n", passdata);
- ast_channel_free(ast);
-@@ -6215,10 +6278,7 @@
- return;
- }
-
-- ast_event_queue_and_cache(event,
-- AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR,
-- AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR,
-- AST_EVENT_IE_END);
-+ ast_event_queue_and_cache(event);
- }
-
- /*!
-@@ -6275,14 +6335,15 @@
- RETRIEVE(todir, msgnum, vmu->mailbox, vmu->context);
-
- /* XXX possible imap issue, should category be NULL XXX */
-- sendmail(myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, cidnum, cidname, fn, NULL, fmt, duration, attach_user_voicemail, chan, category, flag);
-+ sendmail(myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, mbox(0), cidnum, cidname, fn, NULL, fmt, duration, attach_user_voicemail, chan, category, flag);
-
- if (attach_user_voicemail)
- DISPOSE(todir, msgnum);
- }
-
-- if (!ast_strlen_zero(vmu->pager))
-- sendpage(myserveremail, vmu->pager, msgnum, vmu->context, vmu->mailbox, cidnum, cidname, duration, vmu, category, flag);
-+ if (!ast_strlen_zero(vmu->pager)) {
-+ sendpage(myserveremail, vmu->pager, msgnum, vmu->context, vmu->mailbox, mbox(0), cidnum, cidname, duration, vmu, category, flag);
-+ }
-
- if (ast_test_flag(vmu, VM_DELETE))
- DELETE(todir, msgnum, fn, vmu);
-@@ -6462,6 +6523,7 @@
- while ((receiver = AST_LIST_REMOVE_HEAD(&extensions, list))) {
- free_user(receiver);
- }
-+ ast_log(LOG_NOTICE, "'%s' is not a valid mailbox\n", s);
- valid_extensions = 0;
- break;
- }
-@@ -6535,7 +6597,7 @@
- myserveremail = vmtmp->serveremail;
- attach_user_voicemail = ast_test_flag(vmtmp, VM_ATTACH);
- /* NULL category for IMAP storage */
-- sendmail(myserveremail, vmtmp, todircount, vmtmp->context, vmtmp->mailbox, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL), vmstmp.fn, vmstmp.introfn, fmt, duration, attach_user_voicemail, chan, NULL, urgent_str);
-+ sendmail(myserveremail, vmtmp, todircount, vmtmp->context, vmtmp->mailbox, dstvms->curbox, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL), vmstmp.fn, vmstmp.introfn, fmt, duration, attach_user_voicemail, chan, NULL, urgent_str);
- #else
- copy_message(chan, sender, 0, curmsg, duration, vmtmp, fmt, dir, urgent_str);
- #endif
-@@ -7323,7 +7385,8 @@
- if (!res) {
- if (lastnum == 0) {
- res = ast_play_and_wait(chan, "vm-no");
-- } else {
-+ }
-+ if (!res) {
- res = ast_say_counted_noun(chan, lastnum, "vm-message");
- }
- }
-@@ -10270,7 +10333,7 @@
- char *current;
-
- /* Add 16 for fudge factor */
-- struct ast_str *str = ast_str_thread_get(&global_app_buf, strlen(value) + 16);
-+ struct ast_str *str = ast_str_thread_get(&ast_str_thread_global_buf, strlen(value) + 16);
-
- ast_str_reset(str);
-
-Index: apps/app_dial.c
-===================================================================
---- a/apps/app_dial.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/apps/app_dial.c (.../trunk) (revision 186562)
-@@ -54,7 +54,7 @@
- #include "asterisk/utils.h"
- #include "asterisk/app.h"
- #include "asterisk/causes.h"
--#include "asterisk/rtp.h"
-+#include "asterisk/rtp_engine.h"
- #include "asterisk/cdr.h"
- #include "asterisk/manager.h"
- #include "asterisk/privacy.h"
-@@ -109,11 +109,13 @@
- <option name="D" argsep=":">
- <argument name="called" />
- <argument name="calling" />
-+ <argument name="progress" />
- <para>Send the specified DTMF strings <emphasis>after</emphasis> the called
- party has answered, but before the call gets bridged. The
- <replaceable>called</replaceable> DTMF string is sent to the called party, and the
- <replaceable>calling</replaceable> DTMF string is sent to the calling party. Both arguments
-- can be used alone.</para>
-+ can be used alone. If <replaceable>progress</replaceable> is specified, its DTMF is sent
-+ immediately after receiving a PROGRESS message.</para>
- </option>
- <option name="e">
- <para>Execute the <literal>h</literal> extension for peer after the call ends</para>
-@@ -155,6 +157,10 @@
- <option name="i">
- <para>Asterisk will ignore any forwarding requests it may receive on this dial attempt.</para>
- </option>
-+ <option name="I">
-+ <para>Asterisk will ignore any connected line update requests or redirecting party update
-+ requests it may receiveon this dial attempt.</para>
-+ </option>
- <option name="k">
- <para>Allow the called party to enable parking of the call by sending
- the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
-@@ -380,7 +386,6 @@
- This application will report normal termination if the originating channel
- hangs up, or if the call is bridged and either of the parties in the bridge
- ends the call.</para>
--
- <para>If the <variable>OUTBOUND_GROUP</variable> variable is set, all peer channels created by this
- application will be put into that group (as in Set(GROUP()=...).
- If the <variable>OUTBOUND_GROUP_ONCE</variable> variable is set, all peer channels created by this
-@@ -462,12 +467,13 @@
- OPT_GO_ON = (1 << 5),
- OPT_CALLEE_HANGUP = (1 << 6),
- OPT_CALLER_HANGUP = (1 << 7),
-+ OPT_ORIGINAL_CLID = (1 << 8),
- OPT_DURATION_LIMIT = (1 << 9),
- OPT_MUSICBACK = (1 << 10),
- OPT_CALLEE_MACRO = (1 << 11),
- OPT_SCREEN_NOINTRO = (1 << 12),
-- OPT_SCREEN_NOCLID = (1 << 13),
-- OPT_ORIGINAL_CLID = (1 << 14),
-+ OPT_SCREEN_NOCALLERID = (1 << 13),
-+ OPT_IGNORE_CONNECTEDLINE = (1 << 14),
- OPT_SCREENING = (1 << 15),
- OPT_PRIVACY = (1 << 16),
- OPT_RINGBACK = (1 << 17),
-@@ -488,9 +494,10 @@
-
- #define DIAL_STILLGOING (1 << 31)
- #define DIAL_NOFORWARDHTML ((uint64_t)1 << 32) /* flags are now 64 bits, so keep it up! */
--#define OPT_CANCEL_ELSEWHERE ((uint64_t)1 << 33)
--#define OPT_PEER_H ((uint64_t)1 << 34)
--#define OPT_CALLEE_GO_ON ((uint64_t)1 << 35)
-+#define DIAL_NOCONNECTEDLINE ((uint64_t)1 << 33)
-+#define OPT_CANCEL_ELSEWHERE ((uint64_t)1 << 34)
-+#define OPT_PEER_H ((uint64_t)1 << 35)
-+#define OPT_CALLEE_GO_ON ((uint64_t)1 << 36)
-
- enum {
- OPT_ARG_ANNOUNCE = 0,
-@@ -522,13 +529,14 @@
- AST_APP_OPTION('h', OPT_CALLEE_HANGUP),
- AST_APP_OPTION('H', OPT_CALLER_HANGUP),
- AST_APP_OPTION('i', OPT_IGNORE_FORWARDING),
-+ AST_APP_OPTION('I', OPT_IGNORE_CONNECTEDLINE),
- AST_APP_OPTION('k', OPT_CALLEE_PARK),
- AST_APP_OPTION('K', OPT_CALLER_PARK),
- AST_APP_OPTION_ARG('L', OPT_DURATION_LIMIT, OPT_ARG_DURATION_LIMIT),
- AST_APP_OPTION_ARG('m', OPT_MUSICBACK, OPT_ARG_MUSICBACK),
- AST_APP_OPTION_ARG('M', OPT_CALLEE_MACRO, OPT_ARG_CALLEE_MACRO),
- AST_APP_OPTION('n', OPT_SCREEN_NOINTRO),
-- AST_APP_OPTION('N', OPT_SCREEN_NOCLID),
-+ AST_APP_OPTION('N', OPT_SCREEN_NOCALLERID),
- AST_APP_OPTION('o', OPT_ORIGINAL_CLID),
- AST_APP_OPTION_ARG('O', OPT_OPERMODE, OPT_ARG_OPERMODE),
- AST_APP_OPTION('p', OPT_SCREENING),
-@@ -556,8 +564,10 @@
- struct chanlist *next;
- struct ast_channel *chan;
- uint64_t flags;
-+ struct ast_party_connected_line connected;
- };
-
-+static int detect_disconnect(struct ast_channel *chan, char code, struct ast_str *featurecode);
-
- static void hanguptree(struct chanlist *outgoing, struct ast_channel *exception, int answered_elsewhere)
- {
-@@ -651,7 +661,6 @@
- return 0;
- }
-
--
- static const char *get_cid_name(char *name, int namelen, struct ast_channel *chan)
- {
- const char *context = S_OR(chan->macrocontext, chan->context);
-@@ -699,6 +708,8 @@
- struct ast_channel *original = o->chan;
- struct ast_channel *c = o->chan; /* the winner */
- struct ast_channel *in = num->chan; /* the input channel */
-+ struct ast_party_redirecting *apr = &o->chan->redirecting;
-+ struct ast_party_connected_line *apc = &o->chan->connected;
- char *stuff;
- char *tech;
- int cause;
-@@ -739,28 +750,38 @@
- handle_cause(cause, num);
- ast_hangup(original);
- } else {
-- char *new_cid_num, *new_cid_name;
-- struct ast_channel *src;
-+ if (single) {
-+ ast_rtp_instance_early_bridge_make_compatible(c, in);
-+ }
-
-- ast_rtp_make_compatible(c, in, single);
-+ c->cdrflags = in->cdrflags;
-+
-+ ast_channel_set_redirecting(c, apr);
-+ ast_channel_lock(c);
-+ while (ast_channel_trylock(in)) {
-+ CHANNEL_DEADLOCK_AVOIDANCE(c);
-+ }
-+ S_REPLACE(c->cid.cid_rdnis, ast_strdup(S_OR(original->cid.cid_rdnis, S_OR(in->macroexten, in->exten))));
-+
-+ c->cid.cid_tns = in->cid.cid_tns;
-+
- if (ast_test_flag64(o, OPT_FORCECLID)) {
-- new_cid_num = ast_strdup(S_OR(in->macroexten, in->exten));
-- new_cid_name = NULL; /* XXX no name ? */
-- src = c; /* XXX possible bug in previous code, which used 'winner' ? it may have changed */
-+ S_REPLACE(c->cid.cid_num, ast_strdupa(S_OR(in->macroexten, in->exten)));
-+ S_REPLACE(c->cid.cid_name, NULL);
-+ ast_string_field_set(c, accountcode, c->accountcode);
- } else {
-- new_cid_num = ast_strdup(in->cid.cid_num);
-- new_cid_name = ast_strdup(in->cid.cid_name);
-- src = in;
-+ ast_party_caller_copy(&c->cid, &in->cid);
-+ ast_string_field_set(c, accountcode, in->accountcode);
- }
-- ast_string_field_set(c, accountcode, src->accountcode);
-- c->cdrflags = src->cdrflags;
-- S_REPLACE(c->cid.cid_num, new_cid_num);
-- S_REPLACE(c->cid.cid_name, new_cid_name);
-+ ast_party_connected_line_copy(&c->connected, apc);
-
-- if (in->cid.cid_ani) { /* XXX or maybe unconditional ? */
-- S_REPLACE(c->cid.cid_ani, ast_strdup(in->cid.cid_ani));
-- }
-- S_REPLACE(c->cid.cid_rdnis, ast_strdup(S_OR(in->macroexten, in->exten)));
-+ S_REPLACE(in->cid.cid_rdnis, ast_strdup(c->cid.cid_rdnis));
-+ ast_channel_unlock(in);
-+ ast_channel_unlock(c);
-+ ast_channel_update_redirecting(in, apr);
-+
-+ ast_clear_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE);
-+
- if (ast_call(c, tmpchan, 0)) {
- ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
- ast_clear_flag64(o, DIAL_STILLGOING);
-@@ -770,7 +791,6 @@
- num->nochan++;
- } else {
- senddialevent(in, c, stuff);
-- /* After calling, set callerid to extension */
- if (!ast_test_flag64(peerflags, OPT_ORIGINAL_CLID)) {
- char cidname[AST_MAX_EXTENSION] = "";
- ast_set_callerid(c, S_OR(in->macroexten, in->exten), get_cid_name(cidname, sizeof(cidname), in), NULL);
-@@ -796,23 +816,35 @@
- static struct ast_channel *wait_for_answer(struct ast_channel *in,
- struct chanlist *outgoing, int *to, struct ast_flags64 *peerflags,
- struct privacy_args *pa,
-- const struct cause_args *num_in, int *result)
-+ const struct cause_args *num_in, int *result, char *dtmf_progress)
- {
- struct cause_args num = *num_in;
- int prestart = num.busy + num.congestion + num.nochan;
- int orig = *to;
- struct ast_channel *peer = NULL;
- /* single is set if only one destination is enabled */
-- int single = outgoing && !outgoing->next && !ast_test_flag64(outgoing, OPT_MUSICBACK | OPT_RINGBACK);
-+ int single = outgoing && !outgoing->next;
- #ifdef HAVE_EPOLL
- struct chanlist *epollo;
- #endif
--
-+ struct ast_party_connected_line connected_caller;
-+ struct ast_str *featurecode = ast_str_alloca(FEATURE_MAX_LEN + 1);
- if (single) {
- /* Turn off hold music, etc */
-- ast_deactivate_generator(in);
-+ if (!ast_test_flag64(outgoing, OPT_MUSICBACK | OPT_RINGBACK))
-+ ast_deactivate_generator(in);
-+
- /* If we are calling a single channel, make them compatible for in-band tone purpose */
- ast_channel_make_compatible(outgoing->chan, in);
-+
-+ if (!ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE) && !ast_test_flag64(outgoing, DIAL_NOCONNECTEDLINE)) {
-+ ast_channel_lock(outgoing->chan);
-+ ast_connected_line_copy_from_caller(&connected_caller, &outgoing->chan->cid);
-+ ast_channel_unlock(outgoing->chan);
-+ connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
-+ ast_channel_update_connected_line(in, &connected_caller);
-+ ast_party_connected_line_free(&connected_caller);
-+ }
- }
-
- #ifdef HAVE_EPOLL
-@@ -859,6 +891,18 @@
- if (ast_test_flag64(o, DIAL_STILLGOING) && c->_state == AST_STATE_UP) {
- if (!peer) {
- ast_verb(3, "%s answered %s\n", c->name, in->name);
-+ if (!single && !ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE)) {
-+ if (o->connected.id.number) {
-+ ast_channel_update_connected_line(in, &o->connected);
-+ } else if (!ast_test_flag64(o, DIAL_NOCONNECTEDLINE)) {
-+ ast_channel_lock(c);
-+ ast_connected_line_copy_from_caller(&connected_caller, &c->cid);
-+ ast_channel_unlock(c);
-+ connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
-+ ast_channel_update_connected_line(in, &connected_caller);
-+ ast_party_connected_line_free(&connected_caller);
-+ }
-+ }
- peer = c;
- ast_copy_flags64(peerflags, o,
- OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
-@@ -897,6 +941,18 @@
- /* This is our guy if someone answered. */
- if (!peer) {
- ast_verb(3, "%s answered %s\n", c->name, in->name);
-+ if (!single && !ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE)) {
-+ if (o->connected.id.number) {
-+ ast_channel_update_connected_line(in, &o->connected);
-+ } else if (!ast_test_flag64(o, DIAL_NOCONNECTEDLINE)) {
-+ ast_channel_lock(c);
-+ ast_connected_line_copy_from_caller(&connected_caller, &c->cid);
-+ ast_channel_unlock(c);
-+ connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
-+ ast_channel_update_connected_line(in, &connected_caller);
-+ ast_party_connected_line_free(&connected_caller);
-+ }
-+ }
- peer = c;
- if (peer->cdr) {
- peer->cdr->answer = ast_tvnow();
-@@ -952,6 +1008,10 @@
- ast_channel_early_bridge(in, c);
- if (!ast_test_flag64(outgoing, OPT_RINGBACK))
- ast_indicate(in, AST_CONTROL_PROGRESS);
-+ if(!ast_strlen_zero(dtmf_progress)) {
-+ ast_verb(3, "Sending DTMF '%s' to the called party as result of receiving a PROGRESS message.\n", dtmf_progress);
-+ ast_dtmf_stream(c, in, dtmf_progress, 250, 0);
-+ }
- break;
- case AST_CONTROL_VIDUPDATE:
- ast_verb(3, "%s requested a video update, passing it to %s\n", c->name, in->name);
-@@ -961,6 +1021,29 @@
- ast_verb(3, "%s requested a source update, passing it to %s\n", c->name, in->name);
- ast_indicate(in, AST_CONTROL_SRCUPDATE);
- break;
-+ case AST_CONTROL_CONNECTED_LINE:
-+ if (ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE)) {
-+ ast_verb(3, "Connected line update to %s prevented.\n", in->name);
-+ } else if (!single) {
-+ struct ast_party_connected_line connected;
-+ ast_verb(3, "%s connected line has changed. Saving it until answer for %s\n", c->name, in->name);
-+ ast_party_connected_line_set_init(&connected, &o->connected);
-+ ast_connected_line_parse_data(f->data.ptr, f->datalen, &connected);
-+ ast_party_connected_line_set(&o->connected, &connected);
-+ ast_party_connected_line_free(&connected);
-+ } else {
-+ ast_verb(3, "%s connected line has changed, passing it to %s\n", c->name, in->name);
-+ ast_indicate_data(in, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen);
-+ }
-+ break;
-+ case AST_CONTROL_REDIRECTING:
-+ if (ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE)) {
-+ ast_verb(3, "Redirecting update to %s prevented.\n", in->name);
-+ } else {
-+ ast_verb(3, "%s redirecting info has changed, passing it to %s\n", c->name, in->name);
-+ ast_indicate_data(in, AST_CONTROL_REDIRECTING, f->data.ptr, f->datalen);
-+ }
-+ break;
- case AST_CONTROL_PROCEEDING:
- ast_verb(3, "%s is proceeding passing it to %s\n", c->name, in->name);
- if (single && CAN_EARLY_BRIDGE(peerflags, in, c))
-@@ -1052,8 +1135,8 @@
- }
-
- if (ast_test_flag64(peerflags, OPT_CALLER_HANGUP) &&
-- (f->subclass == '*')) { /* hmm it it not guaranteed to be '*' anymore. */
-- ast_verb(3, "User hit %c to disconnect call.\n", f->subclass);
-+ detect_disconnect(in, f->subclass, featurecode)) {
-+ ast_verb(3, "User requested call disconnect.\n");
- *to = 0;
- strcpy(pa->status, "CANCEL");
- ast_cdr_noanswer(in->cdr);
-@@ -1075,7 +1158,9 @@
- ((f->subclass == AST_CONTROL_HOLD) ||
- (f->subclass == AST_CONTROL_UNHOLD) ||
- (f->subclass == AST_CONTROL_VIDUPDATE) ||
-- (f->subclass == AST_CONTROL_SRCUPDATE))) {
-+ (f->subclass == AST_CONTROL_SRCUPDATE) ||
-+ (f->subclass == AST_CONTROL_CONNECTED_LINE) ||
-+ (f->subclass == AST_CONTROL_REDIRECTING))) {
- ast_verb(3, "%s requested special control %d, passing it to %s\n", in->name, f->subclass, outgoing->chan->name);
- ast_indicate_data(outgoing->chan, f->subclass, f->data.ptr, f->datalen);
- }
-@@ -1097,6 +1182,26 @@
- return peer;
- }
-
-+static int detect_disconnect(struct ast_channel *chan, char code, struct ast_str *featurecode)
-+{
-+ struct ast_flags features = { AST_FEATURE_DISCONNECT }; /* only concerned with disconnect feature */
-+ struct ast_call_feature feature = { 0, };
-+ int res;
-+
-+ ast_str_append(&featurecode, 1, "%c", code);
-+
-+ res = ast_feature_detect(chan, &features, ast_str_buffer(featurecode), &feature);
-+
-+ if (res != AST_FEATURE_RETURN_STOREDIGITS) {
-+ ast_str_reset(featurecode);
-+ }
-+ if (feature.feature_mask & AST_FEATURE_DISCONNECT) {
-+ return 1;
-+ }
-+
-+ return 0;
-+}
-+
- static void replace_macro_delimiter(char *s)
- {
- for (; *s; s++)
-@@ -1394,11 +1499,11 @@
-
- ast_copy_string(pa->privcid, l, sizeof(pa->privcid));
-
-- if (strncmp(pa->privcid, "NOCALLERID", 10) != 0 && ast_test_flag64(opts, OPT_SCREEN_NOCLID)) {
-- /* if callerid is set and OPT_SCREEN_NOCLID is set also */
-+ if (strncmp(pa->privcid, "NOCALLERID", 10) != 0 && ast_test_flag64(opts, OPT_SCREEN_NOCALLERID)) {
-+ /* if callerid is set and OPT_SCREEN_NOCALLERID is set also */
- ast_verb(3, "CallerID set (%s); N option set; Screening should be off\n", pa->privcid);
- pa->privdb_val = AST_PRIVACY_ALLOW;
-- } else if (ast_test_flag64(opts, OPT_SCREEN_NOCLID) && strncmp(pa->privcid, "NOCALLERID", 10) == 0) {
-+ } else if (ast_test_flag64(opts, OPT_SCREEN_NOCALLERID) && strncmp(pa->privcid, "NOCALLERID", 10) == 0) {
- ast_verb(3, "CallerID blank; N option set; Screening should happen; dbval is %d\n", pa->privdb_val);
- }
-
-@@ -1502,7 +1607,7 @@
-
- struct ast_bridge_config config = { { 0, } };
- struct timeval calldurationlimit = { 0, };
-- char *dtmfcalled = NULL, *dtmfcalling = NULL;
-+ char *dtmfcalled = NULL, *dtmfcalling = NULL, *dtmf_progress=NULL;
- struct privacy_args pa = {
- .sentringing = 0,
- .privdb_val = 0,
-@@ -1553,12 +1658,11 @@
- goto done;
- }
-
--
- if (ast_test_flag64(&opts, OPT_OPERMODE)) {
- opermode = ast_strlen_zero(opt_args[OPT_ARG_OPERMODE]) ? 1 : atoi(opt_args[OPT_ARG_OPERMODE]);
- ast_verb(3, "Setting operator services mode to %d.\n", opermode);
- }
--
-+
- if (ast_test_flag64(&opts, OPT_DURATION_STOP) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_STOP])) {
- calldurationlimit.tv_sec = atoi(opt_args[OPT_ARG_DURATION_STOP]);
- if (!calldurationlimit.tv_sec) {
-@@ -1570,8 +1674,9 @@
- }
-
- if (ast_test_flag64(&opts, OPT_SENDDTMF) && !ast_strlen_zero(opt_args[OPT_ARG_SENDDTMF])) {
-- dtmfcalling = opt_args[OPT_ARG_SENDDTMF];
-- dtmfcalled = strsep(&dtmfcalling, ":");
-+ dtmf_progress = opt_args[OPT_ARG_SENDDTMF];
-+ dtmfcalled = strsep(&dtmf_progress, ":");
-+ dtmfcalling = strsep(&dtmf_progress, ":");
- }
-
- if (ast_test_flag64(&opts, OPT_DURATION_LIMIT) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_LIMIT])) {
-@@ -1591,7 +1696,7 @@
- res = -1; /* reset default */
- }
-
-- if (ast_test_flag64(&opts, OPT_DTMF_EXIT)) {
-+ if (ast_test_flag64(&opts, OPT_DTMF_EXIT) || ast_test_flag64(&opts, OPT_CALLER_HANGUP)) {
- __ast_answer(chan, 0, 0);
- }
-
-@@ -1608,7 +1713,7 @@
- outbound_group = ast_strdupa(outbound_group);
- }
- ast_channel_unlock(chan);
-- ast_copy_flags64(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP | OPT_IGNORE_FORWARDING);
-+ ast_copy_flags64(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP | OPT_IGNORE_FORWARDING | OPT_IGNORE_CONNECTEDLINE);
-
- /* loop through the list of dial destinations */
- rest = args.peers;
-@@ -1645,6 +1750,14 @@
-
- ast_channel_lock(chan);
- datastore = ast_channel_datastore_find(chan, &dialed_interface_info, NULL);
-+ /* If the incoming channel has previously had connected line information
-+ * set on it (perhaps through the CONNECTED_LINE dialplan function) then
-+ * seed the calllist's connected line information with this previously
-+ * acquired info
-+ */
-+ if (chan->connected.id.number) {
-+ ast_party_connected_line_copy(&tmp->connected, &chan->connected);
-+ }
- ast_channel_unlock(chan);
-
- if (datastore)
-@@ -1717,8 +1830,14 @@
- }
- pbx_builtin_setvar_helper(tc, "DIALEDPEERNUMBER", numsubst);
-
-+ ast_channel_lock(tc);
-+ while (ast_channel_trylock(chan)) {
-+ CHANNEL_DEADLOCK_AVOIDANCE(tc);
-+ }
- /* Setup outgoing SDP to match incoming one */
-- ast_rtp_make_compatible(tc, chan, !outgoing && !rest);
-+ if (!outgoing && !rest) {
-+ ast_rtp_instance_early_bridge_make_compatible(tc, chan);
-+ }
-
- /* Inherit specially named variables from parent channel */
- ast_channel_inherit_variables(chan, tc);
-@@ -1728,20 +1847,31 @@
- tc->data = "(Outgoing Line)";
- memset(&tc->whentohangup, 0, sizeof(tc->whentohangup));
-
-- S_REPLACE(tc->cid.cid_num, ast_strdup(chan->cid.cid_num));
-- S_REPLACE(tc->cid.cid_name, ast_strdup(chan->cid.cid_name));
-- S_REPLACE(tc->cid.cid_ani, ast_strdup(chan->cid.cid_ani));
-+ /* If the new channel has no callerid, try to guess what it should be */
-+ if (ast_strlen_zero(tc->cid.cid_num)) {
-+ if (!ast_strlen_zero(chan->connected.id.number)) {
-+ ast_set_callerid(tc, chan->connected.id.number, chan->connected.id.name, chan->connected.ani);
-+ } else if (!ast_strlen_zero(chan->cid.cid_dnid)) {
-+ ast_set_callerid(tc, chan->cid.cid_dnid, NULL, NULL);
-+ } else if (!ast_strlen_zero(S_OR(chan->macroexten, chan->exten))) {
-+ ast_set_callerid(tc, S_OR(chan->macroexten, chan->exten), NULL, NULL);
-+ }
-+ ast_set_flag64(tmp, DIAL_NOCONNECTEDLINE);
-+ }
-+
-+ ast_connected_line_copy_from_caller(&tc->connected, &chan->cid);
-+
- S_REPLACE(tc->cid.cid_rdnis, ast_strdup(chan->cid.cid_rdnis));
--
-+ ast_party_redirecting_copy(&tc->redirecting, &chan->redirecting);
-+
-+ tc->cid.cid_tns = chan->cid.cid_tns;
-+
- ast_string_field_set(tc, accountcode, chan->accountcode);
- tc->cdrflags = chan->cdrflags;
- if (ast_strlen_zero(tc->musicclass))
- ast_string_field_set(tc, musicclass, chan->musicclass);
-- /* Pass callingpres, type of number, tns, ADSI CPE, transfer capability */
-- tc->cid.cid_pres = chan->cid.cid_pres;
-- tc->cid.cid_ton = chan->cid.cid_ton;
-- tc->cid.cid_tns = chan->cid.cid_tns;
-- tc->cid.cid_ani2 = chan->cid.cid_ani2;
-+
-+ /* Pass ADSI CPE and transfer capability */
- tc->adsicpe = chan->adsicpe;
- tc->transfercapability = chan->transfercapability;
-
-@@ -1778,6 +1908,8 @@
- if (tc->hangupcause) {
- chan->hangupcause = tc->hangupcause;
- }
-+ ast_channel_unlock(chan);
-+ ast_channel_unlock(tc);
- ast_hangup(tc);
- tc = NULL;
- ast_free(tmp);
-@@ -1785,8 +1917,11 @@
- } else {
- senddialevent(chan, tc, numsubst);
- ast_verb(3, "Called %s\n", numsubst);
-- if (!ast_test_flag64(peerflags, OPT_ORIGINAL_CLID))
-+ if (!ast_test_flag64(peerflags, OPT_ORIGINAL_CLID)) {
- ast_set_callerid(tc, S_OR(chan->macroexten, chan->exten), get_cid_name(cidname, sizeof(cidname), chan), NULL);
-+ }
-+ ast_channel_unlock(chan);
-+ ast_channel_unlock(tc);
- }
- /* Put them in the list of outgoing thingies... We're ready now.
- XXX If we're forcibly removed, these outgoing calls won't get
-@@ -1838,7 +1973,7 @@
- }
- }
-
-- peer = wait_for_answer(chan, outgoing, &to, peerflags, &pa, &num, &result);
-+ peer = wait_for_answer(chan, outgoing, &to, peerflags, &pa, &num, &result, dtmf_progress);
-
- /* The ast_channel_datastore_remove() function could fail here if the
- * datastore was moved to another channel during a masquerade. If this is
-Index: apps/app_queue.c
-===================================================================
---- a/apps/app_queue.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/apps/app_queue.c (.../trunk) (revision 186562)
-@@ -94,6 +94,7 @@
- #include "asterisk/strings.h"
- #include "asterisk/global_datastores.h"
- #include "asterisk/taskprocessor.h"
-+#include "asterisk/callerid.h"
-
- /*!
- * \par Please read before modifying this file.
-@@ -141,6 +142,10 @@
- <para>Ignore call forward requests from queue members and do nothing
- when they are requested.</para>
- </option>
-+ <option name="I">
-+ <para>Asterisk will ignore any connected line update requests or any redirecting party
-+ update requests it may receive on this dial attempt.</para>
-+ </option>
- <option name="r">
- <para>Ring instead of playing MOH. Periodic Announcements are still made, if applicable.</para>
- </option>
-@@ -625,6 +630,8 @@
- time_t lastcall;
- struct call_queue *lastqueue;
- struct member *member;
-+ unsigned int update_connectedline:1;
-+ struct ast_party_connected_line connected;
- };
-
-
-@@ -1630,7 +1637,7 @@
-
- if ((q = ao2_alloc(sizeof(*q), destroy_queue))) {
- if (ast_string_field_init(q, 64)) {
-- free(q);
-+ ao2_ref(q, -1);
- return NULL;
- }
- ast_string_field_set(q, name, queuename);
-@@ -2268,11 +2275,56 @@
- }
- }
-
--/*!
-- * \brief traverse all defined queues which have calls waiting and contain this member
-- * \retval 0 if no other queue has precedence (higher weight)
-- * \retval 1 if found
--*/
-+/*!
-+ * \brief Get the number of members available to accept a call.
-+ *
-+ * \note The queue passed in should be locked prior to this function call
-+ *
-+ * \param[in] q The queue for which we are couting the number of available members
-+ * \return Return the number of available members in queue q
-+ */
-+static int num_available_members(struct call_queue *q)
-+{
-+ struct member *mem;
-+ int avl = 0;
-+ struct ao2_iterator mem_iter;
-+
-+ mem_iter = ao2_iterator_init(q->members, 0);
-+ while ((mem = ao2_iterator_next(&mem_iter))) {
-+ switch (mem->status) {
-+ case AST_DEVICE_INUSE:
-+ if (!q->ringinuse)
-+ break;
-+ /* else fall through */
-+ case AST_DEVICE_NOT_INUSE:
-+ case AST_DEVICE_UNKNOWN:
-+ if (!mem->paused) {
-+ avl++;
-+ }
-+ break;
-+ }
-+ ao2_ref(mem, -1);
-+
-+ /* If autofill is not enabled or if the queue's strategy is ringall, then
-+ * we really don't care about the number of available members so much as we
-+ * do that there is at least one available.
-+ *
-+ * In fact, we purposely will return from this function stating that only
-+ * one member is available if either of those conditions hold. That way,
-+ * functions which determine what action to take based on the number of available
-+ * members will operate properly. The reasoning is that even if multiple
-+ * members are available, only the head caller can actually be serviced.
-+ */
-+ if ((!q->autofill || q->strategy == QUEUE_STRATEGY_RINGALL) && avl) {
-+ break;
-+ }
-+ }
-+
-+ return avl;
-+}
-+
-+/* traverse all defined queues which have calls waiting and contain this member
-+ return 0 if no other queue has precedence (higher weight) or 1 if found */
- static int compare_weight(struct call_queue *rq, struct member *member)
- {
- struct call_queue *q;
-@@ -2292,7 +2344,7 @@
- if (q->count && q->members) {
- if ((mem = ao2_find(q->members, member, OBJ_POINTER))) {
- ast_debug(1, "Found matching member %s in queue '%s'\n", mem->interface, q->name);
-- if (q->weight > rq->weight) {
-+ if (q->weight > rq->weight && q->count >= num_available_members(q)) {
- ast_debug(1, "Queue '%s' (weight %d, calls %d) is preferred over '%s' (weight %d, calls %d)\n", q->name, q->weight, q->count, rq->name, rq->weight, rq->count);
- found = 1;
- }
-@@ -2319,7 +2371,7 @@
- /*! \brief convert "\n" to "\nVariable: " ready for manager to use */
- static char *vars2manager(struct ast_channel *chan, char *vars, size_t len)
- {
-- struct ast_str *buf = ast_str_thread_get(&global_app_buf, len + 1);
-+ struct ast_str *buf = ast_str_thread_get(&ast_str_thread_global_buf, len + 1);
- char *tmp;
-
- if (pbx_builtin_serialize_variables(chan, &buf)) {
-@@ -2434,23 +2486,41 @@
- (*busies)++;
- return 0;
- }
--
-+
-+ ast_channel_lock(tmp->chan);
-+ while (ast_channel_trylock(qe->chan)) {
-+ CHANNEL_DEADLOCK_AVOIDANCE(tmp->chan);
-+ }
-+
- if (qe->cancel_answered_elsewhere) {
- ast_set_flag(tmp->chan, AST_FLAG_ANSWERED_ELSEWHERE);
- }
- tmp->chan->appl = "AppQueue";
- tmp->chan->data = "(Outgoing Line)";
- memset(&tmp->chan->whentohangup, 0, sizeof(tmp->chan->whentohangup));
-- if (tmp->chan->cid.cid_num)
-- ast_free(tmp->chan->cid.cid_num);
-- tmp->chan->cid.cid_num = ast_strdup(qe->chan->cid.cid_num);
-- if (tmp->chan->cid.cid_name)
-- ast_free(tmp->chan->cid.cid_name);
-- tmp->chan->cid.cid_name = ast_strdup(qe->chan->cid.cid_name);
-- if (tmp->chan->cid.cid_ani)
-- ast_free(tmp->chan->cid.cid_ani);
-- tmp->chan->cid.cid_ani = ast_strdup(qe->chan->cid.cid_ani);
-
-+ /* If the new channel has no callerid, try to guess what it should be */
-+ if (ast_strlen_zero(tmp->chan->cid.cid_num)) {
-+ if (!ast_strlen_zero(qe->chan->connected.id.number)) {
-+ ast_set_callerid(tmp->chan, qe->chan->connected.id.number, qe->chan->connected.id.name, qe->chan->connected.ani);
-+ tmp->chan->cid.cid_pres = qe->chan->connected.id.number_presentation;
-+ } else if (!ast_strlen_zero(qe->chan->cid.cid_dnid)) {
-+ ast_set_callerid(tmp->chan, qe->chan->cid.cid_dnid, NULL, NULL);
-+ } else if (!ast_strlen_zero(S_OR(qe->chan->macroexten, qe->chan->exten))) {
-+ ast_set_callerid(tmp->chan, S_OR(qe->chan->macroexten, qe->chan->exten), NULL, NULL);
-+ }
-+ tmp->update_connectedline = 0;
-+ }
-+
-+ if (tmp->chan->cid.cid_rdnis)
-+ ast_free(tmp->chan->cid.cid_rdnis);
-+ tmp->chan->cid.cid_rdnis = ast_strdup(qe->chan->cid.cid_rdnis);
-+ ast_party_redirecting_copy(&tmp->chan->redirecting, &qe->chan->redirecting);
-+
-+ tmp->chan->cid.cid_tns = qe->chan->cid.cid_tns;
-+
-+ ast_connected_line_copy_from_caller(&tmp->chan->connected, &qe->chan->cid);
-+
- /* Inherit specially named variables from parent channel */
- ast_channel_inherit_variables(qe->chan, tmp->chan);
-
-@@ -2458,7 +2528,6 @@
- tmp->chan->adsicpe = qe->chan->adsicpe;
-
- /* Inherit context and extension */
-- ast_channel_lock(qe->chan);
- macrocontext = pbx_builtin_getvar_helper(qe->chan, "MACRO_CONTEXT");
- ast_string_field_set(tmp->chan, dialcontext, ast_strlen_zero(macrocontext) ? qe->chan->context : macrocontext);
- macroexten = pbx_builtin_getvar_helper(qe->chan, "MACRO_EXTEN");
-@@ -2466,13 +2535,14 @@
- ast_copy_string(tmp->chan->exten, macroexten, sizeof(tmp->chan->exten));
- else
- ast_copy_string(tmp->chan->exten, qe->chan->exten, sizeof(tmp->chan->exten));
-- ast_channel_unlock(qe->chan);
-
- /* Place the call, but don't wait on the answer */
- if ((res = ast_call(tmp->chan, location, 0))) {
- /* Again, keep going even if there's an error */
- ast_debug(1, "ast call on peer returned %d\n", res);
- ast_verb(3, "Couldn't call %s\n", tmp->interface);
-+ ast_channel_unlock(tmp->chan);
-+ ast_channel_unlock(qe->chan);
- do_hang(tmp);
- (*busies)++;
- update_status(qe->parent, tmp->member, ast_device_state(tmp->member->state_interface));
-@@ -2500,6 +2570,8 @@
- qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
- ast_verb(3, "Called %s\n", tmp->interface);
- }
-+ ast_channel_unlock(tmp->chan);
-+ ast_channel_unlock(qe->chan);
-
- update_status(qe->parent, tmp->member, ast_device_state(tmp->member->state_interface));
- return 1;
-@@ -2730,7 +2802,7 @@
- * \param[in] caller_disconnect if the 'H' option is used when calling Queue(), this is used to detect if the caller pressed * to disconnect the call
- * \param[in] forwardsallowed used to detect if we should allow call forwarding, based on the 'i' option to Queue()
- */
--static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed)
-+static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed, int update_connectedline)
- {
- const char *queue = qe->parent->name;
- struct callattempt *o, *start = NULL, *prev = NULL;
-@@ -2750,7 +2822,13 @@
- #ifdef HAVE_EPOLL
- struct callattempt *epollo;
- #endif
-+ struct ast_party_connected_line connected_caller;
-+ char *inchan_name;
-
-+ ast_channel_lock(qe->chan);
-+ inchan_name = ast_strdupa(qe->chan->name);
-+ ast_channel_unlock(qe->chan);
-+
- starttime = (long) time(NULL);
- #ifdef HAVE_EPOLL
- for (epollo = outgoing; epollo; epollo = epollo->q_next) {
-@@ -2800,9 +2878,28 @@
- }
- winner = ast_waitfor_n(watchers, pos, to);
- for (o = start; o; o = o->call_next) {
-+ /* We go with a static buffer here instead of using ast_strdupa. Using
-+ * ast_strdupa in a loop like this one can cause a stack overflow
-+ */
-+ char ochan_name[AST_CHANNEL_NAME];
-+ ast_channel_lock(o->chan);
-+ ast_copy_string(ochan_name, o->chan->name, sizeof(ochan_name));
-+ ast_channel_unlock(o->chan);
- if (o->stillgoing && (o->chan) && (o->chan->_state == AST_STATE_UP)) {
- if (!peer) {
-- ast_verb(3, "%s answered %s\n", o->chan->name, in->name);
-+ ast_verb(3, "%s answered %s\n", ochan_name, inchan_name);
-+ if (update_connectedline) {
-+ if (o->connected.id.number) {
-+ ast_channel_update_connected_line(in, &o->connected);
-+ } else if (o->update_connectedline) {
-+ ast_channel_lock(o->chan);
-+ ast_connected_line_copy_from_caller(&connected_caller, &o->chan->cid);
-+ ast_channel_unlock(o->chan);
-+ connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
-+ ast_channel_update_connected_line(in, &connected_caller);
-+ ast_party_connected_line_free(&connected_caller);
-+ }
-+ }
- peer = o;
- }
- } else if (o->chan && (o->chan == winner)) {
-@@ -2811,12 +2908,15 @@
- ast_copy_string(membername, o->member->membername, sizeof(membername));
-
- if (!ast_strlen_zero(o->chan->call_forward) && !forwardsallowed) {
-- ast_verb(3, "Forwarding %s to '%s' prevented.\n", in->name, o->chan->call_forward);
-+ ast_verb(3, "Forwarding %s to '%s' prevented.\n", inchan_name, o->chan->call_forward);
- numnochan++;
- do_hang(o);
- winner = NULL;
- continue;
- } else if (!ast_strlen_zero(o->chan->call_forward)) {
-+ struct ast_party_redirecting *apr = &o->chan->redirecting;
-+ struct ast_party_connected_line *apc = &o->chan->connected;
-+ struct ast_channel *original = o->chan;
- char tmpchan[256];
- char *stuff;
- char *tech;
-@@ -2831,7 +2931,7 @@
- tech = "Local";
- }
- /* Before processing channel, go ahead and check for forwarding */
-- ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
-+ ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n", inchan_name, tech, stuff, ochan_name);
- /* Setup parameters */
- o->chan = ast_request(tech, in->nativeformats, stuff, &status);
- if (!o->chan) {
-@@ -2839,32 +2939,42 @@
- o->stillgoing = 0;
- numnochan++;
- } else {
-+ ast_channel_lock(o->chan);
-+ while (ast_channel_trylock(in)) {
-+ CHANNEL_DEADLOCK_AVOIDANCE(o->chan);
-+ }
- ast_channel_inherit_variables(in, o->chan);
- ast_channel_datastore_inherit(in, o->chan);
-- if (o->chan->cid.cid_num)
-- ast_free(o->chan->cid.cid_num);
-- o->chan->cid.cid_num = ast_strdup(in->cid.cid_num);
-
-- if (o->chan->cid.cid_name)
-- ast_free(o->chan->cid.cid_name);
-- o->chan->cid.cid_name = ast_strdup(in->cid.cid_name);
--
- ast_string_field_set(o->chan, accountcode, in->accountcode);
- o->chan->cdrflags = in->cdrflags;
-
-- if (in->cid.cid_ani) {
-- if (o->chan->cid.cid_ani)
-- ast_free(o->chan->cid.cid_ani);
-- o->chan->cid.cid_ani = ast_strdup(in->cid.cid_ani);
-- }
-+ ast_channel_set_redirecting(o->chan, apr);
-+
- if (o->chan->cid.cid_rdnis)
- ast_free(o->chan->cid.cid_rdnis);
-- o->chan->cid.cid_rdnis = ast_strdup(S_OR(in->macroexten, in->exten));
-+ o->chan->cid.cid_rdnis = ast_strdup(S_OR(original->cid.cid_rdnis,S_OR(in->macroexten, in->exten)));
-+
-+ o->chan->cid.cid_tns = in->cid.cid_tns;
-+
-+ ast_party_caller_copy(&o->chan->cid, &in->cid);
-+ ast_party_connected_line_copy(&o->chan->connected, apc);
-+
-+ ast_channel_update_redirecting(in, apr);
-+ if (in->cid.cid_rdnis) {
-+ ast_free(in->cid.cid_rdnis);
-+ }
-+ in->cid.cid_rdnis = ast_strdup(o->chan->cid.cid_rdnis);
-+
-+ update_connectedline = 1;
-+
- if (ast_call(o->chan, tmpchan, 0)) {
- ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
- do_hang(o);
- numnochan++;
- }
-+ ast_channel_unlock(in);
-+ ast_channel_unlock(o->chan);
- }
- /* Hangup the original channel now, in case we needed it */
- ast_hangup(winner);
-@@ -2877,12 +2987,24 @@
- case AST_CONTROL_ANSWER:
- /* This is our guy if someone answered. */
- if (!peer) {
-- ast_verb(3, "%s answered %s\n", o->chan->name, in->name);
-+ ast_verb(3, "%s answered %s\n", ochan_name, inchan_name);
-+ if (update_connectedline) {
-+ if (o->connected.id.number) {
-+ ast_channel_update_connected_line(in, &o->connected);
-+ } else if (o->update_connectedline) {
-+ ast_channel_lock(o->chan);
-+ ast_connected_line_copy_from_caller(&connected_caller, &o->chan->cid);
-+ ast_channel_unlock(o->chan);
-+ connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
-+ ast_channel_update_connected_line(in, &connected_caller);
-+ ast_party_connected_line_free(&connected_caller);
-+ }
-+ }
- peer = o;
- }
- break;
- case AST_CONTROL_BUSY:
-- ast_verb(3, "%s is busy\n", o->chan->name);
-+ ast_verb(3, "%s is busy\n", ochan_name);
- if (in->cdr)
- ast_cdr_busy(in->cdr);
- do_hang(o);
-@@ -2897,7 +3019,7 @@
- numbusies++;
- break;
- case AST_CONTROL_CONGESTION:
-- ast_verb(3, "%s is circuit-busy\n", o->chan->name);
-+ ast_verb(3, "%s is circuit-busy\n", ochan_name);
- if (in->cdr)
- ast_cdr_busy(in->cdr);
- endtime = (long) time(NULL);
-@@ -2912,13 +3034,37 @@
- numbusies++;
- break;
- case AST_CONTROL_RINGING:
-- ast_verb(3, "%s is ringing\n", o->chan->name);
-+ ast_verb(3, "%s is ringing\n", ochan_name);
- break;
- case AST_CONTROL_OFFHOOK:
- /* Ignore going off hook */
- break;
-+ case AST_CONTROL_CONNECTED_LINE:
-+ if (!update_connectedline) {
-+ ast_verb(3, "Connected line update to %s prevented.\n", inchan_name);
-+ } else if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
-+ struct ast_party_connected_line connected;
-+ ast_verb(3, "%s connected line has changed. Saving it until answer for %s\n", ochan_name, inchan_name);
-+ ast_party_connected_line_set_init(&connected, &o->connected);
-+ ast_connected_line_parse_data(f->data.ptr, f->datalen, &connected);
-+ ast_party_connected_line_set(&o->connected, &connected);
-+ ast_party_connected_line_free(&connected);
-+ } else {
-+ ast_verb(3, "%s connected line has changed, passing it to %s\n", ochan_name, inchan_name);
-+ ast_indicate_data(in, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen);
-+ }
-+ break;
-+ case AST_CONTROL_REDIRECTING:
-+ if (!update_connectedline) {
-+ ast_verb(3, "Redirecting update to %s prevented\n", inchan_name);
-+ } else {
-+ ast_verb(3, "%s redirecting info has changed, passing it to %s\n", ochan_name, inchan_name);
-+ ast_indicate_data(in, AST_CONTROL_REDIRECTING, f->data.ptr, f->datalen);
-+ }
-+ break;
- default:
- ast_debug(1, "Dunno what to do with control type %d\n", f->subclass);
-+ break;
- }
- }
- ast_frfree(f);
-@@ -2981,80 +3127,46 @@
- /*!
- * \brief Check if we should start attempting to call queue members.
- *
-- * The behavior of this function is dependent first on whether autofill is enabled
-- * and second on whether the ring strategy is ringall. If autofill is not enabled,
-- * then return true if we're the head of the queue. If autofill is enabled, then
-- * we count the available members and see if the number of available members is enough
-- * that given our position in the queue, we would theoretically be able to connect to
-- * one of those available members
-+ * A simple process, really. Count the number of members who are available
-+ * to take our call and then see if we are in a position in the queue at
-+ * which a member could accept our call.
-+ *
-+ * \param[in] qe The caller who wants to know if it is his turn
-+ * \retval 0 It is not our turn
-+ * \retval 1 It is our turn
- */
- static int is_our_turn(struct queue_ent *qe)
- {
- struct queue_ent *ch;
-- struct member *cur;
-- int avl = 0;
-+ int res;
-+ int avl;
- int idx = 0;
-- int res;
-+ /* This needs a lock. How many members are available to be served? */
-+ ao2_lock(qe->parent);
-
-- if (!qe->parent->autofill) {
-- /* Atomically read the parent head -- does not need a lock */
-- ch = qe->parent->head;
-- /* If we are now at the top of the head, break out */
-- if (ch == qe) {
-- ast_debug(1, "It's our turn (%s).\n", qe->chan->name);
-- res = 1;
-- } else {
-- ast_debug(1, "It's not our turn (%s).\n", qe->chan->name);
-- res = 0;
-- }
-+ avl = num_available_members(qe->parent);
-
-- } else {
-- /* This needs a lock. How many members are available to be served? */
-- ao2_lock(qe->parent);
--
-- ch = qe->parent->head;
--
-- if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
-- ast_debug(1, "Even though there may be multiple members available, the strategy is ringall so only the head call is allowed in\n");
-- avl = 1;
-- } else {
-- struct ao2_iterator mem_iter = ao2_iterator_init(qe->parent->members, 0);
-- while ((cur = ao2_iterator_next(&mem_iter))) {
-- switch (cur->status) {
-- case AST_DEVICE_INUSE:
-- if (!qe->parent->ringinuse)
-- break;
-- /* else fall through */
-- case AST_DEVICE_NOT_INUSE:
-- case AST_DEVICE_UNKNOWN:
-- if (!cur->paused)
-- avl++;
-- break;
-- }
-- ao2_ref(cur, -1);
-- }
-- }
-+ ch = qe->parent->head;
-
-- ast_debug(1, "There are %d available members.\n", avl);
--
-- while ((idx < avl) && (ch) && (ch != qe)) {
-- if (!ch->pending)
-- idx++;
-- ch = ch->next;
-- }
--
-- /* If the queue entry is within avl [the number of available members] calls from the top ... */
-- if (ch && idx < avl) {
-- ast_debug(1, "It's our turn (%s).\n", qe->chan->name);
-- res = 1;
-- } else {
-- ast_debug(1, "It's not our turn (%s).\n", qe->chan->name);
-- res = 0;
-- }
--
-- ao2_unlock(qe->parent);
-+ ast_debug(1, "There %s %d available %s.\n", avl != 1 ? "are" : "is", avl, avl != 1 ? "members" : "member");
-+
-+ while ((idx < avl) && (ch) && (ch != qe)) {
-+ if (!ch->pending)
-+ idx++;
-+ ch = ch->next;
- }
-
-+ ao2_unlock(qe->parent);
-+
-+ /* If the queue entry is within avl [the number of available members] calls from the top ... */
-+ if (ch && idx < avl) {
-+ ast_debug(1, "It's our turn (%s).\n", qe->chan->name);
-+ res = 1;
-+ } else {
-+ ast_debug(1, "It's not our turn (%s).\n", qe->chan->name);
-+ res = 0;
-+ }
-+
- return res;
- }
-
-@@ -3506,6 +3618,7 @@
- char *p;
- char vars[2048];
- int forwardsallowed = 1;
-+ int update_connectedline = 1;
- int callcompletedinsl;
- struct ao2_iterator memi;
- struct ast_datastore *datastore, *transfer_ds;
-@@ -3571,6 +3684,9 @@
- case 'i':
- forwardsallowed = 0;
- break;
-+ case 'I':
-+ update_connectedline = 0;
-+ break;
- case 'x':
- ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_AUTOMIXMON);
- break;
-@@ -3580,22 +3696,8 @@
- case 'C':
- qe->cancel_answered_elsewhere = 1;
- break;
--
- }
-
-- if ((queue_end_bridge = ao2_alloc(sizeof(*queue_end_bridge), NULL))) {
-- queue_end_bridge->q = qe->parent;
-- queue_end_bridge->chan = qe->chan;
-- bridge_config.end_bridge_callback = end_bridge_callback;
-- bridge_config.end_bridge_callback_data = queue_end_bridge;
-- bridge_config.end_bridge_callback_data_fixup = end_bridge_callback_data_fixup;
-- /* Since queue_end_bridge can survive beyond the life of this call to Queue, we need
-- * to make sure to increase the refcount of this queue so it cannot be freed until we
-- * are done with it. We remove this reference in end_bridge_callback.
-- */
-- queue_ref(qe->parent);
-- }
--
- /* if the calling channel has the ANSWERED_ELSEWHERE flag set, make sure this is inherited.
- (this is mainly to support chan_local)
- */
-@@ -3663,6 +3765,17 @@
- }
- }
- AST_LIST_UNLOCK(dialed_interfaces);
-+
-+ ast_channel_lock(qe->chan);
-+ /* If any pre-existing connected line information exists on this
-+ * channel, like from the CONNECTED_LINE dialplan function, use this
-+ * to seed the connected line information. It may, of course, be updated
-+ * during the call
-+ */
-+ if (qe->chan->connected.id.number) {
-+ ast_party_connected_line_copy(&tmp->connected, &qe->chan->connected);
-+ }
-+ ast_channel_unlock(qe->chan);
-
- if (di) {
- free(tmp);
-@@ -3694,6 +3807,7 @@
- tmp->oldstatus = cur->status;
- tmp->lastcall = cur->lastcall;
- tmp->lastqueue = cur->lastqueue;
-+ tmp->update_connectedline = 1;
- ast_copy_string(tmp->interface, cur->interface, sizeof(tmp->interface));
- /* Special case: If we ring everyone, go ahead and ring them, otherwise
- just calculate their metric for the appropriate strategy */
-@@ -3734,7 +3848,7 @@
- ring_one(qe, outgoing, &numbusies);
- if (use_weight)
- ao2_unlock(queues);
-- lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies, ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT), forwardsallowed);
-+ lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies, ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT), forwardsallowed, update_connectedline);
- /* The ast_channel_datastore_remove() function could fail here if the
- * datastore was moved to another channel during a masquerade. If this is
- * the case, don't free the datastore here because later, when the channel
-@@ -4147,6 +4261,20 @@
- qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
- ast_copy_string(oldcontext, qe->chan->context, sizeof(oldcontext));
- ast_copy_string(oldexten, qe->chan->exten, sizeof(oldexten));
-+
-+ if ((queue_end_bridge = ao2_alloc(sizeof(*queue_end_bridge), NULL))) {
-+ queue_end_bridge->q = qe->parent;
-+ queue_end_bridge->chan = qe->chan;
-+ bridge_config.end_bridge_callback = end_bridge_callback;
-+ bridge_config.end_bridge_callback_data = queue_end_bridge;
-+ bridge_config.end_bridge_callback_data_fixup = end_bridge_callback_data_fixup;
-+ /* Since queue_end_bridge can survive beyond the life of this call to Queue, we need
-+ * to make sure to increase the refcount of this queue so it cannot be freed until we
-+ * are done with it. We remove this reference in end_bridge_callback.
-+ */
-+ queue_ref(qe->parent);
-+ }
-+
- time(&callstart);
- transfer_ds = setup_transfer_datastore(qe, member, callstart, callcompletedinsl);
- bridge = ast_bridge_call(qe->chan,peer, &bridge_config);
-@@ -5591,6 +5719,11 @@
- AST_APP_ARG(state_interface);
- );
-
-+ if (ast_strlen_zero(memberdata)) {
-+ ast_log(LOG_WARNING, "Empty queue member definition. Moving on!\n");
-+ return;
-+ }
-+
- /* Add a new member */
- parse = ast_strdupa(memberdata);
-
-Index: apps/app_followme.c
-===================================================================
---- a/apps/app_followme.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/apps/app_followme.c (.../trunk) (revision 186562)
-@@ -998,7 +998,7 @@
-
- static int app_exec(struct ast_channel *chan, void *data)
- {
-- struct fm_args targs;
-+ struct fm_args targs = { 0, };
- struct ast_bridge_config config;
- struct call_followme *f;
- struct number *nm, *newnm;
-Index: UPGRADE.txt
-===================================================================
---- a/UPGRADE.txt (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/UPGRADE.txt (.../trunk) (revision 186562)
-@@ -18,6 +18,14 @@
- ===
- ===========================================================
-
-+From 1.6.2 to 1.6.3:
-+
-+* The usage of RTP inside of Asterisk has now become modularized. This means
-+ the Asterisk RTP stack now exists as a loadable module, res_rtp_asterisk.
-+ If you are not using autoload=yes in modules.conf you will need to ensure
-+ it is set to load. If not, then any module which uses RTP (such as chan_sip)
-+ will not be able to send or receive calls.
-+
- From 1.6.1 to 1.6.2:
-
- * The res_indications module has been removed. Its functionality was important
-Index: CHANGES
-===================================================================
---- a/CHANGES (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/CHANGES (.../trunk) (revision 186562)
-@@ -7,7 +7,67 @@
- === and the other UPGRADE files for older releases.
- ===
- ======================================================================
-+------------------------------------------------------------------------------
-+--- Functionality changes from Asterisk 1.6.2 to Asterisk 1.6.3 -------------
-+------------------------------------------------------------------------------
-
-+SIP Changes
-+-----------
-+ * Added preferred_codec_only option in sip.conf. This feature limits the joint
-+ codecs sent in response to an INVITE to the single most preferred codec.
-+
-+Applications
-+------------
-+ * Added progress option to the app_dial D() option. When progress DTMF is
-+ present, those values are sent immediatly upon receiving a PROGRESS message
-+ regardless if the call has been answered or not.
-+
-+Dialplan Functions
-+------------------
-+ * Added new dialplan functions CONNECTEDLINE and REDIRECTING which permits
-+ setting various connected line and redirecting party information.
-+ * The CHANNEL() function now supports the "name" option.
-+
-+Queue changes
-+-------------
-+ * A new option, 'I' has been added to both app_queue and app_dial.
-+ By setting this option, Asterisk will not update the caller with
-+ connected line changes or redirecting party changes when they occur.
-+
-+mISDN channel driver (chan_misdn) changes
-+----------------------------------------
-+ * Added display_connected parameter to misdn.conf to put a display string
-+ in the CONNECT message containing the connected name and/or number if
-+ the presentation setting permits it.
-+ * Added display_setup parameter to misdn.conf to put a display string
-+ in the SETUP message containing the caller name and/or number if the
-+ presentation setting permits it.
-+ * Made misdn.conf parameters localdialplan and cpndialplan take a -1 to
-+ indicate the dialplan settings are to be obtained from the asterisk
-+ channel.
-+ * Made misdn.conf parameter callerid accept the "name" <number> format
-+ used by the rest of the system.
-+ * Made use the nationalprefix and internationalprefix misdn.conf
-+ parameters to prefix any received number from the ISDN link if that
-+ number has the corresponding Type-Of-Number.
-+ * Added the following new parameters: unknownprefix, netspecificprefix,
-+ subscriberprefix, and abbreviatedprefix in misdn.conf to prefix any
-+ received number from the ISDN link if that number has the corresponding
-+ Type-Of-Number.
-+
-+
-+SIP channel driver (chan_sip) changes
-+-------------------------------------------
-+ * The sendrpid parameter has been expanded to include the options
-+ 'rpid' and 'pai'. Setting sendrpid to 'rpid' will cause Remote-Party-ID
-+ header to be sent (equivalent to setting sendrpid=yes) and setting
-+ sendrpid to 'pai' will cause P-Asserted-Identity header to be sent.
-+
-+Asterisk Manager Interface
-+--------------------------
-+ * The Hangup action now accepts a Cause header which may be used to
-+ set the channel's hangup cause.
-+
- ------------------------------------------------------------------------------
- --- Functionality changes from Asterisk 1.6.1 to Asterisk 1.6.2 -------------
- ------------------------------------------------------------------------------
-Index: sounds/Makefile
-===================================================================
---- a/sounds/Makefile (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/sounds/Makefile (.../trunk) (revision 186562)
-@@ -17,8 +17,8 @@
-
- SOUNDS_DIR:=$(DESTDIR)$(ASTDATADIR)/sounds
- MOH_DIR:=$(DESTDIR)$(ASTDATADIR)/moh
--CORE_SOUNDS_VERSION:=1.4.14
--EXTRA_SOUNDS_VERSION:=1.4.8
-+CORE_SOUNDS_VERSION:=1.4.15
-+EXTRA_SOUNDS_VERSION:=1.4.9
- SOUNDS_URL:=http://downloads.digium.com/pub/telephony/sounds/releases
- MCS:=$(subst -EN-,-en-,$(MENUSELECT_CORE_SOUNDS))
- MCS:=$(subst -FR-,-fr-,$(MCS))
-Index: autoconf/ast_ext_lib.m4
-===================================================================
---- a/autoconf/ast_ext_lib.m4 (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/autoconf/ast_ext_lib.m4 (.../trunk) (revision 186562)
-@@ -11,7 +11,7 @@
- $1_DESCRIP="$2"
- $1_OPTION="$3"
- PBX_$1=0
-- AC_ARG_WITH([$3], AC_HELP_STRING([--with-$3=PATH],[use $2 files in PATH $4]),
-+ AC_ARG_WITH([$3], AC_HELP_STRING([--with-$3=PATH],[use $2 files in PATH$4]),
- [
- case ${withval} in
- n|no)
-Index: funcs/func_channel.c
-===================================================================
---- a/funcs/func_channel.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/funcs/func_channel.c (.../trunk) (revision 186562)
-@@ -83,6 +83,9 @@
- <enum name="musicclass">
- <para>R/W class (from musiconhold.conf) for hold music.</para>
- </enum>
-+ <enum name="name">
-+ <para>The name of the channel</para>
-+ </enum>
- <enum name="parkinglot">
- <para>R/W parkinglot for parking.</para>
- </enum>
-@@ -249,7 +252,9 @@
- locked_copy_string(chan, buf, chan->language, len);
- else if (!strcasecmp(data, "musicclass"))
- locked_copy_string(chan, buf, chan->musicclass, len);
-- else if (!strcasecmp(data, "parkinglot"))
-+ else if (!strcasecmp(data, "name")) {
-+ locked_copy_string(chan, buf, chan->name, len);
-+ } else if (!strcasecmp(data, "parkinglot"))
- locked_copy_string(chan, buf, chan->parkinglot, len);
- else if (!strcasecmp(data, "state"))
- locked_copy_string(chan, buf, ast_state2str(chan->_state), len);
-Index: include/asterisk/rtp.h
-===================================================================
---- a/include/asterisk/rtp.h (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/include/asterisk/rtp.h (.../trunk) (revision 186562)
-@@ -1,416 +0,0 @@
--/*
-- * Asterisk -- An open source telephony toolkit.
-- *
-- * Copyright (C) 1999 - 2006, Digium, Inc.
-- *
-- * Mark Spencer <markster@digium.com>
-- *
-- * See http://www.asterisk.org for more information about
-- * the Asterisk project. Please do not directly contact
-- * any of the maintainers of this project for assistance;
-- * the project provides a web site, mailing lists and IRC
-- * channels for your use.
-- *
-- * 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.
-- */
--
--/*!
-- * \file rtp.h
-- * \brief Supports RTP and RTCP with Symmetric RTP support for NAT traversal.
-- *
-- * RTP is defined in RFC 3550.
-- */
--
--#ifndef _ASTERISK_RTP_H
--#define _ASTERISK_RTP_H
--
--#include "asterisk/network.h"
--
--#include "asterisk/frame.h"
--#include "asterisk/io.h"
--#include "asterisk/sched.h"
--#include "asterisk/channel.h"
--#include "asterisk/linkedlists.h"
--
--#if defined(__cplusplus) || defined(c_plusplus)
--extern "C" {
--#endif
--
--/* Codes for RTP-specific data - not defined by our AST_FORMAT codes */
--/*! DTMF (RFC2833) */
--#define AST_RTP_DTMF (1 << 0)
--/*! 'Comfort Noise' (RFC3389) */
--#define AST_RTP_CN (1 << 1)
--/*! DTMF (Cisco Proprietary) */
--#define AST_RTP_CISCO_DTMF (1 << 2)
--/*! Maximum RTP-specific code */
--#define AST_RTP_MAX AST_RTP_CISCO_DTMF
--
--/*! Maxmum number of payload defintions for a RTP session */
--#define MAX_RTP_PT 256
--
--/*! T.140 Redundancy Maxium number of generations */
--#define RED_MAX_GENERATION 5
--
--#define FLAG_3389_WARNING (1 << 0)
--
--enum ast_rtp_options {
-- AST_RTP_OPT_G726_NONSTANDARD = (1 << 0),
--};
--
--enum ast_rtp_get_result {
-- /*! Failed to find the RTP structure */
-- AST_RTP_GET_FAILED = 0,
-- /*! RTP structure exists but true native bridge can not occur so try partial */
-- AST_RTP_TRY_PARTIAL,
-- /*! RTP structure exists and native bridge can occur */
-- AST_RTP_TRY_NATIVE,
--};
--
--/*! \brief Variables used in ast_rtcp_get function */
--enum ast_rtp_qos_vars {
-- AST_RTP_TXCOUNT,
-- AST_RTP_RXCOUNT,
-- AST_RTP_TXJITTER,
-- AST_RTP_RXJITTER,
-- AST_RTP_RXPLOSS,
-- AST_RTP_TXPLOSS,
-- AST_RTP_RTT
--};
--
--struct ast_rtp;
--/*! T.140 Redundancy structure*/
--struct rtp_red;
--
--/*! \brief The value of each payload format mapping: */
--struct rtpPayloadType {
-- int isAstFormat; /*!< whether the following code is an AST_FORMAT */
-- int code;
--};
--
--/*! \brief This is the structure that binds a channel (SIP/Jingle/H.323) to the RTP subsystem
--*/
--struct ast_rtp_protocol {
-- /*! Get RTP struct, or NULL if unwilling to transfer */
-- enum ast_rtp_get_result (* const get_rtp_info)(struct ast_channel *chan, struct ast_rtp **rtp);
-- /*! Get RTP struct, or NULL if unwilling to transfer */
-- enum ast_rtp_get_result (* const get_vrtp_info)(struct ast_channel *chan, struct ast_rtp **rtp);
-- /*! Get RTP struct, or NULL if unwilling to transfer */
-- enum ast_rtp_get_result (* const get_trtp_info)(struct ast_channel *chan, struct ast_rtp **rtp);
-- /*! Set RTP peer */
-- int (* const set_rtp_peer)(struct ast_channel *chan, struct ast_rtp *peer, struct ast_rtp *vpeer, struct ast_rtp *tpeer, int codecs, int nat_active);
-- int (* const get_codec)(struct ast_channel *chan);
-- const char * const type;
-- AST_LIST_ENTRY(ast_rtp_protocol) list;
--};
--
--enum ast_rtp_quality_type {
-- RTPQOS_SUMMARY = 0,
-- RTPQOS_JITTER,
-- RTPQOS_LOSS,
-- RTPQOS_RTT
--};
--
--/*! \brief RTCP quality report storage */
--struct ast_rtp_quality {
-- unsigned int local_ssrc; /*!< Our SSRC */
-- unsigned int local_lostpackets; /*!< Our lost packets */
-- double local_jitter; /*!< Our calculated jitter */
-- unsigned int local_count; /*!< Number of received packets */
-- unsigned int remote_ssrc; /*!< Their SSRC */
-- unsigned int remote_lostpackets; /*!< Their lost packets */
-- double remote_jitter; /*!< Their reported jitter */
-- unsigned int remote_count; /*!< Number of transmitted packets */
-- double rtt; /*!< Round trip time */
--};
--
--/*! RTP callback structure */
--typedef int (*ast_rtp_callback)(struct ast_rtp *rtp, struct ast_frame *f, void *data);
--
--/*!
-- * \brief Get the amount of space required to hold an RTP session
-- * \return number of bytes required
-- */
--size_t ast_rtp_alloc_size(void);
--
--/*!
-- * \brief Initializate a RTP session.
-- *
-- * \param sched
-- * \param io
-- * \param rtcpenable
-- * \param callbackmode
-- * \return A representation (structure) of an RTP session.
-- */
--struct ast_rtp *ast_rtp_new(struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode);
--
--/*!
-- * \brief Initializate a RTP session using an in_addr structure.
-- *
-- * This fuction gets called by ast_rtp_new().
-- *
-- * \param sched
-- * \param io
-- * \param rtcpenable
-- * \param callbackmode
-- * \param in
-- * \return A representation (structure) of an RTP session.
-- */
--struct ast_rtp *ast_rtp_new_with_bindaddr(struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode, struct in_addr in);
--
--void ast_rtp_set_peer(struct ast_rtp *rtp, struct sockaddr_in *them);
--
--/* Copies from rtp to them and returns 1 if there was a change or 0 if it was already the same */
--int ast_rtp_get_peer(struct ast_rtp *rtp, struct sockaddr_in *them);
--
--void ast_rtp_get_us(struct ast_rtp *rtp, struct sockaddr_in *us);
--
--struct ast_rtp *ast_rtp_get_bridged(struct ast_rtp *rtp);
--
--/*! Destroy RTP session */
--void ast_rtp_destroy(struct ast_rtp *rtp);
--
--void ast_rtp_reset(struct ast_rtp *rtp);
--
--/*! Stop RTP session, do not destroy structure */
--void ast_rtp_stop(struct ast_rtp *rtp);
--
--void ast_rtp_set_callback(struct ast_rtp *rtp, ast_rtp_callback callback);
--
--void ast_rtp_set_data(struct ast_rtp *rtp, void *data);
--
--int ast_rtp_write(struct ast_rtp *rtp, struct ast_frame *f);
--
--struct ast_frame *ast_rtp_read(struct ast_rtp *rtp);
--
--struct ast_frame *ast_rtcp_read(struct ast_rtp *rtp);
--
--int ast_rtp_fd(struct ast_rtp *rtp);
--
--int ast_rtcp_fd(struct ast_rtp *rtp);
--
--int ast_rtp_senddigit_begin(struct ast_rtp *rtp, char digit);
--
--int ast_rtp_senddigit_end(struct ast_rtp *rtp, char digit);
--
--int ast_rtp_sendcng(struct ast_rtp *rtp, int level);
--
--int ast_rtp_setqos(struct ast_rtp *rtp, int tos, int cos, char *desc);
--
--void ast_rtp_new_source(struct ast_rtp *rtp);
--
--/*! \brief Setting RTP payload types from lines in a SDP description: */
--void ast_rtp_pt_clear(struct ast_rtp* rtp);
--/*! \brief Set payload types to defaults */
--void ast_rtp_pt_default(struct ast_rtp* rtp);
--
--/*! \brief Copy payload types between RTP structures */
--void ast_rtp_pt_copy(struct ast_rtp *dest, struct ast_rtp *src);
--
--/*! \brief Activate payload type */
--void ast_rtp_set_m_type(struct ast_rtp* rtp, int pt);
--
--/*! \brief clear payload type */
--void ast_rtp_unset_m_type(struct ast_rtp* rtp, int pt);
--
--/*! \brief Set payload type to a known MIME media type for a codec
-- *
-- * \param rtp RTP structure to modify
-- * \param pt Payload type entry to modify
-- * \param mimeType top-level MIME type of media stream (typically "audio", "video", "text", etc.)
-- * \param mimeSubtype MIME subtype of media stream (typically a codec name)
-- * \param options Zero or more flags from the ast_rtp_options enum
-- *
-- * This function 'fills in' an entry in the list of possible formats for
-- * a media stream associated with an RTP structure.
-- *
-- * \retval 0 on success
-- * \retval -1 if the payload type is out of range
-- * \retval -2 if the mimeType/mimeSubtype combination was not found
-- */
--int ast_rtp_set_rtpmap_type(struct ast_rtp* rtp, int pt,
-- char *mimeType, char *mimeSubtype,
-- enum ast_rtp_options options);
--
--/*! \brief Set payload type to a known MIME media type for a codec with a specific sample rate
-- *
-- * \param rtp RTP structure to modify
-- * \param pt Payload type entry to modify
-- * \param mimeType top-level MIME type of media stream (typically "audio", "video", "text", etc.)
-- * \param mimeSubtype MIME subtype of media stream (typically a codec name)
-- * \param options Zero or more flags from the ast_rtp_options enum
-- * \param sample_rate The sample rate of the media stream
-- *
-- * This function 'fills in' an entry in the list of possible formats for
-- * a media stream associated with an RTP structure.
-- *
-- * \retval 0 on success
-- * \retval -1 if the payload type is out of range
-- * \retval -2 if the mimeType/mimeSubtype combination was not found
-- */
--int ast_rtp_set_rtpmap_type_rate(struct ast_rtp* rtp, int pt,
-- char *mimeType, char *mimeSubtype,
-- enum ast_rtp_options options,
-- unsigned int sample_rate);
--
--/*! \brief Mapping between RTP payload format codes and Asterisk codes: */
--struct rtpPayloadType ast_rtp_lookup_pt(struct ast_rtp* rtp, int pt);
--int ast_rtp_lookup_code(struct ast_rtp* rtp, int isAstFormat, int code);
--
--void ast_rtp_get_current_formats(struct ast_rtp* rtp,
-- int* astFormats, int* nonAstFormats);
--
--/*! \brief Mapping an Asterisk code into a MIME subtype (string): */
--const char *ast_rtp_lookup_mime_subtype(int isAstFormat, int code,
-- enum ast_rtp_options options);
--
--/*! \brief Get the sample rate associated with known RTP payload types
-- *
-- * \param isAstFormat True if the value in the 'code' parameter is an AST_FORMAT value
-- * \param code Format code, either from AST_FORMAT list or from AST_RTP list
-- *
-- * \return the sample rate if the format was found, zero if it was not found
-- */
--unsigned int ast_rtp_lookup_sample_rate(int isAstFormat, int code);
--
--/*! \brief Build a string of MIME subtype names from a capability list */
--char *ast_rtp_lookup_mime_multiple(char *buf, size_t size, const int capability,
-- const int isAstFormat, enum ast_rtp_options options);
--
--void ast_rtp_setnat(struct ast_rtp *rtp, int nat);
--
--int ast_rtp_getnat(struct ast_rtp *rtp);
--
--/*! \brief Indicate whether this RTP session is carrying DTMF or not */
--void ast_rtp_setdtmf(struct ast_rtp *rtp, int dtmf);
--
--/*! \brief Compensate for devices that send RFC2833 packets all at once */
--void ast_rtp_setdtmfcompensate(struct ast_rtp *rtp, int compensate);
--
--/*! \brief Enable STUN capability */
--void ast_rtp_setstun(struct ast_rtp *rtp, int stun_enable);
--
--/*! \brief Generic STUN request
-- * send a generic stun request to the server specified.
-- * \param s the socket used to send the request
-- * \param dst the address of the STUN server
-- * \param username if non null, add the username in the request
-- * \param answer if non null, the function waits for a response and
-- * puts here the externally visible address.
-- * \return 0 on success, other values on error.
-- * The interface it may change in the future.
-- */
--int ast_stun_request(int s, struct sockaddr_in *dst,
-- const char *username, struct sockaddr_in *answer);
--
--/*! \brief Send STUN request for an RTP socket
-- * Deprecated, this is just a wrapper for ast_rtp_stun_request()
-- */
--void ast_rtp_stun_request(struct ast_rtp *rtp, struct sockaddr_in *suggestion, const char *username);
--
--/*! \brief The RTP bridge.
-- \arg \ref AstRTPbridge
--*/
--int ast_rtp_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms);
--
--/*! \brief Register an RTP channel client */
--int ast_rtp_proto_register(struct ast_rtp_protocol *proto);
--
--/*! \brief Unregister an RTP channel client */
--void ast_rtp_proto_unregister(struct ast_rtp_protocol *proto);
--
--int ast_rtp_make_compatible(struct ast_channel *dest, struct ast_channel *src, int media);
--
--/*! \brief If possible, create an early bridge directly between the devices without
-- having to send a re-invite later */
--int ast_rtp_early_bridge(struct ast_channel *c0, struct ast_channel *c1);
--
--/*! \brief Get QOS stats on a RTP channel
-- * \since 1.6.1
-- */
--int ast_rtp_get_qos(struct ast_rtp *rtp, const char *qos, char *buf, unsigned int buflen);
--
--/*! \brief Return RTP and RTCP QoS values
-- * \since 1.6.1
-- */
--unsigned int ast_rtp_get_qosvalue(struct ast_rtp *rtp, enum ast_rtp_qos_vars value);
--
--/*! \brief Set RTPAUDIOQOS(...) variables on a channel when it is being hung up
-- * \since 1.6.1
-- */
--void ast_rtp_set_vars(struct ast_channel *chan, struct ast_rtp *rtp);
--
--/*! \brief Return RTCP quality string
-- *
-- * \param rtp An rtp structure to get qos information about.
-- *
-- * \param qual An (optional) rtp quality structure that will be
-- * filled with the quality information described in
-- * the ast_rtp_quality structure. This structure is
-- * not dependent on any qtype, so a call for any
-- * type of information would yield the same results
-- * because ast_rtp_quality is not a data type
-- * specific to any qos type.
-- *
-- * \param qtype The quality type you'd like, default should be
-- * RTPQOS_SUMMARY which returns basic information
-- * about the call. The return from RTPQOS_SUMMARY
-- * is basically ast_rtp_quality in a string. The
-- * other types are RTPQOS_JITTER, RTPQOS_LOSS and
-- * RTPQOS_RTT which will return more specific
-- * statistics.
-- * \version 1.6.1 added qtype parameter
-- */
--char *ast_rtp_get_quality(struct ast_rtp *rtp, struct ast_rtp_quality *qual, enum ast_rtp_quality_type qtype);
--/*! \brief Send an H.261 fast update request. Some devices need this rather than the XML message in SIP */
--int ast_rtcp_send_h261fur(void *data);
--
--void ast_rtp_init(void); /*! Initialize RTP subsystem */
--int ast_rtp_reload(void); /*! reload rtp configuration */
--void ast_rtp_new_init(struct ast_rtp *rtp);
--
--/*! \brief Set codec preference */
--void ast_rtp_codec_setpref(struct ast_rtp *rtp, struct ast_codec_pref *prefs);
--
--/*! \brief Get codec preference */
--struct ast_codec_pref *ast_rtp_codec_getpref(struct ast_rtp *rtp);
--
--/*! \brief get format from predefined dynamic payload format */
--int ast_rtp_codec_getformat(int pt);
--
--/*! \brief Set rtp timeout */
--void ast_rtp_set_rtptimeout(struct ast_rtp *rtp, int timeout);
--/*! \brief Set rtp hold timeout */
--void ast_rtp_set_rtpholdtimeout(struct ast_rtp *rtp, int timeout);
--/*! \brief set RTP keepalive interval */
--void ast_rtp_set_rtpkeepalive(struct ast_rtp *rtp, int period);
--/*! \brief Get RTP keepalive interval */
--int ast_rtp_get_rtpkeepalive(struct ast_rtp *rtp);
--/*! \brief Get rtp hold timeout */
--int ast_rtp_get_rtpholdtimeout(struct ast_rtp *rtp);
--/*! \brief Get rtp timeout */
--int ast_rtp_get_rtptimeout(struct ast_rtp *rtp);
--/* \brief Put RTP timeout timers on hold during another transaction, like T.38 */
--void ast_rtp_set_rtptimers_onhold(struct ast_rtp *rtp);
--
--/*! \brief Initalize t.140 redudancy
-- * \param ti time between each t140red frame is sent
-- * \param red_pt payloadtype for RTP packet
-- * \param pt payloadtype numbers for each generation including primary data
-- * \param num_gen number of redundant generations, primary data excluded
-- * \since 1.6.1
-- */
--int rtp_red_init(struct ast_rtp *rtp, int ti, int *pt, int num_gen);
--
--/*! \brief Buffer t.140 data */
--void red_buffer_t140(struct ast_rtp *rtp, struct ast_frame *f);
--
--
--
--#if defined(__cplusplus) || defined(c_plusplus)
--}
--#endif
--
--#endif /* _ASTERISK_RTP_H */
-Index: include/asterisk/rtp_engine.h
-===================================================================
---- a/include/asterisk/rtp_engine.h (.../tags/1.6.2.0-beta1) (revision 0)
-+++ b/include/asterisk/rtp_engine.h (.../trunk) (revision 186562)
-@@ -0,0 +1,1594 @@
-+/*
-+ * Asterisk -- An open source telephony toolkit.
-+ *
-+ * Copyright (C) 1999 - 2009, Digium, Inc.
-+ *
-+ * Mark Spencer <markster@digium.com>
-+ * Joshua Colp <jcolp@digium.com>
-+ *
-+ * See http://www.asterisk.org for more information about
-+ * the Asterisk project. Please do not directly contact
-+ * any of the maintainers of this project for assistance;
-+ * the project provides a web site, mailing lists and IRC
-+ * channels for your use.
-+ *
-+ * 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.
-+ */
-+
-+/*! \file
-+ * \brief Pluggable RTP Architecture
-+ * \author Joshua Colp <jcolp@digium.com>
-+ * \ref AstRTPEngine
-+ */
-+
-+/*!
-+ * \page AstRTPEngine Asterisk RTP Engine API
-+ *
-+ * The purpose of this API is to provide a way for multiple RTP stacks to be used inside
-+ * of Asterisk without any module that uses RTP knowing any different. To the module each RTP
-+ * stack behaves the same.
-+ *
-+ * An RTP session is called an instance and is made up of a combination of codec information,
-+ * RTP engine, RTP properties, and address information. An engine name may be passed in to explicitly
-+ * choose an RTP stack to be used but a default one will be used if none is provided. An address to use
-+ * for RTP may also be provided but the underlying RTP engine may choose a different address depending on
-+ * it's configuration.
-+ *
-+ * An RTP engine is the layer between the RTP engine core and the RTP stack itself. The RTP engine core provides
-+ * a set of callbacks to do various things (such as write audio out) that the RTP engine has to have implemented.
-+ *
-+ * Glue is what binds an RTP instance to a channel. It is used to retrieve RTP instance information when
-+ * performing remote or local bridging and is used to have the channel driver tell the remote side to change
-+ * destination of the RTP stream.
-+ *
-+ * Statistics from an RTP instance can be retrieved using the ast_rtp_instance_get_stats API call. This essentially
-+ * asks the RTP engine in use to fill in a structure with the requested values. It is not required for an RTP engine
-+ * to support all statistic values.
-+ *
-+ * Properties allow behavior of the RTP engine and RTP engine core to be changed. For example, there is a property named
-+ * AST_RTP_PROPERTY_NAT which is used to tell the RTP engine to enable symmetric RTP if it supports it. It is not required
-+ * for an RTP engine to support all properties.
-+ *
-+ * Codec information is stored using a separate data structure which has it's own set of API calls to add/remove/retrieve
-+ * information. They are used by the module after an RTP instance is created so that payload information is available for
-+ * the RTP engine.
-+ */
-+
-+#ifndef _ASTERISK_RTP_ENGINE_H
-+#define _ASTERISK_RTP_ENGINE_H
-+
-+#if defined(__cplusplus) || defined(c_plusplus)
-+extern "C" {
-+#endif
-+
-+#include "asterisk/astobj2.h"
-+
-+/* Maximum number of payloads supported */
-+#define AST_RTP_MAX_PT 256
-+
-+/* Maximum number of generations */
-+#define AST_RED_MAX_GENERATION 5
-+
-+struct ast_rtp_instance;
-+struct ast_rtp_glue;
-+
-+/*! RTP Properties that can be set on an RTP instance */
-+enum ast_rtp_property {
-+ /*! Enable symmetric RTP support */
-+ AST_RTP_PROPERTY_NAT = 0,
-+ /*! RTP instance will be carrying DTMF (using RFC2833) */
-+ AST_RTP_PROPERTY_DTMF,
-+ /*! Expect unreliable DTMF from remote party */
-+ AST_RTP_PROPERTY_DTMF_COMPENSATE,
-+ /*! Enable STUN support */
-+ AST_RTP_PROPERTY_STUN,
-+ /*! Enable RTCP support */
-+ AST_RTP_PROPERTY_RTCP,
-+ /*! Maximum number of RTP properties supported */
-+ AST_RTP_PROPERTY_MAX,
-+};
-+
-+/*! Additional RTP options */
-+enum ast_rtp_options {
-+ /*! Remote side is using non-standard G.726 */
-+ AST_RTP_OPT_G726_NONSTANDARD = (1 << 0),
-+};
-+
-+/*! RTP DTMF Modes */
-+enum ast_rtp_dtmf_mode {
-+ /*! No DTMF is being carried over the RTP stream */
-+ AST_RTP_DTMF_MODE_NONE = 0,
-+ /*! DTMF is being carried out of band using RFC2833 */
-+ AST_RTP_DTMF_MODE_RFC2833,
-+ /*! DTMF is being carried inband over the RTP stream */
-+ AST_RTP_DTMF_MODE_INBAND,
-+};
-+
-+/*! Result codes when RTP glue is queried for information */
-+enum ast_rtp_glue_result {
-+ /*! No remote or local bridging is permitted */
-+ AST_RTP_GLUE_RESULT_FORBID = 0,
-+ /*! Move RTP stream to be remote between devices directly */
-+ AST_RTP_GLUE_RESULT_REMOTE,
-+ /*! Perform RTP engine level bridging if possible */
-+ AST_RTP_GLUE_RESULT_LOCAL,
-+};
-+
-+/*! Field statistics that can be retrieved from an RTP instance */
-+enum ast_rtp_instance_stat_field {
-+ /*! Retrieve quality information */
-+ AST_RTP_INSTANCE_STAT_FIELD_QUALITY = 0,
-+ /*! Retrieve quality information about jitter */
-+ AST_RTP_INSTANCE_STAT_FIELD_QUALITY_JITTER,
-+ /*! Retrieve quality information about packet loss */
-+ AST_RTP_INSTANCE_STAT_FIELD_QUALITY_LOSS,
-+ /*! Retrieve quality information about round trip time */
-+ AST_RTP_INSTANCE_STAT_FIELD_QUALITY_RTT,
-+};
-+
-+/*! Statistics that can be retrieved from an RTP instance */
-+enum ast_rtp_instance_stat {
-+ /*! Retrieve all statistics */
-+ AST_RTP_INSTANCE_STAT_ALL = 0,
-+ /*! Retrieve number of packets transmitted */
-+ AST_RTP_INSTANCE_STAT_TXCOUNT,
-+ /*! Retrieve number of packets received */
-+ AST_RTP_INSTANCE_STAT_RXCOUNT,
-+ /*! Retrieve ALL statistics relating to packet loss */
-+ AST_RTP_INSTANCE_STAT_COMBINED_LOSS,
-+ /*! Retrieve number of packets lost for transmitting */
-+ AST_RTP_INSTANCE_STAT_TXPLOSS,
-+ /*! Retrieve number of packets lost for receiving */
-+ AST_RTP_INSTANCE_STAT_RXPLOSS,
-+ /*! Retrieve maximum number of packets lost on remote side */
-+ AST_RTP_INSTANCE_STAT_REMOTE_MAXRXPLOSS,
-+ /*! Retrieve minimum number of packets lost on remote side */
-+ AST_RTP_INSTANCE_STAT_REMOTE_MINRXPLOSS,
-+ /*! Retrieve average number of packets lost on remote side */
-+ AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVRXPLOSS,
-+ /*! Retrieve standard deviation of packets lost on remote side */
-+ AST_RTP_INSTANCE_STAT_REMOTE_STDEVRXPLOSS,
-+ /*! Retrieve maximum number of packets lost on local side */
-+ AST_RTP_INSTANCE_STAT_LOCAL_MAXRXPLOSS,
-+ /*! Retrieve minimum number of packets lost on local side */
-+ AST_RTP_INSTANCE_STAT_LOCAL_MINRXPLOSS,
-+ /*! Retrieve average number of packets lost on local side */
-+ AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVRXPLOSS,
-+ /*! Retrieve standard deviation of packets lost on local side */
-+ AST_RTP_INSTANCE_STAT_LOCAL_STDEVRXPLOSS,
-+ /*! Retrieve ALL statistics relating to jitter */
-+ AST_RTP_INSTANCE_STAT_COMBINED_JITTER,
-+ /*! Retrieve jitter on transmitted packets */
-+ AST_RTP_INSTANCE_STAT_TXJITTER,
-+ /*! Retrieve jitter on received packets */
-+ AST_RTP_INSTANCE_STAT_RXJITTER,
-+ /*! Retrieve maximum jitter on remote side */
-+ AST_RTP_INSTANCE_STAT_REMOTE_MAXJITTER,
-+ /*! Retrieve minimum jitter on remote side */
-+ AST_RTP_INSTANCE_STAT_REMOTE_MINJITTER,
-+ /*! Retrieve average jitter on remote side */
-+ AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVJITTER,
-+ /*! Retrieve standard deviation jitter on remote side */
-+ AST_RTP_INSTANCE_STAT_REMOTE_STDEVJITTER,
-+ /*! Retrieve maximum jitter on local side */
-+ AST_RTP_INSTANCE_STAT_LOCAL_MAXJITTER,
-+ /*! Retrieve minimum jitter on local side */
-+ AST_RTP_INSTANCE_STAT_LOCAL_MINJITTER,
-+ /*! Retrieve average jitter on local side */
-+ AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVJITTER,
-+ /*! Retrieve standard deviation jitter on local side */
-+ AST_RTP_INSTANCE_STAT_LOCAL_STDEVJITTER,
-+ /*! Retrieve ALL statistics relating to round trip time */
-+ AST_RTP_INSTANCE_STAT_COMBINED_RTT,
-+ /*! Retrieve round trip time */
-+ AST_RTP_INSTANCE_STAT_RTT,
-+ /*! Retrieve maximum round trip time */
-+ AST_RTP_INSTANCE_STAT_MAX_RTT,
-+ /*! Retrieve minimum round trip time */
-+ AST_RTP_INSTANCE_STAT_MIN_RTT,
-+ /*! Retrieve average round trip time */
-+ AST_RTP_INSTANCE_STAT_NORMDEVRTT,
-+ /*! Retrieve standard deviation round trip time */
-+ AST_RTP_INSTANCE_STAT_STDEVRTT,
-+ /*! Retrieve local SSRC */
-+ AST_RTP_INSTANCE_STAT_LOCAL_SSRC,
-+ /*! Retrieve remote SSRC */
-+ AST_RTP_INSTANCE_STAT_REMOTE_SSRC,
-+};
-+
-+/* Codes for RTP-specific data - not defined by our AST_FORMAT codes */
-+/*! DTMF (RFC2833) */
-+#define AST_RTP_DTMF (1 << 0)
-+/*! 'Comfort Noise' (RFC3389) */
-+#define AST_RTP_CN (1 << 1)
-+/*! DTMF (Cisco Proprietary) */
-+#define AST_RTP_CISCO_DTMF (1 << 2)
-+/*! Maximum RTP-specific code */
-+#define AST_RTP_MAX AST_RTP_CISCO_DTMF
-+
-+/*! Structure that represents a payload */
-+struct ast_rtp_payload_type {
-+ /*! Is this an Asterisk value */
-+ int asterisk_format;
-+ /*! Actual internal value of the payload */
-+ int code;
-+};
-+
-+/*! Structure that represents statistics from an RTP instance */
-+struct ast_rtp_instance_stats {
-+ /*! Number of packets transmitted */
-+ unsigned int txcount;
-+ /*! Number of packets received */
-+ unsigned int rxcount;
-+ /*! Jitter on transmitted packets */
-+ unsigned int txjitter;
-+ /*! Jitter on received packets */
-+ unsigned int rxjitter;
-+ /*! Maximum jitter on remote side */
-+ double remote_maxjitter;
-+ /*! Minimum jitter on remote side */
-+ double remote_minjitter;
-+ /*! Average jitter on remote side */
-+ double remote_normdevjitter;
-+ /*! Standard deviation jitter on remote side */
-+ double remote_stdevjitter;
-+ /*! Maximum jitter on local side */
-+ double local_maxjitter;
-+ /*! Minimum jitter on local side */
-+ double local_minjitter;
-+ /*! Average jitter on local side */
-+ double local_normdevjitter;
-+ /*! Standard deviation jitter on local side */
-+ double local_stdevjitter;
-+ /*! Number of transmitted packets lost */
-+ unsigned int txploss;
-+ /*! Number of received packets lost */
-+ unsigned int rxploss;
-+ /*! Maximum number of packets lost on remote side */
-+ double remote_maxrxploss;
-+ /*! Minimum number of packets lost on remote side */
-+ double remote_minrxploss;
-+ /*! Average number of packets lost on remote side */
-+ double remote_normdevrxploss;
-+ /*! Standard deviation packets lost on remote side */
-+ double remote_stdevrxploss;
-+ /*! Maximum number of packets lost on local side */
-+ double local_maxrxploss;
-+ /*! Minimum number of packets lost on local side */
-+ double local_minrxploss;
-+ /*! Average number of packets lost on local side */
-+ double local_normdevrxploss;
-+ /*! Standard deviation packets lost on local side */
-+ double local_stdevrxploss;
-+ /*! Total round trip time */
-+ unsigned int rtt;
-+ /*! Maximum round trip time */
-+ double maxrtt;
-+ /*! Minimum round trip time */
-+ double minrtt;
-+ /*! Average round trip time */
-+ double normdevrtt;
-+ /*! Standard deviation round trip time */
-+ double stdevrtt;
-+ /*! Our SSRC */
-+ unsigned int local_ssrc;
-+ /*! Their SSRC */
-+ unsigned int remote_ssrc;
-+};
-+
-+#define AST_RTP_STAT_SET(current_stat, combined, placement, value) \
-+if (stat == current_stat || stat == AST_RTP_INSTANCE_STAT_ALL || (combined >= 0 && combined == current_stat)) { \
-+placement = value; \
-+if (stat == current_stat) { \
-+return 0; \
-+} \
-+}
-+
-+#define AST_RTP_STAT_TERMINATOR(combined) \
-+if (stat == combined) { \
-+return 0; \
-+}
-+
-+/*! Structure that represents an RTP stack (engine) */
-+struct ast_rtp_engine {
-+ /*! Name of the RTP engine, used when explicitly requested */
-+ const char *name;
-+ /*! Module this RTP engine came from, used for reference counting */
-+ struct ast_module *mod;
-+ /*! Callback for setting up a new RTP instance */
-+ int (*new)(struct ast_rtp_instance *instance, struct sched_context *sched, struct sockaddr_in *sin, void *data);
-+ /*! Callback for destroying an RTP instance */
-+ int (*destroy)(struct ast_rtp_instance *instance);
-+ /*! Callback for writing out a frame */
-+ int (*write)(struct ast_rtp_instance *instance, struct ast_frame *frame);
-+ /*! Callback for stopping the RTP instance */
-+ void (*stop)(struct ast_rtp_instance *instance);
-+ /*! Callback for starting RFC2833 DTMF transmission */
-+ int (*dtmf_begin)(struct ast_rtp_instance *instance, char digit);
-+ /*! Callback for stopping RFC2833 DTMF transmission */
-+ int (*dtmf_end)(struct ast_rtp_instance *instance, char digit);
-+ /*! Callback to indicate that a new source of media has come in */
-+ void (*new_source)(struct ast_rtp_instance *instance);
-+ /*! Callback for setting an extended RTP property */
-+ int (*extended_prop_set)(struct ast_rtp_instance *instance, int property, void *value);
-+ /*! Callback for getting an extended RTP property */
-+ void *(*extended_prop_get)(struct ast_rtp_instance *instance, int property);
-+ /*! Callback for setting an RTP property */
-+ void (*prop_set)(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value);
-+ /*! Callback for setting a payload */
-+ void (*payload_set)(struct ast_rtp_instance *instance, int payload, int astformat, int format);
-+ /*! Callback for setting packetization preferences */
-+ void (*packetization_set)(struct ast_rtp_instance *instance, struct ast_codec_pref *pref);
-+ /*! Callback for setting the remote address that RTP is to be sent to */
-+ void (*remote_address_set)(struct ast_rtp_instance *instance, struct sockaddr_in *sin);
-+ /*! Callback for changing DTMF mode */
-+ int (*dtmf_mode_set)(struct ast_rtp_instance *instance, enum ast_rtp_dtmf_mode dtmf_mode);
-+ /*! Callback for retrieving statistics */
-+ int (*get_stat)(struct ast_rtp_instance *instance, struct ast_rtp_instance_stats *stats, enum ast_rtp_instance_stat stat);
-+ /*! Callback for setting QoS values */
-+ int (*qos)(struct ast_rtp_instance *instance, int tos, int cos, const char *desc);
-+ /*! Callback for retrieving a file descriptor to poll on, not always required */
-+ int (*fd)(struct ast_rtp_instance *instance, int rtcp);
-+ /*! Callback for initializing RED support */
-+ int (*red_init)(struct ast_rtp_instance *instance, int buffer_time, int *payloads, int generations);
-+ /*! Callback for buffering a frame using RED */
-+ int (*red_buffer)(struct ast_rtp_instance *instance, struct ast_frame *frame);
-+ /*! Callback for reading a frame from the RTP engine */
-+ struct ast_frame *(*read)(struct ast_rtp_instance *instance, int rtcp);
-+ /*! Callback to locally bridge two RTP instances */
-+ int (*local_bridge)(struct ast_rtp_instance *instance0, struct ast_rtp_instance *instance1);
-+ /*! Callback to set the read format */
-+ int (*set_read_format)(struct ast_rtp_instance *instance, int format);
-+ /*! Callback to set the write format */
-+ int (*set_write_format)(struct ast_rtp_instance *instance, int format);
-+ /*! Callback to make two instances compatible */
-+ int (*make_compatible)(struct ast_channel *chan0, struct ast_rtp_instance *instance0, struct ast_channel *chan1, struct ast_rtp_instance *instance1);
-+ /*! Callback to see if two instances are compatible with DTMF */
-+ int (*dtmf_compatible)(struct ast_channel *chan0, struct ast_rtp_instance *instance0, struct ast_channel *chan1, struct ast_rtp_instance *instance1);
-+ /*! Callback to indicate that packets will now flow */
-+ int (*activate)(struct ast_rtp_instance *instance);
-+ /*! Callback to request that the RTP engine send a STUN BIND request */
-+ void (*stun_request)(struct ast_rtp_instance *instance, struct sockaddr_in *suggestion, const char *username);
-+ /*! Linked list information */
-+ AST_RWLIST_ENTRY(ast_rtp_engine) entry;
-+};
-+
-+/*! Structure that represents codec and packetization information */
-+struct ast_rtp_codecs {
-+ /*! Codec packetization preferences */
-+ struct ast_codec_pref pref;
-+ /*! Payloads present */
-+ struct ast_rtp_payload_type payloads[AST_RTP_MAX_PT];
-+};
-+
-+/*! Structure that represents the glue that binds an RTP instance to a channel */
-+struct ast_rtp_glue {
-+ /*! Name of the channel driver that this glue is responsible for */
-+ const char *type;
-+ /*! Module that the RTP glue came from */
-+ struct ast_module *mod;
-+ /*!
-+ * \brief Callback for retrieving the RTP instance carrying audio
-+ * \note This function increases the reference count on the returned RTP instance.
-+ */
-+ enum ast_rtp_glue_result (*get_rtp_info)(struct ast_channel *chan, struct ast_rtp_instance **instance);
-+ /*!
-+ * \brief Callback for retrieving the RTP instance carrying video
-+ * \note This function increases the reference count on the returned RTP instance.
-+ */
-+ enum ast_rtp_glue_result (*get_vrtp_info)(struct ast_channel *chan, struct ast_rtp_instance **instance);
-+ /*!
-+ * \brief Callback for retrieving the RTP instance carrying text
-+ * \note This function increases the reference count on the returned RTP instance.
-+ */
-+ enum ast_rtp_glue_result (*get_trtp_info)(struct ast_channel *chan, struct ast_rtp_instance **instance);
-+ /*! Callback for updating the destination that the remote side should send RTP to */
-+ int (*update_peer)(struct ast_channel *chan, struct ast_rtp_instance *instance, struct ast_rtp_instance *vinstance, struct ast_rtp_instance *tinstance, int codecs, int nat_active);
-+ /*! Callback for retrieving codecs that the channel can do */
-+ int (*get_codec)(struct ast_channel *chan);
-+ /*! Linked list information */
-+ AST_RWLIST_ENTRY(ast_rtp_glue) entry;
-+};
-+
-+#define ast_rtp_engine_register(engine) ast_rtp_engine_register2(engine, ast_module_info->self)
-+
-+/*!
-+ * \brief Register an RTP engine
-+ *
-+ * \param engine Structure of the RTP engine to register
-+ * \param module Module that the RTP engine is part of
-+ *
-+ * \retval 0 success
-+ * \retval -1 failure
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * ast_rtp_engine_register2(&example_rtp_engine, NULL);
-+ * \endcode
-+ *
-+ * This registers the RTP engine declared as example_rtp_engine with the RTP engine core, but does not
-+ * associate a module with it.
-+ *
-+ * \note It is recommended that you use the ast_rtp_engine_register macro so that the module is
-+ * associated with the RTP engine and use counting is performed.
-+ *
-+ * \since 1.6.3
-+ */
-+int ast_rtp_engine_register2(struct ast_rtp_engine *engine, struct ast_module *module);
-+
-+/*!
-+ * \brief Unregister an RTP engine
-+ *
-+ * \param engine Structure of the RTP engine to unregister
-+ *
-+ * \retval 0 success
-+ * \retval -1 failure
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * ast_rtp_engine_unregister(&example_rtp_engine);
-+ * \endcode
-+ *
-+ * This unregisters the RTP engine declared as example_rtp_engine from the RTP engine core. If a module
-+ * reference was provided when it was registered then this will only be called once the RTP engine is no longer in use.
-+ *
-+ * \since 1.6.3
-+ */
-+int ast_rtp_engine_unregister(struct ast_rtp_engine *engine);
-+
-+#define ast_rtp_glue_register(glue) ast_rtp_glue_register2(glue, ast_module_info->self)
-+
-+/*!
-+ * \brief Register RTP glue
-+ *
-+ * \param glue The glue to register
-+ * \param module Module that the RTP glue is part of
-+ *
-+ * \retval 0 success
-+ * \retval -1 failure
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * ast_rtp_glue_register2(&example_rtp_glue, NULL);
-+ * \endcode
-+ *
-+ * This registers the RTP glue declared as example_rtp_glue with the RTP engine core, but does not
-+ * associate a module with it.
-+ *
-+ * \note It is recommended that you use the ast_rtp_glue_register macro so that the module is
-+ * associated with the RTP glue and use counting is performed.
-+ *
-+ * \since 1.6.3
-+ */
-+int ast_rtp_glue_register2(struct ast_rtp_glue *glue, struct ast_module *module);
-+
-+/*!
-+ * \brief Unregister RTP glue
-+ *
-+ * \param glue The glue to unregister
-+ *
-+ * \retval 0 success
-+ * \retval -1 failure
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * ast_rtp_glue_unregister(&example_rtp_glue);
-+ * \endcode
-+ *
-+ * This unregisters the RTP glue declared as example_rtp_gkue from the RTP engine core. If a module
-+ * reference was provided when it was registered then this will only be called once the RTP engine is no longer in use.
-+ *
-+ * \since 1.6.3
-+ */
-+int ast_rtp_glue_unregister(struct ast_rtp_glue *glue);
-+
-+/*!
-+ * \brief Create a new RTP instance
-+ *
-+ * \param engine_name Name of the engine to use for the RTP instance
-+ * \param sched Scheduler context that the RTP engine may want to use
-+ * \param sin Address we want to bind to
-+ * \param data Unique data for the engine
-+ *
-+ * \retval non-NULL success
-+ * \retval NULL failure
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * struct ast_rtp_instance *instance = NULL;
-+ * instance = ast_rtp_instance_new(NULL, sched, &sin, NULL);
-+ * \endcode
-+ *
-+ * This creates a new RTP instance using the default engine and asks the RTP engine to bind to the address given
-+ * in the sin structure.
-+ *
-+ * \note The RTP engine does not have to use the address provided when creating an RTP instance. It may choose to use
-+ * another depending on it's own configuration.
-+ *
-+ * \since 1.6.3
-+ */
-+struct ast_rtp_instance *ast_rtp_instance_new(const char *engine_name, struct sched_context *sched, struct sockaddr_in *sin, void *data);
-+
-+/*!
-+ * \brief Destroy an RTP instance
-+ *
-+ * \param instance The RTP instance to destroy
-+ *
-+ * \retval 0 success
-+ * \retval -1 failure
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * ast_rtp_instance_destroy(instance);
-+ * \endcode
-+ *
-+ * This destroys the RTP instance pointed to by instance. Once this function returns instance no longer points to valid
-+ * memory and may not be used again.
-+ *
-+ * \since 1.6.3
-+ */
-+int ast_rtp_instance_destroy(struct ast_rtp_instance *instance);
-+
-+/*!
-+ * \brief Set the data portion of an RTP instance
-+ *
-+ * \param instance The RTP instance to manipulate
-+ * \param data Pointer to data
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * ast_rtp_instance_set_data(instance, blob);
-+ * \endcode
-+ *
-+ * This sets the data pointer on the RTP instance pointed to by 'instance' to
-+ * blob.
-+ *
-+ * \since 1.6.3
-+ */
-+void ast_rtp_instance_set_data(struct ast_rtp_instance *instance, void *data);
-+
-+/*!
-+ * \brief Get the data portion of an RTP instance
-+ *
-+ * \param instance The RTP instance we want the data portion from
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * struct *blob = ast_rtp_instance_get_data(instance);
-+ ( \endcode
-+ *
-+ * This gets the data pointer on the RTP instance pointed to by 'instance'.
-+ *
-+ * \since 1.6.3
-+ */
-+void *ast_rtp_instance_get_data(struct ast_rtp_instance *instance);
-+
-+/*!
-+ * \brief Send a frame out over RTP
-+ *
-+ * \param instance The RTP instance to send frame out on
-+ *
-+ * \retval 0 success
-+ * \retval -1 failure
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * ast_rtp_instance_write(instance, frame);
-+ * \endcode
-+ *
-+ * This gives the frame pointed to by frame to the RTP engine being used for the instance
-+ * and asks that it be transmitted to the current remote address set on the RTP instance.
-+ *
-+ * \since 1.6.3
-+ */
-+int ast_rtp_instance_write(struct ast_rtp_instance *instance, struct ast_frame *frame);
-+
-+/*!
-+ * \brief Receive a frame over RTP
-+ *
-+ * \param instance The RTP instance to receive frame on
-+ * \param rtcp Whether to read in RTCP or not
-+ *
-+ * \retval non-NULL success
-+ * \retval NULL failure
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * struct ast_frame *frame;
-+ * frame = ast_rtp_instance_read(instance, 0);
-+ * \endcode
-+ *
-+ * This asks the RTP engine to read in RTP from the instance and return it as an Asterisk frame.
-+ *
-+ * \since 1.6.3
-+ */
-+struct ast_frame *ast_rtp_instance_read(struct ast_rtp_instance *instance, int rtcp);
-+
-+/*!
-+ * \brief Set the address of the remote endpoint that we are sending RTP to
-+ *
-+ * \param instance The RTP instance to change the address on
-+ * \param address Address to set it to
-+ *
-+ * \retval 0 success
-+ * \retval -1 failure
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * ast_rtp_instance_set_remote_address(instance, &sin);
-+ * \endcode
-+ *
-+ * This changes the remote address that RTP will be sent to on instance to the address given in the sin
-+ * structure.
-+ *
-+ * \since 1.6.3
-+ */
-+int ast_rtp_instance_set_remote_address(struct ast_rtp_instance *instance, struct sockaddr_in *address);
-+
-+/*!
-+ * \brief Set the address that we are expecting to receive RTP on
-+ *
-+ * \param instance The RTP instance to change the address on
-+ * \param address Address to set it to
-+ *
-+ * \retval 0 success
-+ * \retval -1 failure
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * ast_rtp_instance_set_local_address(instance, &sin);
-+ * \endcode
-+ *
-+ * This changes the local address that RTP is expected on to the address given in the sin
-+ * structure.
-+ *
-+ * \since 1.6.3
-+ */
-+int ast_rtp_instance_set_local_address(struct ast_rtp_instance *instance, struct sockaddr_in *address);
-+
-+/*!
-+ * \brief Get the local address that we are expecting RTP on
-+ *
-+ * \param instance The RTP instance to get the address from
-+ * \param address The variable to store the address in
-+ *
-+ * \retval 0 success
-+ * \retval -1 failure
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * struct sockaddr_in sin;
-+ * ast_rtp_instance_get_local_address(instance, &sin);
-+ * \endcode
-+ *
-+ * This gets the local address that we are expecting RTP on and stores it in the 'sin' structure.
-+ *
-+ * \since 1.6.3
-+ */
-+int ast_rtp_instance_get_local_address(struct ast_rtp_instance *instance, struct sockaddr_in *address);
-+
-+/*!
-+ * \brief Get the address of the remote endpoint that we are sending RTP to
-+ *
-+ * \param instance The instance that we want to get the remote address for
-+ * \param address A structure to put the address into
-+ *
-+ * \retval 0 success
-+ * \retval -1 failure
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * struct sockaddr_in sin;
-+ * ast_rtp_instance_get_remote_address(instance, &sin);
-+ * \endcode
-+ *
-+ * This retrieves the current remote address set on the instance pointed to by instance and puts the value
-+ * into the sin structure.
-+ *
-+ * \since 1.6.3
-+ */
-+int ast_rtp_instance_get_remote_address(struct ast_rtp_instance *instance, struct sockaddr_in *address);
-+
-+/*!
-+ * \brief Set the value of an RTP instance extended property
-+ *
-+ * \param instance The RTP instance to set the extended property on
-+ * \param property The extended property to set
-+ * \param value The value to set the extended property to
-+ *
-+ * \since 1.6.3
-+ */
-+void ast_rtp_instance_set_extended_prop(struct ast_rtp_instance *instance, int property, void *value);
-+
-+/*!
-+ * \brief Get the value of an RTP instance extended property
-+ *
-+ * \param instance The RTP instance to get the extended property on
-+ * \param property The extended property to get
-+ *
-+ * \since 1.6.3
-+ */
-+void *ast_rtp_instance_get_extended_prop(struct ast_rtp_instance *instance, int property);
-+
-+/*!
-+ * \brief Set the value of an RTP instance property
-+ *
-+ * \param instance The RTP instance to set the property on
-+ * \param property The property to modify
-+ * \param value The value to set the property to
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * ast_rtp_instance_set_prop(instance, AST_RTP_PROPERTY_NAT, 1);
-+ * \endcode
-+ *
-+ * This enables the AST_RTP_PROPERTY_NAT property on the instance pointed to by instance.
-+ *
-+ * \since 1.6.3
-+ */
-+void ast_rtp_instance_set_prop(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value);
-+
-+/*!
-+ * \brief Get the value of an RTP instance property
-+ *
-+ * \param instance The RTP instance to get the property from
-+ * \param property The property to get
-+ *
-+ * \retval Current value of the property
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT);
-+ * \endcode
-+ *
-+ * This returns the current value of the NAT property on the instance pointed to by instance.
-+ *
-+ * \since 1.6.3
-+ */
-+int ast_rtp_instance_get_prop(struct ast_rtp_instance *instance, enum ast_rtp_property property);
-+
-+/*!
-+ * \brief Get the codecs structure of an RTP instance
-+ *
-+ * \param instance The RTP instance to get the codecs structure from
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * struct ast_rtp_codecs *codecs = ast_rtp_instance_get_codecs(instance);
-+ * \endcode
-+ *
-+ * This gets the codecs structure on the RTP instance pointed to by 'instance'.
-+ *
-+ * \since 1.6.3
-+ */
-+struct ast_rtp_codecs *ast_rtp_instance_get_codecs(struct ast_rtp_instance *instance);
-+
-+/*!
-+ * \brief Clear payload information from an RTP instance
-+ *
-+ * \param codecs The codecs structure that payloads will be cleared from
-+ * \param instance Optionally the instance that the codecs structure belongs to
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * struct ast_rtp_codecs codecs;
-+ * ast_rtp_codecs_payloads_clear(&codecs, NULL);
-+ * \endcode
-+ *
-+ * This clears the codecs structure and puts it into a pristine state.
-+ *
-+ * \since 1.6.3
-+ */
-+void ast_rtp_codecs_payloads_clear(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance);
-+
-+/*!
-+ * \brief Set payload information on an RTP instance to the default
-+ *
-+ * \param codecs The codecs structure to set defaults on
-+ * \param instance Optionally the instance that the codecs structure belongs to
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * struct ast_rtp_codecs codecs;
-+ * ast_rtp_codecs_payloads_default(&codecs, NULL);
-+ * \endcode
-+ *
-+ * This sets the default payloads on the codecs structure.
-+ *
-+ * \since 1.6.3
-+ */
-+void ast_rtp_codecs_payloads_default(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance);
-+
-+/*!
-+ * \brief Copy payload information from one RTP instance to another
-+ *
-+ * \param src The source codecs structure
-+ * \param dst The destination codecs structure that the values from src will be copied to
-+ * \param instance Optionally the instance that the dst codecs structure belongs to
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * ast_rtp_codecs_payloads_copy(&codecs0, &codecs1, NULL);
-+ * \endcode
-+ *
-+ * This copies the payloads from the codecs0 structure to the codecs1 structure, overwriting any current values.
-+ *
-+ * \since 1.6.3
-+ */
-+void ast_rtp_codecs_payloads_copy(struct ast_rtp_codecs *src, struct ast_rtp_codecs *dest, struct ast_rtp_instance *instance);
-+
-+/*!
-+ * \brief Record payload information that was seen in an m= SDP line
-+ *
-+ * \param codecs The codecs structure to muck with
-+ * \param instance Optionally the instance that the codecs structure belongs to
-+ * \param payload Numerical payload that was seen in the m= SDP line
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * ast_rtp_codecs_payloads_set_m_type(&codecs, NULL, 0);
-+ * \endcode
-+ *
-+ * This records that the numerical payload '0' was seen in the codecs structure.
-+ *
-+ * \since 1.6.3
-+ */
-+void ast_rtp_codecs_payloads_set_m_type(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload);
-+
-+/*!
-+ * \brief Record payload information that was seen in an a=rtpmap: SDP line
-+ *
-+ * \param codecs The codecs structure to muck with
-+ * \param instance Optionally the instance that the codecs structure belongs to
-+ * \param payload Numerical payload that was seen in the a=rtpmap: SDP line
-+ * \param mimetype The string mime type that was seen
-+ * \param mimesubtype The strin mime sub type that was seen
-+ * \param options Optional options that may change the behavior of this specific payload
-+ *
-+ * \retval 0 success
-+ * \retval -1 failure
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * ast_rtp_codecs_payloads_set_rtpmap_type(&codecs, NULL, 0, "audio", "PCMU", 0);
-+ * \endcode
-+ *
-+ * This records that the numerical payload '0' was seen with mime type 'audio' and sub mime type 'PCMU' in the codecs structure.
-+ *
-+ * \since 1.6.3
-+ */
-+int ast_rtp_codecs_payloads_set_rtpmap_type(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload, char *mimetype, char *mimesubtype, enum ast_rtp_options options);
-+
-+/*!
-+ * \brief Set payload type to a known MIME media type for a codec with a specific sample rate
-+ *
-+ * \param rtp RTP structure to modify
-+ * \param instance Optionally the instance that the codecs structure belongs to
-+ * \param pt Payload type entry to modify
-+ * \param mimetype top-level MIME type of media stream (typically "audio", "video", "text", etc.)
-+ * \param mimesubtype MIME subtype of media stream (typically a codec name)
-+ * \param options Zero or more flags from the ast_rtp_options enum
-+ * \param sample_rate The sample rate of the media stream
-+ *
-+ * This function 'fills in' an entry in the list of possible formats for
-+ * a media stream associated with an RTP structure.
-+ *
-+ * \retval 0 on success
-+ * \retval -1 if the payload type is out of range
-+ * \retval -2 if the mimeType/mimeSubtype combination was not found
-+ *
-+ * \since 1.6.3
-+ */
-+int ast_rtp_codecs_payloads_set_rtpmap_type_rate(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int pt,
-+ char *mimetype, char *mimesubtype,
-+ enum ast_rtp_options options,
-+ unsigned int sample_rate);
-+
-+/*!
-+ * \brief Remove payload information
-+ *
-+ * \param codecs The codecs structure to muck with
-+ * \param instance Optionally the instance that the codecs structure belongs to
-+ * \param payload Numerical payload to unset
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * ast_rtp_codecs_payloads_unset(&codecs, NULL, 0);
-+ * \endcode
-+ *
-+ * This clears the payload '0' from the codecs structure. It will be as if it was never set.
-+ *
-+ * \since 1.6.3
-+ */
-+void ast_rtp_codecs_payloads_unset(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload);
-+
-+/*!
-+ * \brief Retrieve payload information by payload
-+ *
-+ * \param codecs Codecs structure to look in
-+ * \param payload Numerical payload to look up
-+ *
-+ * \retval Payload information
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * struct ast_rtp_payload_type payload_type;
-+ * payload_type = ast_rtp_codecs_payload_lookup(&codecs, 0);
-+ * \endcode
-+ *
-+ * This looks up the information for payload '0' from the codecs structure.
-+ *
-+ * \since 1.6.3
-+ */
-+struct ast_rtp_payload_type ast_rtp_codecs_payload_lookup(struct ast_rtp_codecs *codecs, int payload);
-+
-+/*!
-+ * \brief Get the sample rate associated with known RTP payload types
-+ *
-+ * \param asterisk_format True if the value in the 'code' parameter is an AST_FORMAT value
-+ * \param code Format code, either from AST_FORMAT list or from AST_RTP list
-+ *
-+ * \return the sample rate if the format was found, zero if it was not found
-+ *
-+ * \since 1.6.3
-+ */
-+unsigned int ast_rtp_lookup_sample_rate2(int asterisk_format, int code);
-+
-+/*!
-+ * \brief Retrieve all formats that were found
-+ *
-+ * \param codecs Codecs structure to look in
-+ * \param astFormats An integer to put the Asterisk formats in
-+ * \param nonastformats An integer to put the non-Asterisk formats in
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * int astformats, nonastformats;
-+ * ast_rtp_codecs_payload_Formats(&codecs, &astformats, &nonastformats);
-+ * \endcode
-+ *
-+ * This retrieves all the formats known about in the codecs structure and puts the Asterisk ones in the integer
-+ * pointed to by astformats and the non-Asterisk ones in the integer pointed to by nonastformats.
-+ *
-+ * \since 1.6.3
-+ */
-+void ast_rtp_codecs_payload_formats(struct ast_rtp_codecs *codecs, int *astformats, int *nonastformats);
-+
-+/*!
-+ * \brief Retrieve a payload based on whether it is an Asterisk format and the code
-+ *
-+ * \param codecs Codecs structure to look in
-+ * \param asterisk_format Non-zero if the given code is an Asterisk format value
-+ * \param code The format to look for
-+ *
-+ * \retval Numerical payload
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * int payload = ast_rtp_codecs_payload_code(&codecs, 1, AST_FORMAT_ULAW);
-+ * \endcode
-+ *
-+ * This looks for the numerical payload for ULAW in the codecs structure.
-+ *
-+ * \since 1.6.3
-+ */
-+int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, const int asterisk_format, const int code);
-+
-+/*!
-+ * \brief Retrieve mime subtype information on a payload
-+ *
-+ * \param asterisk_format Non-zero if the given code is an Asterisk format value
-+ * \param code Format to look up
-+ * \param options Additional options that may change the result
-+ *
-+ * \retval Mime subtype success
-+ * \retval NULL failure
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * const char *subtype = ast_rtp_lookup_mime_subtype2(1, AST_FORMAT_ULAW, 0);
-+ * \endcode
-+ *
-+ * This looks up the mime subtype for the ULAW format.
-+ *
-+ * \since 1.6.3
-+ */
-+const char *ast_rtp_lookup_mime_subtype2(const int asterisk_format, const int code, enum ast_rtp_options options);
-+
-+/*!
-+ * \brief Convert formats into a string and put them into a buffer
-+ *
-+ * \param buf Buffer to put the mime output into
-+ * \param capability Formats that we are looking up
-+ * \param asterisk_format Non-zero if the given capability are Asterisk format capabilities
-+ * \param options Additional options that may change the result
-+ *
-+ * \retval non-NULL success
-+ * \retval NULL failure
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * char buf[256] = "";
-+ * char *mime = ast_rtp_lookup_mime_multiple2(&buf, sizeof(buf), AST_FORMAT_ULAW | AST_FORMAT_ALAW, 1, 0);
-+ * \endcode
-+ *
-+ * This returns the mime values for ULAW and ALAW in the buffer pointed to by buf.
-+ *
-+ * \since 1.6.3
-+ */
-+char *ast_rtp_lookup_mime_multiple2(struct ast_str *buf, const int capability, const int asterisk_format, enum ast_rtp_options options);
-+
-+/*!
-+ * \brief Set codec packetization preferences
-+ *
-+ * \param codecs Codecs structure to muck with
-+ * \param instance Optionally the instance that the codecs structure belongs to
-+ * \param prefs Codec packetization preferences
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * ast_rtp_codecs_packetization_set(&codecs, NULL, &prefs);
-+ * \endcode
-+ *
-+ * This sets the packetization preferences pointed to by prefs on the codecs structure pointed to by codecs.
-+ *
-+ * \since 1.6.3
-+ */
-+void ast_rtp_codecs_packetization_set(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, struct ast_codec_pref *prefs);
-+
-+/*!
-+ * \brief Begin sending a DTMF digit
-+ *
-+ * \param instance The RTP instance to send the DTMF on
-+ * \param digit What DTMF digit to send
-+ *
-+ * \retval 0 success
-+ * \retval -1 failure
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * ast_rtp_instance_dtmf_begin(instance, '1');
-+ * \endcode
-+ *
-+ * This starts sending the DTMF '1' on the RTP instance pointed to by instance. It will
-+ * continue being sent until it is ended.
-+ *
-+ * \since 1.6.3
-+ */
-+int ast_rtp_instance_dtmf_begin(struct ast_rtp_instance *instance, char digit);
-+
-+/*!
-+ * \brief Stop sending a DTMF digit
-+ *
-+ * \param instance The RTP instance to stop the DTMF on
-+ * \param digit What DTMF digit to stop
-+ *
-+ * \retval 0 success
-+ * \retval -1 failure
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * ast_rtp_instance_dtmf_end(instance, '1');
-+ * \endcode
-+ *
-+ * This stops sending the DTMF '1' on the RTP instance pointed to by instance.
-+ *
-+ * \since 1.6.3
-+ */
-+int ast_rtp_instance_dtmf_end(struct ast_rtp_instance *instance, char digit);
-+
-+/*!
-+ * \brief Set the DTMF mode that should be used
-+ *
-+ * \param instance the RTP instance to set DTMF mode on
-+ * \param dtmf_mode The DTMF mode that is in use
-+ *
-+ * \retval 0 success
-+ * \retval -1 failure
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * ast_rtp_instance_dtmf_mode_set(instance, AST_RTP_DTMF_MODE_RFC2833);
-+ * \endcode
-+ *
-+ * This sets the RTP instance to use RFC2833 for DTMF transmission and receiving.
-+ *
-+ * \since 1.6.3
-+ */
-+int ast_rtp_instance_dtmf_mode_set(struct ast_rtp_instance *instance, enum ast_rtp_dtmf_mode dtmf_mode);
-+
-+/*!
-+ * \brief Get the DTMF mode of an RTP instance
-+ *
-+ * \param instance The RTP instance to get the DTMF mode of
-+ *
-+ * \retval DTMF mode
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * enum ast_rtp_dtmf_mode dtmf_mode = ast_rtp_instance_dtmf_mode_get(instance);
-+ * \endcode
-+ *
-+ * This gets the DTMF mode set on the RTP instance pointed to by 'instance'.
-+ *
-+ * \since 1.6.3
-+ */
-+enum ast_rtp_dtmf_mode ast_rtp_instance_dtmf_mode_get(struct ast_rtp_instance *instance);
-+
-+/*!
-+ * \brief Indicate a new source of audio has dropped in
-+ *
-+ * \param instance Instance that the new media source is feeding into
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * ast_rtp_instance_new_source(instance);
-+ * \endcode
-+ *
-+ * This indicates that a new source of media is feeding the instance pointed to by
-+ * instance.
-+ *
-+ * \since 1.6.3
-+ */
-+void ast_rtp_instance_new_source(struct ast_rtp_instance *instance);
-+
-+/*!
-+ * \brief Set QoS parameters on an RTP session
-+ *
-+ * \param instance Instance to set the QoS parameters on
-+ * \param tos Terms of service value
-+ * \param cos Class of service value
-+ * \param desc What is setting the QoS values
-+ *
-+ * \retval 0 success
-+ * \retval -1 failure
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * ast_rtp_instance_set_qos(instance, 0, 0, "Example");
-+ * \endcode
-+ *
-+ * This sets the TOS and COS values to 0 on the instance pointed to by instance.
-+ *
-+ * \since 1.6.3
-+ */
-+int ast_rtp_instance_set_qos(struct ast_rtp_instance *instance, int tos, int cos, const char *desc);
-+
-+/*!
-+ * \brief Stop an RTP instance
-+ *
-+ * \param instance Instance that media is no longer going to at this time
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * ast_rtp_instance_stop(instance);
-+ * \endcode
-+ *
-+ * This tells the RTP engine being used for the instance pointed to by instance
-+ * that media is no longer going to it at this time, but may in the future.
-+ *
-+ * \since 1.6.3
-+ */
-+void ast_rtp_instance_stop(struct ast_rtp_instance *instance);
-+
-+/*!
-+ * \brief Get the file descriptor for an RTP session (or RTCP)
-+ *
-+ * \param instance Instance to get the file descriptor for
-+ * \param rtcp Whether to retrieve the file descriptor for RTCP or not
-+ *
-+ * \retval fd success
-+ * \retval -1 failure
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * int rtp_fd = ast_rtp_instance_fd(instance, 0);
-+ * \endcode
-+ *
-+ * This retrieves the file descriptor for the socket carrying media on the instance
-+ * pointed to by instance.
-+ *
-+ * \since 1.6.3
-+ */
-+int ast_rtp_instance_fd(struct ast_rtp_instance *instance, int rtcp);
-+
-+/*!
-+ * \brief Get the RTP glue that binds a channel to the RTP engine
-+ *
-+ * \param type Name of the glue we want
-+ *
-+ * \retval non-NULL success
-+ * \retval NULL failure
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * struct ast_rtp_glue *glue = ast_rtp_instance_get_glue("Example");
-+ * \endcode
-+ *
-+ * This retrieves the RTP glue that has the name 'Example'.
-+ *
-+ * \since 1.6.3
-+ */
-+struct ast_rtp_glue *ast_rtp_instance_get_glue(const char *type);
-+
-+/*!
-+ * \brief Bridge two channels that use RTP instances
-+ *
-+ * \param c0 First channel part of the bridge
-+ * \param c1 Second channel part of the bridge
-+ * \param flags Bridging flags
-+ * \param fo If a frame needs to be passed up it is stored here
-+ * \param rc Channel that passed the above frame up
-+ * \param timeoutms How long the channels should be bridged for
-+ *
-+ * \retval Bridge result
-+ *
-+ * \note This should only be used by channel drivers in their technology declaration.
-+ *
-+ * \since 1.6.3
-+ */
-+enum ast_bridge_result ast_rtp_instance_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms);
-+
-+/*!
-+ * \brief Get the other RTP instance that an instance is bridged to
-+ *
-+ * \param instance The RTP instance that we want
-+ *
-+ * \retval non-NULL success
-+ * \retval NULL failure
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * struct ast_rtp_instance *bridged = ast_rtp_instance_get_bridged(instance0);
-+ * \endcode
-+ *
-+ * This gets the RTP instance that instance0 is bridged to.
-+ *
-+ * \since 1.6.3
-+ */
-+struct ast_rtp_instance *ast_rtp_instance_get_bridged(struct ast_rtp_instance *instance);
-+
-+/*!
-+ * \brief Make two channels compatible for early bridging
-+ *
-+ * \param c0 First channel part of the bridge
-+ * \param c1 Second channel part of the bridge
-+ *
-+ * \since 1.6.3
-+ */
-+void ast_rtp_instance_early_bridge_make_compatible(struct ast_channel *c0, struct ast_channel *c1);
-+
-+/*!
-+ * \brief Early bridge two channels that use RTP instances
-+ *
-+ * \param c0 First channel part of the bridge
-+ * \param c1 Second channel part of the bridge
-+ *
-+ * \retval 0 success
-+ * \retval -1 failure
-+ *
-+ * \note This should only be used by channel drivers in their technology declaration.
-+ *
-+ * \since 1.6.3
-+ */
-+int ast_rtp_instance_early_bridge(struct ast_channel *c0, struct ast_channel *c1);
-+
-+/*!
-+ * \brief Initialize RED support on an RTP instance
-+ *
-+ * \param instance The instance to initialize RED support on
-+ * \param buffer_time How long to buffer before sending
-+ * \param payloads Payload values
-+ * \param generations Number of generations
-+ *
-+ * \retval 0 success
-+ * \retval -1 failure
-+ *
-+ * \since 1.6.3
-+ */
-+int ast_rtp_red_init(struct ast_rtp_instance *instance, int buffer_time, int *payloads, int generations);
-+
-+/*!
-+ * \brief Buffer a frame in an RTP instance for RED
-+ *
-+ * \param instance The instance to buffer the frame on
-+ * \param frame Frame that we want to buffer
-+ *
-+ * \retval 0 success
-+ * \retval -1 failure
-+ *
-+ * \since 1.6.3
-+ */
-+int ast_rtp_red_buffer(struct ast_rtp_instance *instance, struct ast_frame *frame);
-+
-+/*!
-+ * \brief Retrieve statistics about an RTP instance
-+ *
-+ * \param instance Instance to get statistics on
-+ * \param stats Structure to put results into
-+ * \param stat What statistic(s) to retrieve
-+ *
-+ * \retval 0 success
-+ * \retval -1 failure
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * struct ast_rtp_instance_stats stats;
-+ * ast_rtp_instance_get_stats(instance, &stats, AST_RTP_INSTANCE_STAT_ALL);
-+ * \endcode
-+ *
-+ * This retrieves all statistics the underlying RTP engine supports and puts the values into the
-+ * stats structure.
-+ *
-+ * \since 1.6.3
-+ */
-+int ast_rtp_instance_get_stats(struct ast_rtp_instance *instance, struct ast_rtp_instance_stats *stats, enum ast_rtp_instance_stat stat);
-+
-+/*!
-+ * \brief Set standard statistics from an RTP instance on a channel
-+ *
-+ * \param chan Channel to set the statistics on
-+ * \param instance The RTP instance that statistics will be retrieved from
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * ast_rtp_instance_set_stats_vars(chan, rtp);
-+ * \endcode
-+ *
-+ * This retrieves standard statistics from the RTP instance rtp and sets it on the channel pointed to
-+ * by chan.
-+ *
-+ * \since 1.6.3
-+ */
-+void ast_rtp_instance_set_stats_vars(struct ast_channel *chan, struct ast_rtp_instance *instance);
-+
-+/*!
-+ * \brief Retrieve quality statistics about an RTP instance
-+ *
-+ * \param instance Instance to get statistics on
-+ * \param field What quality statistic to retrieve
-+ * \param buf What buffer to put the result into
-+ * \param size Size of the above buffer
-+ *
-+ * \retval non-NULL success
-+ * \retval NULL failure
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * char quality[AST_MAX_USER_FIELD];
-+ * ast_rtp_instance_get_quality(instance, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, &buf, sizeof(buf));
-+ * \endcode
-+ *
-+ * This retrieves general quality statistics and places a text representation into the buf pointed to by buf.
-+ *
-+ * \since 1.6.3
-+ */
-+char *ast_rtp_instance_get_quality(struct ast_rtp_instance *instance, enum ast_rtp_instance_stat_field field, char *buf, size_t size);
-+
-+/*!
-+ * \brief Request that the underlying RTP engine provide audio frames in a specific format
-+ *
-+ * \param instance The RTP instance to change read format on
-+ * \param format Format that frames are wanted in
-+ *
-+ * \retval 0 success
-+ * \retval -1 failure
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * ast_rtp_instance_set_read_format(instance, AST_FORMAT_ULAW);
-+ * \endcode
-+ *
-+ * This requests that the RTP engine provide audio frames in the ULAW format.
-+ *
-+ * \since 1.6.3
-+ */
-+int ast_rtp_instance_set_read_format(struct ast_rtp_instance *instance, int format);
-+
-+/*!
-+ * \brief Tell underlying RTP engine that audio frames will be provided in a specific format
-+ *
-+ * \param instance The RTP instance to change write format on
-+ * \param format Format that frames will be provided in
-+ *
-+ * \retval 0 success
-+ * \retval -1 failure
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * ast_rtp_instance_set_write_format(instance, AST_FORMAT_ULAW);
-+ * \endcode
-+ *
-+ * This tells the underlying RTP engine that audio frames will be provided to it in ULAW format.
-+ *
-+ * \since 1.6.3
-+ */
-+int ast_rtp_instance_set_write_format(struct ast_rtp_instance *instance, int format);
-+
-+/*!
-+ * \brief Request that the underlying RTP engine make two RTP instances compatible with eachother
-+ *
-+ * \param chan Our own Asterisk channel
-+ * \param instance The first RTP instance
-+ * \param peer The peer Asterisk channel
-+ *
-+ * \retval 0 success
-+ * \retval -1 failure
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * ast_rtp_instance_make_compatible(instance, peer);
-+ * \endcode
-+ *
-+ * This makes the RTP instance for 'peer' compatible with 'instance' and vice versa.
-+ *
-+ * \since 1.6.3
-+ */
-+int ast_rtp_instance_make_compatible(struct ast_channel *chan, struct ast_rtp_instance *instance, struct ast_channel *peer);
-+
-+/*!
-+ * \brief Indicate to the RTP engine that packets are now expected to be sent/received on the RTP instance
-+ *
-+ * \param instance The RTP instance
-+ *
-+ * \retval 0 success
-+ * \retval -1 failure
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * ast_rtp_instance_activate(instance);
-+ * \endcode
-+ *
-+ * This tells the underlying RTP engine of instance that packets will now flow.
-+ *
-+ * \since 1.6.3
-+ */
-+int ast_rtp_instance_activate(struct ast_rtp_instance *instance);
-+
-+/*!
-+ * \brief Request that the underlying RTP engine send a STUN BIND request
-+ *
-+ * \param instance The RTP instance
-+ * \param suggestion The suggested destination
-+ * \param username Optionally a username for the request
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * ast_rtp_instance_stun_request(instance, NULL, NULL);
-+ * \endcode
-+ *
-+ * This requests that the RTP engine send a STUN BIND request on the session pointed to by
-+ * 'instance'.
-+ *
-+ * \since 1.6.3
-+ */
-+void ast_rtp_instance_stun_request(struct ast_rtp_instance *instance, struct sockaddr_in *suggestion, const char *username);
-+
-+/*!
-+ * \brief Set the RTP timeout value
-+ *
-+ * \param instance The RTP instance
-+ * \param timeout Value to set the timeout to
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * ast_rtp_instance_set_timeout(instance, 5000);
-+ * \endcode
-+ *
-+ * This sets the RTP timeout value on 'instance' to be 5000.
-+ *
-+ * \since 1.6.3
-+ */
-+void ast_rtp_instance_set_timeout(struct ast_rtp_instance *instance, int timeout);
-+
-+/*!
-+ * \brief Set the RTP timeout value for when the instance is on hold
-+ *
-+ * \param instance The RTP instance
-+ * \param timeout Value to set the timeout to
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * ast_rtp_instance_set_hold_timeout(instance, 5000);
-+ * \endcode
-+ *
-+ * This sets the RTP hold timeout value on 'instance' to be 5000.
-+ *
-+ * \since 1.6.3
-+ */
-+void ast_rtp_instance_set_hold_timeout(struct ast_rtp_instance *instance, int timeout);
-+
-+/*!
-+ * \brief Get the RTP timeout value
-+ *
-+ * \param instance The RTP instance
-+ *
-+ * \retval timeout value
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * int timeout = ast_rtp_instance_get_timeout(instance);
-+ * \endcode
-+ *
-+ * This gets the RTP timeout value for the RTP instance pointed to by 'instance'.
-+ *
-+ * \since 1.6.3
-+ */
-+int ast_rtp_instance_get_timeout(struct ast_rtp_instance *instance);
-+
-+/*!
-+ * \brief Get the RTP timeout value for when an RTP instance is on hold
-+ *
-+ * \param instance The RTP instance
-+ *
-+ * \retval timeout value
-+ *
-+ * Example usage:
-+ *
-+ * \code
-+ * int timeout = ast_rtp_instance_get_hold_timeout(instance);
-+ * \endcode
-+ *
-+ * This gets the RTP hold timeout value for the RTP instance pointed to by 'instance'.
-+ *
-+ * \since 1.6.3
-+ */
-+int ast_rtp_instance_get_hold_timeout(struct ast_rtp_instance *instance);
-+
-+#if defined(__cplusplus) || defined(c_plusplus)
-+}
-+#endif
-+
-+#endif /* _ASTERISK_RTP_ENGINE_H */
-
-Property changes on: include/asterisk/rtp_engine.h
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + Author Date Id Revision
-
-Index: include/asterisk/utils.h
-===================================================================
---- a/include/asterisk/utils.h (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/include/asterisk/utils.h (.../trunk) (revision 186562)
-@@ -688,7 +688,7 @@
- * This is set in asterisk.conf, or determined automatically by taking the mac
- * address of an Ethernet interface on the system.
- */
--extern struct ast_eid g_eid;
-+extern struct ast_eid ast_eid_default;
-
- /*!
- * \brief Fill in an ast_eid with the default eid of this machine
-Index: include/asterisk/channel.h
-===================================================================
---- a/include/asterisk/channel.h (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/include/asterisk/channel.h (.../trunk) (revision 186562)
-@@ -102,7 +102,7 @@
- can create a native bridge without sending media through the
- core.
-
-- Native briding can be disabled by a number of reasons,
-+ Native bridging can be disabled by a number of reasons,
- like DTMF being needed by the core or codecs being incompatible
- so a transcoding module is needed.
-
-@@ -183,45 +183,173 @@
- void (*digit)(struct ast_channel *chan, char digit);
- };
-
--/*! \brief Structure for all kinds of caller ID identifications.
-+/*!
-+ * \brief Structure for all kinds of caller ID identifications.
- * \note All string fields here are malloc'ed, so they need to be
- * freed when the structure is deleted.
- * Also, NULL and "" must be considered equivalent.
- *
-- * SIP and IAX2 has utf8 encoded Unicode caller ID names.
-+ * \note SIP and IAX2 has utf8 encoded Unicode caller ID names.
- * In some cases, we also have an alternative (RPID) E.164 number that can be used
-- * as caller ID on numeric E.164 phone networks (DAHDI or SIP/IAX2 to pstn gateway).
-+ * as caller ID on numeric E.164 phone networks (DAHDI or SIP/IAX2 to PSTN gateway).
- *
- * \todo Implement settings for transliteration between UTF8 caller ID names in
- * to Ascii Caller ID's (DAHDI). Östen Åsklund might be transliterated into
-- * Osten Asklund or Oesten Aasklund depending upon language and person...
-- * We need automatic routines for incoming calls and static settings for
-- * our own accounts.
-+ * Osten Asklund or Oesten Aasklund depending upon language and person...
-+ * We need automatic routines for incoming calls and static settings for
-+ * our own accounts.
- */
- struct ast_callerid {
-- char *cid_dnid; /*!< Malloc'd Dialed Number Identifier */
-- char *cid_num; /*!< Malloc'd Caller Number */
-- char *cid_name; /*!< Malloc'd Caller Name (ASCII) */
-- char *cid_ani; /*!< Malloc'd ANI */
-- char *cid_rdnis; /*!< Malloc'd RDNIS */
-- int cid_pres; /*!< Callerid presentation/screening */
-- int cid_ani2; /*!< Callerid ANI 2 (Info digits) */
-- int cid_ton; /*!< Callerid Type of Number */
-- int cid_tns; /*!< Callerid Transit Network Select */
-+ /*!
-+ * \brief Malloc'd Dialed Number Identifier
-+ * (Field will eventually move to struct ast_channel.dialed.number)
-+ */
-+ char *cid_dnid;
-+
-+ /*!
-+ * \brief Malloc'd Caller Number
-+ * (Field will eventually move to struct ast_channel.caller.id.number)
-+ */
-+ char *cid_num;
-+
-+ /*!
-+ * \brief Malloc'd Caller Name (ASCII)
-+ * (Field will eventually move to struct ast_channel.caller.id.name)
-+ */
-+ char *cid_name;
-+
-+ /*!
-+ * \brief Malloc'd Automatic Number Identification (ANI)
-+ * (Field will eventually move to struct ast_channel.caller.ani)
-+ */
-+ char *cid_ani;
-+
-+ /*!
-+ * \brief Malloc'd Redirecting Directory Number Information Service (RDNIS)
-+ * (Field will eventually move to struct ast_channel.redirecting.from.number)
-+ */
-+ char *cid_rdnis;
-+
-+ /*!
-+ * \brief Callerid Q.931 encoded number presentation/screening fields
-+ * (Field will eventually move to struct ast_channel.caller.id.number_presentation)
-+ */
-+ int cid_pres;
-+
-+ /*!
-+ * \brief Callerid ANI 2 (Info digits)
-+ * (Field will eventually move to struct ast_channel.caller.ani2)
-+ */
-+ int cid_ani2;
-+
-+ /*!
-+ * \brief Callerid Q.931 encoded type-of-number/numbering-plan fields
-+ * \note Currently this value is mostly just passed around the system.
-+ * The H.323 interfaces set the value from received messages and uses the value for sent messages.
-+ * The DAHDI PRI interfaces set the value from received messages but does not use it for sent messages.
-+ * You can read it and set it but only H.323 uses it.
-+ * (Field will eventually move to struct ast_channel.caller.id.number_type)
-+ */
-+ int cid_ton;
-+
-+ /*!
-+ * \brief Callerid Transit Network Select
-+ * \note Currently this value is just passed around the system.
-+ * You can read it and set it but it is never used for anything.
-+ * (Field will eventually move to struct ast_channel.dialed.transit_network_select)
-+ */
-+ int cid_tns;
- };
-
--/*! \brief
-- Structure to describe a channel "technology", ie a channel driver
-- See for examples:
-- \arg chan_iax2.c - The Inter-Asterisk exchange protocol
-- \arg chan_sip.c - The SIP channel driver
-- \arg chan_dahdi.c - PSTN connectivity (TDM, PRI, T1/E1, FXO, FXS)
-+/*!
-+ * \since 1.6.3
-+ * \brief Information needed to identify an endpoint in a call.
-+ * \note All string fields here are malloc'ed, so they need to be
-+ * freed when the structure is deleted.
-+ * \note NULL and "" must be considered equivalent.
-+ */
-+struct ast_party_id {
-+ /*! \brief Subscriber phone number (Malloced) */
-+ char *number;
-
-- If you develop your own channel driver, this is where you
-- tell the PBX at registration of your driver what properties
-- this driver supports and where different callbacks are
-- implemented.
--*/
-+ /*! \brief Subscriber name (Malloced) */
-+ char *name;
-+
-+ /*! \brief Q.931 encoded type-of-number/numbering-plan fields */
-+ int number_type;
-+
-+ /*! \brief Q.931 encoded number presentation/screening fields */
-+ int number_presentation;
-+};
-+
-+/*!
-+ * \since 1.6.3
-+ * \brief Connected Line/Party information.
-+ * \note All string fields here are malloc'ed, so they need to be
-+ * freed when the structure is deleted.
-+ * \note NULL and "" must be considered equivalent.
-+ */
-+struct ast_party_connected_line {
-+ struct ast_party_id id; /*! \brief Connected party ID */
-+
-+ /*!
-+ * \brief Automatic Number Identification (ANI) (Malloced)
-+ * \note Not really part of connected line data but needed to
-+ * save the corresponding caller id value.
-+ */
-+ char *ani;
-+
-+ /*!
-+ * \brief Automatic Number Identification 2 (Info Digits)
-+ * \note Not really part of connected line data but needed to
-+ * save the corresponding caller id value.
-+ */
-+ int ani2;
-+
-+ /*! \brief Information about the source of an update (Q.SIG/ISDN requirement).
-+ * \note enum AST_CONNECTED_LINE_UPDATE_SOURCE values
-+ * for Normal-Answer, Call-transfer, Call-diversion
-+ */
-+ int source;
-+};
-+
-+/*!
-+ * \since 1.6.3
-+ * \brief Redirecting Line information.
-+ * RDNIS (Redirecting Directory Number Information Service)
-+ * Where a call diversion or transfer was invoked.
-+ * \note All string fields here are malloc'ed, so they need to be
-+ * freed when the structure is deleted.
-+ * \note NULL and "" must be considered equivalent.
-+ */
-+struct ast_party_redirecting {
-+ /*! \brief Who is redirecting the call (Sent to the party the call is redirected toward) */
-+ struct ast_party_id from;
-+
-+ /*! \brief Call is redirecting to a new party (Sent to the caller) */
-+ struct ast_party_id to;
-+
-+ /*! \brief Number of times the call was redirected */
-+ int count;
-+
-+ /*! \brief enum AST_REDIRECTING_REASON value for redirection */
-+ int reason;
-+};
-+
-+/*!
-+ * \brief
-+ * Structure to describe a channel "technology", ie a channel driver
-+ * See for examples:
-+ * \arg chan_iax2.c - The Inter-Asterisk exchange protocol
-+ * \arg chan_sip.c - The SIP channel driver
-+ * \arg chan_dahdi.c - PSTN connectivity (TDM, PRI, T1/E1, FXO, FXS)
-+ *
-+ * \details
-+ * If you develop your own channel driver, this is where you
-+ * tell the PBX at registration of your driver what properties
-+ * this driver supports and where different callbacks are
-+ * implemented.
-+ */
- struct ast_channel_tech {
- const char * const type;
- const char * const description;
-@@ -250,7 +378,7 @@
- int (* const send_digit_end)(struct ast_channel *chan, char digit, unsigned int duration);
-
- /*! \brief Call a given phone number (address, etc), but don't
-- take longer than timeout seconds to do so. */
-+ * take longer than timeout seconds to do so. */
- int (* const call)(struct ast_channel *chan, char *addr, int timeout);
-
- /*! \brief Hangup (and possibly destroy) the channel */
-@@ -381,7 +509,8 @@
- T38_STATE_NEGOTIATED, /*!< T38 established */
- };
-
--/*! \brief Main Channel structure associated with a channel.
-+/*!
-+ * \brief Main Channel structure associated with a channel.
- * This is the side of it mostly used by the pbx and call management.
- *
- * \note XXX It is important to remember to increment .cleancount each time
-@@ -395,7 +524,6 @@
- * and 8-byte fields causes 4 bytes of padding to be added before many
- * 8-byte fields.
- */
--
- struct ast_channel {
- const struct ast_channel_tech *tech; /*!< Technology (point to channel driver) */
- void *tech_pvt; /*!< Private data used by the technology driver */
-@@ -403,8 +531,8 @@
- void *generatordata; /*!< Current generator data if there is any */
- struct ast_generator *generator; /*!< Current active data generator */
- struct ast_channel *_bridge; /*!< Who are we bridged to, if we're bridged.
-- Who is proxying for us, if we are proxied (i.e. chan_agent).
-- Do not access directly, use ast_bridged_channel(chan) */
-+ * Who is proxying for us, if we are proxied (i.e. chan_agent).
-+ * Do not access directly, use ast_bridged_channel(chan) */
- struct ast_channel *masq; /*!< Channel that will masquerade as us */
- struct ast_channel *masqr; /*!< Who we are masquerading as */
- const char *blockproc; /*!< Procedure causing blocking */
-@@ -421,7 +549,7 @@
- struct ast_audiohook_list *audiohooks;
- struct ast_cdr *cdr; /*!< Call Detail Record */
- struct ast_tone_zone *zone; /*!< Tone zone as set in indications.conf or
-- in the CHANNEL dialplan function */
-+ * in the CHANNEL dialplan function */
- struct ast_channel_monitor *monitor; /*!< Channel monitoring */
- #ifdef HAVE_EPOLL
- struct ast_epoll_data *epfd_data[AST_MAX_FDS];
-@@ -441,7 +569,29 @@
- struct timeval whentohangup; /*!< Non-zero, set to actual time when channel is to be hung up */
- pthread_t blocker; /*!< If anyone is blocking, this is them */
- ast_mutex_t lock_dont_use; /*!< Lock a channel for some operations. See ast_channel_lock() */
-- struct ast_callerid cid; /*!< Caller ID, name, presentation etc */
-+
-+ /*!
-+ * \brief Channel Caller ID information.
-+ * \note The caller id information is the caller id of this
-+ * channel when it is used to initiate a call.
-+ */
-+ struct ast_callerid cid;
-+
-+ /*!
-+ * \brief Channel Connected Line ID information.
-+ * \note The connected line information identifies the channel
-+ * connected/bridged to this channel.
-+ */
-+ struct ast_party_connected_line connected;
-+
-+ /*!
-+ * \brief Redirecting/Diversion information
-+ * \note Until struct ast_channel.cid.cid_rdnis is replaced
-+ * with ast_channel.redirecting.from.number, the
-+ * ast_channel.redirecting.from.number field is not used.
-+ */
-+ struct ast_party_redirecting redirecting;
-+
- struct ast_frame dtmff; /*!< DTMF frame */
- struct varshead varshead; /*!< A linked list for channel variables. See \ref AstChanVar */
- ast_group_t callgroup; /*!< Call group for call pickups */
-@@ -456,11 +606,11 @@
- unsigned long outsmpl; /*!< Track the read/written samples for monitor use */
-
- int fds[AST_MAX_FDS]; /*!< File descriptors for channel -- Drivers will poll on
-- these file descriptors, so at least one must be non -1.
-- See \arg \ref AstFileDesc */
-+ * these file descriptors, so at least one must be non -1.
-+ * See \arg \ref AstFileDesc */
- int cdrflags; /*!< Call Detail Record Flags */
- int _softhangup; /*!< Whether or not we have been hung up... Do not set this value
-- directly, use ast_softhangup() */
-+ * directly, use ast_softhangup() */
- int fdno; /*!< Which fd had an event detected on */
- int streamid; /*!< For streaming playback, the schedule ID */
- int vstreamid; /*!< For streaming video playback, the schedule ID */
-@@ -473,9 +623,9 @@
- int amaflags; /*!< Set BEFORE PBX is started to determine AMA flags */
- enum ast_channel_adsicpe adsicpe; /*!< Whether or not ADSI is detected on CPE */
- unsigned int fin; /*!< Frames in counters. The high bit is a debug mask, so
-- the counter is only in the remaining bits */
-+ * the counter is only in the remaining bits */
- unsigned int fout; /*!< Frames out counters. The high bit is a debug mask, so
-- the counter is only in the remaining bits */
-+ * the counter is only in the remaining bits */
- int hangupcause; /*!< Why is the channel hanged up. See causes.h */
- unsigned int flags; /*!< channel flags of AST_FLAG_ type */
- int alertpipe[2];
-@@ -490,12 +640,13 @@
- #endif
- int visible_indication; /*!< Indication currently playing on the channel */
-
-- unsigned short transfercapability; /*!< ISDN Transfer Capbility - AST_FLAG_DIGITAL is not enough */
-+ unsigned short transfercapability; /*!< ISDN Transfer Capability - AST_FLAG_DIGITAL is not enough */
-
- union {
- char unused_old_dtmfq[AST_MAX_EXTENSION]; /*!< (deprecated, use readq instead) Any/all queued DTMF characters */
- struct {
- struct ast_bridge *bridge; /*!< Bridge this channel is participating in */
-+ struct ast_timer *timer; /*!< timer object that provided timingfd */
- };
- };
-
-@@ -508,17 +659,21 @@
-
- /*! \brief ast_channel_tech Properties */
- enum {
-- /*! \brief Channels have this property if they can accept input with jitter;
-- * i.e. most VoIP channels */
-+ /*!
-+ * \brief Channels have this property if they can accept input with jitter;
-+ * i.e. most VoIP channels
-+ */
- AST_CHAN_TP_WANTSJITTER = (1 << 0),
-- /*! \brief Channels have this property if they can create jitter;
-- * i.e. most VoIP channels */
-+ /*!
-+ * \brief Channels have this property if they can create jitter;
-+ * i.e. most VoIP channels
-+ */
- AST_CHAN_TP_CREATESJITTER = (1 << 1),
- };
-
- /*! \brief ast_channel flags */
- enum {
-- /*! Queue incoming dtmf, to be released when this flag is turned off */
-+ /*! Queue incoming DTMF, to be released when this flag is turned off */
- AST_FLAG_DEFER_DTMF = (1 << 1),
- /*! write should be interrupt generator */
- AST_FLAG_WRITE_INT = (1 << 2),
-@@ -549,7 +704,7 @@
- * to instead only generate END frames. */
- AST_FLAG_END_DTMF_ONLY = (1 << 14),
- /*! Flag to show channels that this call is hangup due to the fact that the call
-- was indeed anwered, but in another channel */
-+ was indeed answered, but in another channel */
- AST_FLAG_ANSWERED_ELSEWHERE = (1 << 15),
- /*! This flag indicates that on a masquerade, an active stream should not
- * be carried over */
-@@ -674,7 +829,6 @@
- * \retval 0 success
- * \retval non-zero failure
- */
--
- int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore);
-
- /*!
-@@ -777,6 +931,7 @@
- * \retval 0 success
- * \retval non-zero failure
- *
-+ * \details
- * The supplied payload data is copied into the frame, so the caller's copy
- * is not modified nor freed, and the resulting frame will retain a copy of
- * the data even if the caller frees their local copy.
-@@ -811,6 +966,7 @@
- * \param data data to pass to the channel requester
- * \param status status
- *
-+ * \details
- * Request a channel of a given type, with data as optional information used
- * by the low level module
- *
-@@ -854,54 +1010,63 @@
- struct ast_channel *__ast_request_and_dial(const char *type, int format, void *data,
- int timeout, int *reason, const char *cid_num, const char *cid_name, struct outgoing_helper *oh);
-
--/*!\brief Register a channel technology (a new channel driver)
-+/*!
-+ * \brief Register a channel technology (a new channel driver)
- * Called by a channel module to register the kind of channels it supports.
- * \param tech Structure defining channel technology or "type"
- * \return Returns 0 on success, -1 on failure.
- */
- int ast_channel_register(const struct ast_channel_tech *tech);
-
--/*! \brief Unregister a channel technology
-+/*!
-+ * \brief Unregister a channel technology
- * \param tech Structure defining channel technology or "type" that was previously registered
- * \return No return value.
- */
- void ast_channel_unregister(const struct ast_channel_tech *tech);
-
--/*! \brief Get a channel technology structure by name
-+/*!
-+ * \brief Get a channel technology structure by name
- * \param name name of technology to find
- * \return a pointer to the structure, or NULL if no matching technology found
- */
- const struct ast_channel_tech *ast_get_channel_tech(const char *name);
-
- #ifdef CHANNEL_TRACE
--/*! \brief Update the context backtrace if tracing is enabled
-+/*!
-+ * \brief Update the context backtrace if tracing is enabled
- * \return Returns 0 on success, -1 on failure
- */
- int ast_channel_trace_update(struct ast_channel *chan);
-
--/*! \brief Enable context tracing in the channel
-+/*!
-+ * \brief Enable context tracing in the channel
- * \return Returns 0 on success, -1 on failure
- */
- int ast_channel_trace_enable(struct ast_channel *chan);
-
--/*! \brief Disable context tracing in the channel.
-+/*!
-+ * \brief Disable context tracing in the channel.
- * \note Does not remove current trace entries
- * \return Returns 0 on success, -1 on failure
- */
- int ast_channel_trace_disable(struct ast_channel *chan);
-
--/*! \brief Whether or not context tracing is enabled
-+/*!
-+ * \brief Whether or not context tracing is enabled
- * \return Returns -1 when the trace is enabled. 0 if not.
- */
- int ast_channel_trace_is_enabled(struct ast_channel *chan);
-
--/*! \brief Put the channel backtrace in a string
-+/*!
-+ * \brief Put the channel backtrace in a string
- * \return Returns the amount of lines in the backtrace. -1 on error.
- */
- int ast_channel_trace_serialize(struct ast_channel *chan, struct ast_str **out);
- #endif
-
--/*! \brief Hang up a channel
-+/*!
-+ * \brief Hang up a channel
- * \note This function performs a hard hangup on a channel. Unlike the soft-hangup, this function
- * performs all stream stopping, etc, on the channel that needs to end.
- * chan is no longer valid after this call.
-@@ -916,6 +1081,7 @@
- * \param chan channel to be soft-hung-up
- * \param cause Ast hangupcause for hangup
- *
-+ * \details
- * Call the protocol layer, but don't destroy the channel structure
- * (use this if you are trying to
- * safely hangup a channel managed by another thread.
-@@ -926,9 +1092,11 @@
- */
- int ast_softhangup(struct ast_channel *chan, int cause);
-
--/*! \brief Softly hangup up a channel (no channel lock)
-+/*!
-+ * \brief Softly hangup up a channel (no channel lock)
- * \param chan channel to be soft-hung-up
-- * \param cause Ast hangupcause for hangup (see cause.h) */
-+ * \param cause Ast hangupcause for hangup (see cause.h)
-+ */
- int ast_softhangup_nolock(struct ast_channel *chan, int cause);
-
- /*! \brief Check to see if a channel is needing hang up
-@@ -943,6 +1111,7 @@
- * \param chan channel on which to check for hang up
- * \param offset offset in seconds from current time
- * \return 1, 0, or -1
-+ * \details
- * This function compares a offset from current time with the absolute time
- * out on a channel (when to hang up). If the absolute time out on a channel
- * is earlier than current time plus the offset, it returns 1, if the two
-@@ -965,11 +1134,13 @@
- */
- int ast_channel_cmpwhentohangup_tv(struct ast_channel *chan, struct timeval offset);
-
--/*! \brief Set when to hang a channel up
-+/*!
-+ * \brief Set when to hang a channel up
- *
- * \param chan channel on which to check for hang up
- * \param offset offset in seconds relative to the current time of when to hang up
- *
-+ * \details
- * This function sets the absolute time out on a channel (when to hang up).
- *
- * \note This function does not require that the channel is locked before
-@@ -981,7 +1152,8 @@
- */
- void ast_channel_setwhentohangup(struct ast_channel *chan, time_t offset) __attribute__((deprecated));
-
--/*! \brief Set when to hang a channel up
-+/*!
-+ * \brief Set when to hang a channel up
- *
- * \param chan channel on which to check for hang up
- * \param offset offset in seconds and useconds relative to the current time of when to hang up
-@@ -1001,6 +1173,7 @@
- *
- * \param chan channel to answer
- *
-+ * \details
- * This function answers a channel and handles all necessary call
- * setup functions.
- *
-@@ -1061,18 +1234,21 @@
- */
- int __ast_answer(struct ast_channel *chan, unsigned int delay, int cdr_answer);
-
--/*! \brief Make a call
-+/*!
-+ * \brief Make a call
- * \param chan which channel to make the call on
- * \param addr destination of the call
- * \param timeout time to wait on for connect
-+ * \details
- * Place a call, take no longer than timeout ms.
-- \return Returns -1 on failure, 0 on not enough time
-- (does not automatically stop ringing), and
-- the number of seconds the connect took otherwise.
-- */
-+ * \return -1 on failure, 0 on not enough time
-+ * (does not automatically stop ringing), and
-+ * the number of seconds the connect took otherwise.
-+ */
- int ast_call(struct ast_channel *chan, char *addr, int timeout);
-
--/*! \brief Indicates condition of channel
-+/*!
-+ * \brief Indicates condition of channel
- * \note Indicate a condition such as AST_CONTROL_BUSY, AST_CONTROL_RINGING, or AST_CONTROL_CONGESTION on a channel
- * \param chan channel to change the indication
- * \param condition which condition to indicate on the channel
-@@ -1080,7 +1256,8 @@
- */
- int ast_indicate(struct ast_channel *chan, int condition);
-
--/*! \brief Indicates condition of channel, with payload
-+/*!
-+ * \brief Indicates condition of channel, with payload
- * \note Indicate a condition such as AST_CONTROL_HOLD with payload being music on hold class
- * \param chan channel to change the indication
- * \param condition which condition to indicate on the channel
-@@ -1092,33 +1269,43 @@
-
- /* Misc stuff ------------------------------------------------ */
-
--/*! \brief Wait for input on a channel
-+/*!
-+ * \brief Wait for input on a channel
- * \param chan channel to wait on
- * \param ms length of time to wait on the channel
-+ * \details
- * Wait for input on a channel for a given # of milliseconds (<0 for indefinite).
-- \return Returns < 0 on failure, 0 if nothing ever arrived, and the # of ms remaining otherwise */
-+ * \retval < 0 on failure
-+ * \retval 0 if nothing ever arrived
-+ * \retval the # of ms remaining otherwise
-+ */
- int ast_waitfor(struct ast_channel *chan, int ms);
-
--/*! \brief Wait for a specified amount of time, looking for hangups
-+/*!
-+ * \brief Wait for a specified amount of time, looking for hangups
- * \param chan channel to wait for
- * \param ms length of time in milliseconds to sleep
-+ * \details
- * Waits for a specified amount of time, servicing the channel as required.
- * \return returns -1 on hangup, otherwise 0.
- */
- int ast_safe_sleep(struct ast_channel *chan, int ms);
-
--/*! \brief Wait for a specified amount of time, looking for hangups and a condition argument
-+/*!
-+ * \brief Wait for a specified amount of time, looking for hangups and a condition argument
- * \param chan channel to wait for
- * \param ms length of time in milliseconds to sleep
- * \param cond a function pointer for testing continue condition
- * \param data argument to be passed to the condition test function
- * \return returns -1 on hangup, otherwise 0.
-+ * \details
- * Waits for a specified amount of time, servicing the channel as required. If cond
- * returns 0, this function returns.
- */
- int ast_safe_sleep_conditional(struct ast_channel *chan, int ms, int (*cond)(void*), void *data );
-
--/*! \brief Waits for activity on a group of channels
-+/*!
-+ * \brief Waits for activity on a group of channels
- * \param chan an array of pointers to channels
- * \param n number of channels that are to be waited upon
- * \param fds an array of fds to wait upon
-@@ -1126,44 +1313,55 @@
- * \param exception exception flag
- * \param outfd fd that had activity on it
- * \param ms how long the wait was
-+ * \details
- * Big momma function here. Wait for activity on any of the n channels, or any of the nfds
-- file descriptors.
-- \return Returns the channel with activity, or NULL on error or if an FD
-- came first. If the FD came first, it will be returned in outfd, otherwise, outfd
-- will be -1 */
-+ * file descriptors.
-+ * \return Returns the channel with activity, or NULL on error or if an FD
-+ * came first. If the FD came first, it will be returned in outfd, otherwise, outfd
-+ * will be -1
-+ */
- struct ast_channel *ast_waitfor_nandfds(struct ast_channel **chan, int n,
- int *fds, int nfds, int *exception, int *outfd, int *ms);
-
--/*! \brief Waits for input on a group of channels
-- Wait for input on an array of channels for a given # of milliseconds.
-- \return Return channel with activity, or NULL if none has activity.
-- \param chan an array of pointers to channels
-- \param n number of channels that are to be waited upon
-- \param ms time "ms" is modified in-place, if applicable */
-+/*!
-+ * \brief Waits for input on a group of channels
-+ * Wait for input on an array of channels for a given # of milliseconds.
-+ * \return Return channel with activity, or NULL if none has activity.
-+ * \param chan an array of pointers to channels
-+ * \param n number of channels that are to be waited upon
-+ * \param ms time "ms" is modified in-place, if applicable
-+ */
- struct ast_channel *ast_waitfor_n(struct ast_channel **chan, int n, int *ms);
-
--/*! \brief Waits for input on an fd
-- This version works on fd's only. Be careful with it. */
-+/*!
-+ * \brief Waits for input on an fd
-+ * \note This version works on fd's only. Be careful with it.
-+ */
- int ast_waitfor_n_fd(int *fds, int n, int *ms, int *exception);
-
-
--/*! \brief Reads a frame
-+/*!
-+ * \brief Reads a frame
- * \param chan channel to read a frame from
- * \return Returns a frame, or NULL on error. If it returns NULL, you
-- best just stop reading frames and assume the channel has been
-- disconnected. */
-+ * best just stop reading frames and assume the channel has been
-+ * disconnected.
-+ */
- struct ast_frame *ast_read(struct ast_channel *chan);
-
--/*! \brief Reads a frame, returning AST_FRAME_NULL frame if audio.
-- \param chan channel to read a frame from
-- \return Returns a frame, or NULL on error. If it returns NULL, you
-- best just stop reading frames and assume the channel has been
-- disconnected.
-- \note Audio is replaced with AST_FRAME_NULL to avoid
-- transcode when the resulting audio is not necessary. */
-+/*!
-+ * \brief Reads a frame, returning AST_FRAME_NULL frame if audio.
-+ * \param chan channel to read a frame from
-+ * \return Returns a frame, or NULL on error. If it returns NULL, you
-+ * best just stop reading frames and assume the channel has been
-+ * disconnected.
-+ * \note Audio is replaced with AST_FRAME_NULL to avoid
-+ * transcode when the resulting audio is not necessary.
-+ */
- struct ast_frame *ast_read_noaudio(struct ast_channel *chan);
-
--/*! \brief Write a frame to a channel
-+/*!
-+ * \brief Write a frame to a channel
- * This function writes the given frame to the indicated channel.
- * \param chan destination channel of the frame
- * \param frame frame that will be written
-@@ -1171,7 +1369,8 @@
- */
- int ast_write(struct ast_channel *chan, struct ast_frame *frame);
-
--/*! \brief Write video frame to a channel
-+/*!
-+ * \brief Write video frame to a channel
- * This function writes the given frame to the indicated channel.
- * \param chan destination channel of the frame
- * \param frame frame that will be written
-@@ -1179,7 +1378,8 @@
- */
- int ast_write_video(struct ast_channel *chan, struct ast_frame *frame);
-
--/*! \brief Write text frame to a channel
-+/*!
-+ * \brief Write text frame to a channel
- * This function writes the given frame to the indicated channel.
- * \param chan destination channel of the frame
- * \param frame frame that will be written
-@@ -1190,7 +1390,8 @@
- /*! \brief Send empty audio to prime a channel driver */
- int ast_prod(struct ast_channel *chan);
-
--/*! \brief Sets read format on channel chan
-+/*!
-+ * \brief Sets read format on channel chan
- * Set read format for channel to whichever component of "format" is best.
- * \param chan channel to change
- * \param format format to change to
-@@ -1198,7 +1399,8 @@
- */
- int ast_set_read_format(struct ast_channel *chan, int format);
-
--/*! \brief Sets write format on channel chan
-+/*!
-+ * \brief Sets write format on channel chan
- * Set write format for channel to whichever component of "format" is best.
- * \param chan channel to change
- * \param format new format for writing
-@@ -1212,6 +1414,7 @@
- * \param chan channel to act upon
- * \param text string of text to send on the channel
- *
-+ * \details
- * Write text to a display on a channel
- *
- * \note The channel does not need to be locked before calling this function.
-@@ -1221,34 +1424,35 @@
- */
- int ast_sendtext(struct ast_channel *chan, const char *text);
-
--/*! \brief Receives a text character from a channel
-+/*!
-+ * \brief Receives a text character from a channel
- * \param chan channel to act upon
- * \param timeout timeout in milliseconds (0 for infinite wait)
-+ * \details
- * Read a char of text from a channel
-- * Returns 0 on success, -1 on failure
-+ * \return 0 on success, -1 on failure
- */
- int ast_recvchar(struct ast_channel *chan, int timeout);
-
--/*! \brief Send a DTMF digit to a channel
-- * Send a DTMF digit to a channel.
-+/*!
-+ * \brief Send a DTMF digit to a channel.
- * \param chan channel to act upon
- * \param digit the DTMF digit to send, encoded in ASCII
- * \param duration the duration of the digit ending in ms
-- * \return Returns 0 on success, -1 on failure
-+ * \return 0 on success, -1 on failure
- */
- int ast_senddigit(struct ast_channel *chan, char digit, unsigned int duration);
-
--/*! \brief Send a DTMF digit to a channel
-- * Send a DTMF digit to a channel.
-+/*!
-+ * \brief Send a DTMF digit to a channel.
- * \param chan channel to act upon
- * \param digit the DTMF digit to send, encoded in ASCII
-- * \return Returns 0 on success, -1 on failure
-+ * \return 0 on success, -1 on failure
- */
- int ast_senddigit_begin(struct ast_channel *chan, char digit);
-
--/*! \brief Send a DTMF digit to a channel
--
-- * Send a DTMF digit to a channel.
-+/*!
-+ * \brief Send a DTMF digit to a channel.
- * \param chan channel to act upon
- * \param digit the DTMF digit to send, encoded in ASCII
- * \param duration the duration of the digit ending in ms
-@@ -1256,7 +1460,8 @@
- */
- int ast_senddigit_end(struct ast_channel *chan, char digit, unsigned int duration);
-
--/*! \brief Receives a text string from a channel
-+/*!
-+ * \brief Receives a text string from a channel
- * Read a string of text from a channel
- * \param chan channel to act upon
- * \param timeout timeout in milliseconds (0 for infinite wait)
-@@ -1264,11 +1469,12 @@
- */
- char *ast_recvtext(struct ast_channel *chan, int timeout);
-
--/*! \brief Browse channels in use
-+/*!
-+ * \brief Browse channels in use
- * Browse the channels currently in use
- * \param prev where you want to start in the channel list
- * \return Returns the next channel in the list, NULL on end.
-- * If it returns a channel, that channel *has been locked*!
-+ * If it returns a channel, that channel *has been locked*!
- */
- struct ast_channel *ast_channel_walk_locked(const struct ast_channel *prev);
-
-@@ -1288,7 +1494,8 @@
- struct ast_channel *ast_walk_channel_by_exten_locked(const struct ast_channel *chan, const char *exten,
- const char *context);
-
--/*! \brief Search for a channel based on the passed channel matching callback
-+/*!
-+ * \brief Search for a channel based on the passed channel matching callback
- * Search for a channel based on the specified is_match callback, and return the
- * first channel that we match. When returned, the channel will be locked. Note
- * that the is_match callback is called with the passed channel locked, and should
-@@ -1300,33 +1507,41 @@
- */
- struct ast_channel *ast_channel_search_locked(int (*is_match)(struct ast_channel *, void *), void *data);
-
--/*! ! \brief Waits for a digit
-+/*!
-+ * \brief Waits for a digit
- * \param c channel to wait for a digit on
- * \param ms how many milliseconds to wait
-- * \return Returns <0 on error, 0 on no entry, and the digit on success. */
-+ * \return Returns <0 on error, 0 on no entry, and the digit on success.
-+ */
- int ast_waitfordigit(struct ast_channel *c, int ms);
-
--/*! \brief Wait for a digit
-- Same as ast_waitfordigit() with audio fd for outputting read audio and ctrlfd to monitor for reading.
-+/*!
-+ * \brief Wait for a digit
-+ * Same as ast_waitfordigit() with audio fd for outputting read audio and ctrlfd to monitor for reading.
- * \param c channel to wait for a digit on
- * \param ms how many milliseconds to wait
- * \param audiofd audio file descriptor to write to if audio frames are received
- * \param ctrlfd control file descriptor to monitor for reading
-- * \return Returns 1 if ctrlfd becomes available */
-+ * \return Returns 1 if ctrlfd becomes available
-+ */
- int ast_waitfordigit_full(struct ast_channel *c, int ms, int audiofd, int ctrlfd);
-
--/*! Reads multiple digits
-+/*!
-+ * \brief Reads multiple digits
- * \param c channel to read from
- * \param s string to read in to. Must be at least the size of your length
- * \param len how many digits to read (maximum)
- * \param timeout how long to timeout between digits
- * \param rtimeout timeout to wait on the first digit
- * \param enders digits to end the string
-+ * \details
- * Read in a digit string "s", max length "len", maximum timeout between
-- digits "timeout" (-1 for none), terminated by anything in "enders". Give them rtimeout
-- for the first digit. Returns 0 on normal return, or 1 on a timeout. In the case of
-- a timeout, any digits that were read before the timeout will still be available in s.
-- RETURNS 2 in full version when ctrlfd is available, NOT 1*/
-+ * digits "timeout" (-1 for none), terminated by anything in "enders". Give them rtimeout
-+ * for the first digit.
-+ * \return Returns 0 on normal return, or 1 on a timeout. In the case of
-+ * a timeout, any digits that were read before the timeout will still be available in s.
-+ * RETURNS 2 in full version when ctrlfd is available, NOT 1
-+ */
- int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders);
- int ast_readstring_full(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders, int audiofd, int ctrlfd);
-
-@@ -1342,28 +1557,37 @@
- #define AST_BRIDGE_IGNORE_SIGS (1 << 4)
-
-
--/*! \brief Makes two channel formats compatible
-+/*!
-+ * \brief Makes two channel formats compatible
- * \param c0 first channel to make compatible
- * \param c1 other channel to make compatible
-- * Set two channels to compatible formats -- call before ast_channel_bridge in general .
-- * \return Returns 0 on success and -1 if it could not be done */
-+ * \details
-+ * Set two channels to compatible formats -- call before ast_channel_bridge in general.
-+ * \return Returns 0 on success and -1 if it could not be done
-+ */
- int ast_channel_make_compatible(struct ast_channel *c0, struct ast_channel *c1);
-
--/*! Bridge two channels together (early)
-+/*!
-+ * \brief Bridge two channels together (early)
- * \param c0 first channel to bridge
- * \param c1 second channel to bridge
-+ * \details
- * Bridge two channels (c0 and c1) together early. This implies either side may not be answered yet.
-- * \return Returns 0 on success and -1 if it could not be done */
-+ * \return Returns 0 on success and -1 if it could not be done
-+ */
- int ast_channel_early_bridge(struct ast_channel *c0, struct ast_channel *c1);
-
--/*! Bridge two channels together
-+/*!
-+ * \brief Bridge two channels together
- * \param c0 first channel to bridge
- * \param c1 second channel to bridge
- * \param config config for the channels
- * \param fo destination frame(?)
- * \param rc destination channel(?)
-+ * \details
- * Bridge two channels (c0 and c1) together. If an important frame occurs, we return that frame in
-- *rf (remember, it could be NULL) and which channel (0 or 1) in rc */
-+ * *rf (remember, it could be NULL) and which channel (0 or 1) in rc
-+ */
- /* int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc); */
- int ast_channel_bridge(struct ast_channel *c0,struct ast_channel *c1,
- struct ast_bridge_config *config, struct ast_frame **fo, struct ast_channel **rc);
-@@ -1374,6 +1598,7 @@
- * \param original channel to make a copy of
- * \param clone copy of the original channel
- *
-+ * \details
- * This is a very strange and freaky function used primarily for transfer. Suppose that
- * "original" and "clone" are two channels in random situations. This function takes
- * the guts out of "clone" and puts them into the "original" channel, then alerts the
-@@ -1385,100 +1610,114 @@
- */
- int ast_channel_masquerade(struct ast_channel *original, struct ast_channel *clone);
-
--/*! Gives the string form of a given cause code */
- /*!
-+ * \brief Gives the string form of a given cause code.
-+ *
- * \param state cause to get the description of
-- * Give a name to a cause code
-- * Returns the text form of the binary cause code given
-+ * \return the text form of the binary cause code given
- */
- const char *ast_cause2str(int state) attribute_pure;
-
--/*! Convert the string form of a cause code to a number */
- /*!
-+ * \brief Convert the string form of a cause code to a number
-+ *
- * \param name string form of the cause
-- * Returns the cause code
-+ * \return the cause code
- */
- int ast_str2cause(const char *name) attribute_pure;
-
--/*! Gives the string form of a given channel state */
- /*!
-+ * \brief Gives the string form of a given channel state
-+ *
- * \param ast_channel_state state to get the name of
-- * Give a name to a state
-- * Returns the text form of the binary state given
-+ * \return the text form of the binary state given
- */
- const char *ast_state2str(enum ast_channel_state);
-
--/*! Gives the string form of a given transfer capability */
- /*!
-- * \param transfercapability transfercapabilty to get the name of
-- * Give a name to a transfercapbility
-- * See above
-- * Returns the text form of the binary transfer capability
-+ * \brief Gives the string form of a given transfer capability
-+ *
-+ * \param transfercapability transfer capability to get the name of
-+ * \return the text form of the binary transfer capability
- */
- char *ast_transfercapability2str(int transfercapability) attribute_const;
-
--/* Options: Some low-level drivers may implement "options" allowing fine tuning of the
-- low level channel. See frame.h for options. Note that many channel drivers may support
-- none or a subset of those features, and you should not count on this if you want your
-- asterisk application to be portable. They're mainly useful for tweaking performance */
-+/*
-+ * Options: Some low-level drivers may implement "options" allowing fine tuning of the
-+ * low level channel. See frame.h for options. Note that many channel drivers may support
-+ * none or a subset of those features, and you should not count on this if you want your
-+ * asterisk application to be portable. They're mainly useful for tweaking performance
-+ */
-
--/*! Sets an option on a channel */
- /*!
-+ * \brief Sets an option on a channel
-+ *
- * \param channel channel to set options on
- * \param option option to change
- * \param data data specific to option
- * \param datalen length of the data
- * \param block blocking or not
-+ * \details
- * Set an option on a channel (see frame.h), optionally blocking awaiting the reply
-- * Returns 0 on success and -1 on failure
-+ * \return 0 on success and -1 on failure
- */
- int ast_channel_setoption(struct ast_channel *channel, int option, void *data, int datalen, int block);
-
--/*! Pick the best codec */
--/* Choose the best codec... Uhhh... Yah. */
-+/*! Pick the best codec
-+ * Choose the best codec... Uhhh... Yah. */
- int ast_best_codec(int fmts);
-
-
--/*! Checks the value of an option */
- /*!
-+ * \brief Checks the value of an option
-+ *
- * Query the value of an option
- * Works similarly to setoption except only reads the options.
- */
- int ast_channel_queryoption(struct ast_channel *channel, int option, void *data, int *datalen, int block);
-
--/*! Checks for HTML support on a channel */
--/*! Returns 0 if channel does not support HTML or non-zero if it does */
-+/*!
-+ * \brief Checks for HTML support on a channel
-+ * \return 0 if channel does not support HTML or non-zero if it does
-+ */
- int ast_channel_supports_html(struct ast_channel *channel);
-
--/*! Sends HTML on given channel */
--/*! Send HTML or URL on link. Returns 0 on success or -1 on failure */
-+/*!
-+ * \brief Sends HTML on given channel
-+ * Send HTML or URL on link.
-+ * \return 0 on success or -1 on failure
-+ */
- int ast_channel_sendhtml(struct ast_channel *channel, int subclass, const char *data, int datalen);
-
--/*! Sends a URL on a given link */
--/*! Send URL on link. Returns 0 on success or -1 on failure */
-+/*!
-+ * \brief Sends a URL on a given link
-+ * Send URL on link.
-+ * \return 0 on success or -1 on failure
-+ */
- int ast_channel_sendurl(struct ast_channel *channel, const char *url);
-
--/*! Defers DTMF */
--/*! Defer DTMF so that you only read things like hangups and audio. Returns
-- non-zero if channel was already DTMF-deferred or 0 if channel is just now
-- being DTMF-deferred */
-+/*!
-+ * \brief Defers DTMF so that you only read things like hangups and audio.
-+ * \return non-zero if channel was already DTMF-deferred or
-+ * 0 if channel is just now being DTMF-deferred
-+ */
- int ast_channel_defer_dtmf(struct ast_channel *chan);
-
--/*! Undo defer. ast_read will return any dtmf characters that were queued */
-+/*! Undo defer. ast_read will return any DTMF characters that were queued */
- void ast_channel_undefer_dtmf(struct ast_channel *chan);
-
- /*! Initiate system shutdown -- prevents new channels from being allocated.
-- If "hangup" is non-zero, all existing channels will receive soft
-- hangups */
-+ * \param hangup If "hangup" is non-zero, all existing channels will receive soft
-+ * hangups */
- void ast_begin_shutdown(int hangup);
-
- /*! Cancels an existing shutdown and returns to normal operation */
- void ast_cancel_shutdown(void);
-
--/*! Returns number of active/allocated channels */
-+/*! \return number of active/allocated channels */
- int ast_active_channels(void);
-
--/*! Returns non-zero if Asterisk is being shut down */
-+/*! \return non-zero if Asterisk is being shut down */
- int ast_shutting_down(void);
-
- /*! Activate a given generator */
-@@ -1536,105 +1775,119 @@
- *
- * \param rate number of timer ticks per second
- *
-+ * \details
- * If timers are supported, force a scheduled expiration on the
- * timer fd, at which point we call the callback function / data
- *
-- * Call this function with a rate of 0 to turn off the timer ticks
-+ * \note Call this function with a rate of 0 to turn off the timer ticks
- *
- * \version 1.6.1 changed samples parameter to rate, accomodates new timing methods
- */
- int ast_settimeout(struct ast_channel *c, unsigned int rate, int (*func)(const void *data), void *data);
-
--/*! \brief Transfer a channel (if supported). Returns -1 on error, 0 if not supported
-- and 1 if supported and requested
-- \param chan current channel
-- \param dest destination extension for transfer
--*/
-+/*!
-+ * \brief Transfer a channel (if supported).
-+ * \retval -1 on error
-+ * \retval 0 if not supported
-+ * \retval 1 if supported and requested
-+ * \param chan current channel
-+ * \param dest destination extension for transfer
-+ */
- int ast_transfer(struct ast_channel *chan, char *dest);
-
--/*! \brief Start masquerading a channel
-- XXX This is a seriously whacked out operation. We're essentially putting the guts of
-- the clone channel into the original channel. Start by killing off the original
-- channel's backend. I'm not sure we're going to keep this function, because
-- while the features are nice, the cost is very high in terms of pure nastiness. XXX
-- \param chan Channel to masquerade
--*/
-+/*!
-+ * \brief Start masquerading a channel
-+ * \details
-+ * XXX This is a seriously whacked out operation. We're essentially putting the guts of
-+ * the clone channel into the original channel. Start by killing off the original
-+ * channel's backend. I'm not sure we're going to keep this function, because
-+ * while the features are nice, the cost is very high in terms of pure nastiness. XXX
-+ * \param chan Channel to masquerade
-+ */
- int ast_do_masquerade(struct ast_channel *chan);
-
--/*! \brief Find bridged channel
-- \param chan Current channel
--*/
-+/*!
-+ * \brief Find bridged channel
-+ * \param chan Current channel
-+ */
- struct ast_channel *ast_bridged_channel(struct ast_channel *chan);
-
- /*!
-- \brief Inherits channel variable from parent to child channel
-- \param parent Parent channel
-- \param child Child channel
--
-- Scans all channel variables in the parent channel, looking for those
-- that should be copied into the child channel.
-- Variables whose names begin with a single '_' are copied into the
-- child channel with the prefix removed.
-- Variables whose names begin with '__' are copied into the child
-- channel with their names unchanged.
--*/
-+ * \brief Inherits channel variable from parent to child channel
-+ * \param parent Parent channel
-+ * \param child Child channel
-+ *
-+ * \details
-+ * Scans all channel variables in the parent channel, looking for those
-+ * that should be copied into the child channel.
-+ * Variables whose names begin with a single '_' are copied into the
-+ * child channel with the prefix removed.
-+ * Variables whose names begin with '__' are copied into the child
-+ * channel with their names unchanged.
-+ */
- void ast_channel_inherit_variables(const struct ast_channel *parent, struct ast_channel *child);
-
- /*!
-- \brief adds a list of channel variables to a channel
-- \param chan the channel
-- \param vars a linked list of variables
--
-- Variable names can be for a regular channel variable or a dialplan function
-- that has the ability to be written to.
--*/
-+ * \brief adds a list of channel variables to a channel
-+ * \param chan the channel
-+ * \param vars a linked list of variables
-+ *
-+ * \details
-+ * Variable names can be for a regular channel variable or a dialplan function
-+ * that has the ability to be written to.
-+ */
- void ast_set_variables(struct ast_channel *chan, struct ast_variable *vars);
-
- /*!
-- \brief An opaque 'object' structure use by silence generators on channels.
-+ * \brief An opaque 'object' structure use by silence generators on channels.
- */
- struct ast_silence_generator;
-
- /*!
-- \brief Starts a silence generator on the given channel.
-- \param chan The channel to generate silence on
-- \return An ast_silence_generator pointer, or NULL if an error occurs
--
-- This function will cause SLINEAR silence to be generated on the supplied
-- channel until it is disabled; if the channel cannot be put into SLINEAR
-- mode then the function will fail.
--
-- The pointer returned by this function must be preserved and passed to
-- ast_channel_stop_silence_generator when you wish to stop the silence
-- generation.
-+ * \brief Starts a silence generator on the given channel.
-+ * \param chan The channel to generate silence on
-+ * \return An ast_silence_generator pointer, or NULL if an error occurs
-+ *
-+ * \details
-+ * This function will cause SLINEAR silence to be generated on the supplied
-+ * channel until it is disabled; if the channel cannot be put into SLINEAR
-+ * mode then the function will fail.
-+ *
-+ * \note
-+ * The pointer returned by this function must be preserved and passed to
-+ * ast_channel_stop_silence_generator when you wish to stop the silence
-+ * generation.
- */
- struct ast_silence_generator *ast_channel_start_silence_generator(struct ast_channel *chan);
-
- /*!
-- \brief Stops a previously-started silence generator on the given channel.
-- \param chan The channel to operate on
-- \param state The ast_silence_generator pointer return by a previous call to
-- ast_channel_start_silence_generator.
-- \return nothing
--
-- This function will stop the operating silence generator and return the channel
-- to its previous write format.
-+ * \brief Stops a previously-started silence generator on the given channel.
-+ * \param chan The channel to operate on
-+ * \param state The ast_silence_generator pointer return by a previous call to
-+ * ast_channel_start_silence_generator.
-+ * \return nothing
-+ *
-+ * \details
-+ * This function will stop the operating silence generator and return the channel
-+ * to its previous write format.
- */
- void ast_channel_stop_silence_generator(struct ast_channel *chan, struct ast_silence_generator *state);
-
- /*!
-- \brief Check if the channel can run in internal timing mode.
-- \param chan The channel to check
-- \return boolean
--
-- This function will return 1 if internal timing is enabled and the timing
-- device is available.
-+ * \brief Check if the channel can run in internal timing mode.
-+ * \param chan The channel to check
-+ * \return boolean
-+ *
-+ * \details
-+ * This function will return 1 if internal timing is enabled and the timing
-+ * device is available.
- */
- int ast_internal_timing_enabled(struct ast_channel *chan);
-
- /* Misc. functions below */
-
--/*! \brief if fd is a valid descriptor, set *pfd with the descriptor
-+/*!
-+ * \brief if fd is a valid descriptor, set *pfd with the descriptor
- * \return Return 1 (not -1!) if added, 0 otherwise (so we can add the
- * return value to the index into the array)
- */
-@@ -1677,12 +1930,14 @@
- }
- #endif
-
--/*! \brief Waits for activity on a group of channels
-+/*!
-+ * \brief Waits for activity on a group of channels
- * \param nfds the maximum number of file descriptors in the sets
- * \param rfds file descriptors to check for read availability
- * \param wfds file descriptors to check for write availability
- * \param efds file descriptors to check for exceptions (OOB data)
- * \param tvp timeout while waiting for events
-+ * \details
- * This is the same as a standard select(), except it guarantees the
- * behaviour where the passed struct timeval is updated with how much
- * time was not slept while waiting for the specified events
-@@ -1739,23 +1994,23 @@
- /*! \brief print call- and pickup groups into buffer */
- char *ast_print_group(char *buf, int buflen, ast_group_t group);
-
--/*! \brief Convert enum channelreloadreason to text string for manager event
-- \param reason Enum channelreloadreason - reason for reload (manager, cli, start etc)
--*/
-+/*!
-+ * \brief Convert enum channelreloadreason to text string for manager event
-+ * \param reason The reason for reload (manager, cli, start etc)
-+ */
- const char *channelreloadreason2txt(enum channelreloadreason reason);
-
- /*! \brief return an ast_variable list of channeltypes */
- struct ast_variable *ast_channeltype_list(void);
-
- /*!
-- \brief return an english explanation of the code returned thru __ast_request_and_dial's 'outstate' argument
-- \param reason The integer argument, usually taken from AST_CONTROL_ macros
-- \return char pointer explaining the code
-+ * \brief return an english explanation of the code returned thru __ast_request_and_dial's 'outstate' argument
-+ * \param reason The integer argument, usually taken from AST_CONTROL_ macros
-+ * \return char pointer explaining the code
- */
- const char *ast_channel_reason2str(int reason);
-
--/*! \brief channel group info
-- */
-+/*! \brief channel group info */
- struct ast_group_info {
- struct ast_channel *chan;
- char *category;
-@@ -1764,6 +2019,295 @@
- };
-
-
-+/*!
-+ * \since 1.6.3
-+ * \brief Copy the source caller information to the destination caller.
-+ *
-+ * \param dest Destination caller
-+ * \param src Source caller
-+ *
-+ * \return Nothing
-+ */
-+void ast_party_caller_copy(struct ast_callerid *dest, const struct ast_callerid *src);
-+
-+/*!
-+ * \since 1.6.3
-+ * \brief Initialize the given connected line structure.
-+ *
-+ * \param init Connected line structure to initialize.
-+ *
-+ * \return Nothing
-+ */
-+void ast_party_connected_line_init(struct ast_party_connected_line *init);
-+
-+/*!
-+ * \since 1.6.3
-+ * \brief Copy the source connected line information to the destination connected line.
-+ *
-+ * \param dest Destination connected line
-+ * \param src Source connected line
-+ *
-+ * \return Nothing
-+ */
-+void ast_party_connected_line_copy(struct ast_party_connected_line *dest, const struct ast_party_connected_line *src);
-+
-+/*!
-+ * \since 1.6.3
-+ * \brief Initialize the given connected line structure using the given
-+ * guide for a set update operation.
-+ *
-+ * \details
-+ * The initialization is needed to allow a set operation to know if a
-+ * value needs to be updated. Simple integers need the guide's original
-+ * value in case the set operation is not trying to set a new value.
-+ * String values are simply set to NULL pointers if they are not going
-+ * to be updated.
-+ *
-+ * \param init Connected line structure to initialize.
-+ * \param guide Source connected line to use as a guide in initializing.
-+ *
-+ * \return Nothing
-+ */
-+void ast_party_connected_line_set_init(struct ast_party_connected_line *init, const struct ast_party_connected_line *guide);
-+
-+/*!
-+ * \since 1.6.3
-+ * \brief Set the connected line information based on another connected line source
-+ *
-+ * This is similar to ast_party_connected_line_copy, except that NULL values for
-+ * strings in the src parameter indicate not to update the corresponding dest values.
-+ *
-+ * \param src The source connected line to use as a guide to set the dest
-+ * \param dest The connected line one wishes to update
-+ *
-+ * \return Nada
-+ */
-+void ast_party_connected_line_set(struct ast_party_connected_line *dest, const struct ast_party_connected_line *src);
-+
-+/*!
-+ * \since 1.6.3
-+ * \brief Collect the caller party information into a connected line structure.
-+ *
-+ * \param connected Collected caller information for the connected line
-+ * \param cid Caller information.
-+ *
-+ * \return Nothing
-+ *
-+ * \warning This is a shallow copy.
-+ * \warning DO NOT call ast_party_connected_line_free() on the filled in
-+ * connected line structure!
-+ */
-+void ast_party_connected_line_collect_caller(struct ast_party_connected_line *connected, struct ast_callerid *cid);
-+
-+/*!
-+ * \since 1.6.3
-+ * \brief Destroy the connected line information contents
-+ *
-+ * \param doomed The connected line information to destroy.
-+ *
-+ * \return Nothing
-+ */
-+void ast_party_connected_line_free(struct ast_party_connected_line *doomed);
-+
-+/*!
-+ * \since 1.6.3
-+ * \brief Copy the source redirecting information to the destination redirecting.
-+ *
-+ * \param dest Destination redirecting
-+ * \param src Source redirecting
-+ *
-+ * \return Nothing
-+ */
-+void ast_party_redirecting_copy(struct ast_party_redirecting *dest, const struct ast_party_redirecting *src);
-+
-+/*!
-+ * \since 1.6.3
-+ * \brief Initialize the given redirecting id structure using the given guide
-+ * for a set update operation.
-+ *
-+ * \details
-+ * The initialization is needed to allow a set operation to know if a
-+ * value needs to be updated. Simple integers need the guide's original
-+ * value in case the set operation is not trying to set a new value.
-+ * String values are simply set to NULL pointers if they are not going
-+ * to be updated.
-+ *
-+ * \param init Redirecting id structure to initialize.
-+ * \param guide Source redirecting id to use as a guide in initializing.
-+ *
-+ * \return Nothing
-+ */
-+void ast_party_redirecting_set_init(struct ast_party_redirecting *init, const struct ast_party_redirecting *guide);
-+
-+/*!
-+ * \since 1.6.3
-+ * \brief Destroy the redirecting information contents
-+ *
-+ * \param doomed The redirecting information to destroy.
-+ *
-+ * \return Nothing
-+ */
-+void ast_party_redirecting_free(struct ast_party_redirecting *doomed);
-+
-+/*!
-+ * \since 1.6.3
-+ * \brief Copy the caller information to the connected line information.
-+ *
-+ * \param dest Destination connected line information
-+ * \param src Source caller information
-+ *
-+ * \return Nothing
-+ *
-+ * \note Assumes locks are already acquired
-+ */
-+void ast_connected_line_copy_from_caller(struct ast_party_connected_line *dest, const struct ast_callerid *src);
-+
-+/*!
-+ * \since 1.6.3
-+ * \brief Copy the connected line information to the caller information.
-+ *
-+ * \param dest Destination caller information
-+ * \param src Source connected line information
-+ *
-+ * \return Nothing
-+ *
-+ * \note Assumes locks are already acquired
-+ */
-+void ast_connected_line_copy_to_caller(struct ast_callerid *dest, const struct ast_party_connected_line *src);
-+
-+/*!
-+ * \since 1.6.3
-+ * \brief Set the connected line information in the Asterisk channel
-+ *
-+ * \param chan Asterisk channel to set connected line information
-+ * \param connected Connected line information
-+ *
-+ * \return Nothing
-+ *
-+ * \note The channel does not need to be locked before calling this function.
-+ */
-+void ast_channel_set_connected_line(struct ast_channel *chan, const struct ast_party_connected_line *connected);
-+
-+/*!
-+ * \since 1.6.3
-+ * \brief Build the connected line information data frame.
-+ *
-+ * \param data Buffer to fill with the frame data
-+ * \param datalen Size of the buffer to fill
-+ * \param connected Connected line information
-+ *
-+ * \retval -1 if error
-+ * \retval Amount of data buffer used
-+ */
-+int ast_connected_line_build_data(unsigned char *data, size_t datalen, const struct ast_party_connected_line *connected);
-+
-+/*!
-+ * \since 1.6.3
-+ * \brief Parse connected line indication frame data
-+ *
-+ * \param data Buffer with the frame data to parse
-+ * \param datalen Size of the buffer
-+ * \param connected Extracted connected line information
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ *
-+ * \note The filled in connected line structure needs to be initialized by
-+ * ast_party_connected_line_set_init() before calling. If defaults are not
-+ * required use ast_party_connected_line_init().
-+ * \note The filled in connected line structure needs to be destroyed by
-+ * ast_party_connected_line_free() when it is no longer needed.
-+ */
-+int ast_connected_line_parse_data(const unsigned char *data, size_t datalen, struct ast_party_connected_line *connected);
-+
-+/*!
-+ * \since 1.6.3
-+ * \brief Indicate that the connected line information has changed
-+ *
-+ * \param chan Asterisk channel to indicate connected line information
-+ * \param connected Connected line information
-+ *
-+ * \return Nothing
-+ */
-+void ast_channel_update_connected_line(struct ast_channel *chan, const struct ast_party_connected_line *connected);
-+
-+/*!
-+ * \since 1.6.3
-+ * \brief Queue a connected line update frame on a channel
-+ *
-+ * \param chan Asterisk channel to indicate connected line information
-+ * \param connected Connected line information
-+ *
-+ * \return Nothing
-+ */
-+void ast_channel_queue_connected_line_update(struct ast_channel *chan, const struct ast_party_connected_line *connected);
-+
-+/*!
-+ * \since 1.6.3
-+ * \brief Set the redirecting id information in the Asterisk channel
-+ *
-+ * \param chan Asterisk channel to set redirecting id information
-+ * \param redirecting Redirecting id information
-+ *
-+ * \return Nothing
-+ *
-+ * \note The channel does not need to be locked before calling this function.
-+ */
-+void ast_channel_set_redirecting(struct ast_channel *chan, const struct ast_party_redirecting *redirecting);
-+
-+/*!
-+ * \since 1.6.3
-+ * \brief Build the redirecting id data frame.
-+ *
-+ * \param data Buffer to fill with the frame data
-+ * \param datalen Size of the buffer to fill
-+ * \param redirecting Redirecting id information
-+ *
-+ * \retval -1 if error
-+ * \retval Amount of data buffer used
-+ */
-+int ast_redirecting_build_data(unsigned char *data, size_t datalen, const struct ast_party_redirecting *redirecting);
-+
-+/*!
-+ * \since 1.6.3
-+ * \brief Parse redirecting indication frame data
-+ *
-+ * \param data Buffer with the frame data to parse
-+ * \param datalen Size of the buffer
-+ * \param redirecting Extracted redirecting id information
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ *
-+ * \note The filled in id structure needs to be initialized by
-+ * ast_party_redirecting_set_init() before calling.
-+ * \note The filled in id structure needs to be destroyed by
-+ * ast_party_redirecting_free() when it is no longer needed.
-+ */
-+int ast_redirecting_parse_data(const unsigned char *data, size_t datalen, struct ast_party_redirecting *redirecting);
-+
-+/*!
-+ * \since 1.6.3
-+ * \brief Indicate that the redirecting id has changed
-+ *
-+ * \param chan Asterisk channel to indicate redirecting id information
-+ * \param redirecting Redirecting id information
-+ *
-+ * \return Nothing
-+ */
-+void ast_channel_update_redirecting(struct ast_channel *chan, const struct ast_party_redirecting *redirecting);
-+
-+/*!
-+ * \since 1.6.3
-+ * \brief Queue a redirecting update frame on a channel
-+ *
-+ * \param chan Asterisk channel to indicate redirecting id information
-+ * \param redirecting Redirecting id information
-+ *
-+ * \return Nothing
-+ */
-+void ast_channel_queue_redirecting_update(struct ast_channel *chan, const struct ast_party_redirecting *redirecting);
-+
- #if defined(__cplusplus) || defined(c_plusplus)
- }
- #endif
-Index: include/asterisk/_private.h
-===================================================================
---- a/include/asterisk/_private.h (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/include/asterisk/_private.h (.../trunk) (revision 186562)
-@@ -29,7 +29,7 @@
- void dnsmgr_start_refresh(void); /*!< Provided by dnsmgr.c */
- int dnsmgr_reload(void); /*!< Provided by dnsmgr.c */
- void threadstorage_init(void); /*!< Provided by threadstorage.c */
--void ast_event_init(void); /*!< Provided by event.c */
-+int ast_event_init(void); /*!< Provided by event.c */
- int ast_device_state_engine_init(void); /*!< Provided by devicestate.c */
- int astobj2_init(void); /*!< Provided by astobj2.c */
- int ast_file_init(void); /*!< Provided by file.c */
-@@ -41,6 +41,7 @@
- int ast_timing_init(void); /*!< Provided by timing.c */
- int ast_indications_init(void); /*!< Provided by indications.c */
- int ast_indications_reload(void);/*!< Provided by indications.c */
-+void ast_stun_init(void); /*!< Provided by stun.c */
-
- /*!
- * \brief Reload asterisk modules.
-Index: include/asterisk/features.h
-===================================================================
---- a/include/asterisk/features.h (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/include/asterisk/features.h (.../trunk) (revision 186562)
-@@ -36,6 +36,21 @@
-
- #define PARK_APP_NAME "Park"
-
-+#define AST_FEATURE_RETURN_HANGUP -1
-+#define AST_FEATURE_RETURN_SUCCESSBREAK 0
-+#define AST_FEATURE_RETURN_PBX_KEEPALIVE AST_PBX_KEEPALIVE
-+#define AST_FEATURE_RETURN_NO_HANGUP_PEER AST_PBX_NO_HANGUP_PEER
-+#define AST_FEATURE_RETURN_PASSDIGITS 21
-+#define AST_FEATURE_RETURN_STOREDIGITS 22
-+#define AST_FEATURE_RETURN_SUCCESS 23
-+#define AST_FEATURE_RETURN_KEEPTRYING 24
-+#define AST_FEATURE_RETURN_PARKFAILED 25
-+
-+#define FEATURE_SENSE_CHAN (1 << 0)
-+#define FEATURE_SENSE_PEER (1 << 1)
-+
-+typedef int (*ast_feature_operation)(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data);
-+
- /*! \brief main call feature structure */
-
- enum {
-@@ -53,7 +68,7 @@
- char sname[FEATURE_SNAME_LEN];
- char exten[FEATURE_MAX_LEN];
- char default_exten[FEATURE_MAX_LEN];
-- int (*operation)(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data);
-+ ast_feature_operation operation;
- unsigned int flags;
- char app[FEATURE_APP_LEN];
- char app_args[FEATURE_APP_ARGS_LEN];
-@@ -61,14 +76,6 @@
- AST_LIST_ENTRY(ast_call_feature) feature_entry;
- };
-
--#define AST_FEATURE_RETURN_HANGUP -1
--#define AST_FEATURE_RETURN_SUCCESSBREAK 0
--#define AST_FEATURE_RETURN_PASSDIGITS 21
--#define AST_FEATURE_RETURN_STOREDIGITS 22
--#define AST_FEATURE_RETURN_SUCCESS 23
--#define AST_FEATURE_RETURN_KEEPTRYING 24
--#define AST_FEATURE_RETURN_PARKFAILED 25
--
- /*!
- * \brief Park a call and read back parked location
- * \param chan the channel to actually be parked
-@@ -123,6 +130,14 @@
- \param feature the ast_call_feature object which was registered before*/
- void ast_unregister_feature(struct ast_call_feature *feature);
-
-+/*! \brief detect a feature before bridging
-+ \param chan
-+ \param ast_flags ptr
-+ \param char ptr of input code
-+ \retval ast_call_feature ptr to be set if found
-+ \return result, was feature found or not */
-+int ast_feature_detect(struct ast_channel *chan, struct ast_flags *features, char *code, struct ast_call_feature *feature);
-+
- /*! \brief look for a call feature entry by its sname
- \param name a string ptr, should match "automon", "blindxfer", "atxfer", etc. */
- struct ast_call_feature *ast_find_call_feature(const char *name);
-Index: include/asterisk/app.h
-===================================================================
---- a/include/asterisk/app.h (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/include/asterisk/app.h (.../trunk) (revision 186562)
-@@ -32,7 +32,7 @@
- extern "C" {
- #endif
-
--AST_THREADSTORAGE_EXTERNAL(global_app_buf);
-+AST_THREADSTORAGE_EXTERNAL(ast_str_thread_global_buf);
-
- /* IVR stuff */
-
-Index: include/asterisk/res_odbc.h
-===================================================================
---- a/include/asterisk/res_odbc.h (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/include/asterisk/res_odbc.h (.../trunk) (revision 186562)
-@@ -35,7 +35,7 @@
-
- typedef enum { ODBC_SUCCESS=0, ODBC_FAIL=-1} odbc_status;
-
--/*! \brief Flags for use with ast_odbc_request_obj2 */
-+/*! \brief Flags for use with \see ast_odbc_request_obj2 */
- enum {
- RES_ODBC_SANITY_CHECK = (1 << 0),
- RES_ODBC_INDEPENDENT_CONNECTION = (1 << 1),
-@@ -102,7 +102,7 @@
- /*!
- * \brief Retrieves a connected ODBC object
- * \param name The name of the ODBC class for which a connection is needed.
-- * \param check Whether to ensure that a connection is valid before returning the handle. Usually unnecessary.
-+ * \param flags Set of flags used to control which connection is returned.
- * \retval ODBC object
- * \retval NULL if there is no connection available with the requested name.
- *
-@@ -129,7 +129,7 @@
- * \brief Retrieve a stored ODBC object, if a transaction has been started.
- * \param chan Channel associated with the transaction.
- * \param objname Name of the database handle. This name corresponds to the name passed
-- * to ast_odbc_request_obj2 (or formerly, to ast_odbc_request_obj). Note that the
-+ * to \see ast_odbc_request_obj2 (or formerly, to ast_odbc_request_obj). Note that the
- * existence of this parameter name explicitly allows for multiple transactions to be open
- * at once, albeit to different databases.
- * \retval A stored ODBC object, if a transaction was already started.
-@@ -180,7 +180,7 @@
- /*!
- * \brief Find or create an entry describing the table specified.
- * \param database Name of an ODBC class on which to query the table
-- * \param table Tablename to describe
-+ * \param tablename Tablename to describe
- * \retval A structure describing the table layout, or NULL, if the table is not found or another error occurs.
- * When a structure is returned, the contained columns list will be
- * rdlock'ed, to ensure that it will be retained in memory.
-@@ -200,7 +200,7 @@
- /*!
- * \brief Remove a cache entry from memory
- * \param database Name of an ODBC class (used to ensure like-named tables in different databases are not confused)
-- * \param table Tablename for which a cached record should be removed
-+ * \param tablename Tablename for which a cached record should be removed
- * \retval 0 if the cache entry was removed, or -1 if no matching entry was found.
- * \since 1.6.1
- */
-@@ -213,7 +213,7 @@
-
- /*!\brief Wrapper for SQLGetData to use with dynamic strings
- * \param buf Address of the pointer to the ast_str structure.
-- * \param maxlen The maximum size of the resulting string, or 0 for no limit.
-+ * \param pmaxlen The maximum size of the resulting string, or 0 for no limit.
- * \param StatementHandle The statement handle from which to retrieve data.
- * \param ColumnNumber Column number (1-based offset) for which to retrieve data.
- * \param TargetType The SQL constant indicating what kind of data is to be retrieved (usually SQL_CHAR)
-Index: include/asterisk/event.h
-===================================================================
---- a/include/asterisk/event.h (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/include/asterisk/event.h (.../trunk) (revision 186562)
-@@ -358,42 +358,18 @@
- *
- * \param event the event to be queued and cached
- *
-- * The rest of the arguments to this function specify information elements to
-- * use for determining which events in the cache that this event should replace.
-- * All events in the cache that match the specified criteria will be removed from
-- * the cache and then this one will be added. The arguments are specified in
-- * the form:
-- *
-- * \code
-- * <enum ast_event_ie_type>, [enum ast_event_ie_pltype]
-- * \endcode
-- * and must end with AST_EVENT_IE_END.
-- *
-- * If the ie_type specified is *not* AST_EVENT_IE_END, then it must be followed
-- * by a valid IE payload type. If the payload type given is EXISTS, then all
-- * events that contain that information element will be removed from the cache.
-- * Otherwise, all events in the cache that contain an information element with
-- * the same value as the new event will be removed.
-- *
-- * \note If more than one IE parameter is specified, they *all* must match for
-- * the event to be removed from the cache.
-- *
-- * Example usage:
-- *
-- * \code
-- * ast_event_queue_and_cache(event,
-- * AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR,
-- * AST_EVENT_IE_END);
-- * \endcode
-- *
-- * This example queues and caches an event. Any events in the cache that have
-- * the same MAILBOX information element as this event will be removed.
-- *
-+ * \details
- * The purpose of caching events is so that the core can retain the last known
- * information for events that represent some sort of state. That way, when
- * code needs to find out the current state, it can query the cache.
-+ *
-+ * The event API already knows which events can be cached and how to cache them.
-+ *
-+ * \retval 0 success
-+ * \retval non-zero failure. If failure is returned, the event must be destroyed
-+ * by the caller of this function.
- */
--int ast_event_queue_and_cache(struct ast_event *event, ...);
-+int ast_event_queue_and_cache(struct ast_event *event);
-
- /*!
- * \brief Retrieve an event from the cache
-@@ -511,6 +487,18 @@
- const char *ast_event_get_ie_str(const struct ast_event *event, enum ast_event_ie_type ie_type);
-
- /*!
-+ * \brief Get the hash for the string payload of an IE
-+ *
-+ * \param event The event to get the IE from
-+ * \param ie_type the type of information element to retrieve the hash for
-+ *
-+ * \return This function returns the hash value as calculated by ast_str_hash()
-+ * for the string payload. This is stored in the event to avoid
-+ * unnecessary string comparisons.
-+ */
-+uint32_t ast_event_get_ie_str_hash(const struct ast_event *event, enum ast_event_ie_type ie_type);
-+
-+/*!
- * \brief Get the value of an information element that has a raw payload
- *
- * \param event The event to get the IE from
-Index: include/asterisk/compat.h
-===================================================================
---- a/include/asterisk/compat.h (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/include/asterisk/compat.h (.../trunk) (revision 186562)
-@@ -67,7 +67,7 @@
- #include <string.h>
- #endif
-
--#ifdef HAVE_SYS_POLL_H
-+#ifndef AST_POLL_COMPAT
- #include <sys/poll.h>
- #else
- #include "asterisk/poll-compat.h"
-Index: include/asterisk/timing.h
-===================================================================
---- a/include/asterisk/timing.h (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/include/asterisk/timing.h (.../trunk) (revision 186562)
-@@ -45,9 +45,6 @@
- 4) Multiple 'event types', so that the code using the timer can
- know whether the wakeup it received was due to a periodic trigger
- or a continuous trigger.
--
-- \todo Create an implementation of this API for Linux based on the
-- following API: http://www.kernel.org/doc/man-pages/online/pages/man2/timerfd_create.2.html
- */
-
- #ifndef _ASTERISK_TIMING_H
-@@ -96,7 +93,7 @@
- */
- #define ast_register_timing_interface(i) _ast_register_timing_interface(i, ast_module_info->self)
- void *_ast_register_timing_interface(struct ast_timing_interface *funcs,
-- struct ast_module *mod);
-+ struct ast_module *mod);
-
- /*!
- * \brief Unregister a previously registered timing interface.
-@@ -110,45 +107,57 @@
- */
- int ast_unregister_timing_interface(void *handle);
-
-+struct ast_timer;
-+
- /*!
-- * \brief Open a timing fd
-+ * \brief Open a timer
- *
-- * \retval -1 error, with errno set
-- * \retval >=0 success
-+ * \retval NULL on error, with errno set
-+ * \retval non-NULL timer handle on success
- * \since 1.6.1
- */
--int ast_timer_open(void);
-+struct ast_timer *ast_timer_open(void);
-
- /*!
- * \brief Close an opened timing handle
- *
-- * \param handle timing fd returned from timer_open()
-+ * \param handle timer handle returned from timer_open()
- *
- * \return nothing
- * \since 1.6.1
- */
--void ast_timer_close(int handle);
-+void ast_timer_close(struct ast_timer *handle);
-
- /*!
-+ * \brief Get a poll()-able file descriptor for a timer
-+ *
-+ * \param handle timer handle returned from timer_open()
-+ *
-+ * \return file descriptor which can be used with poll() to wait for events
-+ * \since 1.6.1
-+ */
-+int ast_timer_fd(const struct ast_timer *handle);
-+
-+/*!
- * \brief Set the timing tick rate
- *
-- * \param handle timing fd returned from timer_open()
-+ * \param handle timer handle returned from timer_open()
- * \param rate ticks per second, 0 turns the ticks off if needed
- *
-- * Use this function if you want the timing fd to show input at a certain
-- * rate. The other alternative use of a timing fd, is using the continuous
-+ * Use this function if you want the timer to show input at a certain
-+ * rate. The other alternative use of a timer is the continuous
- * mode.
- *
- * \retval -1 error, with errno set
- * \retval 0 success
- * \since 1.6.1
- */
--int ast_timer_set_rate(int handle, unsigned int rate);
-+int ast_timer_set_rate(const struct ast_timer *handle, unsigned int rate);
-
- /*!
- * \brief Acknowledge a timer event
- *
-- * \param handle timing fd returned from timer_open()
-+ * \param handle timer handle returned from timer_open()
- * \param quantity number of timer events to acknowledge
- *
- * \note This function should only be called if timer_get_event()
-@@ -157,55 +166,55 @@
- * \return nothing
- * \since 1.6.1
- */
--void ast_timer_ack(int handle, unsigned int quantity);
-+void ast_timer_ack(const struct ast_timer *handle, unsigned int quantity);
-
- /*!
- * \brief Enable continuous mode
- *
-- * \param handle timing fd returned from timer_open()
-+ * \param handle timer handle returned from timer_open()
- *
-- * Continuous mode causes poll() on the timing fd to immediately return
-+ * Continuous mode causes poll() on the timer's fd to immediately return
- * always until continuous mode is disabled.
- *
- * \retval -1 failure, with errno set
- * \retval 0 success
- * \since 1.6.1
- */
--int ast_timer_enable_continuous(int handle);
-+int ast_timer_enable_continuous(const struct ast_timer *handle);
-
- /*!
- * \brief Disable continuous mode
- *
-- * \param handle timing fd returned from timer_close()
-+ * \param handle timer handle returned from timer_close()
- *
- * \retval -1 failure, with errno set
- * \retval 0 success
- * \since 1.6.1
- */
--int ast_timer_disable_continuous(int handle);
-+int ast_timer_disable_continuous(const struct ast_timer *handle);
-
- /*!
-- * \brief Determine timing event
-+ * \brief Retrieve timing event
- *
-- * \param handle timing fd returned by timer_open()
-+ * \param handle timer handle returned by timer_open()
- *
-- * After poll() indicates that there is input on the timing fd, this will
-+ * After poll() indicates that there is input on the timer's fd, this will
- * be called to find out what triggered it.
- *
-- * \return which event triggered the timing fd
-+ * \return which event triggered the timer
- * \since 1.6.1
- */
--enum ast_timer_event ast_timer_get_event(int handle);
-+enum ast_timer_event ast_timer_get_event(const struct ast_timer *handle);
-
- /*!
-- * \brief Get maximum rate supported for a timing handle
-+ * \brief Get maximum rate supported for a timer
- *
-- * \param handle timing fd returned by timer_open()
-+ * \param handle timer handle returned by timer_open()
- *
-- * \return maximum rate supported for timing handle
-+ * \return maximum rate supported by timer
- * \since 1.6.1
- */
--unsigned int ast_timer_get_max_rate(int handle);
-+unsigned int ast_timer_get_max_rate(const struct ast_timer *handle);
-
- #if defined(__cplusplus) || defined(c_plusplus)
- }
-Index: include/asterisk/frame.h
-===================================================================
---- a/include/asterisk/frame.h (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/include/asterisk/frame.h (.../trunk) (revision 186562)
-@@ -39,54 +39,56 @@
- char framing[32];
- };
-
--/*! \page Def_Frame AST Multimedia and signalling frames
-- \section Def_AstFrame What is an ast_frame ?
-- A frame of data read used to communicate between
-- between channels and applications.
-- Frames are divided into frame types and subclasses.
-+/*!
-+ * \page Def_Frame AST Multimedia and signalling frames
-+ * \section Def_AstFrame What is an ast_frame ?
-+ * A frame of data read used to communicate between
-+ * between channels and applications.
-+ * Frames are divided into frame types and subclasses.
-+ *
-+ * \par Frame types
-+ * \arg \b VOICE: Voice data, subclass is codec (AST_FORMAT_*)
-+ * \arg \b VIDEO: Video data, subclass is codec (AST_FORMAT_*)
-+ * \arg \b DTMF: A DTMF digit, subclass is the digit
-+ * \arg \b IMAGE: Image transport, mostly used in IAX
-+ * \arg \b TEXT: Text messages and character by character (real time text)
-+ * \arg \b HTML: URL's and web pages
-+ * \arg \b MODEM: Modulated data encodings, such as T.38 and V.150
-+ * \arg \b IAX: Private frame type for the IAX protocol
-+ * \arg \b CNG: Comfort noice frames
-+ * \arg \b CONTROL:A control frame, subclass defined as AST_CONTROL_
-+ * \arg \b NULL: Empty, useless frame
-+ *
-+ * \par Files
-+ * \arg frame.h Definitions
-+ * \arg frame.c Function library
-+ * \arg \ref Def_Channel Asterisk channels
-+ * \section Def_ControlFrame Control Frames
-+ * Control frames send signalling information between channels
-+ * and devices. They are prefixed with AST_CONTROL_, like AST_CONTROL_FRAME_HANGUP
-+ * \arg \b HANGUP The other end has hungup
-+ * \arg \b RING Local ring
-+ * \arg \b RINGING The other end is ringing
-+ * \arg \b ANSWER The other end has answered
-+ * \arg \b BUSY Remote end is busy
-+ * \arg \b TAKEOFFHOOK Make it go off hook (what's "it" ? )
-+ * \arg \b OFFHOOK Line is off hook
-+ * \arg \b CONGESTION Congestion (circuit is busy, not available)
-+ * \arg \b FLASH Other end sends flash hook
-+ * \arg \b WINK Other end sends wink
-+ * \arg \b OPTION Send low-level option
-+ * \arg \b RADIO_KEY Key radio (see app_rpt.c)
-+ * \arg \b RADIO_UNKEY Un-key radio (see app_rpt.c)
-+ * \arg \b PROGRESS Other end indicates call progress
-+ * \arg \b PROCEEDING Indicates proceeding
-+ * \arg \b HOLD Call is placed on hold
-+ * \arg \b UNHOLD Call is back from hold
-+ * \arg \b VIDUPDATE Video update requested
-+ * \arg \b SRCUPDATE The source of media has changed
-+ * \arg \b CONNECTED_LINE Connected line has changed
-+ * \arg \b REDIRECTING Call redirecting information has changed.
-+ */
-
-- \par Frame types
-- \arg \b VOICE: Voice data, subclass is codec (AST_FORMAT_*)
-- \arg \b VIDEO: Video data, subclass is codec (AST_FORMAT_*)
-- \arg \b DTMF: A DTMF digit, subclass is the digit
-- \arg \b IMAGE: Image transport, mostly used in IAX
-- \arg \b TEXT: Text messages and character by character (real time text)
-- \arg \b HTML: URL's and web pages
-- \arg \b MODEM: Modulated data encodings, such as T.38 and V.150
-- \arg \b IAX: Private frame type for the IAX protocol
-- \arg \b CNG: Comfort noice frames
-- \arg \b CONTROL: A control frame, subclass defined as AST_CONTROL_
-- \arg \b NULL: Empty, useless frame
--
-- \par Files
-- \arg frame.h Definitions
-- \arg frame.c Function library
-- \arg \ref Def_Channel Asterisk channels
-- \section Def_ControlFrame Control Frames
-- Control frames send signalling information between channels
-- and devices. They are prefixed with AST_CONTROL_, like AST_CONTROL_FRAME_HANGUP
-- \arg \b HANGUP The other end has hungup
-- \arg \b RING Local ring
-- \arg \b RINGING The other end is ringing
-- \arg \b ANSWER The other end has answered
-- \arg \b BUSY Remote end is busy
-- \arg \b TAKEOFFHOOK Make it go off hook (what's "it" ? )
-- \arg \b OFFHOOK Line is off hook
-- \arg \b CONGESTION Congestion (circuit is busy, not available)
-- \arg \b FLASH Other end sends flash hook
-- \arg \b WINK Other end sends wink
-- \arg \b OPTION Send low-level option
-- \arg \b RADIO_KEY Key radio (see app_rpt.c)
-- \arg \b RADIO_UNKEY Un-key radio (see app_rpt.c)
-- \arg \b PROGRESS Other end indicates call progress
-- \arg \b PROCEEDING Indicates proceeding
-- \arg \b HOLD Call is placed on hold
-- \arg \b UNHOLD Call is back from hold
-- \arg \b VIDUPDATE Video update requested
-- \arg \b SRCUPDATE The source of media has changed
--
--*/
--
- /*!
- * \brief Frame types
- *
-@@ -319,6 +321,9 @@
- AST_CONTROL_VIDUPDATE = 18, /*!< Indicate video frame update */
- AST_CONTROL_T38 = 19, /*!< T38 state change request/notification */
- AST_CONTROL_SRCUPDATE = 20, /*!< Indicate source of media has changed */
-+ AST_CONTROL_TRANSFER = 21, /*!< Indicate status of a transfer request */
-+ AST_CONTROL_CONNECTED_LINE = 22, /*!< Indicate connected line has changed */
-+ AST_CONTROL_REDIRECTING = 23 /*!< Indicate redirecting id has changed */
- };
-
- enum ast_control_t38 {
-@@ -329,6 +334,11 @@
- AST_T38_REFUSED /*!< T38 refused for some reason (usually rejected by remote end) */
- };
-
-+enum ast_control_transfer {
-+ AST_TRANSFER_SUCCESS = 0, /*!< Transfer request on the channel worked */
-+ AST_TRANSFER_FAILED, /*!< Transfer request on the channel failed */
-+};
-+
- #define AST_SMOOTHER_FLAG_G729 (1 << 0)
- #define AST_SMOOTHER_FLAG_BE (1 << 1)
-
-Index: include/asterisk/devicestate.h
-===================================================================
---- a/include/asterisk/devicestate.h (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/include/asterisk/devicestate.h (.../trunk) (revision 186562)
-@@ -37,6 +37,8 @@
- #ifndef _ASTERISK_DEVICESTATE_H
- #define _ASTERISK_DEVICESTATE_H
-
-+#include "asterisk/channel.h"
-+
- #if defined(__cplusplus) || defined(c_plusplus)
- extern "C" {
- #endif
-@@ -260,6 +262,21 @@
- unsigned int ring:1;
- };
-
-+/*!
-+ * \brief Enable distributed device state processing.
-+ *
-+ * \details
-+ * By default, Asterisk assumes that device state change events will only be
-+ * originating from one instance. If a module gets loaded and configured such
-+ * that multiple instances of Asterisk will be sharing device state, this
-+ * function should be called to enable distributed device state processing.
-+ * It is off by default to save on unnecessary processing.
-+ *
-+ * \retval 0 success
-+ * \retval -1 failure
-+ */
-+int ast_enable_distributed_devstate(void);
-+
- #if defined(__cplusplus) || defined(c_plusplus)
- }
- #endif
-Index: include/asterisk/astobj2.h
-===================================================================
---- a/include/asterisk/astobj2.h (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/include/asterisk/astobj2.h (.../trunk) (revision 186562)
-@@ -388,6 +388,7 @@
- *
- * \param data_size The sizeof() of the user-defined structure.
- * \param destructor_fn The destructor function (can be NULL)
-+ * \param debug_msg
- * \return A pointer to user-data.
- *
- * Allocates a struct astobj2 with sufficient space for the
-@@ -397,24 +398,26 @@
- * - the refcount of the object just created is 1
- * - the returned pointer cannot be free()'d or realloc()'ed;
- * rather, we just call ao2_ref(o, -1);
-+ *
-+ * @{
- */
-
- #ifdef REF_DEBUG
-
-
--#define ao2_t_alloc(arg1, arg2, arg3) _ao2_alloc_debug((arg1), (arg2), (arg3), __FILE__, __LINE__, __PRETTY_FUNCTION__)
--#define ao2_alloc(arg1, arg2) _ao2_alloc_debug((arg1), (arg2), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
-+#define ao2_t_alloc(data_size, destructor_fn, debug_msg) __ao2_alloc_debug((data_size), (destructor_fn), (debug_msg), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-+#define ao2_alloc(data_size, destructor_fn) __ao2_alloc_debug((data_size), (destructor_fn), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
-
- #else
-
--#define ao2_t_alloc(arg1,arg2,arg3) _ao2_alloc((arg1), (arg2))
--#define ao2_alloc(arg1,arg2) _ao2_alloc((arg1), (arg2))
-+#define ao2_t_alloc(data_size, destructor_fn, debug_msg) __ao2_alloc((data_size), (destructor_fn))
-+#define ao2_alloc(data_size, destructor_fn) __ao2_alloc((data_size), (destructor_fn))
-
- #endif
--void *_ao2_alloc_debug(const size_t data_size, ao2_destructor_fn destructor_fn, char *tag, char *file, int line, const char *funcname);
--void *_ao2_alloc(const size_t data_size, ao2_destructor_fn destructor_fn);
-+void *__ao2_alloc_debug(const size_t data_size, ao2_destructor_fn destructor_fn, char *tag, char *file, int line, const char *funcname);
-+void *__ao2_alloc(const size_t data_size, ao2_destructor_fn destructor_fn);
-+/*! @} */
-
--
- /*! \brief
- * Reference/unreference an object and return the old refcount.
- *
-@@ -434,17 +437,20 @@
- * have a reference count to it, so the only case when the object
- * can go away is when we release our reference, and it is
- * the last one in existence.
-+ *
-+ * @{
- */
-
- #ifdef REF_DEBUG
--#define ao2_t_ref(arg1,arg2,arg3) _ao2_ref_debug((arg1), (arg2), (arg3), __FILE__, __LINE__, __PRETTY_FUNCTION__)
--#define ao2_ref(arg1,arg2) _ao2_ref_debug((arg1), (arg2), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
-+#define ao2_t_ref(o,delta,tag) __ao2_ref_debug((o), (delta), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-+#define ao2_ref(o,delta) __ao2_ref_debug((o), (delta), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
- #else
--#define ao2_t_ref(arg1,arg2,arg3) _ao2_ref((arg1), (arg2))
--#define ao2_ref(arg1,arg2) _ao2_ref((arg1), (arg2))
-+#define ao2_t_ref(o,delta,tag) __ao2_ref((o), (delta))
-+#define ao2_ref(o,delta) __ao2_ref((o), (delta))
- #endif
--int _ao2_ref_debug(void *o, int delta, char *tag, char *file, int line, const char *funcname);
--int _ao2_ref(void *o, int delta);
-+int __ao2_ref_debug(void *o, int delta, char *tag, char *file, int line, const char *funcname);
-+int __ao2_ref(void *o, int delta);
-+/*! @} */
-
- /*! \brief
- * Lock an object.
-@@ -455,8 +461,8 @@
- #ifndef DEBUG_THREADS
- int ao2_lock(void *a);
- #else
--#define ao2_lock(a) _ao2_lock(a, __FILE__, __PRETTY_FUNCTION__, __LINE__, #a)
--int _ao2_lock(void *a, const char *file, const char *func, int line, const char *var);
-+#define ao2_lock(a) __ao2_lock(a, __FILE__, __PRETTY_FUNCTION__, __LINE__, #a)
-+int __ao2_lock(void *a, const char *file, const char *func, int line, const char *var);
- #endif
-
- /*! \brief
-@@ -468,8 +474,8 @@
- #ifndef DEBUG_THREADS
- int ao2_unlock(void *a);
- #else
--#define ao2_unlock(a) _ao2_unlock(a, __FILE__, __PRETTY_FUNCTION__, __LINE__, #a)
--int _ao2_unlock(void *a, const char *file, const char *func, int line, const char *var);
-+#define ao2_unlock(a) __ao2_unlock(a, __FILE__, __PRETTY_FUNCTION__, __LINE__, #a)
-+int __ao2_unlock(void *a, const char *file, const char *func, int line, const char *var);
- #endif
-
- /*! \brief
-@@ -481,8 +487,8 @@
- #ifndef DEBUG_THREADS
- int ao2_trylock(void *a);
- #else
--#define ao2_trylock(a) _ao2_trylock(a, __FILE__, __PRETTY_FUNCTION__, __LINE__, #a)
--int _ao2_trylock(void *a, const char *file, const char *func, int line, const char *var);
-+#define ao2_trylock(a) __ao2_trylock(a, __FILE__, __PRETTY_FUNCTION__, __LINE__, #a)
-+int __ao2_trylock(void *a, const char *file, const char *func, int line, const char *var);
- #endif
-
- /*!
-@@ -686,15 +692,15 @@
- */
-
- #ifdef REF_DEBUG
--#define ao2_t_container_alloc(arg1,arg2,arg3,arg4) _ao2_container_alloc_debug((arg1), (arg2), (arg3), (arg4), __FILE__, __LINE__, __PRETTY_FUNCTION__)
--#define ao2_container_alloc(arg1,arg2,arg3) _ao2_container_alloc_debug((arg1), (arg2), (arg3), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
-+#define ao2_t_container_alloc(arg1,arg2,arg3,arg4) __ao2_container_alloc_debug((arg1), (arg2), (arg3), (arg4), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-+#define ao2_container_alloc(arg1,arg2,arg3) __ao2_container_alloc_debug((arg1), (arg2), (arg3), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
- #else
--#define ao2_t_container_alloc(arg1,arg2,arg3,arg4) _ao2_container_alloc((arg1), (arg2), (arg3))
--#define ao2_container_alloc(arg1,arg2,arg3) _ao2_container_alloc((arg1), (arg2), (arg3))
-+#define ao2_t_container_alloc(arg1,arg2,arg3,arg4) __ao2_container_alloc((arg1), (arg2), (arg3))
-+#define ao2_container_alloc(arg1,arg2,arg3) __ao2_container_alloc((arg1), (arg2), (arg3))
- #endif
--struct ao2_container *_ao2_container_alloc(const unsigned int n_buckets,
-+struct ao2_container *__ao2_container_alloc(const unsigned int n_buckets,
- ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn);
--struct ao2_container *_ao2_container_alloc_debug(const unsigned int n_buckets,
-+struct ao2_container *__ao2_container_alloc_debug(const unsigned int n_buckets,
- ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn,
- char *tag, char *file, int line, const char *funcname);
-
-@@ -730,14 +736,14 @@
- */
- #ifdef REF_DEBUG
-
--#define ao2_t_link(arg1, arg2, arg3) _ao2_link_debug((arg1), (arg2), (arg3), __FILE__, __LINE__, __PRETTY_FUNCTION__)
--#define ao2_link(arg1, arg2) _ao2_link_debug((arg1), (arg2), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
-+#define ao2_t_link(arg1, arg2, arg3) __ao2_link_debug((arg1), (arg2), (arg3), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-+#define ao2_link(arg1, arg2) __ao2_link_debug((arg1), (arg2), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
- #else
--#define ao2_t_link(arg1, arg2, arg3) _ao2_link((arg1), (arg2))
--#define ao2_link(arg1, arg2) _ao2_link((arg1), (arg2))
-+#define ao2_t_link(arg1, arg2, arg3) __ao2_link((arg1), (arg2))
-+#define ao2_link(arg1, arg2) __ao2_link((arg1), (arg2))
- #endif
--void *_ao2_link_debug(struct ao2_container *c, void *new_obj, char *tag, char *file, int line, const char *funcname);
--void *_ao2_link(struct ao2_container *c, void *newobj);
-+void *__ao2_link_debug(struct ao2_container *c, void *new_obj, char *tag, char *file, int line, const char *funcname);
-+void *__ao2_link(struct ao2_container *c, void *newobj);
-
- /*!
- * \brief Remove an object from the container
-@@ -756,14 +762,14 @@
- * refcount will be decremented).
- */
- #ifdef REF_DEBUG
--#define ao2_t_unlink(arg1, arg2, arg3) _ao2_unlink_debug((arg1), (arg2), (arg3), __FILE__, __LINE__, __PRETTY_FUNCTION__)
--#define ao2_unlink(arg1, arg2) _ao2_unlink_debug((arg1), (arg2), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
-+#define ao2_t_unlink(arg1, arg2, arg3) __ao2_unlink_debug((arg1), (arg2), (arg3), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-+#define ao2_unlink(arg1, arg2) __ao2_unlink_debug((arg1), (arg2), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
- #else
--#define ao2_t_unlink(arg1, arg2, arg3) _ao2_unlink((arg1), (arg2))
--#define ao2_unlink(arg1, arg2) _ao2_unlink((arg1), (arg2))
-+#define ao2_t_unlink(arg1, arg2, arg3) __ao2_unlink((arg1), (arg2))
-+#define ao2_unlink(arg1, arg2) __ao2_unlink((arg1), (arg2))
- #endif
--void *_ao2_unlink_debug(struct ao2_container *c, void *obj, char *tag, char *file, int line, const char *funcname);
--void *_ao2_unlink(struct ao2_container *c, void *obj);
-+void *__ao2_unlink_debug(struct ao2_container *c, void *obj, char *tag, char *file, int line, const char *funcname);
-+void *__ao2_unlink(struct ao2_container *c, void *obj);
-
-
- /*! \brief Used as return value if the flag OBJ_MULTIPLE is set */
-@@ -849,20 +855,23 @@
- *
- * \note When the returned object is no longer in use, ao2_ref() should
- * be used to free the additional reference possibly created by this function.
-+ *
-+ * @{
- */
- #ifdef REF_DEBUG
--#define ao2_t_callback(arg1,arg2,arg3,arg4,arg5) _ao2_callback_debug((arg1), (arg2), (arg3), (arg4), (arg5), __FILE__, __LINE__, __PRETTY_FUNCTION__)
--#define ao2_callback(arg1,arg2,arg3,arg4) _ao2_callback_debug((arg1), (arg2), (arg3), (arg4), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
-+#define ao2_t_callback(c,flags,cb_fn,arg,tag) __ao2_callback_debug((c), (flags), (cb_fn), (arg), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-+#define ao2_callback(c,flags,cb_fn,arg) __ao2_callback_debug((c), (flags), (cb_fn), (arg), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
- #else
--#define ao2_t_callback(arg1,arg2,arg3,arg4,arg5) _ao2_callback((arg1), (arg2), (arg3), (arg4))
--#define ao2_callback(arg1,arg2,arg3,arg4) _ao2_callback((arg1), (arg2), (arg3), (arg4))
-+#define ao2_t_callback(c,flags,cb_fn,arg,tag) __ao2_callback((c), (flags), (cb_fn), (arg))
-+#define ao2_callback(c,flags,cb_fn,arg) __ao2_callback((c), (flags), (cb_fn), (arg))
- #endif
--void *_ao2_callback_debug(struct ao2_container *c, enum search_flags flags,
-+void *__ao2_callback_debug(struct ao2_container *c, enum search_flags flags,
- ao2_callback_fn *cb_fn, void *arg, char *tag,
- char *file, int line, const char *funcname);
--void *_ao2_callback(struct ao2_container *c,
-+void *__ao2_callback(struct ao2_container *c,
- enum search_flags flags,
- ao2_callback_fn *cb_fn, void *arg);
-+/*! @} */
-
- /*! \brief
- * ao2_callback_data() is a generic function that applies cb_fn() to all objects
-@@ -880,16 +889,16 @@
- * \see ao2_callback()
- */
- #ifdef REF_DEBUG
--#define ao2_t_callback_data(arg1,arg2,arg3,arg4,arg5,arg6) _ao2_callback_data_debug((arg1), (arg2), (arg3), (arg4), (arg5), (arg6), __FILE__, __LINE__, __PRETTY_FUNCTION__)
--#define ao2_callback_data(arg1,arg2,arg3,arg4,arg5) _ao2_callback_data_debug((arg1), (arg2), (arg3), (arg4), (arg5), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
-+#define ao2_t_callback_data(arg1,arg2,arg3,arg4,arg5,arg6) __ao2_callback_data_debug((arg1), (arg2), (arg3), (arg4), (arg5), (arg6), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-+#define ao2_callback_data(arg1,arg2,arg3,arg4,arg5) __ao2_callback_data_debug((arg1), (arg2), (arg3), (arg4), (arg5), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
- #else
--#define ao2_t_callback_data(arg1,arg2,arg3,arg4,arg5,arg6) _ao2_callback_data((arg1), (arg2), (arg3), (arg4), (arg5))
--#define ao2_callback_data(arg1,arg2,arg3,arg4,arg5) _ao2_callback_data((arg1), (arg2), (arg3), (arg4), (arg5))
-+#define ao2_t_callback_data(arg1,arg2,arg3,arg4,arg5,arg6) __ao2_callback_data((arg1), (arg2), (arg3), (arg4), (arg5))
-+#define ao2_callback_data(arg1,arg2,arg3,arg4,arg5) __ao2_callback_data((arg1), (arg2), (arg3), (arg4), (arg5))
- #endif
--void *_ao2_callback_data_debug(struct ao2_container *c, enum search_flags flags,
-+void *__ao2_callback_data_debug(struct ao2_container *c, enum search_flags flags,
- ao2_callback_data_fn *cb_fn, void *arg, void *data, char *tag,
- char *file, int line, const char *funcname);
--void *_ao2_callback_data(struct ao2_container *c,
-+void *__ao2_callback_data(struct ao2_container *c,
- enum search_flags flags,
- ao2_callback_data_fn *cb_fn, void *arg, void *data);
-
-@@ -897,14 +906,14 @@
- * XXX possibly change order of arguments ?
- */
- #ifdef REF_DEBUG
--#define ao2_t_find(arg1,arg2,arg3,arg4) _ao2_find_debug((arg1), (arg2), (arg3), (arg4), __FILE__, __LINE__, __PRETTY_FUNCTION__)
--#define ao2_find(arg1,arg2,arg3) _ao2_find_debug((arg1), (arg2), (arg3), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
-+#define ao2_t_find(arg1,arg2,arg3,arg4) __ao2_find_debug((arg1), (arg2), (arg3), (arg4), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-+#define ao2_find(arg1,arg2,arg3) __ao2_find_debug((arg1), (arg2), (arg3), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
- #else
--#define ao2_t_find(arg1,arg2,arg3,arg4) _ao2_find((arg1), (arg2), (arg3))
--#define ao2_find(arg1,arg2,arg3) _ao2_find((arg1), (arg2), (arg3))
-+#define ao2_t_find(arg1,arg2,arg3,arg4) __ao2_find((arg1), (arg2), (arg3))
-+#define ao2_find(arg1,arg2,arg3) __ao2_find((arg1), (arg2), (arg3))
- #endif
--void *_ao2_find_debug(struct ao2_container *c, void *arg, enum search_flags flags, char *tag, char *file, int line, const char *funcname);
--void *_ao2_find(struct ao2_container *c, void *arg, enum search_flags flags);
-+void *__ao2_find_debug(struct ao2_container *c, void *arg, enum search_flags flags, char *tag, char *file, int line, const char *funcname);
-+void *__ao2_find(struct ao2_container *c, void *arg, enum search_flags flags);
-
- /*! \brief
- *
-@@ -1003,14 +1012,14 @@
-
- struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags);
- #ifdef REF_DEBUG
--#define ao2_t_iterator_next(arg1, arg2) _ao2_iterator_next_debug((arg1), (arg2), __FILE__, __LINE__, __PRETTY_FUNCTION__)
--#define ao2_iterator_next(arg1) _ao2_iterator_next_debug((arg1), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
-+#define ao2_t_iterator_next(arg1, arg2) __ao2_iterator_next_debug((arg1), (arg2), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-+#define ao2_iterator_next(arg1) __ao2_iterator_next_debug((arg1), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
- #else
--#define ao2_t_iterator_next(arg1, arg2) _ao2_iterator_next((arg1))
--#define ao2_iterator_next(arg1) _ao2_iterator_next((arg1))
-+#define ao2_t_iterator_next(arg1, arg2) __ao2_iterator_next((arg1))
-+#define ao2_iterator_next(arg1) __ao2_iterator_next((arg1))
- #endif
--void *_ao2_iterator_next_debug(struct ao2_iterator *a, char *tag, char *file, int line, const char *funcname);
--void *_ao2_iterator_next(struct ao2_iterator *a);
-+void *__ao2_iterator_next_debug(struct ao2_iterator *a, char *tag, char *file, int line, const char *funcname);
-+void *__ao2_iterator_next(struct ao2_iterator *a);
-
- /* extra functions */
- void ao2_bt(void); /* backtrace */
-Index: include/asterisk/heap.h
-===================================================================
---- a/include/asterisk/heap.h (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/include/asterisk/heap.h (.../trunk) (revision 186562)
-@@ -209,6 +209,8 @@
- */
- size_t ast_heap_size(struct ast_heap *h);
-
-+#ifndef DEBUG_THREADS
-+
- /*!
- * \brief Write-Lock a heap
- *
-@@ -247,6 +249,17 @@
- */
- int ast_heap_unlock(struct ast_heap *h);
-
-+#else /* DEBUG_THREADS */
-+
-+#define ast_heap_wrlock(h) __ast_heap_wrlock(h, __FILE__, __PRETTY_FUNCTION__, __LINE__)
-+int __ast_heap_wrlock(struct ast_heap *h, const char *file, const char *func, int line);
-+#define ast_heap_rdlock(h) __ast_heap_rdlock(h, __FILE__, __PRETTY_FUNCTION__, __LINE__)
-+int __ast_heap_rdlock(struct ast_heap *h, const char *file, const char *func, int line);
-+#define ast_heap_unlock(h) __ast_heap_unlock(h, __FILE__, __PRETTY_FUNCTION__, __LINE__)
-+int __ast_heap_unlock(struct ast_heap *h, const char *file, const char *func, int line);
-+
-+#endif /* DEBUG_THREADS */
-+
- /*!
- * \brief Verify that a heap has been properly constructed
- *
-Index: include/asterisk/lock.h
-===================================================================
---- a/include/asterisk/lock.h (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/include/asterisk/lock.h (.../trunk) (revision 186562)
-@@ -500,8 +500,10 @@
- if (t->tracking) {
- #ifdef HAVE_BKTR
- ast_reentrancy_lock(lt);
-- ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
-- bt = &lt->backtrace[lt->reentrancy];
-+ if (lt->reentrancy != AST_MAX_REENTRANCY) {
-+ ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
-+ bt = &lt->backtrace[lt->reentrancy];
-+ }
- ast_reentrancy_unlock(lt);
- ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t, bt);
- #else
-@@ -622,8 +624,10 @@
- if (t->tracking) {
- #ifdef HAVE_BKTR
- ast_reentrancy_lock(lt);
-- ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
-- bt = &lt->backtrace[lt->reentrancy];
-+ if (lt->reentrancy != AST_MAX_REENTRANCY) {
-+ ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
-+ bt = &lt->backtrace[lt->reentrancy];
-+ }
- ast_reentrancy_unlock(lt);
- ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t, bt);
- #else
-@@ -1069,6 +1073,7 @@
- #ifdef HAVE_BKTR
- struct ast_bt *bt = NULL;
- #endif
-+ int lock_found = 0;
-
-
- #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
-@@ -1086,44 +1091,35 @@
-
- ast_reentrancy_lock(lt);
- if (lt->reentrancy) {
-- int lock_found = 0;
- int i;
- pthread_t self = pthread_self();
-- for (i = lt->reentrancy-1; i >= 0; --i) {
-+ for (i = lt->reentrancy - 1; i >= 0; --i) {
- if (lt->thread[i] == self) {
- lock_found = 1;
-- if (i != lt->reentrancy-1) {
-- lt->file[i] = lt->file[lt->reentrancy-1];
-- lt->lineno[i] = lt->lineno[lt->reentrancy-1];
-- lt->func[i] = lt->func[lt->reentrancy-1];
-- lt->thread[i] = lt->thread[lt->reentrancy-1];
-+ if (i != lt->reentrancy - 1) {
-+ lt->file[i] = lt->file[lt->reentrancy - 1];
-+ lt->lineno[i] = lt->lineno[lt->reentrancy - 1];
-+ lt->func[i] = lt->func[lt->reentrancy - 1];
-+ lt->thread[i] = lt->thread[lt->reentrancy - 1];
- }
-+#ifdef HAVE_BKTR
-+ bt = &lt->backtrace[i];
-+#endif
-+ lt->file[lt->reentrancy - 1] = NULL;
-+ lt->lineno[lt->reentrancy - 1] = 0;
-+ lt->func[lt->reentrancy - 1] = NULL;
-+ lt->thread[lt->reentrancy - 1] = AST_PTHREADT_NULL;
- break;
- }
- }
-- if (!lock_found) {
-- __ast_mutex_logger("%s line %d (%s): attempted unlock rwlock '%s' without owning it!\n",
-- filename, line, func, name);
-- __ast_mutex_logger("%s line %d (%s): '%s' was last locked here.\n",
-- lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1], lt->func[lt->reentrancy-1], name);
--#ifdef HAVE_BKTR
-- __dump_backtrace(&lt->backtrace[lt->reentrancy-1], canlog);
--#endif
-- DO_THREAD_CRASH;
-- }
- }
-
-- if (--lt->reentrancy < 0) {
-+ if (lock_found && --lt->reentrancy < 0) {
- __ast_mutex_logger("%s line %d (%s): rwlock '%s' freed more times than we've locked!\n",
- filename, line, func, name);
- lt->reentrancy = 0;
- }
-
--#ifdef HAVE_BKTR
-- if (lt->reentrancy) {
-- bt = &lt->backtrace[lt->reentrancy - 1];
-- }
--#endif
- ast_reentrancy_unlock(lt);
-
- if (t->tracking) {
-@@ -1171,8 +1167,10 @@
- if (t->tracking) {
- #ifdef HAVE_BKTR
- ast_reentrancy_lock(lt);
-- ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
-- bt = &lt->backtrace[lt->reentrancy];
-+ if (lt->reentrancy != AST_MAX_REENTRANCY) {
-+ ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
-+ bt = &lt->backtrace[lt->reentrancy];
-+ }
- ast_reentrancy_unlock(lt);
- ast_store_lock_info(AST_RDLOCK, filename, line, func, name, t, bt);
- #else
-@@ -1220,9 +1218,6 @@
- lt->func[lt->reentrancy] = func;
- lt->thread[lt->reentrancy] = pthread_self();
- lt->reentrancy++;
-- } else {
-- __ast_mutex_logger("%s line %d (%s): read lock '%s' really deep reentrancy!\n",
-- filename, line, func, name);
- }
- ast_reentrancy_unlock(lt);
- if (t->tracking) {
-@@ -1280,8 +1275,10 @@
- if (t->tracking) {
- #ifdef HAVE_BKTR
- ast_reentrancy_lock(lt);
-- ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
-- bt = &lt->backtrace[lt->reentrancy];
-+ if (lt->reentrancy != AST_MAX_REENTRANCY) {
-+ ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
-+ bt = &lt->backtrace[lt->reentrancy];
-+ }
- ast_reentrancy_unlock(lt);
- ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t, bt);
- #else
-@@ -1328,9 +1325,6 @@
- lt->func[lt->reentrancy] = func;
- lt->thread[lt->reentrancy] = pthread_self();
- lt->reentrancy++;
-- } else {
-- __ast_mutex_logger("%s line %d (%s): write lock '%s' really deep reentrancy!\n",
-- filename, line, func, name);
- }
- ast_reentrancy_unlock(lt);
- if (t->tracking) {
-@@ -1364,7 +1358,6 @@
- {
- int res;
- struct ast_lock_track *lt = &t->track;
-- int canlog = strcmp(filename, "logger.c") & t->tracking;
- #ifdef HAVE_BKTR
- struct ast_bt *bt = NULL;
- #endif
-@@ -1388,8 +1381,10 @@
- if (t->tracking) {
- #ifdef HAVE_BKTR
- ast_reentrancy_lock(lt);
-- ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
-- bt = &lt->backtrace[lt->reentrancy];
-+ if (lt->reentrancy != AST_MAX_REENTRANCY) {
-+ ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
-+ bt = &lt->backtrace[lt->reentrancy];
-+ }
- ast_reentrancy_unlock(lt);
- ast_store_lock_info(AST_RDLOCK, filename, line, func, name, t, bt);
- #else
-@@ -1405,9 +1400,6 @@
- lt->func[lt->reentrancy] = func;
- lt->thread[lt->reentrancy] = pthread_self();
- lt->reentrancy++;
-- } else {
-- __ast_mutex_logger("%s line %d (%s): read lock '%s' really deep reentrancy!\n",
-- filename, line, func, name);
- }
- ast_reentrancy_unlock(lt);
- if (t->tracking) {
-@@ -1424,7 +1416,6 @@
- {
- int res;
- struct ast_lock_track *lt= &t->track;
-- int canlog = strcmp(filename, "logger.c") & t->tracking;
- #ifdef HAVE_BKTR
- struct ast_bt *bt = NULL;
- #endif
-@@ -1448,8 +1439,10 @@
- if (t->tracking) {
- #ifdef HAVE_BKTR
- ast_reentrancy_lock(lt);
-- ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
-- bt = &lt->backtrace[lt->reentrancy];
-+ if (lt->reentrancy != AST_MAX_REENTRANCY) {
-+ ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
-+ bt = &lt->backtrace[lt->reentrancy];
-+ }
- ast_reentrancy_unlock(lt);
- ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t, bt);
- #else
-@@ -1465,9 +1458,6 @@
- lt->func[lt->reentrancy] = func;
- lt->thread[lt->reentrancy] = pthread_self();
- lt->reentrancy++;
-- } else {
-- __ast_mutex_logger("%s line %d (%s): write lock '%s' really deep reentrancy!\n",
-- filename, line, func, name);
- }
- ast_reentrancy_unlock(lt);
- if (t->tracking) {
-Index: include/asterisk/pbx.h
-===================================================================
---- a/include/asterisk/pbx.h (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/include/asterisk/pbx.h (.../trunk) (revision 186562)
-@@ -37,12 +37,13 @@
- #define AST_PBX_KEEP 0
- #define AST_PBX_REPLACE 1
-
--/*! \brief Special return values from applications to the PBX { */
-+/*! \brief Special return values from applications to the PBX
-+ * @{ */
- #define AST_PBX_HANGUP -1 /*!< Jump to the 'h' exten */
- #define AST_PBX_OK 0 /*!< No errors */
- #define AST_PBX_ERROR 1 /*!< Jump to the 'e' exten */
- #define AST_PBX_INCOMPLETE 12 /*!< Return to PBX matching, allowing more digits for the extension */
--/*! } */
-+/*! @} */
-
- #define PRIORITY_HINT -1 /*!< Special Priority for a hint */
-
-@@ -134,7 +135,8 @@
-
- /*!\brief Deallocates memory structures associated with a timing bitmap.
- * \param i Pointer to an ast_timing structure.
-- * \retval Returns 0 on success or a number suitable for passing into strerror, otherwise.
-+ * \retval 0 success
-+ * \retval non-zero failure (number suitable to pass to \see strerror)
- */
- int ast_destroy_timing(struct ast_timing *i);
-
-@@ -152,7 +154,8 @@
- * This function registers a populated ast_switch structure with the
- * asterisk switching architecture.
- *
-- * \return 0 on success, and other than 0 on failure
-+ * \retval 0 success
-+ * \retval non-zero failure
- */
- int ast_register_switch(struct ast_switch *sw);
-
-@@ -191,7 +194,8 @@
- * saves the stack and executes the given application passing in
- * the given data.
- *
-- * \return 0 on success, and -1 on failure
-+ * \retval 0 success
-+ * \retval -1 failure
- */
- int pbx_exec(struct ast_channel *c, struct ast_app *app, void *data);
-
-@@ -251,7 +255,7 @@
- */
- struct ast_context *ast_context_find(const char *name);
-
--/*! \brief The result codes when starting the PBX on a channelwith \see ast_pbx_start.
-+/*! \brief The result codes when starting the PBX on a channel with \see ast_pbx_start.
- AST_PBX_CALL_LIMIT refers to the maxcalls call limit in asterisk.conf
- */
- enum ast_pbx_result {
-@@ -403,18 +407,18 @@
- * \brief If an extension hint exists, return non-zero
- *
- * \param hint buffer for hint
-- * \param maxlen size of hint buffer
-+ * \param hintsize size of hint buffer, in bytes
- * \param name buffer for name portion of hint
-- * \param maxnamelen size of name buffer
-- * \param c this is not important
-+ * \param namesize size of name buffer
-+ * \param c Channel from which to return the hint. This is only important when the hint or name contains an expression to be expanded.
- * \param context which context to look in
- * \param exten which extension to search for
- *
- * \return If an extension within the given context with the priority PRIORITY_HINT
-- * is found a non zero value will be returned.
-+ * is found, a non zero value will be returned.
- * Otherwise, 0 is returned.
- */
--int ast_get_hint(char *hint, int maxlen, char *name, int maxnamelen,
-+int ast_get_hint(char *hint, int hintsize, char *name, int namesize,
- struct ast_channel *c, const char *context, const char *exten);
-
- /*!
-@@ -679,6 +683,8 @@
- *
- * \retval 0 on success
- * \retval -1 on failure
-+ *
-+ * @{
- */
- int ast_context_remove_extension(const char *context, const char *extension, int priority,
- const char *registrar);
-@@ -692,6 +698,7 @@
- int ast_context_remove_extension_callerid2(struct ast_context *con, const char *extension,
- int priority, const char *callerid, int matchcid, const char *registrar,
- int already_locked);
-+/*! @} */
-
- /*!
- * \brief Add an ignorepat
-@@ -818,8 +825,13 @@
- */
- int ast_context_unlockmacro(const char *macrocontext);
-
-+/*!\brief Set the channel to next execute the specified dialplan location.
-+ * \see ast_async_parseable_goto, ast_async_goto_if_exists
-+ */
- int ast_async_goto(struct ast_channel *chan, const char *context, const char *exten, int priority);
-
-+/*!\brief Set the channel to next execute the specified dialplan location.
-+ */
- int ast_async_goto_by_name(const char *chan, const char *context, const char *exten, int priority);
-
- /*! Synchronously or asynchronously make an outbound call and send it to a
-@@ -873,7 +885,8 @@
- const char *ast_get_switch_registrar(struct ast_sw *sw);
- /*! @} */
-
--/* Walking functions ... */
-+/*! @name Walking functions ... */
-+/*! @{ */
- struct ast_context *ast_walk_contexts(struct ast_context *con);
- struct ast_exten *ast_walk_context_extensions(struct ast_context *con,
- struct ast_exten *priority);
-@@ -884,13 +897,16 @@
- struct ast_ignorepat *ast_walk_context_ignorepats(struct ast_context *con,
- struct ast_ignorepat *ip);
- struct ast_sw *ast_walk_context_switches(struct ast_context *con, struct ast_sw *sw);
-+/*! @} */
-
--/*!
-+/*!\brief Create a human-readable string, specifying all variables and their corresponding values.
-+ * \param chan Channel from which to read variables
-+ * \param buf Dynamic string in which to place the result (should be allocated with \see ast_str_create).
- * \note Will lock the channel.
- */
- int pbx_builtin_serialize_variables(struct ast_channel *chan, struct ast_str **buf);
-
--/*!
-+/*!\brief Return a pointer to the value of the corresponding channel variable.
- * \note Will lock the channel.
- *
- * \note This function will return a pointer to the buffer inside the channel
-@@ -909,43 +925,51 @@
- */
- const char *pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name);
-
--/*!
-+/*!\brief Add a variable to the channel variable stack, without removing any previously set value.
- * \note Will lock the channel.
- */
- void pbx_builtin_pushvar_helper(struct ast_channel *chan, const char *name, const char *value);
-
--/*!
-- * \note Will lock the channel.
-+/*!\brief Add a variable to the channel variable stack, removing the most recently set value for the same name.
-+ * \note Will lock the channel. May also be used to set a channel dialplan function to a particular value.
-+ * \see ast_func_write
- */
- void pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value);
-
--/*!
-+/*!\brief Retrieve the value of a builtin variable or variable from the channel variable stack.
- * \note Will lock the channel.
- */
- void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp);
- void pbx_builtin_clear_globals(void);
-
--/*!
-+/*!\brief Parse and set a single channel variable, where the name and value are separated with an '=' character.
- * \note Will lock the channel.
- */
- int pbx_builtin_setvar(struct ast_channel *chan, void *data);
-+
-+/*!\brief Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character.
-+ * \note Will lock the channel.
-+ */
- int pbx_builtin_setvar_multiple(struct ast_channel *chan, void *data);
-
- int pbx_builtin_raise_exception(struct ast_channel *chan, void *data);
-
--void pbx_substitute_variables_helper(struct ast_channel *c,const char *cp1,char *cp2,int count);
-+/*! @name Substitution routines, using static string buffers
-+ * @{ */
-+void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count);
- void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count);
- void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int cp2_size, size_t *used);
- void ast_str_substitute_variables(struct ast_str **buf, size_t maxlen, struct ast_channel *chan, const char *templ);
-+/*! @} */
-
- int ast_extension_patmatch(const char *pattern, const char *data);
-
--/*! Set "autofallthrough" flag, if newval is <0, does not acutally set. If
-+/*! Set "autofallthrough" flag, if newval is <0, does not actually set. If
- set to 1, sets to auto fall through. If newval set to 0, sets to no auto
- fall through (reads extension instead). Returns previous value. */
- int pbx_set_autofallthrough(int newval);
-
--/*! Set "extenpatternmatchnew" flag, if newval is <0, does not acutally set. If
-+/*! Set "extenpatternmatchnew" flag, if newval is <0, does not actually set. If
- set to 1, sets to use the new Trie-based pattern matcher. If newval set to 0, sets to use
- the old linear-search algorithm. Returns previous value. */
- int pbx_set_extenpatternmatchnew(int newval);
-@@ -963,10 +987,6 @@
- int ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority);
-
- /*!
-- * \note I can find neither parsable nor parseable at dictionary.com,
-- * but google gives me 169000 hits for parseable and only 49,800
-- * for parsable
-- *
- * \note This function will handle locking the channel as needed.
- */
- int ast_parseable_goto(struct ast_channel *chan, const char *goto_string);
-@@ -1023,7 +1043,8 @@
- *
- * This application executes a function in read mode on a given channel.
- *
-- * \return zero on success, non-zero on failure
-+ * \retval 0 success
-+ * \retval non-zero failure
- */
- int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len);
-
-@@ -1036,7 +1057,8 @@
- *
- * This application executes a function in write mode on a given channel.
- *
-- * \return zero on success, non-zero on failure
-+ * \retval 0 success
-+ * \retval non-zero failure
- */
- int ast_func_write(struct ast_channel *chan, const char *function, const char *value);
-
-@@ -1092,9 +1114,11 @@
- int ast_wrlock_contexts_version(void);
-
-
--/* hashtable functions for contexts */
-+/*!\brief hashtable functions for contexts */
-+/*! @{ */
- int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b);
- unsigned int ast_hashtab_hash_contexts(const void *obj);
-+/*! @} */
-
- #if defined(__cplusplus) || defined(c_plusplus)
- }
-Index: include/asterisk/strings.h
-===================================================================
---- a/include/asterisk/strings.h (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/include/asterisk/strings.h (.../trunk) (revision 186562)
-@@ -451,7 +451,7 @@
- )
-
- /*!\brief Returns the current length of the string stored within buf.
-- * \param A pointer to the ast_str string.
-+ * \param buf A pointer to the ast_str structure.
- */
- AST_INLINE_API(
- size_t attribute_pure ast_str_strlen(struct ast_str *buf),
-@@ -461,7 +461,8 @@
- )
-
- /*!\brief Returns the current maximum length (without reallocation) of the current buffer.
-- * \param A pointer to the ast_str string.
-+ * \param buf A pointer to the ast_str structure.
-+ * \retval Current maximum length of the buffer.
- */
- AST_INLINE_API(
- size_t attribute_pure ast_str_size(struct ast_str *buf),
-@@ -471,7 +472,8 @@
- )
-
- /*!\brief Returns the string buffer within the ast_str buf.
-- * \param A pointer to the ast_str string.
-+ * \param buf A pointer to the ast_str structure.
-+ * \retval A pointer to the enclosed string.
- */
- AST_INLINE_API(
- char * attribute_pure ast_str_buffer(struct ast_str *buf),
-@@ -480,6 +482,11 @@
- }
- )
-
-+/*!\brief Truncates the enclosed string to the given length.
-+ * \param buf A pointer to the ast_str structure.
-+ * \param len Maximum length of the string.
-+ * \retval A pointer to the resulting string.
-+ */
- AST_INLINE_API(
- char *ast_str_truncate(struct ast_str *buf, ssize_t len),
- {
-@@ -852,6 +859,29 @@
- }
-
- /*!
-+ * \brief Compute a hash value on a string
-+ *
-+ * \param[in] str The string to add to the hash
-+ * \param[in] hash The hash value to add to
-+ *
-+ * \details
-+ * This version of the function is for when you need to compute a
-+ * string hash of more than one string.
-+ *
-+ * This famous hash algorithm was written by Dan Bernstein and is
-+ * commonly used.
-+ *
-+ * \sa http://www.cse.yorku.ca/~oz/hash.html
-+ */
-+static force_inline int ast_str_hash_add(const char *str, int hash)
-+{
-+ while (*str)
-+ hash = hash * 33 ^ *str++;
-+
-+ return abs(hash);
-+}
-+
-+/*!
- * \brief Compute a hash value on a case-insensitive string
- *
- * Uses the same hash algorithm as ast_str_hash, but converts
-Index: include/asterisk/stun.h
-===================================================================
---- a/include/asterisk/stun.h (.../tags/1.6.2.0-beta1) (revision 0)
-+++ b/include/asterisk/stun.h (.../trunk) (revision 186562)
-@@ -0,0 +1,71 @@
-+/*
-+ * Asterisk -- An open source telephony toolkit.
-+ *
-+ * Copyright (C) 1999 - 2008, Digium, Inc.
-+ *
-+ * Mark Spencer <markster@digium.com>
-+ *
-+ * See http://www.asterisk.org for more information about
-+ * the Asterisk project. Please do not directly contact
-+ * any of the maintainers of this project for assistance;
-+ * the project provides a web site, mailing lists and IRC
-+ * channels for your use.
-+ *
-+ * 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.
-+ */
-+
-+/*!
-+ * \file stun.h
-+ * \brief STUN support.
-+ *
-+ * STUN is defined in RFC 3489.
-+ */
-+
-+#ifndef _ASTERISK_STUN_H
-+#define _ASTERISK_STUN_H
-+
-+#include "asterisk/network.h"
-+
-+#if defined(__cplusplus) || defined(c_plusplus)
-+extern "C" {
-+#endif
-+
-+enum ast_stun_result {
-+ AST_STUN_IGNORE = 0,
-+ AST_STUN_ACCEPT,
-+};
-+
-+struct stun_attr;
-+
-+/*! \brief Generic STUN request
-+ * send a generic stun request to the server specified.
-+ * \param s the socket used to send the request
-+ * \param dst the address of the STUN server
-+ * \param username if non null, add the username in the request
-+ * \param answer if non null, the function waits for a response and
-+ * puts here the externally visible address.
-+ * \return 0 on success, other values on error.
-+ * The interface it may change in the future.
-+ */
-+int ast_stun_request(int s, struct sockaddr_in *dst, const char *username, struct sockaddr_in *answer);
-+
-+/*! \brief callback type to be invoked on stun responses. */
-+typedef int (stun_cb_f)(struct stun_attr *attr, void *arg);
-+
-+/*! \brief handle an incoming STUN message.
-+ *
-+ * Do some basic sanity checks on packet size and content,
-+ * try to extract a bit of information, and possibly reply.
-+ * At the moment this only processes BIND requests, and returns
-+ * the externally visible address of the request.
-+ * If a callback is specified, invoke it with the attribute.
-+ */
-+int ast_stun_handle_packet(int s, struct sockaddr_in *src, unsigned char *data, size_t len, stun_cb_f *stun_cb, void *arg);
-+
-+#if defined(__cplusplus) || defined(c_plusplus)
-+}
-+#endif
-+
-+#endif /* _ASTERISK_STUN_H */
-
-Property changes on: include/asterisk/stun.h
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + Author Date Id Revision
-
-Index: include/asterisk/stringfields.h
-===================================================================
---- a/include/asterisk/stringfields.h (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/include/asterisk/stringfields.h (.../trunk) (revision 186562)
-@@ -57,25 +57,23 @@
-
- Fields will default to pointing to an empty string, and will revert to
- that when ast_string_field_set() is called with a NULL argument.
-- A string field will \b never contain NULL (this feature is not used
-- in this code, but comes from external requirements).
-+ A string field will \b never contain NULL.
-
- ast_string_field_init(x, 0) will reset fields to the
- initial value while keeping the pool allocated.
-
- Reading the fields is much like using 'const char * const' fields in the
-- structure: you cannot write to the field or to the memory it points to
-- (XXX perhaps the latter is too much of a restriction since values
-- are not shared).
-+ structure: you cannot write to the field or to the memory it points to.
-
- Writing to the fields must be done using the wrapper macros listed below;
- and assignments are always by value (i.e. strings are copied):
- * ast_string_field_set() stores a simple value;
-- * ast_string_field_build() builds the string using a printf-style;
-+ * ast_string_field_build() builds the string using a printf-style format;
- * ast_string_field_build_va() is the varargs version of the above (for
-- portability reasons it uses two vararg);
-+ portability reasons it uses two vararg arguments);
- * variants of these function allow passing a pointer to the field
- as an argument.
-+
- \code
- ast_string_field_set(x, foo, "infinite loop");
- ast_string_field_set(x, foo, NULL); // set to an empty string
-@@ -110,6 +108,9 @@
-
- Don't declare instances of this type directly; use the AST_STRING_FIELD()
- macro instead.
-+
-+ In addition to the string itself, the amount of space allocated for the
-+ field is stored in the two bytes immediately preceding it.
- */
- typedef const char * ast_string_field;
-
-@@ -117,7 +118,7 @@
- \internal
- \brief A constant empty string used for fields that have no other value
- */
--extern const char __ast_string_field_empty[];
-+extern const char *__ast_string_field_empty;
-
- /*!
- \internal
-@@ -125,18 +126,17 @@
- */
- struct ast_string_field_pool {
- struct ast_string_field_pool *prev; /*!< pointer to the previous pool, if any */
-+ size_t size; /*!< the total size of the pool */
-+ size_t used; /*!< the space used in the pool */
-+ size_t active; /*!< the amount of space actively in use by fields */
- char base[0]; /*!< storage space for the fields */
- };
-
- /*!
- \internal
- \brief Structure used to manage the storage for a set of string fields.
-- Because of the way pools are managed, we can only allocate from the topmost
-- pool, so the numbers here reflect just that.
- */
- struct ast_string_field_mgr {
-- size_t size; /*!< the total size of the current pool */
-- size_t used; /*!< the space used in the current pool */
- ast_string_field last_alloc; /*!< the last field allocated */
- };
-
-@@ -154,7 +154,8 @@
- the pool has enough space available. If so, the additional space will be
- allocated to this field and the field's address will not be changed.
- */
--int __ast_string_field_ptr_grow(struct ast_string_field_mgr *mgr, size_t needed,
-+int __ast_string_field_ptr_grow(struct ast_string_field_mgr *mgr,
-+ struct ast_string_field_pool **pool_head, size_t needed,
- const ast_string_field *ptr);
-
- /*!
-@@ -176,7 +177,7 @@
- \internal
- \brief Set a field to a complex (built) value
- \param mgr Pointer to the pool manager structure
-- \param fields Pointer to the first entry of the field array
-+ \param pool_head Pointer to the current pool
- \param ptr Pointer to a field within the structure
- \param format printf-style format string
- \return nothing
-@@ -189,7 +190,7 @@
- \internal
- \brief Set a field to a complex (built) value
- \param mgr Pointer to the pool manager structure
-- \param fields Pointer to the first entry of the field array
-+ \param pool_head Pointer to the current pool
- \param ptr Pointer to a field within the structure
- \param format printf-style format string
- \param args va_list of the args for the format_string
-@@ -242,29 +243,55 @@
-
- /*! \internal \brief internal version of ast_string_field_init */
- int __ast_string_field_init(struct ast_string_field_mgr *mgr,
-- struct ast_string_field_pool **pool_head, int needed);
-+ struct ast_string_field_pool **pool_head, int needed);
-
- /*!
-+ \internal
-+ \brief Release a field's allocation from a pool
-+ \param pool_head Pointer to the current pool
-+ \param ptr Field to be released
-+ \return nothing
-+
-+ This function will search the pool list to find the pool that contains
-+ the allocation for the specified field, then remove the field's allocation
-+ from that pool's 'active' count. If the pool's active count reaches zero,
-+ and it is not the current pool, then it will be freed.
-+ */
-+void __ast_string_field_release_active(struct ast_string_field_pool *pool_head,
-+ const ast_string_field ptr);
-+
-+/* the type of storage used to track how many bytes were allocated for a field */
-+
-+typedef uint16_t ast_string_field_allocation;
-+
-+/*!
-+ \brief Macro to provide access to the allocation field that lives immediately in front of a string field
-+ \param x Pointer to the string field
-+*/
-+#define AST_STRING_FIELD_ALLOCATION(x) *((ast_string_field_allocation *) (x - sizeof(ast_string_field_allocation)))
-+
-+/*!
- \brief Set a field to a simple string value
- \param x Pointer to a structure containing fields
- \param ptr Pointer to a field within the structure
-- \param data String value to be copied into the field
-+ \param data String value to be copied into the field
- \return nothing
- */
--#define ast_string_field_ptr_set(x, ptr, data) do { \
-- const char *__d__ = (data); \
-- size_t __dlen__ = (__d__) ? strlen(__d__) + 1 : 1; \
-- const char **__p__ = (const char **) (ptr); \
-- char *__q__; \
-- if (__dlen__ == 1) \
-- *__p__ = __ast_string_field_empty; \
-- else if (!__ast_string_field_ptr_grow(&(x)->__field_mgr, __dlen__, ptr)) { \
-- __q__ = (char *) *__p__; \
-- memcpy(__q__, __d__, __dlen__); \
-- } else if ((*__p__ = __ast_string_field_alloc_space(&(x)->__field_mgr, &(x)->__field_mgr_pool, __dlen__))) { \
-- __q__ = (char *) *__p__; \
-- memcpy(__q__, __d__, __dlen__); \
-- } \
-+#define ast_string_field_ptr_set(x, ptr, data) do { \
-+ const char *__d__ = (data); \
-+ size_t __dlen__ = (__d__) ? strlen(__d__) + 1 : 1; \
-+ ast_string_field *__p__ = (ast_string_field *) (ptr); \
-+ if (__dlen__ == 1) { \
-+ __ast_string_field_release_active((x)->__field_mgr_pool, *__p__); \
-+ *__p__ = __ast_string_field_empty; \
-+ } else if ((__dlen__ <= AST_STRING_FIELD_ALLOCATION(*__p__)) || \
-+ (!__ast_string_field_ptr_grow(&(x)->__field_mgr, &(x)->__field_mgr_pool, __dlen__, __p__)) || \
-+ (*__p__ = __ast_string_field_alloc_space(&(x)->__field_mgr, &(x)->__field_mgr_pool, __dlen__))) { \
-+ if (*__p__ != (*ptr)) { \
-+ __ast_string_field_release_active((x)->__field_mgr_pool, (*ptr)); \
-+ } \
-+ memcpy(* (void **) __p__, __d__, __dlen__); \
-+ } \
- } while (0)
-
- /*!
-Index: include/asterisk/autoconfig.h.in
-===================================================================
---- a/include/asterisk/autoconfig.h.in (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/include/asterisk/autoconfig.h.in (.../trunk) (revision 186562)
-@@ -767,12 +767,6 @@
- /* Define to indicate the ${ROUND_DESCRIP} library version */
- #undef HAVE_ROUND_VERSION
-
--/* Define if your system has the RTLD_NOLOAD headers. */
--#undef HAVE_RTLD_NOLOAD
--
--/* Define RTLD_NOLOAD headers version */
--#undef HAVE_RTLD_NOLOAD_VERSION
--
- /* Define to 1 if your system has /sbin/launchd. */
- #undef HAVE_SBIN_LAUNCHD
-
-Index: include/asterisk/callerid.h
-===================================================================
---- a/include/asterisk/callerid.h (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/include/asterisk/callerid.h (.../trunk) (revision 186562)
-@@ -86,21 +86,24 @@
- void callerid_init(void);
-
- /*! \brief Generates a CallerID FSK stream in ulaw format suitable for transmission.
-- * \param buf Buffer to use. If "buf" is supplied, it will use that buffer instead of allocating its own. "buf" must be at least 32000 bytes in size of you want to be sure you don't have an overrun.
-+ * \param buf Buffer to use. If "buf" is supplied, it will use that buffer instead of allocating its own.
-+ * "buf" must be at least 32000 bytes in size of you want to be sure you don't have an overrun.
- * \param number Use NULL for no number or "P" for "private"
- * \param name name to be used
- * \param flags passed flags
- * \param callwaiting callwaiting flag
- * \param codec -- either AST_FORMAT_ULAW or AST_FORMAT_ALAW
-+ * \details
- * This function creates a stream of callerid (a callerid spill) data in ulaw format.
- * \return It returns the size
- * (in bytes) of the data (if it returns a size of 0, there is probably an error)
--*/
-+ */
- int callerid_generate(unsigned char *buf, const char *number, const char *name, int flags, int callwaiting, int codec);
-
- /*! \brief Create a callerID state machine
- * \param cid_signalling Type of signalling in use
- *
-+ * \details
- * This function returns a malloc'd instance of the callerid_state data structure.
- * \return Returns a pointer to a malloc'd callerid_state structure, or NULL on error.
- */
-@@ -112,9 +115,11 @@
- * \param samples number of samples contained within the buffer.
- * \param codec which codec (AST_FORMAT_ALAW or AST_FORMAT_ULAW)
- *
-+ * \details
- * Send received audio to the Caller*ID demodulator.
-- * \return Returns -1 on error, 0 for "needs more samples",
-- * and 1 if the CallerID spill reception is complete.
-+ * \retval -1 on error
-+ * \retval 0 for "needs more samples"
-+ * \retval 1 if the CallerID spill reception is complete.
- */
- int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int samples, int codec);
-
-@@ -124,9 +129,11 @@
- * \param samples number of samples contained within the buffer.
- * \param codec which codec (AST_FORMAT_ALAW or AST_FORMAT_ULAW)
- *
-+ * \details
- * Send received audio to the Caller*ID demodulator (for japanese style lines).
-- * \return Returns -1 on error, 0 for "needs more samples",
-- * and 1 if the CallerID spill reception is complete.
-+ * \retval -1 on error
-+ * \retval 0 for "needs more samples"
-+ * \retval 1 if the CallerID spill reception is complete.
- */
- int callerid_feed_jp(struct callerid_state *cid, unsigned char *ubuf, int samples, int codec);
-
-@@ -136,6 +143,7 @@
- * \param name Pass the address of a pointer-to-char (will contain the name)
- * \param flags Pass the address of an int variable(will contain the various callerid flags)
- *
-+ * \details
- * This function extracts a callerid string out of a callerid_state state machine.
- * If no number is found, *number will be set to NULL. Likewise for the name.
- * Flags can contain any of the following:
-@@ -144,18 +152,16 @@
- */
- void callerid_get(struct callerid_state *cid, char **number, char **name, int *flags);
-
--/*! Get and parse DTMF-based callerid */
- /*!
-+ * \brief Get and parse DTMF-based callerid
- * \param cidstring The actual transmitted string.
- * \param number The cid number is returned here.
- * \param flags The cid flags are returned here.
-- * This function parses DTMF callerid.
- */
- void callerid_get_dtmf(char *cidstring, char *number, int *flags);
-
--/*! \brief Free a callerID state
-+/*! \brief This function frees callerid_state cid.
- * \param cid This is the callerid_state state machine to free
-- * This function frees callerid_state cid.
- */
- void callerid_free(struct callerid_state *cid);
-
-@@ -165,36 +171,44 @@
- * \param number Caller-ID Number
- * \param codec Asterisk codec (either AST_FORMAT_ALAW or AST_FORMAT_ULAW)
- *
-+ * \details
- * Acts like callerid_generate except uses an asterisk format callerid string.
- */
- int ast_callerid_generate(unsigned char *buf, const char *name, const char *number, int codec);
-
--/*! \brief Generate message waiting indicator
-- * \param active The message indicator state
-+/*!
-+ * \brief Generate message waiting indicator
-+ * \param active The message indicator state
- * -- either 0 no messages in mailbox or 1 messages in mailbox
-- * \param type Format of message (any of CID_MWI_TYPE_*)
-- * \see callerid_generate() for more info as it use the same encoding
-- * \version 1.6.1 changed mdmf parameter to type, added name, number and flags for caller id message generation
--*/
--int vmwi_generate(unsigned char *buf, int active, int type, int codec, const char *name,
-+ * \param type Format of message (any of CID_MWI_TYPE_*)
-+ * \see callerid_generate() for more info as it uses the same encoding
-+ * \version 1.6.1 changed mdmf parameter to type, added name, number and flags for caller id message generation
-+ */
-+int ast_callerid_vmwi_generate(unsigned char *buf, int active, int type, int codec, const char *name,
- const char *number, int flags);
-
- /*! \brief Generate Caller-ID spill but in a format suitable for Call Waiting(tm)'s Caller*ID(tm)
-- * See ast_callerid_generate() for other details
-+ * \see ast_callerid_generate() for other details
- */
- int ast_callerid_callwaiting_generate(unsigned char *buf, const char *name, const char *number, int codec);
-
- /*! \brief Destructively parse inbuf into name and location (or number)
-+ * \details
- * Parses callerid stream from inbuf and changes into useable form, outputed in name and location.
- * \param instr buffer of callerid stream (in audio form) to be parsed. Warning, data in buffer is changed.
- * \param name address of a pointer-to-char for the name value of the stream.
- * \param location address of a pointer-to-char for the phone number value of the stream.
-+ * \note XXX 'name' is not parsed consistently e.g. we have
-+ * input location name
-+ * " foo bar " <123> 123 ' foo bar ' (with spaces around)
-+ * " foo bar " NULL 'foo bar' (without spaces around)
-+ * The parsing of leading and trailing space/quotes should be more consistent.
- * \return Returns 0 on success, -1 on failure.
- */
- int ast_callerid_parse(char *instr, char **name, char **location);
-
--/*! Generate a CAS (CPE Alert Signal) tone for 'n' samples */
- /*!
-+ * \brief Generate a CAS (CPE Alert Signal) tone for 'n' samples
- * \param outbuf Allocated buffer for data. Must be at least 2400 bytes unless no SAS is desired
- * \param sas Non-zero if CAS should be preceeded by SAS
- * \param len How many samples to generate.
-@@ -203,23 +217,26 @@
- */
- int ast_gen_cas(unsigned char *outbuf, int sas, int len, int codec);
-
--/*! \brief Shrink a phone number in place to just digits (more accurately it just removes ()'s, .'s, and -'s... */
- /*!
-+ * \brief Shrink a phone number in place to just digits (more accurately it just removes ()'s, .'s, and -'s...
- * \param n The number to be stripped/shrunk
- * \return Returns nothing important
- */
- void ast_shrink_phone_number(char *n);
-
--/*! \brief Check if a string consists only of digits and + \#
-- \param n number to be checked.
-- \return Returns 0 if n is a number, 1 if it's not.
-+/*!
-+ * \brief Check if a string consists only of digits and + \#
-+ * \param n number to be checked.
-+ * \return Returns 0 if n is a number, 1 if it's not.
- */
- int ast_isphonenumber(const char *n);
-
--/*! \brief Check if a string consists only of digits and and + \# ( ) - .
-- (meaning it can be cleaned with ast_shrink_phone_number)
-- \param exten The extension (or URI) to be checked.
-- \return Returns 0 if n is a number, 1 if it's not.
-+/*!
-+ * \brief Check if a string consists only of digits and and + \# ( ) - .
-+ * (meaning it can be cleaned with ast_shrink_phone_number)
-+ * \param exten The extension (or URI) to be checked.
-+ * \retval 1 if string is valid AST shrinkable phone number
-+ * \retval 0 if not
- */
- int ast_is_shrinkable_phonenumber(const char *exten);
-
-@@ -289,71 +306,171 @@
-
- /* Various defines and bits for handling PRI- and SS7-type restriction */
-
--#define AST_PRES_NUMBER_TYPE 0x03
-+#define AST_PRES_NUMBER_TYPE 0x03
- #define AST_PRES_USER_NUMBER_UNSCREENED 0x00
- #define AST_PRES_USER_NUMBER_PASSED_SCREEN 0x01
- #define AST_PRES_USER_NUMBER_FAILED_SCREEN 0x02
--#define AST_PRES_NETWORK_NUMBER 0x03
-+#define AST_PRES_NETWORK_NUMBER 0x03
-
--#define AST_PRES_RESTRICTION 0x60
--#define AST_PRES_ALLOWED 0x00
--#define AST_PRES_RESTRICTED 0x20
--#define AST_PRES_UNAVAILABLE 0x40
--#define AST_PRES_RESERVED 0x60
-+#define AST_PRES_RESTRICTION 0x60
-+#define AST_PRES_ALLOWED 0x00
-+#define AST_PRES_RESTRICTED 0x20
-+#define AST_PRES_UNAVAILABLE 0x40
-+#define AST_PRES_RESERVED 0x60
-
- #define AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED \
-- AST_PRES_USER_NUMBER_UNSCREENED + AST_PRES_ALLOWED
-+ (AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_UNSCREENED)
-
- #define AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN \
-- AST_PRES_USER_NUMBER_PASSED_SCREEN + AST_PRES_ALLOWED
-+ (AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_PASSED_SCREEN)
-
- #define AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN \
-- AST_PRES_USER_NUMBER_FAILED_SCREEN + AST_PRES_ALLOWED
-+ (AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_FAILED_SCREEN)
-
- #define AST_PRES_ALLOWED_NETWORK_NUMBER \
-- AST_PRES_NETWORK_NUMBER + AST_PRES_ALLOWED
-+ (AST_PRES_ALLOWED | AST_PRES_NETWORK_NUMBER)
-
- #define AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED \
-- AST_PRES_USER_NUMBER_UNSCREENED + AST_PRES_RESTRICTED
-+ (AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_UNSCREENED)
-
- #define AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN \
-- AST_PRES_USER_NUMBER_PASSED_SCREEN + AST_PRES_RESTRICTED
-+ (AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_PASSED_SCREEN)
-
- #define AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN \
-- AST_PRES_USER_NUMBER_FAILED_SCREEN + AST_PRES_RESTRICTED
-+ (AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_FAILED_SCREEN)
-
- #define AST_PRES_PROHIB_NETWORK_NUMBER \
-- AST_PRES_NETWORK_NUMBER + AST_PRES_RESTRICTED
-+ (AST_PRES_RESTRICTED | AST_PRES_NETWORK_NUMBER)
-
- #define AST_PRES_NUMBER_NOT_AVAILABLE \
-- AST_PRES_NETWORK_NUMBER + AST_PRES_UNAVAILABLE
-+ (AST_PRES_UNAVAILABLE | AST_PRES_NETWORK_NUMBER)
-
- int ast_parse_caller_presentation(const char *data);
- const char *ast_describe_caller_presentation(int data);
- const char *ast_named_caller_presentation(int data);
-
--/*! \page Def_CallerPres Caller ID Presentation
-+/*!
-+ * \page Def_CallerPres Caller ID Presentation
-+ *
-+ * Caller ID presentation values are used to set properties to a
-+ * caller ID in PSTN networks, and as RPID value in SIP transactions.
-+ *
-+ * The following values are available to use:
-+ * \arg \b Defined value, text string in config file, explanation
-+ *
-+ * \arg \b AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, "allowed_not_screened", Presentation Allowed, Not Screened,
-+ * \arg \b AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, "allowed_passed_screen", Presentation Allowed, Passed Screen,
-+ * \arg \b AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN, "allowed_failed_screen", Presentation Allowed, Failed Screen,
-+ * \arg \b AST_PRES_ALLOWED_NETWORK_NUMBER, "allowed", Presentation Allowed, Network Number,
-+ * \arg \b AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED, "prohib_not_screened", Presentation Prohibited, Not Screened,
-+ * \arg \b AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN, "prohib_passed_screen", Presentation Prohibited, Passed Screen,
-+ * \arg \b AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN, "prohib_failed_screen", Presentation Prohibited, Failed Screen,
-+ * \arg \b AST_PRES_PROHIB_NETWORK_NUMBER, "prohib", Presentation Prohibited, Network Number,
-+ *
-+ * \par References
-+ * \arg \ref callerid.h Definitions
-+ * \arg \ref callerid.c Functions
-+ * \arg \ref CID Caller ID names and numbers
-+ */
-
-- Caller ID presentation values are used to set properties to a
-- caller ID in PSTN networks, and as RPID value in SIP transactions.
-+/*!
-+ * \brief redirecting reason codes.
-+ *
-+ * This list attempts to encompass redirecting reasons
-+ * as defined by several channel technologies.
-+ */
-+enum AST_REDIRECTING_REASON {
-+ AST_REDIRECTING_REASON_UNKNOWN,
-+ AST_REDIRECTING_REASON_USER_BUSY,
-+ AST_REDIRECTING_REASON_NO_ANSWER,
-+ AST_REDIRECTING_REASON_UNAVAILABLE,
-+ AST_REDIRECTING_REASON_UNCONDITIONAL,
-+ AST_REDIRECTING_REASON_TIME_OF_DAY,
-+ AST_REDIRECTING_REASON_DO_NOT_DISTURB,
-+ AST_REDIRECTING_REASON_DEFLECTION,
-+ AST_REDIRECTING_REASON_FOLLOW_ME,
-+ AST_REDIRECTING_REASON_OUT_OF_ORDER,
-+ AST_REDIRECTING_REASON_AWAY,
-+ AST_REDIRECTING_REASON_CALL_FWD_DTE, /* This is something defined in Q.931, and no I don't know what it means */
-+};
-
-- The following values are available to use:
-- \arg \b Defined value, text string in config file, explanation
-+/*!
-+ * \since 1.6.3
-+ * \brief Convert redirecting reason text code to value (used in config file parsing)
-+ *
-+ * \param data text string from config file
-+ *
-+ * \retval Q931_REDIRECTING_REASON from callerid.h
-+ * \retval -1 if not in table
-+ */
-+int ast_redirecting_reason_parse(const char *data);
-
-- \arg \b AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, "allowed_not_screened", Presentation Allowed, Not Screened,
-- \arg \b AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, "allowed_passed_screen", Presentation Allowed, Passed Screen,
-- \arg \b AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN, "allowed_failed_screen", Presentation Allowed, Failed Screen,
-- \arg \b AST_PRES_ALLOWED_NETWORK_NUMBER, "allowed", Presentation Allowed, Network Number,
-- \arg \b AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED, "prohib_not_screened", Presentation Prohibited, Not Screened,
-- \arg \b AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN, "prohib_passed_screen", Presentation Prohibited, Passed Screen,
-- \arg \b AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN, "prohib_failed_screen", Presentation Prohibited, Failed Screen,
-- \arg \b AST_PRES_PROHIB_NETWORK_NUMBER, "prohib", Presentation Prohibited, Network Number,
-+/*!
-+ * \since 1.6.3
-+ * \brief Convert redirecting reason value to explanatory string
-+ *
-+ * \param data Q931_REDIRECTING_REASON from callerid.h
-+ *
-+ * \return string for human presentation
-+ */
-+const char *ast_redirecting_reason_describe(int data);
-
-- \par References
-- \arg \ref callerid.h Definitions
-- \arg \ref callerid.c Functions
-- \arg \ref CID Caller ID names and numbers
--*/
-+/*!
-+ * \since 1.6.3
-+ * \brief Convert redirecting reason value to text code
-+ *
-+ * \param data Q931_REDIRECTING_REASON from callerid.h
-+ *
-+ * \return string for config file
-+ */
-+const char *ast_redirecting_reason_name(int data);
-
-+/*!
-+ * \brief Connected line update source code
-+ */
-+enum AST_CONNECTED_LINE_UPDATE_SOURCE {
-+ /*! Update for unknown reason (May be interpreted to mean from answer) */
-+ AST_CONNECTED_LINE_UPDATE_SOURCE_UNKNOWN,
-+ /*! Update from normal call answering */
-+ AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER,
-+ /*! Update from call diversion (Deprecated, use REDIRECTING updates instead.) */
-+ AST_CONNECTED_LINE_UPDATE_SOURCE_DIVERSION,
-+ /*! Update from call transfer(active) (Party has already answered) */
-+ AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER,
-+ /*! Update from call transfer(alerting) (Party has not answered yet) */
-+ AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING
-+};
-
-+/*!
-+ * \since 1.6.3
-+ * \brief Convert connected line update source text code to value (used in config file parsing)
-+ *
-+ * \param data text string from config file
-+ *
-+ * \retval AST_CONNECTED_LINE_UPDATE_SOURCE from callerid.h
-+ * \retval -1 if not in table
-+ */
-+int ast_connected_line_source_parse(const char *data);
-+
-+/*!
-+ * \since 1.6.3
-+ * \brief Convert connected line update source value to explanatory string
-+ *
-+ * \param data AST_CONNECTED_LINE_UPDATE_SOURCE from callerid.h
-+ *
-+ * \return string for human presentation
-+ */
-+const char *ast_connected_line_source_describe(int data);
-+
-+/*!
-+ * \since 1.6.3
-+ * \brief Convert connected line update source value to text code
-+ *
-+ * \param data AST_CONNECTED_LINE_UPDATE_SOURCE from callerid.h
-+ *
-+ * \return string for config file
-+ */
-+const char *ast_connected_line_source_name(int data);
-+
-+
- #endif /* _ASTERISK_CALLERID_H */
-Index: include/asterisk/doxyref.h
-===================================================================
---- a/include/asterisk/doxyref.h (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/include/asterisk/doxyref.h (.../trunk) (revision 186562)
-@@ -360,7 +360,8 @@
- * Some commit history viewers treat the first line of commit messages as the
- * summary for the commit. So, an effort should be made to format our commit
- * messages in that fashion. The verbose description may contain multiple
-- * paragraphs, itemized lists, etc.
-+ * paragraphs, itemized lists, etc. Always end the first sentence (and any
-+ * subsequent sentences) with punctuation.
- *
- * Commit messages should be wrapped at 80 %columns.
- *
-Index: include/asterisk/crypto.h
-===================================================================
---- a/include/asterisk/crypto.h (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/include/asterisk/crypto.h (.../trunk) (revision 186562)
-@@ -40,7 +40,7 @@
- * \retval the key on success.
- * \retval NULL on failure.
- */
--struct ast_key *(*ast_key_get)(const char *key, int type);
-+extern struct ast_key *(*ast_key_get)(const char *key, int type);
-
- /*!
- * \brief Check the authenticity of a message signature using a given public key
-@@ -52,7 +52,7 @@
- * \retval -1 otherwise.
- *
- */
--int (*ast_check_signature)(struct ast_key *key, const char *msg, const char *sig);
-+extern int (*ast_check_signature)(struct ast_key *key, const char *msg, const char *sig);
-
- /*!
- * \brief Check the authenticity of a message signature using a given public key
-@@ -64,7 +64,7 @@
- * \retval -1 otherwise.
- *
- */
--int (*ast_check_signature_bin)(struct ast_key *key, const char *msg, int msglen, const unsigned char *sig);
-+extern int (*ast_check_signature_bin)(struct ast_key *key, const char *msg, int msglen, const unsigned char *sig);
-
- /*!
- * \brief Sign a message signature using a given private key
-@@ -77,7 +77,7 @@
- * \retval -1 on failure.
- *
- */
--int (*ast_sign)(struct ast_key *key, char *msg, char *sig);
-+extern int (*ast_sign)(struct ast_key *key, char *msg, char *sig);
-
- /*!
- * \brief Sign a message signature using a given private key
-@@ -90,7 +90,7 @@
- * \retval -1 on failure.
- *
- */
--int (*ast_sign_bin)(struct ast_key *key, const char *msg, int msglen, unsigned char *sig);
-+extern int (*ast_sign_bin)(struct ast_key *key, const char *msg, int msglen, unsigned char *sig);
-
- /*!
- * \brief Encrypt a message using a given private key
-@@ -104,7 +104,7 @@
- * \retval -1 on failure.
- *
- */
--int (*ast_encrypt_bin)(unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key);
-+extern int (*ast_encrypt_bin)(unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key);
-
- /*!
- * \brief Decrypt a message using a given private key
-@@ -118,7 +118,7 @@
- * \retval -1 on failure.
- *
- */
--int (*ast_decrypt_bin)(unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key);
-+extern int (*ast_decrypt_bin)(unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key);
- #if defined(__cplusplus) || defined(c_plusplus)
- }
- #endif
-Index: include/asterisk.h
-===================================================================
---- a/include/asterisk.h (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/include/asterisk.h (.../trunk) (revision 186562)
-@@ -146,10 +146,10 @@
- *
- * (note, this must be documented a lot more)
- * ast_add_profile allocates a generic 'counter' with a given name,
-- * which can be shown with the command 'show profile <name>'
-+ * which can be shown with the command 'core show profile &lt;name&gt;'
- *
- * The counter accumulates positive or negative values supplied by
-- * ast_add_profile(), dividing them by the 'scale' value passed in the
-+ * \see ast_add_profile(), dividing them by the 'scale' value passed in the
- * create call, and also counts the number of 'events'.
- * Values can also be taked by the TSC counter on ia32 architectures,
- * in which case you can mark the start of an event calling ast_mark(id, 1)
-Index: main/rtp.c
-===================================================================
---- a/main/rtp.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/main/rtp.c (.../trunk) (revision 186562)
--/*
-- * Asterisk -- An open source telephony toolkit.
-- *
-- * Copyright (C) 1999 - 2006, Digium, Inc.
-- *
-- * Mark Spencer <markster@digium.com>
-- *
-- * See http://www.asterisk.org for more information about
-- * the Asterisk project. Please do not directly contact
-- * any of the maintainers of this project for assistance;
-- * the project provides a web site, mailing lists and IRC
-- * channels for your use.
-- *
-- * 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.
-- */
--
--/*!
-- * \file
-- *
-- * \brief Supports RTP and RTCP with Symmetric RTP support for NAT traversal.
-- *
-- * \author Mark Spencer <markster@digium.com>
-- *
-- * \note RTP is defined in RFC 3550.
-- */
--
--#include "asterisk.h"
--
--ASTERISK_FILE_VERSION(__FILE__, "$Revision: 180373 $")
--
--#include <sys/time.h>
--#include <signal.h>
--#include <fcntl.h>
--#include <math.h>
--
--#include "asterisk/rtp.h"
--#include "asterisk/pbx.h"
--#include "asterisk/frame.h"
--#include "asterisk/channel.h"
--#include "asterisk/acl.h"
--#include "asterisk/config.h"
--#include "asterisk/lock.h"
--#include "asterisk/utils.h"
--#include "asterisk/netsock.h"
--#include "asterisk/cli.h"
--#include "asterisk/manager.h"
--#include "asterisk/unaligned.h"
--
--#define MAX_TIMESTAMP_SKEW 640
--
--#define RTP_SEQ_MOD (1<<16) /*!< A sequence number can't be more than 16 bits */
--#define RTCP_DEFAULT_INTERVALMS 5000 /*!< Default milli-seconds between RTCP reports we send */
--#define RTCP_MIN_INTERVALMS 500 /*!< Min milli-seconds between RTCP reports we send */
--#define RTCP_MAX_INTERVALMS 60000 /*!< Max milli-seconds between RTCP reports we send */
--
--#define RTCP_PT_FUR 192
--#define RTCP_PT_SR 200
--#define RTCP_PT_RR 201
--#define RTCP_PT_SDES 202
--#define RTCP_PT_BYE 203
--#define RTCP_PT_APP 204
--
--#define RTP_MTU 1200
--
--#define DEFAULT_DTMF_TIMEOUT 3000 /*!< samples */
--
--static int dtmftimeout = DEFAULT_DTMF_TIMEOUT;
--
--static int rtpstart = 5000; /*!< First port for RTP sessions (set in rtp.conf) */
--static int rtpend = 31000; /*!< Last port for RTP sessions (set in rtp.conf) */
--static int rtpdebug; /*!< Are we debugging? */
--static int rtcpdebug; /*!< Are we debugging RTCP? */
--static int rtcpstats; /*!< Are we debugging RTCP? */
--static int rtcpinterval = RTCP_DEFAULT_INTERVALMS; /*!< Time between rtcp reports in millisecs */
--static int stundebug; /*!< Are we debugging stun? */
--static struct sockaddr_in rtpdebugaddr; /*!< Debug packets to/from this host */
--static struct sockaddr_in rtcpdebugaddr; /*!< Debug RTCP packets to/from this host */
--#ifdef SO_NO_CHECK
--static int nochecksums;
--#endif
--static int strictrtp;
--
--enum strict_rtp_state {
-- STRICT_RTP_OPEN = 0, /*! No RTP packets should be dropped, all sources accepted */
-- STRICT_RTP_LEARN, /*! Accept next packet as source */
-- STRICT_RTP_CLOSED, /*! Drop all RTP packets not coming from source that was learned */
--};
--
--/* Uncomment this to enable more intense native bridging, but note: this is currently buggy */
--/* #define P2P_INTENSE */
--
--/*!
-- * \brief Structure representing a RTP session.
-- *
-- * RTP session is defined on page 9 of RFC 3550: "An association among a set of participants communicating with RTP. A participant may be involved in multiple RTP sessions at the same time [...]"
-- *
-- */
--
--/*! \brief RTP session description */
--struct ast_rtp {
-- int s;
-- struct ast_frame f;
-- unsigned char rawdata[8192 + AST_FRIENDLY_OFFSET];
-- unsigned int ssrc; /*!< Synchronization source, RFC 3550, page 10. */
-- unsigned int themssrc; /*!< Their SSRC */
-- unsigned int rxssrc;
-- unsigned int lastts;
-- unsigned int lastrxts;
-- unsigned int lastividtimestamp;
-- unsigned int lastovidtimestamp;
-- unsigned int lastitexttimestamp;
-- unsigned int lastotexttimestamp;
-- unsigned int lasteventseqn;
-- int lastrxseqno; /*!< Last received sequence number */
-- unsigned short seedrxseqno; /*!< What sequence number did they start with?*/
-- unsigned int seedrxts; /*!< What RTP timestamp did they start with? */
-- unsigned int rxcount; /*!< How many packets have we received? */
-- unsigned int rxoctetcount; /*!< How many octets have we received? should be rxcount *160*/
-- unsigned int txcount; /*!< How many packets have we sent? */
-- unsigned int txoctetcount; /*!< How many octets have we sent? (txcount*160)*/
-- unsigned int cycles; /*!< Shifted count of sequence number cycles */
-- double rxjitter; /*!< Interarrival jitter at the moment */
-- double rxtransit; /*!< Relative transit time for previous packet */
-- int lasttxformat;
-- int lastrxformat;
--
-- int rtptimeout; /*!< RTP timeout time (negative or zero means disabled, negative value means temporarily disabled) */
-- int rtpholdtimeout; /*!< RTP timeout when on hold (negative or zero means disabled, negative value means temporarily disabled). */
-- int rtpkeepalive; /*!< Send RTP comfort noice packets for keepalive */
--
-- /* DTMF Reception Variables */
-- char resp;
-- unsigned int lastevent;
-- int dtmfcount;
-- unsigned int dtmfsamples;
-- /* DTMF Transmission Variables */
-- unsigned int lastdigitts;
-- char sending_digit; /*!< boolean - are we sending digits */
-- char send_digit; /*!< digit we are sending */
-- int send_payload;
-- int send_duration;
-- int nat;
-- unsigned int flags;
-- struct sockaddr_in us; /*!< Socket representation of the local endpoint. */
-- struct sockaddr_in them; /*!< Socket representation of the remote endpoint. */
-- struct timeval rxcore;
-- struct timeval txcore;
-- double drxcore; /*!< The double representation of the first received packet */
-- struct timeval lastrx; /*!< timeval when we last received a packet */
-- struct timeval dtmfmute;
-- struct ast_smoother *smoother;
-- int *ioid;
-- unsigned short seqno; /*!< Sequence number, RFC 3550, page 13. */
-- unsigned short rxseqno;
-- struct sched_context *sched;
-- struct io_context *io;
-- void *data;
-- ast_rtp_callback callback;
--#ifdef P2P_INTENSE
-- ast_mutex_t bridge_lock;
--#endif
-- struct rtpPayloadType current_RTP_PT[MAX_RTP_PT];
-- int rtp_lookup_code_cache_isAstFormat; /*!< a cache for the result of rtp_lookup_code(): */
-- int rtp_lookup_code_cache_code;
-- int rtp_lookup_code_cache_result;
-- struct ast_rtcp *rtcp;
-- struct ast_codec_pref pref;
-- struct ast_rtp *bridged; /*!< Who we are Packet bridged to */
--
-- enum strict_rtp_state strict_rtp_state; /*!< Current state that strict RTP protection is in */
-- struct sockaddr_in strict_rtp_address; /*!< Remote address information for strict RTP purposes */
--
-- int set_marker_bit:1; /*!< Whether to set the marker bit or not */
-- struct rtp_red *red;
--};
--
--static struct ast_frame *red_t140_to_red(struct rtp_red *red);
--static int red_write(const void *data);
--
--struct rtp_red {
-- struct ast_frame t140; /*!< Primary data */
-- struct ast_frame t140red; /*!< Redundant t140*/
-- unsigned char pt[RED_MAX_GENERATION]; /*!< Payload types for redundancy data */
-- unsigned char ts[RED_MAX_GENERATION]; /*!< Time stamps */
-- unsigned char len[RED_MAX_GENERATION]; /*!< length of each generation */
-- int num_gen; /*!< Number of generations */
-- int schedid; /*!< Timer id */
-- int ti; /*!< How long to buffer data before send */
-- unsigned char t140red_data[64000];
-- unsigned char buf_data[64000]; /*!< buffered primary data */
-- int hdrlen;
-- long int prev_ts;
--};
--
--/* Forward declarations */
--static int ast_rtcp_write(const void *data);
--static void timeval2ntp(struct timeval tv, unsigned int *msw, unsigned int *lsw);
--static int ast_rtcp_write_sr(const void *data);
--static int ast_rtcp_write_rr(const void *data);
--static unsigned int ast_rtcp_calc_interval(struct ast_rtp *rtp);
--static int ast_rtp_senddigit_continuation(struct ast_rtp *rtp);
--int ast_rtp_senddigit_end(struct ast_rtp *rtp, char digit);
--
--#define FLAG_3389_WARNING (1 << 0)
--#define FLAG_NAT_ACTIVE (3 << 1)
--#define FLAG_NAT_INACTIVE (0 << 1)
--#define FLAG_NAT_INACTIVE_NOWARN (1 << 1)
--#define FLAG_HAS_DTMF (1 << 3)
--#define FLAG_P2P_SENT_MARK (1 << 4)
--#define FLAG_P2P_NEED_DTMF (1 << 5)
--#define FLAG_CALLBACK_MODE (1 << 6)
--#define FLAG_DTMF_COMPENSATE (1 << 7)
--#define FLAG_HAS_STUN (1 << 8)
--
--/*!
-- * \brief Structure defining an RTCP session.
-- *
-- * The concept "RTCP session" is not defined in RFC 3550, but since
-- * this structure is analogous to ast_rtp, which tracks a RTP session,
-- * it is logical to think of this as a RTCP session.
-- *
-- * RTCP packet is defined on page 9 of RFC 3550.
-- *
-- */
--struct ast_rtcp {
-- int rtcp_info;
-- int s; /*!< Socket */
-- struct sockaddr_in us; /*!< Socket representation of the local endpoint. */
-- struct sockaddr_in them; /*!< Socket representation of the remote endpoint. */
-- unsigned int soc; /*!< What they told us */
-- unsigned int spc; /*!< What they told us */
-- unsigned int themrxlsr; /*!< The middle 32 bits of the NTP timestamp in the last received SR*/
-- struct timeval rxlsr; /*!< Time when we got their last SR */
-- struct timeval txlsr; /*!< Time when we sent or last SR*/
-- unsigned int expected_prior; /*!< no. packets in previous interval */
-- unsigned int received_prior; /*!< no. packets received in previous interval */
-- int schedid; /*!< Schedid returned from ast_sched_add() to schedule RTCP-transmissions*/
-- unsigned int rr_count; /*!< number of RRs we've sent, not including report blocks in SR's */
-- unsigned int sr_count; /*!< number of SRs we've sent */
-- unsigned int lastsrtxcount; /*!< Transmit packet count when last SR sent */
-- double accumulated_transit; /*!< accumulated a-dlsr-lsr */
-- double rtt; /*!< Last reported rtt */
-- unsigned int reported_jitter; /*!< The contents of their last jitter entry in the RR */
-- unsigned int reported_lost; /*!< Reported lost packets in their RR */
-- char quality[AST_MAX_USER_FIELD];
-- char quality_jitter[AST_MAX_USER_FIELD];
-- char quality_loss[AST_MAX_USER_FIELD];
-- char quality_rtt[AST_MAX_USER_FIELD];
--
-- double reported_maxjitter;
-- double reported_minjitter;
-- double reported_normdev_jitter;
-- double reported_stdev_jitter;
-- unsigned int reported_jitter_count;
--
-- double reported_maxlost;
-- double reported_minlost;
-- double reported_normdev_lost;
-- double reported_stdev_lost;
--
-- double rxlost;
-- double maxrxlost;
-- double minrxlost;
-- double normdev_rxlost;
-- double stdev_rxlost;
-- unsigned int rxlost_count;
--
-- double maxrxjitter;
-- double minrxjitter;
-- double normdev_rxjitter;
-- double stdev_rxjitter;
-- unsigned int rxjitter_count;
-- double maxrtt;
-- double minrtt;
-- double normdevrtt;
-- double stdevrtt;
-- unsigned int rtt_count;
-- int sendfur;
--};
--
--/*!
-- * \brief STUN support code
-- *
-- * This code provides some support for doing STUN transactions.
-- * Eventually it should be moved elsewhere as other protocols
-- * than RTP can benefit from it - e.g. SIP.
-- * STUN is described in RFC3489 and it is based on the exchange
-- * of UDP packets between a client and one or more servers to
-- * determine the externally visible address (and port) of the client
-- * once it has gone through the NAT boxes that connect it to the
-- * outside.
-- * The simplest request packet is just the header defined in
-- * struct stun_header, and from the response we may just look at
-- * one attribute, STUN_MAPPED_ADDRESS, that we find in the response.
-- * By doing more transactions with different server addresses we
-- * may determine more about the behaviour of the NAT boxes, of
-- * course - the details are in the RFC.
-- *
-- * All STUN packets start with a simple header made of a type,
-- * length (excluding the header) and a 16-byte random transaction id.
-- * Following the header we may have zero or more attributes, each
-- * structured as a type, length and a value (whose format depends
-- * on the type, but often contains addresses).
-- * Of course all fields are in network format.
-- */
--
--typedef struct { unsigned int id[4]; } __attribute__((packed)) stun_trans_id;
--
--struct stun_header {
-- unsigned short msgtype;
-- unsigned short msglen;
-- stun_trans_id id;
-- unsigned char ies[0];
--} __attribute__((packed));
--
--struct stun_attr {
-- unsigned short attr;
-- unsigned short len;
-- unsigned char value[0];
--} __attribute__((packed));
--
--/*
-- * The format normally used for addresses carried by STUN messages.
-- */
--struct stun_addr {
-- unsigned char unused;
-- unsigned char family;
-- unsigned short port;
-- unsigned int addr;
--} __attribute__((packed));
--
--#define STUN_IGNORE (0)
--#define STUN_ACCEPT (1)
--
--/*! \brief STUN message types
-- * 'BIND' refers to transactions used to determine the externally
-- * visible addresses. 'SEC' refers to transactions used to establish
-- * a session key for subsequent requests.
-- * 'SEC' functionality is not supported here.
-- */
--
--#define STUN_BINDREQ 0x0001
--#define STUN_BINDRESP 0x0101
--#define STUN_BINDERR 0x0111
--#define STUN_SECREQ 0x0002
--#define STUN_SECRESP 0x0102
--#define STUN_SECERR 0x0112
--
--/*! \brief Basic attribute types in stun messages.
-- * Messages can also contain custom attributes (codes above 0x7fff)
-- */
--#define STUN_MAPPED_ADDRESS 0x0001
--#define STUN_RESPONSE_ADDRESS 0x0002
--#define STUN_CHANGE_REQUEST 0x0003
--#define STUN_SOURCE_ADDRESS 0x0004
--#define STUN_CHANGED_ADDRESS 0x0005
--#define STUN_USERNAME 0x0006
--#define STUN_PASSWORD 0x0007
--#define STUN_MESSAGE_INTEGRITY 0x0008
--#define STUN_ERROR_CODE 0x0009
--#define STUN_UNKNOWN_ATTRIBUTES 0x000a
--#define STUN_REFLECTED_FROM 0x000b
--
--/*! \brief helper function to print message names */
--static const char *stun_msg2str(int msg)
--{
-- switch (msg) {
-- case STUN_BINDREQ:
-- return "Binding Request";
-- case STUN_BINDRESP:
-- return "Binding Response";
-- case STUN_BINDERR:
-- return "Binding Error Response";
-- case STUN_SECREQ:
-- return "Shared Secret Request";
-- case STUN_SECRESP:
-- return "Shared Secret Response";
-- case STUN_SECERR:
-- return "Shared Secret Error Response";
-- }
-- return "Non-RFC3489 Message";
--}
--
--/*! \brief helper function to print attribute names */
--static const char *stun_attr2str(int msg)
--{
-- switch (msg) {
-- case STUN_MAPPED_ADDRESS:
-- return "Mapped Address";
-- case STUN_RESPONSE_ADDRESS:
-- return "Response Address";
-- case STUN_CHANGE_REQUEST:
-- return "Change Request";
-- case STUN_SOURCE_ADDRESS:
-- return "Source Address";
-- case STUN_CHANGED_ADDRESS:
-- return "Changed Address";
-- case STUN_USERNAME:
-- return "Username";
-- case STUN_PASSWORD:
-- return "Password";
-- case STUN_MESSAGE_INTEGRITY:
-- return "Message Integrity";
-- case STUN_ERROR_CODE:
-- return "Error Code";
-- case STUN_UNKNOWN_ATTRIBUTES:
-- return "Unknown Attributes";
-- case STUN_REFLECTED_FROM:
-- return "Reflected From";
-- }
-- return "Non-RFC3489 Attribute";
--}
--
--/*! \brief here we store credentials extracted from a message */
--struct stun_state {
-- const char *username;
-- const char *password;
--};
--
--static int stun_process_attr(struct stun_state *state, struct stun_attr *attr)
--{
-- if (stundebug)
-- ast_verbose("Found STUN Attribute %s (%04x), length %d\n",
-- stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len));
-- switch (ntohs(attr->attr)) {
-- case STUN_USERNAME:
-- state->username = (const char *) (attr->value);
-- break;
-- case STUN_PASSWORD:
-- state->password = (const char *) (attr->value);
-- break;
-- default:
-- if (stundebug)
-- ast_verbose("Ignoring STUN attribute %s (%04x), length %d\n",
-- stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len));
-- }
-- return 0;
--}
--
--/*! \brief append a string to an STUN message */
--static void append_attr_string(struct stun_attr **attr, int attrval, const char *s, int *len, int *left)
--{
-- int size = sizeof(**attr) + strlen(s);
-- if (*left > size) {
-- (*attr)->attr = htons(attrval);
-- (*attr)->len = htons(strlen(s));
-- memcpy((*attr)->value, s, strlen(s));
-- (*attr) = (struct stun_attr *)((*attr)->value + strlen(s));
-- *len += size;
-- *left -= size;
-- }
--}
--
--/*! \brief append an address to an STUN message */
--static void append_attr_address(struct stun_attr **attr, int attrval, struct sockaddr_in *sock_in, int *len, int *left)
--{
-- int size = sizeof(**attr) + 8;
-- struct stun_addr *addr;
-- if (*left > size) {
-- (*attr)->attr = htons(attrval);
-- (*attr)->len = htons(8);
-- addr = (struct stun_addr *)((*attr)->value);
-- addr->unused = 0;
-- addr->family = 0x01;
-- addr->port = sock_in->sin_port;
-- addr->addr = sock_in->sin_addr.s_addr;
-- (*attr) = (struct stun_attr *)((*attr)->value + 8);
-- *len += size;
-- *left -= size;
-- }
--}
--
--/*! \brief wrapper to send an STUN message */
--static int stun_send(int s, struct sockaddr_in *dst, struct stun_header *resp)
--{
-- return sendto(s, resp, ntohs(resp->msglen) + sizeof(*resp), 0,
-- (struct sockaddr *)dst, sizeof(*dst));
--}
--
--/*! \brief helper function to generate a random request id */
--static void stun_req_id(struct stun_header *req)
--{
-- int x;
-- for (x = 0; x < 4; x++)
-- req->id.id[x] = ast_random();
--}
--
--size_t ast_rtp_alloc_size(void)
--{
-- return sizeof(struct ast_rtp);
--}
--
--/*! \brief callback type to be invoked on stun responses. */
--typedef int (stun_cb_f)(struct stun_attr *attr, void *arg);
--
--/*! \brief handle an incoming STUN message.
-- *
-- * Do some basic sanity checks on packet size and content,
-- * try to extract a bit of information, and possibly reply.
-- * At the moment this only processes BIND requests, and returns
-- * the externally visible address of the request.
-- * If a callback is specified, invoke it with the attribute.
-- */
--static int stun_handle_packet(int s, struct sockaddr_in *src,
-- unsigned char *data, size_t len, stun_cb_f *stun_cb, void *arg)
--{
-- struct stun_header *hdr = (struct stun_header *)data;
-- struct stun_attr *attr;
-- struct stun_state st;
-- int ret = STUN_IGNORE;
-- int x;
--
-- /* On entry, 'len' is the length of the udp payload. After the
-- * initial checks it becomes the size of unprocessed options,
-- * while 'data' is advanced accordingly.
-- */
-- if (len < sizeof(struct stun_header)) {
-- ast_debug(1, "Runt STUN packet (only %d, wanting at least %d)\n", (int) len, (int) sizeof(struct stun_header));
-- return -1;
-- }
-- len -= sizeof(struct stun_header);
-- data += sizeof(struct stun_header);
-- x = ntohs(hdr->msglen); /* len as advertised in the message */
-- if (stundebug)
-- ast_verbose("STUN Packet, msg %s (%04x), length: %d\n", stun_msg2str(ntohs(hdr->msgtype)), ntohs(hdr->msgtype), x);
-- if (x > len) {
-- ast_debug(1, "Scrambled STUN packet length (got %d, expecting %d)\n", x, (int)len);
-- } else
-- len = x;
-- memset(&st, 0, sizeof(st));
-- while (len) {
-- if (len < sizeof(struct stun_attr)) {
-- ast_debug(1, "Runt Attribute (got %d, expecting %d)\n", (int)len, (int) sizeof(struct stun_attr));
-- break;
-- }
-- attr = (struct stun_attr *)data;
-- /* compute total attribute length */
-- x = ntohs(attr->len) + sizeof(struct stun_attr);
-- if (x > len) {
-- ast_debug(1, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", x, (int)len);
-- break;
-- }
-- if (stun_cb)
-- stun_cb(attr, arg);
-- if (stun_process_attr(&st, attr)) {
-- ast_debug(1, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr));
-- break;
-- }
-- /* Clear attribute id: in case previous entry was a string,
-- * this will act as the terminator for the string.
-- */
-- attr->attr = 0;
-- data += x;
-- len -= x;
-- }
-- /* Null terminate any string.
-- * XXX NOTE, we write past the size of the buffer passed by the
-- * caller, so this is potentially dangerous. The only thing that
-- * saves us is that usually we read the incoming message in a
-- * much larger buffer in the struct ast_rtp
-- */
-- *data = '\0';
--
-- /* Now prepare to generate a reply, which at the moment is done
-- * only for properly formed (len == 0) STUN_BINDREQ messages.
-- */
-- if (len == 0) {
-- unsigned char respdata[1024];
-- struct stun_header *resp = (struct stun_header *)respdata;
-- int resplen = 0; /* len excluding header */
-- int respleft = sizeof(respdata) - sizeof(struct stun_header);
--
-- resp->id = hdr->id;
-- resp->msgtype = 0;
-- resp->msglen = 0;
-- attr = (struct stun_attr *)resp->ies;
-- switch (ntohs(hdr->msgtype)) {
-- case STUN_BINDREQ:
-- if (stundebug)
-- ast_verbose("STUN Bind Request, username: %s\n",
-- st.username ? st.username : "<none>");
-- if (st.username)
-- append_attr_string(&attr, STUN_USERNAME, st.username, &resplen, &respleft);
-- append_attr_address(&attr, STUN_MAPPED_ADDRESS, src, &resplen, &respleft);
-- resp->msglen = htons(resplen);
-- resp->msgtype = htons(STUN_BINDRESP);
-- stun_send(s, src, resp);
-- ret = STUN_ACCEPT;
-- break;
-- default:
-- if (stundebug)
-- ast_verbose("Dunno what to do with STUN message %04x (%s)\n", ntohs(hdr->msgtype), stun_msg2str(ntohs(hdr->msgtype)));
-- }
-- }
-- return ret;
--}
--
--/*! \brief Extract the STUN_MAPPED_ADDRESS from the stun response.
-- * This is used as a callback for stun_handle_response
-- * when called from ast_stun_request.
-- */
--static int stun_get_mapped(struct stun_attr *attr, void *arg)
--{
-- struct stun_addr *addr = (struct stun_addr *)(attr + 1);
-- struct sockaddr_in *sa = (struct sockaddr_in *)arg;
--
-- if (ntohs(attr->attr) != STUN_MAPPED_ADDRESS || ntohs(attr->len) != 8)
-- return 1; /* not us. */
-- sa->sin_port = addr->port;
-- sa->sin_addr.s_addr = addr->addr;
-- return 0;
--}
--
--/*! \brief Generic STUN request
-- * Send a generic stun request to the server specified,
-- * possibly waiting for a reply and filling the 'reply' field with
-- * the externally visible address. Note that in this case the request
-- * will be blocking.
-- * (Note, the interface may change slightly in the future).
-- *
-- * \param s the socket used to send the request
-- * \param dst the address of the STUN server
-- * \param username if non null, add the username in the request
-- * \param answer if non null, the function waits for a response and
-- * puts here the externally visible address.
-- * \return 0 on success, other values on error.
-- */
--int ast_stun_request(int s, struct sockaddr_in *dst,
-- const char *username, struct sockaddr_in *answer)
--{
-- struct stun_header *req;
-- unsigned char reqdata[1024];
-- int reqlen, reqleft;
-- struct stun_attr *attr;
-- int res = 0;
-- int retry;
--
-- req = (struct stun_header *)reqdata;
-- stun_req_id(req);
-- reqlen = 0;
-- reqleft = sizeof(reqdata) - sizeof(struct stun_header);
-- req->msgtype = 0;
-- req->msglen = 0;
-- attr = (struct stun_attr *)req->ies;
-- if (username)
-- append_attr_string(&attr, STUN_USERNAME, username, &reqlen, &reqleft);
-- req->msglen = htons(reqlen);
-- req->msgtype = htons(STUN_BINDREQ);
-- for (retry = 0; retry < 3; retry++) { /* XXX make retries configurable */
-- /* send request, possibly wait for reply */
-- unsigned char reply_buf[1024];
-- fd_set rfds;
-- struct timeval to = { 3, 0 }; /* timeout, make it configurable */
-- struct sockaddr_in src;
-- socklen_t srclen;
--
-- res = stun_send(s, dst, req);
-- if (res < 0) {
-- ast_log(LOG_WARNING, "ast_stun_request send #%d failed error %d, retry\n",
-- retry, res);
-- continue;
-- }
-- if (answer == NULL)
-- break;
-- FD_ZERO(&rfds);
-- FD_SET(s, &rfds);
-- res = ast_select(s + 1, &rfds, NULL, NULL, &to);
-- if (res <= 0) /* timeout or error */
-- continue;
-- memset(&src, '\0', sizeof(src));
-- srclen = sizeof(src);
-- /* XXX pass -1 in the size, because stun_handle_packet might
-- * write past the end of the buffer.
-- */
-- res = recvfrom(s, reply_buf, sizeof(reply_buf) - 1,
-- 0, (struct sockaddr *)&src, &srclen);
-- if (res < 0) {
-- ast_log(LOG_WARNING, "ast_stun_request recvfrom #%d failed error %d, retry\n",
-- retry, res);
-- continue;
-- }
-- memset(answer, '\0', sizeof(struct sockaddr_in));
-- stun_handle_packet(s, &src, reply_buf, res,
-- stun_get_mapped, answer);
-- res = 0; /* signal regular exit */
-- break;
-- }
-- return res;
--}
--
--/*! \brief send a STUN BIND request to the given destination.
-- * Optionally, add a username if specified.
-- */
--void ast_rtp_stun_request(struct ast_rtp *rtp, struct sockaddr_in *suggestion, const char *username)
--{
-- ast_stun_request(rtp->s, suggestion, username, NULL);
--}
--
--/*! \brief List of current sessions */
--static AST_RWLIST_HEAD_STATIC(protos, ast_rtp_protocol);
--
--static void timeval2ntp(struct timeval when, unsigned int *msw, unsigned int *lsw)
--{
-- unsigned int sec, usec, frac;
-- sec = when.tv_sec + 2208988800u; /* Sec between 1900 and 1970 */
-- usec = when.tv_usec;
-- frac = (usec << 12) + (usec << 8) - ((usec * 3650) >> 6);
-- *msw = sec;
-- *lsw = frac;
--}
--
--int ast_rtp_fd(struct ast_rtp *rtp)
--{
-- return rtp->s;
--}
--
--int ast_rtcp_fd(struct ast_rtp *rtp)
--{
-- if (rtp->rtcp)
-- return rtp->rtcp->s;
-- return -1;
--}
--
--unsigned int ast_rtcp_calc_interval(struct ast_rtp *rtp)
--{
-- unsigned int interval;
-- /*! \todo XXX Do a more reasonable calculation on this one
-- * Look in RFC 3550 Section A.7 for an example*/
-- interval = rtcpinterval;
-- return interval;
--}
--
--/* \brief Put RTP timeout timers on hold during another transaction, like T.38 */
--void ast_rtp_set_rtptimers_onhold(struct ast_rtp *rtp)
--{
-- rtp->rtptimeout = (-1) * rtp->rtptimeout;
-- rtp->rtpholdtimeout = (-1) * rtp->rtpholdtimeout;
--}
--
--/*! \brief Set rtp timeout */
--void ast_rtp_set_rtptimeout(struct ast_rtp *rtp, int timeout)
--{
-- rtp->rtptimeout = timeout;
--}
--
--/*! \brief Set rtp hold timeout */
--void ast_rtp_set_rtpholdtimeout(struct ast_rtp *rtp, int timeout)
--{
-- rtp->rtpholdtimeout = timeout;
--}
--
--/*! \brief set RTP keepalive interval */
--void ast_rtp_set_rtpkeepalive(struct ast_rtp *rtp, int period)
--{
-- rtp->rtpkeepalive = period;
--}
--
--/*! \brief Get rtp timeout */
--int ast_rtp_get_rtptimeout(struct ast_rtp *rtp)
--{
-- if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */
-- return 0;
-- return rtp->rtptimeout;
--}
--
--/*! \brief Get rtp hold timeout */
--int ast_rtp_get_rtpholdtimeout(struct ast_rtp *rtp)
--{
-- if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */
-- return 0;
-- return rtp->rtpholdtimeout;
--}
--
--/*! \brief Get RTP keepalive interval */
--int ast_rtp_get_rtpkeepalive(struct ast_rtp *rtp)
--{
-- return rtp->rtpkeepalive;
--}
--
--void ast_rtp_set_data(struct ast_rtp *rtp, void *data)
--{
-- rtp->data = data;
--}
--
--void ast_rtp_set_callback(struct ast_rtp *rtp, ast_rtp_callback callback)
--{
-- rtp->callback = callback;
--}
--
--void ast_rtp_setnat(struct ast_rtp *rtp, int nat)
--{
-- rtp->nat = nat;
--}
--
--int ast_rtp_getnat(struct ast_rtp *rtp)
--{
-- return ast_test_flag(rtp, FLAG_NAT_ACTIVE);
--}
--
--void ast_rtp_setdtmf(struct ast_rtp *rtp, int dtmf)
--{
-- ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF);
--}
--
--void ast_rtp_setdtmfcompensate(struct ast_rtp *rtp, int compensate)
--{
-- ast_set2_flag(rtp, compensate ? 1 : 0, FLAG_DTMF_COMPENSATE);
--}
--
--void ast_rtp_setstun(struct ast_rtp *rtp, int stun_enable)
--{
-- ast_set2_flag(rtp, stun_enable ? 1 : 0, FLAG_HAS_STUN);
--}
--
--static void rtp_bridge_lock(struct ast_rtp *rtp)
--{
--#ifdef P2P_INTENSE
-- ast_mutex_lock(&rtp->bridge_lock);
--#endif
-- return;
--}
--
--static void rtp_bridge_unlock(struct ast_rtp *rtp)
--{
--#ifdef P2P_INTENSE
-- ast_mutex_unlock(&rtp->bridge_lock);
--#endif
-- return;
--}
--
--/*! \brief Calculate normal deviation */
--static double normdev_compute(double normdev, double sample, unsigned int sample_count)
--{
-- normdev = normdev * sample_count + sample;
-- sample_count++;
--
-- return normdev / sample_count;
--}
--
--static double stddev_compute(double stddev, double sample, double normdev, double normdev_curent, unsigned int sample_count)
--{
--/*
-- for the formula check http://www.cs.umd.edu/~austinjp/constSD.pdf
-- return sqrt( (sample_count*pow(stddev,2) + sample_count*pow((sample-normdev)/(sample_count+1),2) + pow(sample-normdev_curent,2)) / (sample_count+1));
-- we can compute the sigma^2 and that way we would have to do the sqrt only 1 time at the end and would save another pow 2 compute
-- optimized formula
--*/
--#define SQUARE(x) ((x) * (x))
--
-- stddev = sample_count * stddev;
-- sample_count++;
--
-- return stddev +
-- ( sample_count * SQUARE( (sample - normdev) / sample_count ) ) +
-- ( SQUARE(sample - normdev_curent) / sample_count );
--
--#undef SQUARE
--}
--
--static struct ast_frame *send_dtmf(struct ast_rtp *rtp, enum ast_frame_type type)
--{
-- if (((ast_test_flag(rtp, FLAG_DTMF_COMPENSATE) && type == AST_FRAME_DTMF_END) ||
-- (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) {
-- ast_debug(1, "Ignore potential DTMF echo from '%s'\n", ast_inet_ntoa(rtp->them.sin_addr));
-- rtp->resp = 0;
-- rtp->dtmfsamples = 0;
-- return &ast_null_frame;
-- }
-- ast_debug(1, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, ast_inet_ntoa(rtp->them.sin_addr));
-- if (rtp->resp == 'X') {
-- rtp->f.frametype = AST_FRAME_CONTROL;
-- rtp->f.subclass = AST_CONTROL_FLASH;
-- } else {
-- rtp->f.frametype = type;
-- rtp->f.subclass = rtp->resp;
-- }
-- rtp->f.datalen = 0;
-- rtp->f.samples = 0;
-- rtp->f.mallocd = 0;
-- rtp->f.src = "RTP";
-- return &rtp->f;
--
--}
--
--static inline int rtp_debug_test_addr(struct sockaddr_in *addr)
--{
-- if (rtpdebug == 0)
-- return 0;
-- if (rtpdebugaddr.sin_addr.s_addr) {
-- if (((ntohs(rtpdebugaddr.sin_port) != 0)
-- && (rtpdebugaddr.sin_port != addr->sin_port))
-- || (rtpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
-- return 0;
-- }
-- return 1;
--}
--
--static inline int rtcp_debug_test_addr(struct sockaddr_in *addr)
--{
-- if (rtcpdebug == 0)
-- return 0;
-- if (rtcpdebugaddr.sin_addr.s_addr) {
-- if (((ntohs(rtcpdebugaddr.sin_port) != 0)
-- && (rtcpdebugaddr.sin_port != addr->sin_port))
-- || (rtcpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
-- return 0;
-- }
-- return 1;
--}
--
--
--static struct ast_frame *process_cisco_dtmf(struct ast_rtp *rtp, unsigned char *data, int len)
--{
-- unsigned int event;
-- char resp = 0;
-- struct ast_frame *f = NULL;
-- unsigned char seq;
-- unsigned int flags;
-- unsigned int power;
--
-- /* We should have at least 4 bytes in RTP data */
-- if (len < 4)
-- return f;
--
-- /* The format of Cisco RTP DTMF packet looks like next:
-- +0 - sequence number of DTMF RTP packet (begins from 1,
-- wrapped to 0)
-- +1 - set of flags
-- +1 (bit 0) - flaps by different DTMF digits delimited by audio
-- or repeated digit without audio???
-- +2 (+4,+6,...) - power level? (rises from 0 to 32 at begin of tone
-- then falls to 0 at its end)
-- +3 (+5,+7,...) - detected DTMF digit (0..9,*,#,A-D,...)
-- Repeated DTMF information (bytes 4/5, 6/7) is history shifted right
-- by each new packet and thus provides some redudancy.
--
-- Sample of Cisco RTP DTMF packet is (all data in hex):
-- 19 07 00 02 12 02 20 02
-- showing end of DTMF digit '2'.
--
-- The packets
-- 27 07 00 02 0A 02 20 02
-- 28 06 20 02 00 02 0A 02
-- shows begin of new digit '2' with very short pause (20 ms) after
-- previous digit '2'. Bit +1.0 flips at begin of new digit.
--
-- Cisco RTP DTMF packets comes as replacement of audio RTP packets
-- so its uses the same sequencing and timestamping rules as replaced
-- audio packets. Repeat interval of DTMF packets is 20 ms and not rely
-- on audio framing parameters. Marker bit isn't used within stream of
-- DTMFs nor audio stream coming immediately after DTMF stream. Timestamps
-- are not sequential at borders between DTMF and audio streams,
-- */
--
-- seq = data[0];
-- flags = data[1];
-- power = data[2];
-- event = data[3] & 0x1f;
--
-- if (option_debug > 2 || rtpdebug)
-- ast_debug(0, "Cisco DTMF Digit: %02x (len=%d, seq=%d, flags=%02x, power=%d, history count=%d)\n", event, len, seq, flags, power, (len - 4) / 2);
-- if (event < 10) {
-- resp = '0' + event;
-- } else if (event < 11) {
-- resp = '*';
-- } else if (event < 12) {
-- resp = '#';
-- } else if (event < 16) {
-- resp = 'A' + (event - 12);
-- } else if (event < 17) {
-- resp = 'X';
-- }
-- if ((!rtp->resp && power) || (rtp->resp && (rtp->resp != resp))) {
-- rtp->resp = resp;
-- /* Why we should care on DTMF compensation at reception? */
-- if (!ast_test_flag(rtp, FLAG_DTMF_COMPENSATE)) {
-- f = send_dtmf(rtp, AST_FRAME_DTMF_BEGIN);
-- rtp->dtmfsamples = 0;
-- }
-- } else if ((rtp->resp == resp) && !power) {
-- f = send_dtmf(rtp, AST_FRAME_DTMF_END);
-- f->samples = rtp->dtmfsamples * 8;
-- rtp->resp = 0;
-- } else if (rtp->resp == resp)
-- rtp->dtmfsamples += 20 * 8;
-- rtp->dtmfcount = dtmftimeout;
-- return f;
--}
--
--/*!
-- * \brief Process RTP DTMF and events according to RFC 2833.
-- *
-- * RFC 2833 is "RTP Payload for DTMF Digits, Telephony Tones and Telephony Signals".
-- *
-- * \param rtp
-- * \param data
-- * \param len
-- * \param seqno
-- * \param timestamp
-- * \returns
-- */
--static struct ast_frame *process_rfc2833(struct ast_rtp *rtp, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp)
--{
-- unsigned int event;
-- unsigned int event_end;
-- unsigned int samples;
-- char resp = 0;
-- struct ast_frame *f = NULL;
--
-- /* Figure out event, event end, and samples */
-- event = ntohl(*((unsigned int *)(data)));
-- event >>= 24;
-- event_end = ntohl(*((unsigned int *)(data)));
-- event_end <<= 8;
-- event_end >>= 24;
-- samples = ntohl(*((unsigned int *)(data)));
-- samples &= 0xFFFF;
--
-- /* Print out debug if turned on */
-- if (rtpdebug || option_debug > 2)
-- ast_debug(0, "- RTP 2833 Event: %08x (len = %d)\n", event, len);
--
-- /* Figure out what digit was pressed */
-- if (event < 10) {
-- resp = '0' + event;
-- } else if (event < 11) {
-- resp = '*';
-- } else if (event < 12) {
-- resp = '#';
-- } else if (event < 16) {
-- resp = 'A' + (event - 12);
-- } else if (event < 17) { /* Event 16: Hook flash */
-- resp = 'X';
-- } else {
-- /* Not a supported event */
-- ast_log(LOG_DEBUG, "Ignoring RTP 2833 Event: %08x. Not a DTMF Digit.\n", event);
-- return &ast_null_frame;
-- }
--
-- if (ast_test_flag(rtp, FLAG_DTMF_COMPENSATE)) {
-- if ((rtp->lastevent != timestamp) || (rtp->resp && rtp->resp != resp)) {
-- rtp->resp = resp;
-- rtp->dtmfcount = 0;
-- f = send_dtmf(rtp, AST_FRAME_DTMF_END);
-- f->len = 0;
-- rtp->lastevent = timestamp;
-- }
-- } else {
-- if ((!(rtp->resp) && (!(event_end & 0x80))) || (rtp->resp && rtp->resp != resp)) {
-- rtp->resp = resp;
-- f = send_dtmf(rtp, AST_FRAME_DTMF_BEGIN);
-- rtp->dtmfcount = dtmftimeout;
-- } else if ((event_end & 0x80) && (rtp->lastevent != seqno) && rtp->resp) {
-- f = send_dtmf(rtp, AST_FRAME_DTMF_END);
-- f->len = ast_tvdiff_ms(ast_samp2tv(samples, 8000), ast_tv(0, 0)); /* XXX hard coded 8kHz */
-- rtp->resp = 0;
-- rtp->dtmfcount = 0;
-- rtp->lastevent = seqno;
-- }
-- }
--
-- rtp->dtmfsamples = samples;
--
-- return f;
--}
--
--/*!
-- * \brief Process Comfort Noise RTP.
-- *
-- * This is incomplete at the moment.
-- *
--*/
--static struct ast_frame *process_rfc3389(struct ast_rtp *rtp, unsigned char *data, int len)
--{
-- struct ast_frame *f = NULL;
-- /* Convert comfort noise into audio with various codecs. Unfortunately this doesn't
-- totally help us out becuase we don't have an engine to keep it going and we are not
-- guaranteed to have it every 20ms or anything */
-- if (rtpdebug)
-- ast_debug(0, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", rtp->lastrxformat, len);
--
-- if (!(ast_test_flag(rtp, FLAG_3389_WARNING))) {
-- ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client IP: %s\n",
-- ast_inet_ntoa(rtp->them.sin_addr));
-- ast_set_flag(rtp, FLAG_3389_WARNING);
-- }
--
-- /* Must have at least one byte */
-- if (!len)
-- return NULL;
-- if (len < 24) {
-- rtp->f.data.ptr = rtp->rawdata + AST_FRIENDLY_OFFSET;
-- rtp->f.datalen = len - 1;
-- rtp->f.offset = AST_FRIENDLY_OFFSET;
-- memcpy(rtp->f.data.ptr, data + 1, len - 1);
-- } else {
-- rtp->f.data.ptr = NULL;
-- rtp->f.offset = 0;
-- rtp->f.datalen = 0;
-- }
-- rtp->f.frametype = AST_FRAME_CNG;
-- rtp->f.subclass = data[0] & 0x7f;
-- rtp->f.datalen = len - 1;
-- rtp->f.samples = 0;
-- rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0;
-- f = &rtp->f;
-- return f;
--}
--
--static int rtpread(int *id, int fd, short events, void *cbdata)
--{
-- struct ast_rtp *rtp = cbdata;
-- struct ast_frame *f;
-- f = ast_rtp_read(rtp);
-- if (f) {
-- if (rtp->callback)
-- rtp->callback(rtp, f, rtp->data);
-- }
-- return 1;
--}
--
--struct ast_frame *ast_rtcp_read(struct ast_rtp *rtp)
--{
-- socklen_t len;
-- int position, i, packetwords;
-- int res;
-- struct sockaddr_in sock_in;
-- unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET];
-- unsigned int *rtcpheader;
-- int pt;
-- struct timeval now;
-- unsigned int length;
-- int rc;
-- double rttsec;
-- uint64_t rtt = 0;
-- unsigned int dlsr;
-- unsigned int lsr;
-- unsigned int msw;
-- unsigned int lsw;
-- unsigned int comp;
-- struct ast_frame *f = &ast_null_frame;
--
-- double reported_jitter;
-- double reported_normdev_jitter_current;
-- double normdevrtt_current;
-- double reported_lost;
-- double reported_normdev_lost_current;
--
-- if (!rtp || !rtp->rtcp)
-- return &ast_null_frame;
--
-- len = sizeof(sock_in);
--
-- res = recvfrom(rtp->rtcp->s, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET,
-- 0, (struct sockaddr *)&sock_in, &len);
-- rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET);
--
-- if (res < 0) {
-- ast_assert(errno != EBADF);
-- if (errno != EAGAIN) {
-- ast_log(LOG_WARNING, "RTCP Read error: %s. Hanging up.\n", strerror(errno));
-- return NULL;
-- }
-- return &ast_null_frame;
-- }
--
-- packetwords = res / 4;
--
-- if (rtp->nat) {
-- /* Send to whoever sent to us */
-- if ((rtp->rtcp->them.sin_addr.s_addr != sock_in.sin_addr.s_addr) ||
-- (rtp->rtcp->them.sin_port != sock_in.sin_port)) {
-- memcpy(&rtp->rtcp->them, &sock_in, sizeof(rtp->rtcp->them));
-- if (option_debug || rtpdebug)
-- ast_debug(0, "RTCP NAT: Got RTCP from other end. Now sending to address %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
-- }
-- }
--
-- ast_debug(1, "Got RTCP report of %d bytes\n", res);
--
-- /* Process a compound packet */
-- position = 0;
-- while (position < packetwords) {
-- i = position;
-- length = ntohl(rtcpheader[i]);
-- pt = (length & 0xff0000) >> 16;
-- rc = (length & 0x1f000000) >> 24;
-- length &= 0xffff;
--
-- if ((i + length) > packetwords) {
-- if (option_debug || rtpdebug)
-- ast_log(LOG_DEBUG, "RTCP Read too short\n");
-- return &ast_null_frame;
-- }
--
-- if (rtcp_debug_test_addr(&sock_in)) {
-- ast_verbose("\n\nGot RTCP from %s:%d\n", ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port));
-- ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown");
-- ast_verbose("Reception reports: %d\n", rc);
-- ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]);
-- }
--
-- i += 2; /* Advance past header and ssrc */
--
-- switch (pt) {
-- case RTCP_PT_SR:
-- gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */
-- rtp->rtcp->spc = ntohl(rtcpheader[i+3]);
-- rtp->rtcp->soc = ntohl(rtcpheader[i + 4]);
-- rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/
--
-- if (rtcp_debug_test_addr(&sock_in)) {
-- ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096);
-- ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2]));
-- ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4]));
-- }
-- i += 5;
-- if (rc < 1)
-- break;
-- /* Intentional fall through */
-- case RTCP_PT_RR:
-- /* Don't handle multiple reception reports (rc > 1) yet */
-- /* Calculate RTT per RFC */
-- gettimeofday(&now, NULL);
-- timeval2ntp(now, &msw, &lsw);
-- if (ntohl(rtcpheader[i + 4]) && ntohl(rtcpheader[i + 5])) { /* We must have the LSR && DLSR */
-- comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16);
-- lsr = ntohl(rtcpheader[i + 4]);
-- dlsr = ntohl(rtcpheader[i + 5]);
-- rtt = comp - lsr - dlsr;
--
-- /* Convert end to end delay to usec (keeping the calculation in 64bit space)
-- sess->ee_delay = (eedelay * 1000) / 65536; */
-- if (rtt < 4294) {
-- rtt = (rtt * 1000000) >> 16;
-- } else {
-- rtt = (rtt * 1000) >> 16;
-- rtt *= 1000;
-- }
-- rtt = rtt / 1000.;
-- rttsec = rtt / 1000.;
-- rtp->rtcp->rtt = rttsec;
--
-- if (comp - dlsr >= lsr) {
-- rtp->rtcp->accumulated_transit += rttsec;
--
-- if (rtp->rtcp->rtt_count == 0)
-- rtp->rtcp->minrtt = rttsec;
--
-- if (rtp->rtcp->maxrtt<rttsec)
-- rtp->rtcp->maxrtt = rttsec;
--
-- if (rtp->rtcp->minrtt>rttsec)
-- rtp->rtcp->minrtt = rttsec;
--
-- normdevrtt_current = normdev_compute(rtp->rtcp->normdevrtt, rttsec, rtp->rtcp->rtt_count);
--
-- rtp->rtcp->stdevrtt = stddev_compute(rtp->rtcp->stdevrtt, rttsec, rtp->rtcp->normdevrtt, normdevrtt_current, rtp->rtcp->rtt_count);
--
-- rtp->rtcp->normdevrtt = normdevrtt_current;
--
-- rtp->rtcp->rtt_count++;
-- } else if (rtcp_debug_test_addr(&sock_in)) {
-- ast_verbose("Internal RTCP NTP clock skew detected: "
-- "lsr=%u, now=%u, dlsr=%u (%d:%03dms), "
-- "diff=%d\n",
-- lsr, comp, dlsr, dlsr / 65536,
-- (dlsr % 65536) * 1000 / 65536,
-- dlsr - (comp - lsr));
-- }
-- }
--
-- rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]);
-- reported_jitter = (double) rtp->rtcp->reported_jitter;
--
-- if (rtp->rtcp->reported_jitter_count == 0)
-- rtp->rtcp->reported_minjitter = reported_jitter;
--
-- if (reported_jitter < rtp->rtcp->reported_minjitter)
-- rtp->rtcp->reported_minjitter = reported_jitter;
--
-- if (reported_jitter > rtp->rtcp->reported_maxjitter)
-- rtp->rtcp->reported_maxjitter = reported_jitter;
--
-- reported_normdev_jitter_current = normdev_compute(rtp->rtcp->reported_normdev_jitter, reported_jitter, rtp->rtcp->reported_jitter_count);
--
-- rtp->rtcp->reported_stdev_jitter = stddev_compute(rtp->rtcp->reported_stdev_jitter, reported_jitter, rtp->rtcp->reported_normdev_jitter, reported_normdev_jitter_current, rtp->rtcp->reported_jitter_count);
--
-- rtp->rtcp->reported_normdev_jitter = reported_normdev_jitter_current;
--
-- rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff;
--
-- reported_lost = (double) rtp->rtcp->reported_lost;
--
-- /* using same counter as for jitter */
-- if (rtp->rtcp->reported_jitter_count == 0)
-- rtp->rtcp->reported_minlost = reported_lost;
--
-- if (reported_lost < rtp->rtcp->reported_minlost)
-- rtp->rtcp->reported_minlost = reported_lost;
--
-- if (reported_lost > rtp->rtcp->reported_maxlost)
-- rtp->rtcp->reported_maxlost = reported_lost;
--
-- reported_normdev_lost_current = normdev_compute(rtp->rtcp->reported_normdev_lost, reported_lost, rtp->rtcp->reported_jitter_count);
--
-- rtp->rtcp->reported_stdev_lost = stddev_compute(rtp->rtcp->reported_stdev_lost, reported_lost, rtp->rtcp->reported_normdev_lost, reported_normdev_lost_current, rtp->rtcp->reported_jitter_count);
--
-- rtp->rtcp->reported_normdev_lost = reported_normdev_lost_current;
--
-- rtp->rtcp->reported_jitter_count++;
--
-- if (rtcp_debug_test_addr(&sock_in)) {
-- ast_verbose(" Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24));
-- ast_verbose(" Packets lost so far: %d\n", rtp->rtcp->reported_lost);
-- ast_verbose(" Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff));
-- ast_verbose(" Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16);
-- ast_verbose(" Interarrival jitter: %u\n", rtp->rtcp->reported_jitter);
-- ast_verbose(" Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096);
-- ast_verbose(" DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0);
-- if (rtt)
-- ast_verbose(" RTT: %lu(sec)\n", (unsigned long) rtt);
-- }
--
-- if (rtt) {
-- manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From: %s:%d\r\n"
-- "PT: %d(%s)\r\n"
-- "ReceptionReports: %d\r\n"
-- "SenderSSRC: %u\r\n"
-- "FractionLost: %ld\r\n"
-- "PacketsLost: %d\r\n"
-- "HighestSequence: %ld\r\n"
-- "SequenceNumberCycles: %ld\r\n"
-- "IAJitter: %u\r\n"
-- "LastSR: %lu.%010lu\r\n"
-- "DLSR: %4.4f(sec)\r\n"
-- "RTT: %llu(sec)\r\n",
-- ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port),
-- pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown",
-- rc,
-- rtcpheader[i + 1],
-- (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24),
-- rtp->rtcp->reported_lost,
-- (long) (ntohl(rtcpheader[i + 2]) & 0xffff),
-- (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16,
-- rtp->rtcp->reported_jitter,
-- (unsigned long) ntohl(rtcpheader[i + 4]) >> 16, ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096,
-- ntohl(rtcpheader[i + 5])/65536.0,
-- (unsigned long long)rtt);
-- } else {
-- manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From: %s:%d\r\n"
-- "PT: %d(%s)\r\n"
-- "ReceptionReports: %d\r\n"
-- "SenderSSRC: %u\r\n"
-- "FractionLost: %ld\r\n"
-- "PacketsLost: %d\r\n"
-- "HighestSequence: %ld\r\n"
-- "SequenceNumberCycles: %ld\r\n"
-- "IAJitter: %u\r\n"
-- "LastSR: %lu.%010lu\r\n"
-- "DLSR: %4.4f(sec)\r\n",
-- ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port),
-- pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown",
-- rc,
-- rtcpheader[i + 1],
-- (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24),
-- rtp->rtcp->reported_lost,
-- (long) (ntohl(rtcpheader[i + 2]) & 0xffff),
-- (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16,
-- rtp->rtcp->reported_jitter,
-- (unsigned long) ntohl(rtcpheader[i + 4]) >> 16,
-- ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096,
-- ntohl(rtcpheader[i + 5])/65536.0);
-- }
-- break;
-- case RTCP_PT_FUR:
-- if (rtcp_debug_test_addr(&sock_in))
-- ast_verbose("Received an RTCP Fast Update Request\n");
-- rtp->f.frametype = AST_FRAME_CONTROL;
-- rtp->f.subclass = AST_CONTROL_VIDUPDATE;
-- rtp->f.datalen = 0;
-- rtp->f.samples = 0;
-- rtp->f.mallocd = 0;
-- rtp->f.src = "RTP";
-- f = &rtp->f;
-- break;
-- case RTCP_PT_SDES:
-- if (rtcp_debug_test_addr(&sock_in))
-- ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
-- break;
-- case RTCP_PT_BYE:
-- if (rtcp_debug_test_addr(&sock_in))
-- ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
-- break;
-- default:
-- ast_debug(1, "Unknown RTCP packet (pt=%d) received from %s:%d\n", pt, ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
-- break;
-- }
-- position += (length + 1);
-- }
-- rtp->rtcp->rtcp_info = 1;
-- return f;
--}
--
--static void calc_rxstamp(struct timeval *when, struct ast_rtp *rtp, unsigned int timestamp, int mark)
--{
-- struct timeval now;
-- double transit;
-- double current_time;
-- double d;
-- double dtv;
-- double prog;
--
-- double normdev_rxjitter_current;
-- if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) {
-- gettimeofday(&rtp->rxcore, NULL);
-- rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000;
-- /* map timestamp to a real time */
-- rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */
-- rtp->rxcore.tv_sec -= timestamp / 8000;
-- rtp->rxcore.tv_usec -= (timestamp % 8000) * 125;
-- /* Round to 0.1ms for nice, pretty timestamps */
-- rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100;
-- if (rtp->rxcore.tv_usec < 0) {
-- /* Adjust appropriately if necessary */
-- rtp->rxcore.tv_usec += 1000000;
-- rtp->rxcore.tv_sec -= 1;
-- }
-- }
--
-- gettimeofday(&now,NULL);
-- /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */
-- when->tv_sec = rtp->rxcore.tv_sec + timestamp / 8000;
-- when->tv_usec = rtp->rxcore.tv_usec + (timestamp % 8000) * 125;
-- if (when->tv_usec >= 1000000) {
-- when->tv_usec -= 1000000;
-- when->tv_sec += 1;
-- }
-- prog = (double)((timestamp-rtp->seedrxts)/8000.);
-- dtv = (double)rtp->drxcore + (double)(prog);
-- current_time = (double)now.tv_sec + (double)now.tv_usec/1000000;
-- transit = current_time - dtv;
-- d = transit - rtp->rxtransit;
-- rtp->rxtransit = transit;
-- if (d<0)
-- d=-d;
-- rtp->rxjitter += (1./16.) * (d - rtp->rxjitter);
-- if (rtp->rtcp && rtp->rxjitter > rtp->rtcp->maxrxjitter)
-- rtp->rtcp->maxrxjitter = rtp->rxjitter;
-- if (rtp->rtcp->rxjitter_count == 1)
-- rtp->rtcp->minrxjitter = rtp->rxjitter;
-- if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter)
-- rtp->rtcp->minrxjitter = rtp->rxjitter;
--
-- normdev_rxjitter_current = normdev_compute(rtp->rtcp->normdev_rxjitter,rtp->rxjitter,rtp->rtcp->rxjitter_count);
-- rtp->rtcp->stdev_rxjitter = stddev_compute(rtp->rtcp->stdev_rxjitter,rtp->rxjitter,rtp->rtcp->normdev_rxjitter,normdev_rxjitter_current,rtp->rtcp->rxjitter_count);
--
-- rtp->rtcp->normdev_rxjitter = normdev_rxjitter_current;
-- rtp->rtcp->rxjitter_count++;
--}
--
--/*! \brief Perform a Packet2Packet RTP write */
--static int bridge_p2p_rtp_write(struct ast_rtp *rtp, struct ast_rtp *bridged, unsigned int *rtpheader, int len, int hdrlen)
--{
-- int res = 0, payload = 0, bridged_payload = 0, mark;
-- struct rtpPayloadType rtpPT;
-- int reconstruct = ntohl(rtpheader[0]);
--
-- /* Get fields from packet */
-- payload = (reconstruct & 0x7f0000) >> 16;
-- mark = (((reconstruct & 0x800000) >> 23) != 0);
--
-- /* Check what the payload value should be */
-- rtpPT = ast_rtp_lookup_pt(rtp, payload);
--
-- /* If the payload is DTMF, and we are listening for DTMF - then feed it into the core */
-- if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) && !rtpPT.isAstFormat && rtpPT.code == AST_RTP_DTMF)
-- return -1;
--
-- /* Otherwise adjust bridged payload to match */
-- bridged_payload = ast_rtp_lookup_code(bridged, rtpPT.isAstFormat, rtpPT.code);
--
-- /* If the payload coming in is not one of the negotiated ones then send it to the core, this will cause formats to change and the bridge to break */
-- if (!bridged->current_RTP_PT[bridged_payload].code)
-- return -1;
--
--
-- /* If the mark bit has not been sent yet... do it now */
-- if (!ast_test_flag(rtp, FLAG_P2P_SENT_MARK)) {
-- mark = 1;
-- ast_set_flag(rtp, FLAG_P2P_SENT_MARK);
-- }
--
-- /* Reconstruct part of the packet */
-- reconstruct &= 0xFF80FFFF;
-- reconstruct |= (bridged_payload << 16);
-- reconstruct |= (mark << 23);
-- rtpheader[0] = htonl(reconstruct);
--
-- /* Send the packet back out */
-- res = sendto(bridged->s, (void *)rtpheader, len, 0, (struct sockaddr *)&bridged->them, sizeof(bridged->them));
-- if (res < 0) {
-- if (!bridged->nat || (bridged->nat && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
-- ast_debug(1, "RTP Transmission error of packet to %s:%d: %s\n", ast_inet_ntoa(bridged->them.sin_addr), ntohs(bridged->them.sin_port), strerror(errno));
-- } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) {
-- if (option_debug || rtpdebug)
-- ast_debug(0, "RTP NAT: Can't write RTP to private address %s:%d, waiting for other end to send audio...\n", ast_inet_ntoa(bridged->them.sin_addr), ntohs(bridged->them.sin_port));
-- ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN);
-- }
-- return 0;
-- } else if (rtp_debug_test_addr(&bridged->them))
-- ast_verbose("Sent RTP P2P packet to %s:%u (type %-2.2d, len %-6.6u)\n", ast_inet_ntoa(bridged->them.sin_addr), ntohs(bridged->them.sin_port), bridged_payload, len - hdrlen);
--
-- return 0;
--}
--
--struct ast_frame *ast_rtp_read(struct ast_rtp *rtp)
--{
-- int res;
-- struct sockaddr_in sock_in;
-- socklen_t len;
-- unsigned int seqno;
-- int version;
-- int payloadtype;
-- int hdrlen = 12;
-- int padding;
-- int mark;
-- int ext;
-- int cc;
-- unsigned int ssrc;
-- unsigned int timestamp;
-- unsigned int *rtpheader;
-- struct rtpPayloadType rtpPT;
-- struct ast_rtp *bridged = NULL;
-- int prev_seqno;
--
-- /* If time is up, kill it */
-- if (rtp->sending_digit)
-- ast_rtp_senddigit_continuation(rtp);
--
-- len = sizeof(sock_in);
--
-- /* Cache where the header will go */
-- res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET,
-- 0, (struct sockaddr *)&sock_in, &len);
--
-- /* If strict RTP protection is enabled see if we need to learn this address or if the packet should be dropped */
-- if (rtp->strict_rtp_state == STRICT_RTP_LEARN) {
-- /* Copy over address that this packet was received on */
-- memcpy(&rtp->strict_rtp_address, &sock_in, sizeof(rtp->strict_rtp_address));
-- /* Now move over to actually protecting the RTP port */
-- rtp->strict_rtp_state = STRICT_RTP_CLOSED;
-- ast_debug(1, "Learned remote address is %s:%d for strict RTP purposes, now protecting the port.\n", ast_inet_ntoa(rtp->strict_rtp_address.sin_addr), ntohs(rtp->strict_rtp_address.sin_port));
-- } else if (rtp->strict_rtp_state == STRICT_RTP_CLOSED) {
-- /* If the address we previously learned doesn't match the address this packet came in on simply drop it */
-- if ((rtp->strict_rtp_address.sin_addr.s_addr != sock_in.sin_addr.s_addr) || (rtp->strict_rtp_address.sin_port != sock_in.sin_port)) {
-- ast_debug(1, "Received RTP packet from %s:%d, dropping due to strict RTP protection. Expected it to be from %s:%d\n", ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port), ast_inet_ntoa(rtp->strict_rtp_address.sin_addr), ntohs(rtp->strict_rtp_address.sin_port));
-- return &ast_null_frame;
-- }
-- }
--
-- rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET);
-- if (res < 0) {
-- ast_assert(errno != EBADF);
-- if (errno != EAGAIN) {
-- ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up.\n", strerror(errno));
-- return NULL;
-- }
-- return &ast_null_frame;
-- }
--
-- if (res < hdrlen) {
-- ast_log(LOG_WARNING, "RTP Read too short\n");
-- return &ast_null_frame;
-- }
--
-- /* Get fields */
-- seqno = ntohl(rtpheader[0]);
--
-- /* Check RTP version */
-- version = (seqno & 0xC0000000) >> 30;
-- if (!version) {
-- /* If the two high bits are 0, this might be a
-- * STUN message, so process it. stun_handle_packet()
-- * answers to requests, and it returns STUN_ACCEPT
-- * if the request is valid.
-- */
-- if ((stun_handle_packet(rtp->s, &sock_in, rtp->rawdata + AST_FRIENDLY_OFFSET, res, NULL, NULL) == STUN_ACCEPT) &&
-- (!rtp->them.sin_port && !rtp->them.sin_addr.s_addr)) {
-- memcpy(&rtp->them, &sock_in, sizeof(rtp->them));
-- }
-- return &ast_null_frame;
-- }
--
--#if 0 /* Allow to receive RTP stream with closed transmission path */
-- /* If we don't have the other side's address, then ignore this */
-- if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
-- return &ast_null_frame;
--#endif
--
-- /* Send to whoever send to us if NAT is turned on */
-- if (rtp->nat) {
-- if ((rtp->them.sin_addr.s_addr != sock_in.sin_addr.s_addr) ||
-- (rtp->them.sin_port != sock_in.sin_port)) {
-- rtp->them = sock_in;
-- if (rtp->rtcp) {
-- int h = 0;
-- memcpy(&rtp->rtcp->them, &sock_in, sizeof(rtp->rtcp->them));
-- h = ntohs(rtp->them.sin_port);
-- rtp->rtcp->them.sin_port = htons(h + 1);
-- }
-- rtp->rxseqno = 0;
-- ast_set_flag(rtp, FLAG_NAT_ACTIVE);
-- if (option_debug || rtpdebug)
-- ast_debug(0, "RTP NAT: Got audio from other end. Now sending to address %s:%d\n", ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port));
-- }
-- }
--
-- /* If we are bridged to another RTP stream, send direct */
-- if ((bridged = ast_rtp_get_bridged(rtp)) && !bridge_p2p_rtp_write(rtp, bridged, rtpheader, res, hdrlen))
-- return &ast_null_frame;
--
-- if (version != 2)
-- return &ast_null_frame;
--
-- payloadtype = (seqno & 0x7f0000) >> 16;
-- padding = seqno & (1 << 29);
-- mark = seqno & (1 << 23);
-- ext = seqno & (1 << 28);
-- cc = (seqno & 0xF000000) >> 24;
-- seqno &= 0xffff;
-- timestamp = ntohl(rtpheader[1]);
-- ssrc = ntohl(rtpheader[2]);
--
-- if (!mark && rtp->rxssrc && rtp->rxssrc != ssrc) {
-- if (option_debug || rtpdebug)
-- ast_debug(0, "Forcing Marker bit, because SSRC has changed\n");
-- mark = 1;
-- }
--
-- rtp->rxssrc = ssrc;
--
-- if (padding) {
-- /* Remove padding bytes */
-- res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1];
-- }
--
-- if (cc) {
-- /* CSRC fields present */
-- hdrlen += cc*4;
-- }
--
-- if (ext) {
-- /* RTP Extension present */
-- hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2;
-- hdrlen += 4;
-- if (option_debug) {
-- int profile;
-- profile = (ntohl(rtpheader[3]) & 0xffff0000) >> 16;
-- if (profile == 0x505a)
-- ast_debug(1, "Found Zfone extension in RTP stream - zrtp - not supported.\n");
-- else
-- ast_debug(1, "Found unknown RTP Extensions %x\n", profile);
-- }
-- }
--
-- if (res < hdrlen) {
-- ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen);
-- return &ast_null_frame;
-- }
--
-- rtp->rxcount++; /* Only count reasonably valid packets, this'll make the rtcp stats more accurate */
--
-- if (rtp->rxcount==1) {
-- /* This is the first RTP packet successfully received from source */
-- rtp->seedrxseqno = seqno;
-- }
--
-- /* Do not schedule RR if RTCP isn't run */
-- if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) {
-- /* Schedule transmission of Receiver Report */
-- rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
-- }
-- if ((int)rtp->lastrxseqno - (int)seqno > 100) /* if so it would indicate that the sender cycled; allow for misordering */
-- rtp->cycles += RTP_SEQ_MOD;
--
-- prev_seqno = rtp->lastrxseqno;
--
-- rtp->lastrxseqno = seqno;
--
-- if (!rtp->themssrc)
-- rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */
--
-- if (rtp_debug_test_addr(&sock_in))
-- ast_verbose("Got RTP packet from %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
-- ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port), payloadtype, seqno, timestamp,res - hdrlen);
--
-- rtpPT = ast_rtp_lookup_pt(rtp, payloadtype);
-- if (!rtpPT.isAstFormat) {
-- struct ast_frame *f = NULL;
--
-- /* This is special in-band data that's not one of our codecs */
-- if (rtpPT.code == AST_RTP_DTMF) {
-- /* It's special -- rfc2833 process it */
-- if (rtp_debug_test_addr(&sock_in)) {
-- unsigned char *data;
-- unsigned int event;
-- unsigned int event_end;
-- unsigned int duration;
-- data = rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen;
-- event = ntohl(*((unsigned int *)(data)));
-- event >>= 24;
-- event_end = ntohl(*((unsigned int *)(data)));
-- event_end <<= 8;
-- event_end >>= 24;
-- duration = ntohl(*((unsigned int *)(data)));
-- duration &= 0xFFFF;
-- ast_verbose("Got RTP RFC2833 from %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u, mark %d, event %08x, end %d, duration %-5.5d) \n", ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port), payloadtype, seqno, timestamp, res - hdrlen, (mark?1:0), event, ((event_end & 0x80)?1:0), duration);
-- }
-- f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp);
-- } else if (rtpPT.code == AST_RTP_CISCO_DTMF) {
-- /* It's really special -- process it the Cisco way */
-- if (rtp->lastevent <= seqno || (rtp->lastevent >= 65530 && seqno <= 6)) {
-- f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
-- rtp->lastevent = seqno;
-- }
-- } else if (rtpPT.code == AST_RTP_CN) {
-- /* Comfort Noise */
-- f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
-- } else {
-- ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", payloadtype, ast_inet_ntoa(rtp->them.sin_addr));
-- }
-- return f ? f : &ast_null_frame;
-- }
-- rtp->lastrxformat = rtp->f.subclass = rtpPT.code;
-- rtp->f.frametype = (rtp->f.subclass & AST_FORMAT_AUDIO_MASK) ? AST_FRAME_VOICE : (rtp->f.subclass & AST_FORMAT_VIDEO_MASK) ? AST_FRAME_VIDEO : AST_FRAME_TEXT;
--
-- rtp->rxseqno = seqno;
--
-- if (rtp->dtmfcount) {
-- rtp->dtmfcount -= (timestamp - rtp->lastrxts);
--
-- if (rtp->dtmfcount < 0) {
-- rtp->dtmfcount = 0;
-- }
--
-- if (rtp->resp && !rtp->dtmfcount) {
-- struct ast_frame *f;
-- f = send_dtmf(rtp, AST_FRAME_DTMF_END);
-- rtp->resp = 0;
-- return f;
-- }
-- }
--
-- /* Record received timestamp as last received now */
-- rtp->lastrxts = timestamp;
--
-- rtp->f.mallocd = 0;
-- rtp->f.datalen = res - hdrlen;
-- rtp->f.data.ptr = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET;
-- rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
-- rtp->f.seqno = seqno;
--
-- if (rtp->f.subclass == AST_FORMAT_T140 && (int)seqno - (prev_seqno+1) > 0 && (int)seqno - (prev_seqno+1) < 10) {
-- unsigned char *data = rtp->f.data.ptr;
--
-- memmove(rtp->f.data.ptr+3, rtp->f.data.ptr, rtp->f.datalen);
-- rtp->f.datalen +=3;
-- *data++ = 0xEF;
-- *data++ = 0xBF;
-- *data = 0xBD;
-- }
--
-- if (rtp->f.subclass == AST_FORMAT_T140RED) {
-- unsigned char *data = rtp->f.data.ptr;
-- unsigned char *header_end;
-- int num_generations;
-- int header_length;
-- int length;
-- int diff =(int)seqno - (prev_seqno+1); /* if diff = 0, no drop*/
-- int x;
--
-- rtp->f.subclass = AST_FORMAT_T140;
-- header_end = memchr(data, ((*data) & 0x7f), rtp->f.datalen);
-- header_end++;
--
-- header_length = header_end - data;
-- num_generations = header_length / 4;
-- length = header_length;
--
-- if (!diff) {
-- for (x = 0; x < num_generations; x++)
-- length += data[x * 4 + 3];
--
-- if (!(rtp->f.datalen - length))
-- return &ast_null_frame;
--
-- rtp->f.data.ptr += length;
-- rtp->f.datalen -= length;
-- } else if (diff > num_generations && diff < 10) {
-- length -= 3;
-- rtp->f.data.ptr += length;
-- rtp->f.datalen -= length;
--
-- data = rtp->f.data.ptr;
-- *data++ = 0xEF;
-- *data++ = 0xBF;
-- *data = 0xBD;
-- } else {
-- for ( x = 0; x < num_generations - diff; x++)
-- length += data[x * 4 + 3];
--
-- rtp->f.data.ptr += length;
-- rtp->f.datalen -= length;
-- }
-- }
--
-- if (rtp->f.subclass & AST_FORMAT_AUDIO_MASK) {
-- rtp->f.samples = ast_codec_get_samples(&rtp->f);
-- if (rtp->f.subclass == AST_FORMAT_SLINEAR)
-- ast_frame_byteswap_be(&rtp->f);
-- calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark);
-- /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */
-- ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO);
-- rtp->f.ts = timestamp / 8;
-- rtp->f.len = rtp->f.samples / ((ast_format_rate(rtp->f.subclass) / 1000));
-- } else if (rtp->f.subclass & AST_FORMAT_VIDEO_MASK) {
-- /* Video -- samples is # of samples vs. 90000 */
-- if (!rtp->lastividtimestamp)
-- rtp->lastividtimestamp = timestamp;
-- rtp->f.samples = timestamp - rtp->lastividtimestamp;
-- rtp->lastividtimestamp = timestamp;
-- rtp->f.delivery.tv_sec = 0;
-- rtp->f.delivery.tv_usec = 0;
-- /* Pass the RTP marker bit as bit 0 in the subclass field.
-- * This is ok because subclass is actually a bitmask, and
-- * the low bits represent audio formats, that are not
-- * involved here since we deal with video.
-- */
-- if (mark)
-- rtp->f.subclass |= 0x1;
-- } else {
-- /* TEXT -- samples is # of samples vs. 1000 */
-- if (!rtp->lastitexttimestamp)
-- rtp->lastitexttimestamp = timestamp;
-- rtp->f.samples = timestamp - rtp->lastitexttimestamp;
-- rtp->lastitexttimestamp = timestamp;
-- rtp->f.delivery.tv_sec = 0;
-- rtp->f.delivery.tv_usec = 0;
-- }
-- rtp->f.src = "RTP";
-- return &rtp->f;
--}
--
--/* The following array defines the MIME Media type (and subtype) for each
-- of our codecs, or RTP-specific data type. */
--static const struct mimeType {
-- struct rtpPayloadType payloadType;
-- char *type;
-- char *subtype;
-- unsigned int sample_rate;
--} mimeTypes[] = {
-- {{1, AST_FORMAT_G723_1}, "audio", "G723", 8000},
-- {{1, AST_FORMAT_GSM}, "audio", "GSM", 8000},
-- {{1, AST_FORMAT_ULAW}, "audio", "PCMU", 8000},
-- {{1, AST_FORMAT_ULAW}, "audio", "G711U", 8000},
-- {{1, AST_FORMAT_ALAW}, "audio", "PCMA", 8000},
-- {{1, AST_FORMAT_ALAW}, "audio", "G711A", 8000},
-- {{1, AST_FORMAT_G726}, "audio", "G726-32", 8000},
-- {{1, AST_FORMAT_ADPCM}, "audio", "DVI4", 8000},
-- {{1, AST_FORMAT_SLINEAR}, "audio", "L16", 8000},
-- {{1, AST_FORMAT_LPC10}, "audio", "LPC", 8000},
-- {{1, AST_FORMAT_G729A}, "audio", "G729", 8000},
-- {{1, AST_FORMAT_G729A}, "audio", "G729A", 8000},
-- {{1, AST_FORMAT_G729A}, "audio", "G.729", 8000},
-- {{1, AST_FORMAT_SPEEX}, "audio", "speex", 8000},
-- {{1, AST_FORMAT_ILBC}, "audio", "iLBC", 8000},
-- /* this is the sample rate listed in the RTP profile for the G.722
-- codec, *NOT* the actual sample rate of the media stream
-- */
-- {{1, AST_FORMAT_G722}, "audio", "G722", 8000},
-- {{1, AST_FORMAT_G726_AAL2}, "audio", "AAL2-G726-32", 8000},
-- {{0, AST_RTP_DTMF}, "audio", "telephone-event", 8000},
-- {{0, AST_RTP_CISCO_DTMF}, "audio", "cisco-telephone-event", 8000},
-- {{0, AST_RTP_CN}, "audio", "CN", 8000},
-- {{1, AST_FORMAT_JPEG}, "video", "JPEG", 90000},
-- {{1, AST_FORMAT_PNG}, "video", "PNG", 90000},
-- {{1, AST_FORMAT_H261}, "video", "H261", 90000},
-- {{1, AST_FORMAT_H263}, "video", "H263", 90000},
-- {{1, AST_FORMAT_H263_PLUS}, "video", "h263-1998", 90000},
-- {{1, AST_FORMAT_H264}, "video", "H264", 90000},
-- {{1, AST_FORMAT_MP4_VIDEO}, "video", "MP4V-ES", 90000},
-- {{1, AST_FORMAT_T140RED}, "text", "RED", 1000},
-- {{1, AST_FORMAT_T140}, "text", "T140", 1000},
-- {{1, AST_FORMAT_SIREN7}, "audio", "G7221", 16000},
-- {{1, AST_FORMAT_SIREN14}, "audio", "G7221", 32000},
--};
--
--/*!
-- * \brief Mapping between Asterisk codecs and rtp payload types
-- *
-- * Static (i.e., well-known) RTP payload types for our "AST_FORMAT..."s:
-- * also, our own choices for dynamic payload types. This is our master
-- * table for transmission
-- *
-- * See http://www.iana.org/assignments/rtp-parameters for a list of
-- * assigned values
-- */
--static const struct rtpPayloadType static_RTP_PT[MAX_RTP_PT] = {
-- [0] = {1, AST_FORMAT_ULAW},
--#ifdef USE_DEPRECATED_G726
-- [2] = {1, AST_FORMAT_G726}, /* Technically this is G.721, but if Cisco can do it, so can we... */
--#endif
-- [3] = {1, AST_FORMAT_GSM},
-- [4] = {1, AST_FORMAT_G723_1},
-- [5] = {1, AST_FORMAT_ADPCM}, /* 8 kHz */
-- [6] = {1, AST_FORMAT_ADPCM}, /* 16 kHz */
-- [7] = {1, AST_FORMAT_LPC10},
-- [8] = {1, AST_FORMAT_ALAW},
-- [9] = {1, AST_FORMAT_G722},
-- [10] = {1, AST_FORMAT_SLINEAR}, /* 2 channels */
-- [11] = {1, AST_FORMAT_SLINEAR}, /* 1 channel */
-- [13] = {0, AST_RTP_CN},
-- [16] = {1, AST_FORMAT_ADPCM}, /* 11.025 kHz */
-- [17] = {1, AST_FORMAT_ADPCM}, /* 22.050 kHz */
-- [18] = {1, AST_FORMAT_G729A},
-- [19] = {0, AST_RTP_CN}, /* Also used for CN */
-- [26] = {1, AST_FORMAT_JPEG},
-- [31] = {1, AST_FORMAT_H261},
-- [34] = {1, AST_FORMAT_H263},
-- [97] = {1, AST_FORMAT_ILBC},
-- [98] = {1, AST_FORMAT_H263_PLUS},
-- [99] = {1, AST_FORMAT_H264},
-- [101] = {0, AST_RTP_DTMF},
-- [102] = {1, AST_FORMAT_SIREN7},
-- [103] = {1, AST_FORMAT_H263_PLUS},
-- [104] = {1, AST_FORMAT_MP4_VIDEO},
-- [105] = {1, AST_FORMAT_T140RED}, /* Real time text chat (with redundancy encoding) */
-- [106] = {1, AST_FORMAT_T140}, /* Real time text chat */
-- [110] = {1, AST_FORMAT_SPEEX},
-- [111] = {1, AST_FORMAT_G726},
-- [112] = {1, AST_FORMAT_G726_AAL2},
-- [115] = {1, AST_FORMAT_SIREN14},
-- [121] = {0, AST_RTP_CISCO_DTMF}, /* Must be type 121 */
--};
--
--void ast_rtp_pt_clear(struct ast_rtp* rtp)
--{
-- int i;
--
-- if (!rtp)
-- return;
--
-- rtp_bridge_lock(rtp);
--
-- for (i = 0; i < MAX_RTP_PT; ++i) {
-- rtp->current_RTP_PT[i].isAstFormat = 0;
-- rtp->current_RTP_PT[i].code = 0;
-- }
--
-- rtp->rtp_lookup_code_cache_isAstFormat = 0;
-- rtp->rtp_lookup_code_cache_code = 0;
-- rtp->rtp_lookup_code_cache_result = 0;
--
-- rtp_bridge_unlock(rtp);
--}
--
--void ast_rtp_pt_default(struct ast_rtp* rtp)
--{
-- int i;
--
-- rtp_bridge_lock(rtp);
--
-- /* Initialize to default payload types */
-- for (i = 0; i < MAX_RTP_PT; ++i) {
-- rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
-- rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
-- }
--
-- rtp->rtp_lookup_code_cache_isAstFormat = 0;
-- rtp->rtp_lookup_code_cache_code = 0;
-- rtp->rtp_lookup_code_cache_result = 0;
--
-- rtp_bridge_unlock(rtp);
--}
--
--void ast_rtp_pt_copy(struct ast_rtp *dest, struct ast_rtp *src)
--{
-- unsigned int i;
--
-- rtp_bridge_lock(dest);
-- rtp_bridge_lock(src);
--
-- for (i = 0; i < MAX_RTP_PT; ++i) {
-- dest->current_RTP_PT[i].isAstFormat =
-- src->current_RTP_PT[i].isAstFormat;
-- dest->current_RTP_PT[i].code =
-- src->current_RTP_PT[i].code;
-- }
-- dest->rtp_lookup_code_cache_isAstFormat = 0;
-- dest->rtp_lookup_code_cache_code = 0;
-- dest->rtp_lookup_code_cache_result = 0;
--
-- rtp_bridge_unlock(src);
-- rtp_bridge_unlock(dest);
--}
--
--/*! \brief Get channel driver interface structure */
--static struct ast_rtp_protocol *get_proto(struct ast_channel *chan)
--{
-- struct ast_rtp_protocol *cur = NULL;
--
-- AST_RWLIST_RDLOCK(&protos);
-- AST_RWLIST_TRAVERSE(&protos, cur, list) {
-- if (cur->type == chan->tech->type)
-- break;
-- }
-- AST_RWLIST_UNLOCK(&protos);
--
-- return cur;
--}
--
--int ast_rtp_early_bridge(struct ast_channel *c0, struct ast_channel *c1)
--{
-- struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */
-- struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */
-- struct ast_rtp *tdestp = NULL, *tsrcp = NULL; /* Text RTP channels */
-- struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
-- enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED, text_dest_res = AST_RTP_GET_FAILED;
-- enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED, text_src_res = AST_RTP_GET_FAILED;
-- int srccodec, destcodec, nat_active = 0;
--
-- /* Lock channels */
-- ast_channel_lock(c0);
-- if (c1) {
-- while (ast_channel_trylock(c1)) {
-- ast_channel_unlock(c0);
-- usleep(1);
-- ast_channel_lock(c0);
-- }
-- }
--
-- /* Find channel driver interfaces */
-- destpr = get_proto(c0);
-- if (c1)
-- srcpr = get_proto(c1);
-- if (!destpr) {
-- ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", c0->name);
-- ast_channel_unlock(c0);
-- if (c1)
-- ast_channel_unlock(c1);
-- return -1;
-- }
-- if (!srcpr) {
-- ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", c1 ? c1->name : "<unspecified>");
-- ast_channel_unlock(c0);
-- if (c1)
-- ast_channel_unlock(c1);
-- return -1;
-- }
--
-- /* Get audio, video and text interface (if native bridge is possible) */
-- audio_dest_res = destpr->get_rtp_info(c0, &destp);
-- video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(c0, &vdestp) : AST_RTP_GET_FAILED;
-- text_dest_res = destpr->get_trtp_info ? destpr->get_trtp_info(c0, &tdestp) : AST_RTP_GET_FAILED;
-- if (srcpr) {
-- audio_src_res = srcpr->get_rtp_info(c1, &srcp);
-- video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(c1, &vsrcp) : AST_RTP_GET_FAILED;
-- text_src_res = srcpr->get_trtp_info ? srcpr->get_trtp_info(c1, &tsrcp) : AST_RTP_GET_FAILED;
-- }
--
-- /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
-- if (audio_dest_res != AST_RTP_TRY_NATIVE || (video_dest_res != AST_RTP_GET_FAILED && video_dest_res != AST_RTP_TRY_NATIVE)) {
-- /* Somebody doesn't want to play... */
-- ast_channel_unlock(c0);
-- if (c1)
-- ast_channel_unlock(c1);
-- return -1;
-- }
-- if (audio_src_res == AST_RTP_TRY_NATIVE && (video_src_res == AST_RTP_GET_FAILED || video_src_res == AST_RTP_TRY_NATIVE) && srcpr->get_codec)
-- srccodec = srcpr->get_codec(c1);
-- else
-- srccodec = 0;
-- if (audio_dest_res == AST_RTP_TRY_NATIVE && (video_dest_res == AST_RTP_GET_FAILED || video_dest_res == AST_RTP_TRY_NATIVE) && destpr->get_codec)
-- destcodec = destpr->get_codec(c0);
-- else
-- destcodec = 0;
-- /* Ensure we have at least one matching codec */
-- if (srcp && !(srccodec & destcodec)) {
-- ast_channel_unlock(c0);
-- ast_channel_unlock(c1);
-- return 0;
-- }
-- /* Consider empty media as non-existent */
-- if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr)
-- srcp = NULL;
-- if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
-- nat_active = 1;
-- /* Bridge media early */
-- if (destpr->set_rtp_peer(c0, srcp, vsrcp, tsrcp, srccodec, nat_active))
-- ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
-- ast_channel_unlock(c0);
-- if (c1)
-- ast_channel_unlock(c1);
-- ast_debug(1, "Setting early bridge SDP of '%s' with that of '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
-- return 0;
--}
--
--int ast_rtp_make_compatible(struct ast_channel *dest, struct ast_channel *src, int media)
--{
-- struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */
-- struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */
-- struct ast_rtp *tdestp = NULL, *tsrcp = NULL; /* Text RTP channels */
-- struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
-- enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED, text_dest_res = AST_RTP_GET_FAILED;
-- enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED, text_src_res = AST_RTP_GET_FAILED;
-- int srccodec, destcodec;
--
-- /* Lock channels */
-- ast_channel_lock(dest);
-- while (ast_channel_trylock(src)) {
-- ast_channel_unlock(dest);
-- usleep(1);
-- ast_channel_lock(dest);
-- }
--
-- /* Find channel driver interfaces */
-- if (!(destpr = get_proto(dest))) {
-- ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", dest->name);
-- ast_channel_unlock(dest);
-- ast_channel_unlock(src);
-- return 0;
-- }
-- if (!(srcpr = get_proto(src))) {
-- ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", src->name);
-- ast_channel_unlock(dest);
-- ast_channel_unlock(src);
-- return 0;
-- }
--
-- /* Get audio and video interface (if native bridge is possible) */
-- audio_dest_res = destpr->get_rtp_info(dest, &destp);
-- video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED;
-- text_dest_res = destpr->get_trtp_info ? destpr->get_trtp_info(dest, &tdestp) : AST_RTP_GET_FAILED;
-- audio_src_res = srcpr->get_rtp_info(src, &srcp);
-- video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED;
-- text_src_res = srcpr->get_trtp_info ? srcpr->get_trtp_info(src, &tsrcp) : AST_RTP_GET_FAILED;
--
-- /* Ensure we have at least one matching codec */
-- if (srcpr->get_codec)
-- srccodec = srcpr->get_codec(src);
-- else
-- srccodec = 0;
-- if (destpr->get_codec)
-- destcodec = destpr->get_codec(dest);
-- else
-- destcodec = 0;
--
-- /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
-- if (audio_dest_res != AST_RTP_TRY_NATIVE || (video_dest_res != AST_RTP_GET_FAILED && video_dest_res != AST_RTP_TRY_NATIVE) || audio_src_res != AST_RTP_TRY_NATIVE || (video_src_res != AST_RTP_GET_FAILED && video_src_res != AST_RTP_TRY_NATIVE) || !(srccodec & destcodec)) {
-- /* Somebody doesn't want to play... */
-- ast_channel_unlock(dest);
-- ast_channel_unlock(src);
-- return 0;
-- }
-- ast_rtp_pt_copy(destp, srcp);
-- if (vdestp && vsrcp)
-- ast_rtp_pt_copy(vdestp, vsrcp);
-- if (tdestp && tsrcp)
-- ast_rtp_pt_copy(tdestp, tsrcp);
-- if (media) {
-- /* Bridge early */
-- if (destpr->set_rtp_peer(dest, srcp, vsrcp, tsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
-- ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name);
-- }
-- ast_channel_unlock(dest);
-- ast_channel_unlock(src);
-- ast_debug(1, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name);
-- return 1;
--}
--
--/*! \brief Make a note of a RTP payload type that was seen in a SDP "m=" line.
-- * By default, use the well-known value for this type (although it may
-- * still be set to a different value by a subsequent "a=rtpmap:" line)
-- */
--void ast_rtp_set_m_type(struct ast_rtp* rtp, int pt)
--{
-- if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].code == 0)
-- return; /* bogus payload type */
--
-- rtp_bridge_lock(rtp);
-- rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
-- rtp_bridge_unlock(rtp);
--}
--
--/*! \brief remove setting from payload type list if the rtpmap header indicates
-- an unknown media type */
--void ast_rtp_unset_m_type(struct ast_rtp* rtp, int pt)
--{
-- if (pt < 0 || pt > MAX_RTP_PT)
-- return; /* bogus payload type */
--
-- rtp_bridge_lock(rtp);
-- rtp->current_RTP_PT[pt].isAstFormat = 0;
-- rtp->current_RTP_PT[pt].code = 0;
-- rtp_bridge_unlock(rtp);
--}
--
--/*! \brief Make a note of a RTP payload type (with MIME type) that was seen in
-- * an SDP "a=rtpmap:" line.
-- * \return 0 if the MIME type was found and set, -1 if it wasn't found
-- */
--int ast_rtp_set_rtpmap_type_rate(struct ast_rtp *rtp, int pt,
-- char *mimeType, char *mimeSubtype,
-- enum ast_rtp_options options,
-- unsigned int sample_rate)
--{
-- unsigned int i;
-- int found = 0;
--
-- if (pt < 0 || pt > MAX_RTP_PT)
-- return -1; /* bogus payload type */
--
-- rtp_bridge_lock(rtp);
--
-- for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) {
-- const struct mimeType *t = &mimeTypes[i];
--
-- if (strcasecmp(mimeSubtype, t->subtype)) {
-- continue;
-- }
--
-- if (strcasecmp(mimeType, t->type)) {
-- continue;
-- }
--
-- /* if both sample rates have been supplied, and they don't match,
-- then this not a match; if one has not been supplied, then the
-- rates are not compared */
-- if (sample_rate && t->sample_rate &&
-- (sample_rate != t->sample_rate)) {
-- continue;
-- }
--
-- found = 1;
-- rtp->current_RTP_PT[pt] = t->payloadType;
--
-- if ((t->payloadType.code == AST_FORMAT_G726) &&
-- t->payloadType.isAstFormat &&
-- (options & AST_RTP_OPT_G726_NONSTANDARD)) {
-- rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2;
-- }
--
-- break;
-- }
--
-- rtp_bridge_unlock(rtp);
--
-- return (found ? 0 : -2);
--}
--
--int ast_rtp_set_rtpmap_type(struct ast_rtp *rtp, int pt,
-- char *mimeType, char *mimeSubtype,
-- enum ast_rtp_options options)
--{
-- return ast_rtp_set_rtpmap_type_rate(rtp, pt, mimeType, mimeSubtype, options, 0);
--}
--
--/*! \brief Return the union of all of the codecs that were set by rtp_set...() calls
-- * They're returned as two distinct sets: AST_FORMATs, and AST_RTPs */
--void ast_rtp_get_current_formats(struct ast_rtp* rtp,
-- int* astFormats, int* nonAstFormats)
--{
-- int pt;
--
-- rtp_bridge_lock(rtp);
--
-- *astFormats = *nonAstFormats = 0;
-- for (pt = 0; pt < MAX_RTP_PT; ++pt) {
-- if (rtp->current_RTP_PT[pt].isAstFormat) {
-- *astFormats |= rtp->current_RTP_PT[pt].code;
-- } else {
-- *nonAstFormats |= rtp->current_RTP_PT[pt].code;
-- }
-- }
--
-- rtp_bridge_unlock(rtp);
--}
--
--struct rtpPayloadType ast_rtp_lookup_pt(struct ast_rtp* rtp, int pt)
--{
-- struct rtpPayloadType result;
--
-- result.isAstFormat = result.code = 0;
--
-- if (pt < 0 || pt > MAX_RTP_PT)
-- return result; /* bogus payload type */
--
-- /* Start with negotiated codecs */
-- rtp_bridge_lock(rtp);
-- result = rtp->current_RTP_PT[pt];
-- rtp_bridge_unlock(rtp);
--
-- /* If it doesn't exist, check our static RTP type list, just in case */
-- if (!result.code)
-- result = static_RTP_PT[pt];
--
-- return result;
--}
--
--/*! \brief Looks up an RTP code out of our *static* outbound list */
--int ast_rtp_lookup_code(struct ast_rtp* rtp, const int isAstFormat, const int code)
--{
-- int pt = 0;
--
-- rtp_bridge_lock(rtp);
--
-- if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat &&
-- code == rtp->rtp_lookup_code_cache_code) {
-- /* Use our cached mapping, to avoid the overhead of the loop below */
-- pt = rtp->rtp_lookup_code_cache_result;
-- rtp_bridge_unlock(rtp);
-- return pt;
-- }
--
-- /* Check the dynamic list first */
-- for (pt = 0; pt < MAX_RTP_PT; ++pt) {
-- if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) {
-- rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
-- rtp->rtp_lookup_code_cache_code = code;
-- rtp->rtp_lookup_code_cache_result = pt;
-- rtp_bridge_unlock(rtp);
-- return pt;
-- }
-- }
--
-- /* Then the static list */
-- for (pt = 0; pt < MAX_RTP_PT; ++pt) {
-- if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) {
-- rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
-- rtp->rtp_lookup_code_cache_code = code;
-- rtp->rtp_lookup_code_cache_result = pt;
-- rtp_bridge_unlock(rtp);
-- return pt;
-- }
-- }
--
-- rtp_bridge_unlock(rtp);
--
-- return -1;
--}
--
--const char *ast_rtp_lookup_mime_subtype(const int isAstFormat, const int code,
-- enum ast_rtp_options options)
--{
-- unsigned int i;
--
-- for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) {
-- if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) {
-- if (isAstFormat &&
-- (code == AST_FORMAT_G726_AAL2) &&
-- (options & AST_RTP_OPT_G726_NONSTANDARD))
-- return "G726-32";
-- else
-- return mimeTypes[i].subtype;
-- }
-- }
--
-- return "";
--}
--
--unsigned int ast_rtp_lookup_sample_rate(int isAstFormat, int code)
--{
-- unsigned int i;
--
-- for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) {
-- if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) {
-- return mimeTypes[i].sample_rate;
-- }
-- }
--
-- return 0;
--}
--
--char *ast_rtp_lookup_mime_multiple(char *buf, size_t size, const int capability,
-- const int isAstFormat, enum ast_rtp_options options)
--{
-- int format;
-- unsigned len;
-- char *end = buf;
-- char *start = buf;
--
-- if (!buf || !size)
-- return NULL;
--
-- snprintf(end, size, "0x%x (", capability);
--
-- len = strlen(end);
-- end += len;
-- size -= len;
-- start = end;
--
-- for (format = 1; format < AST_RTP_MAX; format <<= 1) {
-- if (capability & format) {
-- const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options);
--
-- snprintf(end, size, "%s|", name);
-- len = strlen(end);
-- end += len;
-- size -= len;
-- }
-- }
--
-- if (start == end)
-- ast_copy_string(start, "nothing)", size);
-- else if (size > 1)
-- *(end -1) = ')';
--
-- return buf;
--}
--
--/*! \brief Open RTP or RTCP socket for a session.
-- * Print a message on failure.
-- */
--static int rtp_socket(const char *type)
--{
-- int s = socket(AF_INET, SOCK_DGRAM, 0);
-- if (s < 0) {
-- if (type == NULL)
-- type = "RTP/RTCP";
-- ast_log(LOG_WARNING, "Unable to allocate %s socket: %s\n", type, strerror(errno));
-- } else {
-- long flags = fcntl(s, F_GETFL);
-- fcntl(s, F_SETFL, flags | O_NONBLOCK);
--#ifdef SO_NO_CHECK
-- if (nochecksums)
-- setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
--#endif
-- }
-- return s;
--}
--
--/*!
-- * \brief Initialize a new RTCP session.
-- *
-- * \returns The newly initialized RTCP session.
-- */
--static struct ast_rtcp *ast_rtcp_new(void)
--{
-- struct ast_rtcp *rtcp;
--
-- if (!(rtcp = ast_calloc(1, sizeof(*rtcp))))
-- return NULL;
-- rtcp->s = rtp_socket("RTCP");
-- rtcp->us.sin_family = AF_INET;
-- rtcp->them.sin_family = AF_INET;
-- rtcp->schedid = -1;
--
-- if (rtcp->s < 0) {
-- ast_free(rtcp);
-- return NULL;
-- }
--
-- return rtcp;
--}
--
--/*!
-- * \brief Initialize a new RTP structure.
-- *
-- */
--void ast_rtp_new_init(struct ast_rtp *rtp)
--{
--#ifdef P2P_INTENSE
-- ast_mutex_init(&rtp->bridge_lock);
--#endif
--
-- rtp->them.sin_family = AF_INET;
-- rtp->us.sin_family = AF_INET;
-- rtp->ssrc = ast_random();
-- rtp->seqno = ast_random() & 0xffff;
-- ast_set_flag(rtp, FLAG_HAS_DTMF);
-- rtp->strict_rtp_state = (strictrtp ? STRICT_RTP_LEARN : STRICT_RTP_OPEN);
--}
--
--struct ast_rtp *ast_rtp_new_with_bindaddr(struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode, struct in_addr addr)
--{
-- struct ast_rtp *rtp;
-- int x;
-- int startplace;
--
-- if (!(rtp = ast_calloc(1, sizeof(*rtp))))
-- return NULL;
--
-- ast_rtp_new_init(rtp);
--
-- rtp->s = rtp_socket("RTP");
-- if (rtp->s < 0)
-- goto fail;
-- if (sched && rtcpenable) {
-- rtp->sched = sched;
-- rtp->rtcp = ast_rtcp_new();
-- }
--
-- /*
-- * Try to bind the RTP port, x, and possibly the RTCP port, x+1 as well.
-- * Start from a random (even, by RTP spec) port number, and
-- * iterate until success or no ports are available.
-- * Note that the requirement of RTP port being even, or RTCP being the
-- * next one, cannot be enforced in presence of a NAT box because the
-- * mapping is not under our control.
-- */
-- x = (rtpend == rtpstart) ? rtpstart : (ast_random() % (rtpend - rtpstart)) + rtpstart;
-- x = x & ~1; /* make it an even number */
-- startplace = x; /* remember the starting point */
-- /* this is constant across the loop */
-- rtp->us.sin_addr = addr;
-- if (rtp->rtcp)
-- rtp->rtcp->us.sin_addr = addr;
-- for (;;) {
-- rtp->us.sin_port = htons(x);
-- if (!bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) {
-- /* bind succeeded, if no rtcp then we are done */
-- if (!rtp->rtcp)
-- break;
-- /* have rtcp, try to bind it */
-- rtp->rtcp->us.sin_port = htons(x + 1);
-- if (!bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us)))
-- break; /* success again, we are really done */
-- /*
-- * RTCP bind failed, so close and recreate the
-- * already bound RTP socket for the next round.
-- */
-- close(rtp->s);
-- rtp->s = rtp_socket("RTP");
-- if (rtp->s < 0)
-- goto fail;
-- }
-- /*
-- * If we get here, there was an error in one of the bind()
-- * calls, so make sure it is nothing unexpected.
-- */
-- if (errno != EADDRINUSE) {
-- /* We got an error that wasn't expected, abort! */
-- ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno));
-- goto fail;
-- }
-- /*
-- * One of the ports is in use. For the next iteration,
-- * increment by two and handle wraparound.
-- * If we reach the starting point, then declare failure.
-- */
-- x += 2;
-- if (x > rtpend)
-- x = (rtpstart + 1) & ~1;
-- if (x == startplace) {
-- ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n");
-- goto fail;
-- }
-- }
-- rtp->sched = sched;
-- rtp->io = io;
-- if (callbackmode) {
-- rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
-- ast_set_flag(rtp, FLAG_CALLBACK_MODE);
-- }
-- ast_rtp_pt_default(rtp);
-- return rtp;
--
--fail:
-- if (rtp->s >= 0)
-- close(rtp->s);
-- if (rtp->rtcp) {
-- close(rtp->rtcp->s);
-- ast_free(rtp->rtcp);
-- }
-- ast_free(rtp);
-- return NULL;
--}
--
--struct ast_rtp *ast_rtp_new(struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode)
--{
-- struct in_addr ia;
--
-- memset(&ia, 0, sizeof(ia));
-- return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
--}
--
--int ast_rtp_setqos(struct ast_rtp *rtp, int type_of_service, int class_of_service, char *desc)
--{
-- return ast_netsock_set_qos(rtp->s, type_of_service, class_of_service, desc);
--}
--
--void ast_rtp_new_source(struct ast_rtp *rtp)
--{
-- if (rtp) {
-- rtp->set_marker_bit = 1;
-- }
-- return;
--}
--
--void ast_rtp_set_peer(struct ast_rtp *rtp, struct sockaddr_in *them)
--{
-- rtp->them.sin_port = them->sin_port;
-- rtp->them.sin_addr = them->sin_addr;
-- if (rtp->rtcp) {
-- int h = ntohs(them->sin_port);
-- rtp->rtcp->them.sin_port = htons(h + 1);
-- rtp->rtcp->them.sin_addr = them->sin_addr;
-- }
-- rtp->rxseqno = 0;
-- /* If strict RTP protection is enabled switch back to the learn state so we don't drop packets from above */
-- if (strictrtp)
-- rtp->strict_rtp_state = STRICT_RTP_LEARN;
--}
--
--int ast_rtp_get_peer(struct ast_rtp *rtp, struct sockaddr_in *them)
--{
-- if ((them->sin_family != AF_INET) ||
-- (them->sin_port != rtp->them.sin_port) ||
-- (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) {
-- them->sin_family = AF_INET;
-- them->sin_port = rtp->them.sin_port;
-- them->sin_addr = rtp->them.sin_addr;
-- return 1;
-- }
-- return 0;
--}
--
--void ast_rtp_get_us(struct ast_rtp *rtp, struct sockaddr_in *us)
--{
-- *us = rtp->us;
--}
--
--struct ast_rtp *ast_rtp_get_bridged(struct ast_rtp *rtp)
--{
-- struct ast_rtp *bridged = NULL;
--
-- rtp_bridge_lock(rtp);
-- bridged = rtp->bridged;
-- rtp_bridge_unlock(rtp);
--
-- return bridged;
--}
--
--void ast_rtp_stop(struct ast_rtp *rtp)
--{
-- if (rtp->rtcp) {
-- AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
-- }
-- if (rtp->red) {
-- AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
-- free(rtp->red);
-- rtp->red = NULL;
-- }
--
-- memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
-- memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
-- if (rtp->rtcp) {
-- memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr));
-- memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port));
-- }
--
-- ast_clear_flag(rtp, FLAG_P2P_SENT_MARK);
--}
--
--void ast_rtp_reset(struct ast_rtp *rtp)
--{
-- memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
-- memset(&rtp->txcore, 0, sizeof(rtp->txcore));
-- memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
-- rtp->lastts = 0;
-- rtp->lastdigitts = 0;
-- rtp->lastrxts = 0;
-- rtp->lastividtimestamp = 0;
-- rtp->lastovidtimestamp = 0;
-- rtp->lastitexttimestamp = 0;
-- rtp->lastotexttimestamp = 0;
-- rtp->lasteventseqn = 0;
-- rtp->lastevent = 0;
-- rtp->lasttxformat = 0;
-- rtp->lastrxformat = 0;
-- rtp->dtmfcount = 0;
-- rtp->dtmfsamples = 0;
-- rtp->seqno = 0;
-- rtp->rxseqno = 0;
--}
--
--/*! Get QoS values from RTP and RTCP data (used in "sip show channelstats") */
--unsigned int ast_rtp_get_qosvalue(struct ast_rtp *rtp, enum ast_rtp_qos_vars value)
--{
-- if (rtp == NULL) {
-- if (option_debug > 1)
-- ast_log(LOG_DEBUG, "NO RTP Structure? Kidding me? \n");
-- return 0;
-- }
-- if (option_debug > 1 && rtp->rtcp == NULL) {
-- ast_log(LOG_DEBUG, "NO RTCP structure. Maybe in RTP p2p bridging mode? \n");
-- }
--
-- switch (value) {
-- case AST_RTP_TXCOUNT:
-- return (unsigned int) rtp->txcount;
-- case AST_RTP_RXCOUNT:
-- return (unsigned int) rtp->rxcount;
-- case AST_RTP_TXJITTER:
-- return (unsigned int) (rtp->rxjitter * 100.0);
-- case AST_RTP_RXJITTER:
-- return (unsigned int) (rtp->rtcp ? (rtp->rtcp->reported_jitter / (unsigned int) 65536.0) : 0);
-- case AST_RTP_RXPLOSS:
-- return rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0;
-- case AST_RTP_TXPLOSS:
-- return rtp->rtcp ? rtp->rtcp->reported_lost : 0;
-- case AST_RTP_RTT:
-- return (unsigned int) (rtp->rtcp ? (rtp->rtcp->rtt * 100) : 0);
-- }
-- return 0; /* To make the compiler happy */
--}
--
--static double __ast_rtp_get_qos(struct ast_rtp *rtp, const char *qos, int *found)
--{
-- *found = 1;
--
-- if (!strcasecmp(qos, "remote_maxjitter"))
-- return rtp->rtcp->reported_maxjitter * 1000.0;
-- if (!strcasecmp(qos, "remote_minjitter"))
-- return rtp->rtcp->reported_minjitter * 1000.0;
-- if (!strcasecmp(qos, "remote_normdevjitter"))
-- return rtp->rtcp->reported_normdev_jitter * 1000.0;
-- if (!strcasecmp(qos, "remote_stdevjitter"))
-- return sqrt(rtp->rtcp->reported_stdev_jitter) * 1000.0;
--
-- if (!strcasecmp(qos, "local_maxjitter"))
-- return rtp->rtcp->maxrxjitter * 1000.0;
-- if (!strcasecmp(qos, "local_minjitter"))
-- return rtp->rtcp->minrxjitter * 1000.0;
-- if (!strcasecmp(qos, "local_normdevjitter"))
-- return rtp->rtcp->normdev_rxjitter * 1000.0;
-- if (!strcasecmp(qos, "local_stdevjitter"))
-- return sqrt(rtp->rtcp->stdev_rxjitter) * 1000.0;
--
-- if (!strcasecmp(qos, "maxrtt"))
-- return rtp->rtcp->maxrtt * 1000.0;
-- if (!strcasecmp(qos, "minrtt"))
-- return rtp->rtcp->minrtt * 1000.0;
-- if (!strcasecmp(qos, "normdevrtt"))
-- return rtp->rtcp->normdevrtt * 1000.0;
-- if (!strcasecmp(qos, "stdevrtt"))
-- return sqrt(rtp->rtcp->stdevrtt) * 1000.0;
--
-- *found = 0;
--
-- return 0.0;
--}
--
--int ast_rtp_get_qos(struct ast_rtp *rtp, const char *qos, char *buf, unsigned int buflen)
--{
-- double value;
-- int found;
--
-- value = __ast_rtp_get_qos(rtp, qos, &found);
--
-- if (!found)
-- return -1;
--
-- snprintf(buf, buflen, "%.0lf", value);
--
-- return 0;
--}
--
--void ast_rtp_set_vars(struct ast_channel *chan, struct ast_rtp *rtp) {
-- char *audioqos;
-- char *audioqos_jitter;
-- char *audioqos_loss;
-- char *audioqos_rtt;
-- struct ast_channel *bridge;
--
-- if (!rtp || !chan)
-- return;
--
-- bridge = ast_bridged_channel(chan);
--
-- audioqos = ast_rtp_get_quality(rtp, NULL, RTPQOS_SUMMARY);
-- audioqos_jitter = ast_rtp_get_quality(rtp, NULL, RTPQOS_JITTER);
-- audioqos_loss = ast_rtp_get_quality(rtp, NULL, RTPQOS_LOSS);
-- audioqos_rtt = ast_rtp_get_quality(rtp, NULL, RTPQOS_RTT);
--
-- pbx_builtin_setvar_helper(chan, "RTPAUDIOQOS", audioqos);
-- pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSJITTER", audioqos_jitter);
-- pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSLOSS", audioqos_loss);
-- pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSRTT", audioqos_rtt);
--
-- if (!bridge)
-- return;
--
-- pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSBRIDGED", audioqos);
-- pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSJITTERBRIDGED", audioqos_jitter);
-- pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSLOSSBRIDGED", audioqos_loss);
-- pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSRTTBRIDGED", audioqos_rtt);
--}
--
--static char *__ast_rtp_get_quality_jitter(struct ast_rtp *rtp)
--{
-- /*
-- *ssrc our ssrc
-- *themssrc their ssrc
-- *lp lost packets
-- *rxjitter our calculated jitter(rx)
-- *rxcount no. received packets
-- *txjitter reported jitter of the other end
-- *txcount transmitted packets
-- *rlp remote lost packets
-- *rtt round trip time
-- */
--#define RTCP_JITTER_FORMAT1 \
-- "minrxjitter=%f;" \
-- "maxrxjitter=%f;" \
-- "avgrxjitter=%f;" \
-- "stdevrxjitter=%f;" \
-- "reported_minjitter=%f;" \
-- "reported_maxjitter=%f;" \
-- "reported_avgjitter=%f;" \
-- "reported_stdevjitter=%f;"
--
--#define RTCP_JITTER_FORMAT2 \
-- "rxjitter=%f;"
--
-- if (rtp->rtcp && rtp->rtcp->rtcp_info) {
-- snprintf(rtp->rtcp->quality_jitter, sizeof(rtp->rtcp->quality_jitter), RTCP_JITTER_FORMAT1,
-- rtp->rtcp->minrxjitter,
-- rtp->rtcp->maxrxjitter,
-- rtp->rtcp->normdev_rxjitter,
-- sqrt(rtp->rtcp->stdev_rxjitter),
-- rtp->rtcp->reported_minjitter,
-- rtp->rtcp->reported_maxjitter,
-- rtp->rtcp->reported_normdev_jitter,
-- sqrt(rtp->rtcp->reported_stdev_jitter)
-- );
-- } else {
-- snprintf(rtp->rtcp->quality_jitter, sizeof(rtp->rtcp->quality_jitter), RTCP_JITTER_FORMAT2,
-- rtp->rxjitter
-- );
-- }
--
-- return rtp->rtcp->quality_jitter;
--
--#undef RTCP_JITTER_FORMAT1
--#undef RTCP_JITTER_FORMAT2
--}
--
--static char *__ast_rtp_get_quality_loss(struct ast_rtp *rtp)
--{
-- unsigned int lost;
-- unsigned int extended;
-- unsigned int expected;
-- int fraction;
--
--#define RTCP_LOSS_FORMAT1 \
-- "minrxlost=%f;" \
-- "maxrxlost=%f;" \
-- "avgrxlostr=%f;" \
-- "stdevrxlost=%f;" \
-- "reported_minlost=%f;" \
-- "reported_maxlost=%f;" \
-- "reported_avglost=%f;" \
-- "reported_stdevlost=%f;"
--
--#define RTCP_LOSS_FORMAT2 \
-- "lost=%d;" \
-- "expected=%d;"
--
-- if (rtp->rtcp && rtp->rtcp->rtcp_info && rtp->rtcp->maxrxlost > 0) {
-- snprintf(rtp->rtcp->quality_loss, sizeof(rtp->rtcp->quality_loss), RTCP_LOSS_FORMAT1,
-- rtp->rtcp->minrxlost,
-- rtp->rtcp->maxrxlost,
-- rtp->rtcp->normdev_rxlost,
-- sqrt(rtp->rtcp->stdev_rxlost),
-- rtp->rtcp->reported_minlost,
-- rtp->rtcp->reported_maxlost,
-- rtp->rtcp->reported_normdev_lost,
-- sqrt(rtp->rtcp->reported_stdev_lost)
-- );
-- } else {
-- extended = rtp->cycles + rtp->lastrxseqno;
-- expected = extended - rtp->seedrxseqno + 1;
-- if (rtp->rxcount > expected)
-- expected += rtp->rxcount - expected;
-- lost = expected - rtp->rxcount;
--
-- if (!expected || lost <= 0)
-- fraction = 0;
-- else
-- fraction = (lost << 8) / expected;
--
-- snprintf(rtp->rtcp->quality_loss, sizeof(rtp->rtcp->quality_loss), RTCP_LOSS_FORMAT2,
-- lost,
-- expected
-- );
-- }
--
-- return rtp->rtcp->quality_loss;
--
--#undef RTCP_LOSS_FORMAT1
--#undef RTCP_LOSS_FORMAT2
--}
--
--static char *__ast_rtp_get_quality_rtt(struct ast_rtp *rtp)
--{
-- if (rtp->rtcp && rtp->rtcp->rtcp_info) {
-- snprintf(rtp->rtcp->quality_rtt, sizeof(rtp->rtcp->quality_rtt), "minrtt=%f;maxrtt=%f;avgrtt=%f;stdevrtt=%f;",
-- rtp->rtcp->minrtt,
-- rtp->rtcp->maxrtt,
-- rtp->rtcp->normdevrtt,
-- sqrt(rtp->rtcp->stdevrtt)
-- );
-- } else {
-- snprintf(rtp->rtcp->quality_rtt, sizeof(rtp->rtcp->quality_rtt), "Not available");
-- }
--
-- return rtp->rtcp->quality_rtt;
--}
--
--static char *__ast_rtp_get_quality(struct ast_rtp *rtp)
--{
-- /*
-- *ssrc our ssrc
-- *themssrc their ssrc
-- *lp lost packets
-- *rxjitter our calculated jitter(rx)
-- *rxcount no. received packets
-- *txjitter reported jitter of the other end
-- *txcount transmitted packets
-- *rlp remote lost packets
-- *rtt round trip time
-- */
--
-- if (rtp->rtcp && rtp->rtcp->rtcp_info) {
-- snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality),
-- "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f",
-- rtp->ssrc,
-- rtp->themssrc,
-- rtp->rtcp->expected_prior - rtp->rtcp->received_prior,
-- rtp->rxjitter,
-- rtp->rxcount,
-- (double)rtp->rtcp->reported_jitter / 65536.0,
-- rtp->txcount,
-- rtp->rtcp->reported_lost,
-- rtp->rtcp->rtt
-- );
-- } else {
-- snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality), "ssrc=%u;themssrc=%u;rxjitter=%f;rxcount=%u;txcount=%u;",
-- rtp->ssrc,
-- rtp->themssrc,
-- rtp->rxjitter,
-- rtp->rxcount,
-- rtp->txcount
-- );
-- }
--
-- return rtp->rtcp->quality;
--}
--
--char *ast_rtp_get_quality(struct ast_rtp *rtp, struct ast_rtp_quality *qual, enum ast_rtp_quality_type qtype)
--{
-- if (qual && rtp) {
-- qual->local_ssrc = rtp->ssrc;
-- qual->local_jitter = rtp->rxjitter;
-- qual->local_count = rtp->rxcount;
-- qual->remote_ssrc = rtp->themssrc;
-- qual->remote_count = rtp->txcount;
--
-- if (rtp->rtcp) {
-- qual->local_lostpackets = rtp->rtcp->expected_prior - rtp->rtcp->received_prior;
-- qual->remote_lostpackets = rtp->rtcp->reported_lost;
-- qual->remote_jitter = rtp->rtcp->reported_jitter / 65536.0;
-- qual->rtt = rtp->rtcp->rtt;
-- }
-- }
--
-- switch (qtype) {
-- case RTPQOS_SUMMARY:
-- return __ast_rtp_get_quality(rtp);
-- case RTPQOS_JITTER:
-- return __ast_rtp_get_quality_jitter(rtp);
-- case RTPQOS_LOSS:
-- return __ast_rtp_get_quality_loss(rtp);
-- case RTPQOS_RTT:
-- return __ast_rtp_get_quality_rtt(rtp);
-- }
--
-- return NULL;
--}
--
--void ast_rtp_destroy(struct ast_rtp *rtp)
--{
-- if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) {
-- /*Print some info on the call here */
-- ast_verbose(" RTP-stats\n");
-- ast_verbose("* Our Receiver:\n");
-- ast_verbose(" SSRC: %u\n", rtp->themssrc);
-- ast_verbose(" Received packets: %u\n", rtp->rxcount);
-- ast_verbose(" Lost packets: %u\n", rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0);
-- ast_verbose(" Jitter: %.4f\n", rtp->rxjitter);
-- ast_verbose(" Transit: %.4f\n", rtp->rxtransit);
-- ast_verbose(" RR-count: %u\n", rtp->rtcp ? rtp->rtcp->rr_count : 0);
-- ast_verbose("* Our Sender:\n");
-- ast_verbose(" SSRC: %u\n", rtp->ssrc);
-- ast_verbose(" Sent packets: %u\n", rtp->txcount);
-- ast_verbose(" Lost packets: %u\n", rtp->rtcp ? rtp->rtcp->reported_lost : 0);
-- ast_verbose(" Jitter: %u\n", rtp->rtcp ? (rtp->rtcp->reported_jitter / (unsigned int)65536.0) : 0);
-- ast_verbose(" SR-count: %u\n", rtp->rtcp ? rtp->rtcp->sr_count : 0);
-- ast_verbose(" RTT: %f\n", rtp->rtcp ? rtp->rtcp->rtt : 0);
-- }
--
-- manager_event(EVENT_FLAG_REPORTING, "RTPReceiverStat", "SSRC: %u\r\n"
-- "ReceivedPackets: %u\r\n"
-- "LostPackets: %u\r\n"
-- "Jitter: %.4f\r\n"
-- "Transit: %.4f\r\n"
-- "RRCount: %u\r\n",
-- rtp->themssrc,
-- rtp->rxcount,
-- rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0,
-- rtp->rxjitter,
-- rtp->rxtransit,
-- rtp->rtcp ? rtp->rtcp->rr_count : 0);
-- manager_event(EVENT_FLAG_REPORTING, "RTPSenderStat", "SSRC: %u\r\n"
-- "SentPackets: %u\r\n"
-- "LostPackets: %u\r\n"
-- "Jitter: %u\r\n"
-- "SRCount: %u\r\n"
-- "RTT: %f\r\n",
-- rtp->ssrc,
-- rtp->txcount,
-- rtp->rtcp ? rtp->rtcp->reported_lost : 0,
-- rtp->rtcp ? rtp->rtcp->reported_jitter : 0,
-- rtp->rtcp ? rtp->rtcp->sr_count : 0,
-- rtp->rtcp ? rtp->rtcp->rtt : 0);
-- if (rtp->smoother)
-- ast_smoother_free(rtp->smoother);
-- if (rtp->ioid)
-- ast_io_remove(rtp->io, rtp->ioid);
-- if (rtp->s > -1)
-- close(rtp->s);
-- if (rtp->rtcp) {
-- AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
-- close(rtp->rtcp->s);
-- ast_free(rtp->rtcp);
-- rtp->rtcp=NULL;
-- }
--#ifdef P2P_INTENSE
-- ast_mutex_destroy(&rtp->bridge_lock);
--#endif
-- ast_free(rtp);
--}
--
--static unsigned int calc_txstamp(struct ast_rtp *rtp, struct timeval *delivery)
--{
-- struct timeval t;
-- long ms;
-- if (ast_tvzero(rtp->txcore)) {
-- rtp->txcore = ast_tvnow();
-- /* Round to 20ms for nice, pretty timestamps */
-- rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
-- }
-- /* Use previous txcore if available */
-- t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
-- ms = ast_tvdiff_ms(t, rtp->txcore);
-- if (ms < 0)
-- ms = 0;
-- /* Use what we just got for next time */
-- rtp->txcore = t;
-- return (unsigned int) ms;
--}
--
--/*! \brief Send begin frames for DTMF */
--int ast_rtp_senddigit_begin(struct ast_rtp *rtp, char digit)
--{
-- unsigned int *rtpheader;
-- int hdrlen = 12, res = 0, i = 0, payload = 0;
-- char data[256];
--
-- if ((digit <= '9') && (digit >= '0'))
-- digit -= '0';
-- else if (digit == '*')
-- digit = 10;
-- else if (digit == '#')
-- digit = 11;
-- else if ((digit >= 'A') && (digit <= 'D'))
-- digit = digit - 'A' + 12;
-- else if ((digit >= 'a') && (digit <= 'd'))
-- digit = digit - 'a' + 12;
-- else {
-- ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
-- return 0;
-- }
--
-- /* If we have no peer, return immediately */
-- if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
-- return 0;
--
-- payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF);
--
-- rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
-- rtp->send_duration = 160;
-- rtp->lastdigitts = rtp->lastts + rtp->send_duration;
--
-- /* Get a pointer to the header */
-- rtpheader = (unsigned int *)data;
-- rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
-- rtpheader[1] = htonl(rtp->lastdigitts);
-- rtpheader[2] = htonl(rtp->ssrc);
--
-- for (i = 0; i < 2; i++) {
-- rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
-- res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
-- if (res < 0)
-- ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n",
-- ast_inet_ntoa(rtp->them.sin_addr),
-- ntohs(rtp->them.sin_port), strerror(errno));
-- if (rtp_debug_test_addr(&rtp->them))
-- ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
-- ast_inet_ntoa(rtp->them.sin_addr),
-- ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
-- /* Increment sequence number */
-- rtp->seqno++;
-- /* Increment duration */
-- rtp->send_duration += 160;
-- /* Clear marker bit and set seqno */
-- rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
-- }
--
-- /* Since we received a begin, we can safely store the digit and disable any compensation */
-- rtp->sending_digit = 1;
-- rtp->send_digit = digit;
-- rtp->send_payload = payload;
--
-- return 0;
--}
--
--/*! \brief Send continuation frame for DTMF */
--static int ast_rtp_senddigit_continuation(struct ast_rtp *rtp)
--{
-- unsigned int *rtpheader;
-- int hdrlen = 12, res = 0;
-- char data[256];
--
-- if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
-- return 0;
--
-- /* Setup packet to send */
-- rtpheader = (unsigned int *)data;
-- rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno));
-- rtpheader[1] = htonl(rtp->lastdigitts);
-- rtpheader[2] = htonl(rtp->ssrc);
-- rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration));
-- rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
--
-- /* Transmit */
-- res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
-- if (res < 0)
-- ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
-- ast_inet_ntoa(rtp->them.sin_addr),
-- ntohs(rtp->them.sin_port), strerror(errno));
-- if (rtp_debug_test_addr(&rtp->them))
-- ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
-- ast_inet_ntoa(rtp->them.sin_addr),
-- ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
--
-- /* Increment sequence number */
-- rtp->seqno++;
-- /* Increment duration */
-- rtp->send_duration += 160;
--
-- return 0;
--}
--
--/*! \brief Send end packets for DTMF */
--int ast_rtp_senddigit_end(struct ast_rtp *rtp, char digit)
--{
-- unsigned int *rtpheader;
-- int hdrlen = 12, res = 0, i = 0;
-- char data[256];
--
-- /* If no address, then bail out */
-- if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
-- return 0;
--
-- if ((digit <= '9') && (digit >= '0'))
-- digit -= '0';
-- else if (digit == '*')
-- digit = 10;
-- else if (digit == '#')
-- digit = 11;
-- else if ((digit >= 'A') && (digit <= 'D'))
-- digit = digit - 'A' + 12;
-- else if ((digit >= 'a') && (digit <= 'd'))
-- digit = digit - 'a' + 12;
-- else {
-- ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
-- return 0;
-- }
--
-- rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
--
-- rtpheader = (unsigned int *)data;
-- rtpheader[1] = htonl(rtp->lastdigitts);
-- rtpheader[2] = htonl(rtp->ssrc);
-- rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
-- /* Set end bit */
-- rtpheader[3] |= htonl((1 << 23));
--
-- /* Send 3 termination packets */
-- for (i = 0; i < 3; i++) {
-- rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
-- res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
-- rtp->seqno++;
-- if (res < 0)
-- ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
-- ast_inet_ntoa(rtp->them.sin_addr),
-- ntohs(rtp->them.sin_port), strerror(errno));
-- if (rtp_debug_test_addr(&rtp->them))
-- ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
-- ast_inet_ntoa(rtp->them.sin_addr),
-- ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
-- }
-- rtp->lastts += rtp->send_duration;
-- rtp->sending_digit = 0;
-- rtp->send_digit = 0;
--
-- return res;
--}
--
--/*! \brief Public function: Send an H.261 fast update request, some devices need this rather than SIP XML */
--int ast_rtcp_send_h261fur(void *data)
--{
-- struct ast_rtp *rtp = data;
-- int res;
--
-- rtp->rtcp->sendfur = 1;
-- res = ast_rtcp_write(data);
--
-- return res;
--}
--
--/*! \brief Send RTCP sender's report */
--static int ast_rtcp_write_sr(const void *data)
--{
-- struct ast_rtp *rtp = (struct ast_rtp *)data;
-- int res;
-- int len = 0;
-- struct timeval now;
-- unsigned int now_lsw;
-- unsigned int now_msw;
-- unsigned int *rtcpheader;
-- unsigned int lost;
-- unsigned int extended;
-- unsigned int expected;
-- unsigned int expected_interval;
-- unsigned int received_interval;
-- int lost_interval;
-- int fraction;
-- struct timeval dlsr;
-- char bdata[512];
--
-- /* Commented condition is always not NULL if rtp->rtcp is not NULL */
-- if (!rtp || !rtp->rtcp/* || (&rtp->rtcp->them.sin_addr == 0)*/)
-- return 0;
--
-- if (!rtp->rtcp->them.sin_addr.s_addr) { /* This'll stop rtcp for this rtp session */
-- ast_verbose("RTCP SR transmission error, rtcp halted\n");
-- AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
-- return 0;
-- }
--
-- gettimeofday(&now, NULL);
-- timeval2ntp(now, &now_msw, &now_lsw); /* fill thses ones in from utils.c*/
-- rtcpheader = (unsigned int *)bdata;
-- rtcpheader[1] = htonl(rtp->ssrc); /* Our SSRC */
-- rtcpheader[2] = htonl(now_msw); /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970*/
-- rtcpheader[3] = htonl(now_lsw); /* now, LSW */
-- rtcpheader[4] = htonl(rtp->lastts); /* FIXME shouldn't be that, it should be now */
-- rtcpheader[5] = htonl(rtp->txcount); /* No. packets sent */
-- rtcpheader[6] = htonl(rtp->txoctetcount); /* No. bytes sent */
-- len += 28;
--
-- extended = rtp->cycles + rtp->lastrxseqno;
-- expected = extended - rtp->seedrxseqno + 1;
-- if (rtp->rxcount > expected)
-- expected += rtp->rxcount - expected;
-- lost = expected - rtp->rxcount;
-- expected_interval = expected - rtp->rtcp->expected_prior;
-- rtp->rtcp->expected_prior = expected;
-- received_interval = rtp->rxcount - rtp->rtcp->received_prior;
-- rtp->rtcp->received_prior = rtp->rxcount;
-- lost_interval = expected_interval - received_interval;
-- if (expected_interval == 0 || lost_interval <= 0)
-- fraction = 0;
-- else
-- fraction = (lost_interval << 8) / expected_interval;
-- timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
-- rtcpheader[7] = htonl(rtp->themssrc);
-- rtcpheader[8] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff));
-- rtcpheader[9] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff)));
-- rtcpheader[10] = htonl((unsigned int)(rtp->rxjitter * 65536.));
-- rtcpheader[11] = htonl(rtp->rtcp->themrxlsr);
-- rtcpheader[12] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
-- len += 24;
--
-- rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1));
--
-- if (rtp->rtcp->sendfur) {
-- rtcpheader[13] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1);
-- rtcpheader[14] = htonl(rtp->ssrc); /* Our SSRC */
-- len += 8;
-- rtp->rtcp->sendfur = 0;
-- }
--
-- /* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */
-- /* it can change mid call, and SDES can't) */
-- rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
-- rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */
-- rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */
-- len += 12;
--
-- res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
-- if (res < 0) {
-- ast_log(LOG_ERROR, "RTCP SR transmission error to %s:%d, rtcp halted %s\n",ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port), strerror(errno));
-- AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
-- return 0;
-- }
--
-- /* FIXME Don't need to get a new one */
-- gettimeofday(&rtp->rtcp->txlsr, NULL);
-- rtp->rtcp->sr_count++;
--
-- rtp->rtcp->lastsrtxcount = rtp->txcount;
--
-- if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
-- ast_verbose("* Sent RTCP SR to %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
-- ast_verbose(" Our SSRC: %u\n", rtp->ssrc);
-- ast_verbose(" Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096);
-- ast_verbose(" Sent(RTP): %u\n", rtp->lastts);
-- ast_verbose(" Sent packets: %u\n", rtp->txcount);
-- ast_verbose(" Sent octets: %u\n", rtp->txoctetcount);
-- ast_verbose(" Report block:\n");
-- ast_verbose(" Fraction lost: %u\n", fraction);
-- ast_verbose(" Cumulative loss: %u\n", lost);
-- ast_verbose(" IA jitter: %.4f\n", rtp->rxjitter);
-- ast_verbose(" Their last SR: %u\n", rtp->rtcp->themrxlsr);
-- ast_verbose(" DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0));
-- }
-- manager_event(EVENT_FLAG_REPORTING, "RTCPSent", "To: %s:%d\r\n"
-- "OurSSRC: %u\r\n"
-- "SentNTP: %u.%010u\r\n"
-- "SentRTP: %u\r\n"
-- "SentPackets: %u\r\n"
-- "SentOctets: %u\r\n"
-- "ReportBlock:\r\n"
-- "FractionLost: %u\r\n"
-- "CumulativeLoss: %u\r\n"
-- "IAJitter: %.4f\r\n"
-- "TheirLastSR: %u\r\n"
-- "DLSR: %4.4f (sec)\r\n",
-- ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port),
-- rtp->ssrc,
-- (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096,
-- rtp->lastts,
-- rtp->txcount,
-- rtp->txoctetcount,
-- fraction,
-- lost,
-- rtp->rxjitter,
-- rtp->rtcp->themrxlsr,
-- (double)(ntohl(rtcpheader[12])/65536.0));
-- return res;
--}
--
--/*! \brief Send RTCP recipient's report */
--static int ast_rtcp_write_rr(const void *data)
--{
-- struct ast_rtp *rtp = (struct ast_rtp *)data;
-- int res;
-- int len = 32;
-- unsigned int lost;
-- unsigned int extended;
-- unsigned int expected;
-- unsigned int expected_interval;
-- unsigned int received_interval;
-- int lost_interval;
-- struct timeval now;
-- unsigned int *rtcpheader;
-- char bdata[1024];
-- struct timeval dlsr;
-- int fraction;
--
-- double rxlost_current;
--
-- if (!rtp || !rtp->rtcp || (&rtp->rtcp->them.sin_addr == 0))
-- return 0;
--
-- if (!rtp->rtcp->them.sin_addr.s_addr) {
-- ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted\n");
-- AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
-- return 0;
-- }
--
-- extended = rtp->cycles + rtp->lastrxseqno;
-- expected = extended - rtp->seedrxseqno + 1;
-- lost = expected - rtp->rxcount;
-- expected_interval = expected - rtp->rtcp->expected_prior;
-- rtp->rtcp->expected_prior = expected;
-- received_interval = rtp->rxcount - rtp->rtcp->received_prior;
-- rtp->rtcp->received_prior = rtp->rxcount;
-- lost_interval = expected_interval - received_interval;
--
-- if (lost_interval <= 0)
-- rtp->rtcp->rxlost = 0;
-- else rtp->rtcp->rxlost = rtp->rtcp->rxlost;
-- if (rtp->rtcp->rxlost_count == 0)
-- rtp->rtcp->minrxlost = rtp->rtcp->rxlost;
-- if (lost_interval < rtp->rtcp->minrxlost)
-- rtp->rtcp->minrxlost = rtp->rtcp->rxlost;
-- if (lost_interval > rtp->rtcp->maxrxlost)
-- rtp->rtcp->maxrxlost = rtp->rtcp->rxlost;
--
-- rxlost_current = normdev_compute(rtp->rtcp->normdev_rxlost, rtp->rtcp->rxlost, rtp->rtcp->rxlost_count);
-- rtp->rtcp->stdev_rxlost = stddev_compute(rtp->rtcp->stdev_rxlost, rtp->rtcp->rxlost, rtp->rtcp->normdev_rxlost, rxlost_current, rtp->rtcp->rxlost_count);
-- rtp->rtcp->normdev_rxlost = rxlost_current;
-- rtp->rtcp->rxlost_count++;
--
-- if (expected_interval == 0 || lost_interval <= 0)
-- fraction = 0;
-- else
-- fraction = (lost_interval << 8) / expected_interval;
-- gettimeofday(&now, NULL);
-- timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
-- rtcpheader = (unsigned int *)bdata;
-- rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_RR << 16) | ((len/4)-1));
-- rtcpheader[1] = htonl(rtp->ssrc);
-- rtcpheader[2] = htonl(rtp->themssrc);
-- rtcpheader[3] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff));
-- rtcpheader[4] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff)));
-- rtcpheader[5] = htonl((unsigned int)(rtp->rxjitter * 65536.));
-- rtcpheader[6] = htonl(rtp->rtcp->themrxlsr);
-- rtcpheader[7] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
--
-- if (rtp->rtcp->sendfur) {
-- rtcpheader[8] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); /* Header from page 36 in RFC 3550 */
-- rtcpheader[9] = htonl(rtp->ssrc); /* Our SSRC */
-- len += 8;
-- rtp->rtcp->sendfur = 0;
-- }
--
-- /*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos
-- it can change mid call, and SDES can't) */
-- rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
-- rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */
-- rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */
-- len += 12;
--
-- res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
--
-- if (res < 0) {
-- ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno));
-- /* Remove the scheduler */
-- AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
-- return 0;
-- }
--
-- rtp->rtcp->rr_count++;
--
-- if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
-- ast_verbose("\n* Sending RTCP RR to %s:%d\n"
-- " Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n"
-- " IA jitter: %.4f\n"
-- " Their last SR: %u\n"
-- " DLSR: %4.4f (sec)\n\n",
-- ast_inet_ntoa(rtp->rtcp->them.sin_addr),
-- ntohs(rtp->rtcp->them.sin_port),
-- rtp->ssrc, rtp->themssrc, fraction, lost,
-- rtp->rxjitter,
-- rtp->rtcp->themrxlsr,
-- (double)(ntohl(rtcpheader[7])/65536.0));
-- }
--
-- return res;
--}
--
--/*! \brief Write and RTCP packet to the far end
-- * \note Decide if we are going to send an SR (with Reception Block) or RR
-- * RR is sent if we have not sent any rtp packets in the previous interval */
--static int ast_rtcp_write(const void *data)
--{
-- struct ast_rtp *rtp = (struct ast_rtp *)data;
-- int res;
--
-- if (!rtp || !rtp->rtcp)
-- return 0;
--
-- if (rtp->txcount > rtp->rtcp->lastsrtxcount)
-- res = ast_rtcp_write_sr(data);
-- else
-- res = ast_rtcp_write_rr(data);
--
-- return res;
--}
--
--/*! \brief generate comfort noice (CNG) */
--int ast_rtp_sendcng(struct ast_rtp *rtp, int level)
--{
-- unsigned int *rtpheader;
-- int hdrlen = 12;
-- int res;
-- int payload;
-- char data[256];
-- level = 127 - (level & 0x7f);
-- payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN);
--
-- /* If we have no peer, return immediately */
-- if (!rtp->them.sin_addr.s_addr)
-- return 0;
--
-- rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
--
-- /* Get a pointer to the header */
-- rtpheader = (unsigned int *)data;
-- rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++));
-- rtpheader[1] = htonl(rtp->lastts);
-- rtpheader[2] = htonl(rtp->ssrc);
-- data[12] = level;
-- if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
-- res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
-- if (res <0)
-- ast_log(LOG_ERROR, "RTP Comfort Noise Transmission error to %s:%d: %s\n", ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno));
-- if (rtp_debug_test_addr(&rtp->them))
-- ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n"
-- , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen);
--
-- }
-- return 0;
--}
--
--/*! \brief Write RTP packet with audio or video media frames into UDP packet */
--static int ast_rtp_raw_write(struct ast_rtp *rtp, struct ast_frame *f, int codec)
--{
-- unsigned char *rtpheader;
-- int hdrlen = 12;
-- int res;
-- unsigned int ms;
-- int pred;
-- int mark = 0;
--
-- if (rtp->sending_digit) {
-- return 0;
-- }
--
-- ms = calc_txstamp(rtp, &f->delivery);
-- /* Default prediction */
-- if (f->frametype == AST_FRAME_VOICE) {
-- pred = rtp->lastts + f->samples;
--
-- /* Re-calculate last TS */
-- rtp->lastts = rtp->lastts + ms * 8;
-- if (ast_tvzero(f->delivery)) {
-- /* If this isn't an absolute delivery time, Check if it is close to our prediction,
-- and if so, go with our prediction */
-- if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW)
-- rtp->lastts = pred;
-- else {
-- ast_debug(3, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms);
-- mark = 1;
-- }
-- }
-- } else if (f->frametype == AST_FRAME_VIDEO) {
-- mark = f->subclass & 0x1;
-- pred = rtp->lastovidtimestamp + f->samples;
-- /* Re-calculate last TS */
-- rtp->lastts = rtp->lastts + ms * 90;
-- /* If it's close to our prediction, go for it */
-- if (ast_tvzero(f->delivery)) {
-- if (abs(rtp->lastts - pred) < 7200) {
-- rtp->lastts = pred;
-- rtp->lastovidtimestamp += f->samples;
-- } else {
-- ast_debug(3, "Difference is %d, ms is %d (%d), pred/ts/samples %d/%d/%d\n", abs(rtp->lastts - pred), ms, ms * 90, rtp->lastts, pred, f->samples);
-- rtp->lastovidtimestamp = rtp->lastts;
-- }
-- }
-- } else {
-- pred = rtp->lastotexttimestamp + f->samples;
-- /* Re-calculate last TS */
-- rtp->lastts = rtp->lastts + ms * 90;
-- /* If it's close to our prediction, go for it */
-- if (ast_tvzero(f->delivery)) {
-- if (abs(rtp->lastts - pred) < 7200) {
-- rtp->lastts = pred;
-- rtp->lastotexttimestamp += f->samples;
-- } else {
-- ast_debug(3, "Difference is %d, ms is %d (%d), pred/ts/samples %d/%d/%d\n", abs(rtp->lastts - pred), ms, ms * 90, rtp->lastts, pred, f->samples);
-- rtp->lastotexttimestamp = rtp->lastts;
-- }
-- }
-- }
--
-- /* If we have been explicitly told to set the marker bit do so */
-- if (rtp->set_marker_bit) {
-- mark = 1;
-- rtp->set_marker_bit = 0;
-- }
--
-- /* If the timestamp for non-digit packets has moved beyond the timestamp
-- for digits, update the digit timestamp.
-- */
-- if (rtp->lastts > rtp->lastdigitts)
-- rtp->lastdigitts = rtp->lastts;
--
-- if (ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO))
-- rtp->lastts = f->ts * 8;
--
-- /* Get a pointer to the header */
-- rtpheader = (unsigned char *)(f->data.ptr - hdrlen);
--
-- put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23)));
-- put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts));
-- put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc));
--
-- if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
-- res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
-- if (res < 0) {
-- if (!rtp->nat || (rtp->nat && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
-- ast_debug(1, "RTP Transmission error of packet %d to %s:%d: %s\n", rtp->seqno, ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno));
-- } else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) {
-- /* Only give this error message once if we are not RTP debugging */
-- if (option_debug || rtpdebug)
-- ast_debug(0, "RTP NAT: Can't write RTP to private address %s:%d, waiting for other end to send audio...\n", ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port));
-- ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN);
-- }
-- } else {
-- rtp->txcount++;
-- rtp->txoctetcount +=(res - hdrlen);
--
-- /* Do not schedule RR if RTCP isn't run */
-- if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) {
-- rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
-- }
-- }
--
-- if (rtp_debug_test_addr(&rtp->them))
-- ast_verbose("Sent RTP packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
-- ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), codec, rtp->seqno, rtp->lastts,res - hdrlen);
-- }
--
-- rtp->seqno++;
--
-- return 0;
--}
--
--void ast_rtp_codec_setpref(struct ast_rtp *rtp, struct ast_codec_pref *prefs)
--{
-- struct ast_format_list current_format_old, current_format_new;
--
-- /* if no packets have been sent through this session yet, then
-- * changing preferences does not require any extra work
-- */
-- if (rtp->lasttxformat == 0) {
-- rtp->pref = *prefs;
-- return;
-- }
--
-- current_format_old = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat);
--
-- rtp->pref = *prefs;
--
-- current_format_new = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat);
--
-- /* if the framing desired for the current format has changed, we may have to create
-- * or adjust the smoother for this session
-- */
-- if ((current_format_new.inc_ms != 0) &&
-- (current_format_new.cur_ms != current_format_old.cur_ms)) {
-- int new_size = (current_format_new.cur_ms * current_format_new.fr_len) / current_format_new.inc_ms;
--
-- if (rtp->smoother) {
-- ast_smoother_reconfigure(rtp->smoother, new_size);
-- if (option_debug) {
-- ast_log(LOG_DEBUG, "Adjusted smoother to %d ms and %d bytes\n", current_format_new.cur_ms, new_size);
-- }
-- } else {
-- if (!(rtp->smoother = ast_smoother_new(new_size))) {
-- ast_log(LOG_WARNING, "Unable to create smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size);
-- return;
-- }
-- if (current_format_new.flags) {
-- ast_smoother_set_flags(rtp->smoother, current_format_new.flags);
-- }
-- if (option_debug) {
-- ast_log(LOG_DEBUG, "Created smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size);
-- }
-- }
-- }
--
--}
--
--struct ast_codec_pref *ast_rtp_codec_getpref(struct ast_rtp *rtp)
--{
-- return &rtp->pref;
--}
--
--int ast_rtp_codec_getformat(int pt)
--{
-- if (pt < 0 || pt > MAX_RTP_PT)
-- return 0; /* bogus payload type */
--
-- if (static_RTP_PT[pt].isAstFormat)
-- return static_RTP_PT[pt].code;
-- else
-- return 0;
--}
--
--int ast_rtp_write(struct ast_rtp *rtp, struct ast_frame *_f)
--{
-- struct ast_frame *f;
-- int codec;
-- int hdrlen = 12;
-- int subclass;
--
--
-- /* If we have no peer, return immediately */
-- if (!rtp->them.sin_addr.s_addr)
-- return 0;
--
-- /* If there is no data length, return immediately */
-- if (!_f->datalen && !rtp->red)
-- return 0;
--
-- /* Make sure we have enough space for RTP header */
-- if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO) && (_f->frametype != AST_FRAME_TEXT)) {
-- ast_log(LOG_WARNING, "RTP can only send voice, video and text\n");
-- return -1;
-- }
--
-- if (rtp->red) {
-- /* return 0; */
-- /* no primary data or generations to send */
-- if ((_f = red_t140_to_red(rtp->red)) == NULL)
-- return 0;
-- }
--
-- /* The bottom bit of a video subclass contains the marker bit */
-- subclass = _f->subclass;
-- if (_f->frametype == AST_FRAME_VIDEO)
-- subclass &= ~0x1;
--
-- codec = ast_rtp_lookup_code(rtp, 1, subclass);
-- if (codec < 0) {
-- ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass));
-- return -1;
-- }
--
-- if (rtp->lasttxformat != subclass) {
-- /* New format, reset the smoother */
-- ast_debug(1, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass));
-- rtp->lasttxformat = subclass;
-- if (rtp->smoother)
-- ast_smoother_free(rtp->smoother);
-- rtp->smoother = NULL;
-- }
--
-- if (!rtp->smoother) {
-- struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass);
--
-- switch (subclass) {
-- case AST_FORMAT_SPEEX:
-- case AST_FORMAT_G723_1:
-- case AST_FORMAT_SIREN7:
-- case AST_FORMAT_SIREN14:
-- /* these are all frame-based codecs and cannot be safely run through
-- a smoother */
-- break;
-- default:
-- if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */
-- if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) {
-- ast_log(LOG_WARNING, "Unable to create smoother: format: %d ms: %d len: %d\n", subclass, fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
-- return -1;
-- }
-- if (fmt.flags)
-- ast_smoother_set_flags(rtp->smoother, fmt.flags);
-- ast_debug(1, "Created smoother: format: %d ms: %d len: %d\n", subclass, fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
-- }
-- }
-- }
-- if (rtp->smoother) {
-- if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) {
-- ast_smoother_feed_be(rtp->smoother, _f);
-- } else {
-- ast_smoother_feed(rtp->smoother, _f);
-- }
--
-- while ((f = ast_smoother_read(rtp->smoother)) && (f->data.ptr)) {
-- if (f->subclass == AST_FORMAT_G722) {
-- /* G.722 is silllllllllllllly */
-- f->samples /= 2;
-- }
--
-- ast_rtp_raw_write(rtp, f, codec);
-- }
-- } else {
-- /* Don't buffer outgoing frames; send them one-per-packet: */
-- if (_f->offset < hdrlen)
-- f = ast_frdup(_f); /*! \bug XXX this might never be free'd. Why do we do this? */
-- else
-- f = _f;
-- if (f->data.ptr)
-- ast_rtp_raw_write(rtp, f, codec);
-- if (f != _f)
-- ast_frfree(f);
-- }
--
-- return 0;
--}
--
--/*! \brief Unregister interface to channel driver */
--void ast_rtp_proto_unregister(struct ast_rtp_protocol *proto)
--{
-- AST_RWLIST_WRLOCK(&protos);
-- AST_RWLIST_REMOVE(&protos, proto, list);
-- AST_RWLIST_UNLOCK(&protos);
--}
--
--/*! \brief Register interface to channel driver */
--int ast_rtp_proto_register(struct ast_rtp_protocol *proto)
--{
-- struct ast_rtp_protocol *cur;
--
-- AST_RWLIST_WRLOCK(&protos);
-- AST_RWLIST_TRAVERSE(&protos, cur, list) {
-- if (!strcmp(cur->type, proto->type)) {
-- ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
-- AST_RWLIST_UNLOCK(&protos);
-- return -1;
-- }
-- }
-- AST_RWLIST_INSERT_HEAD(&protos, proto, list);
-- AST_RWLIST_UNLOCK(&protos);
--
-- return 0;
--}
--
--/*! \brief Bridge loop for true native bridge (reinvite) */
--static enum ast_bridge_result bridge_native_loop(struct ast_channel *c0, struct ast_channel *c1, struct ast_rtp *p0, struct ast_rtp *p1, struct ast_rtp *vp0, struct ast_rtp *vp1, struct ast_rtp *tp0, struct ast_rtp *tp1, struct ast_rtp_protocol *pr0, struct ast_rtp_protocol *pr1, int codec0, int codec1, int timeoutms, int flags, struct ast_frame **fo, struct ast_channel **rc, void *pvt0, void *pvt1)
--{
-- struct ast_frame *fr = NULL;
-- struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, };
-- int oldcodec0 = codec0, oldcodec1 = codec1;
-- struct sockaddr_in ac1 = {0,}, vac1 = {0,}, tac1 = {0,}, ac0 = {0,}, vac0 = {0,}, tac0 = {0,};
-- struct sockaddr_in t1 = {0,}, vt1 = {0,}, tt1 = {0,}, t0 = {0,}, vt0 = {0,}, tt0 = {0,};
--
-- /* Set it up so audio goes directly between the two endpoints */
--
-- /* Test the first channel */
-- if (!(pr0->set_rtp_peer(c0, p1, vp1, tp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))) {
-- ast_rtp_get_peer(p1, &ac1);
-- if (vp1)
-- ast_rtp_get_peer(vp1, &vac1);
-- if (tp1)
-- ast_rtp_get_peer(tp1, &tac1);
-- } else
-- ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name);
--
-- /* Test the second channel */
-- if (!(pr1->set_rtp_peer(c1, p0, vp0, tp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))) {
-- ast_rtp_get_peer(p0, &ac0);
-- if (vp0)
-- ast_rtp_get_peer(vp0, &vac0);
-- if (tp0)
-- ast_rtp_get_peer(tp0, &tac0);
-- } else
-- ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c1->name, c0->name);
--
-- /* Now we can unlock and move into our loop */
-- ast_channel_unlock(c0);
-- ast_channel_unlock(c1);
--
-- ast_poll_channel_add(c0, c1);
--
-- /* Throw our channels into the structure and enter the loop */
-- cs[0] = c0;
-- cs[1] = c1;
-- cs[2] = NULL;
-- for (;;) {
-- /* Check if anything changed */
-- if ((c0->tech_pvt != pvt0) ||
-- (c1->tech_pvt != pvt1) ||
-- (c0->masq || c0->masqr || c1->masq || c1->masqr) ||
-- (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) {
-- ast_debug(1, "Oooh, something is weird, backing out\n");
-- if (c0->tech_pvt == pvt0)
-- if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0))
-- ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
-- if (c1->tech_pvt == pvt1)
-- if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0))
-- ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
-- ast_poll_channel_del(c0, c1);
-- return AST_BRIDGE_RETRY;
-- }
--
-- /* Check if they have changed their address */
-- ast_rtp_get_peer(p1, &t1);
-- if (vp1)
-- ast_rtp_get_peer(vp1, &vt1);
-- if (tp1)
-- ast_rtp_get_peer(tp1, &tt1);
-- if (pr1->get_codec)
-- codec1 = pr1->get_codec(c1);
-- ast_rtp_get_peer(p0, &t0);
-- if (vp0)
-- ast_rtp_get_peer(vp0, &vt0);
-- if (tp0)
-- ast_rtp_get_peer(tp0, &tt0);
-- if (pr0->get_codec)
-- codec0 = pr0->get_codec(c0);
-- if ((inaddrcmp(&t1, &ac1)) ||
-- (vp1 && inaddrcmp(&vt1, &vac1)) ||
-- (tp1 && inaddrcmp(&tt1, &tac1)) ||
-- (codec1 != oldcodec1)) {
-- ast_debug(2, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
-- c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port), codec1);
-- ast_debug(2, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n",
-- c1->name, ast_inet_ntoa(vt1.sin_addr), ntohs(vt1.sin_port), codec1);
-- ast_debug(2, "Oooh, '%s' changed end taddress to %s:%d (format %d)\n",
-- c1->name, ast_inet_ntoa(tt1.sin_addr), ntohs(tt1.sin_port), codec1);
-- ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n",
-- c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1);
-- ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n",
-- c1->name, ast_inet_ntoa(vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1);
-- ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n",
-- c1->name, ast_inet_ntoa(tac1.sin_addr), ntohs(tac1.sin_port), oldcodec1);
-- if (pr0->set_rtp_peer(c0, t1.sin_addr.s_addr ? p1 : NULL, vt1.sin_addr.s_addr ? vp1 : NULL, tt1.sin_addr.s_addr ? tp1 : NULL, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))
-- ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name);
-- memcpy(&ac1, &t1, sizeof(ac1));
-- memcpy(&vac1, &vt1, sizeof(vac1));
-- memcpy(&tac1, &tt1, sizeof(tac1));
-- oldcodec1 = codec1;
-- }
-- if ((inaddrcmp(&t0, &ac0)) ||
-- (vp0 && inaddrcmp(&vt0, &vac0)) ||
-- (tp0 && inaddrcmp(&tt0, &tac0))) {
-- ast_debug(2, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
-- c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port), codec0);
-- ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n",
-- c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0);
-- if (pr1->set_rtp_peer(c1, t0.sin_addr.s_addr ? p0 : NULL, vt0.sin_addr.s_addr ? vp0 : NULL, tt0.sin_addr.s_addr ? tp0 : NULL, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))
-- ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name);
-- memcpy(&ac0, &t0, sizeof(ac0));
-- memcpy(&vac0, &vt0, sizeof(vac0));
-- memcpy(&tac0, &tt0, sizeof(tac0));
-- oldcodec0 = codec0;
-- }
--
-- /* Wait for frame to come in on the channels */
-- if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
-- if (!timeoutms) {
-- if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0))
-- ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
-- if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0))
-- ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
-- return AST_BRIDGE_RETRY;
-- }
-- ast_debug(1, "Ooh, empty read...\n");
-- if (ast_check_hangup(c0) || ast_check_hangup(c1))
-- break;
-- continue;
-- }
-- fr = ast_read(who);
-- other = (who == c0) ? c1 : c0;
-- if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) &&
-- (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) ||
-- ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) {
-- /* Break out of bridge */
-- *fo = fr;
-- *rc = who;
-- ast_debug(1, "Oooh, got a %s\n", fr ? "digit" : "hangup");
-- if (c0->tech_pvt == pvt0)
-- if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0))
-- ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
-- if (c1->tech_pvt == pvt1)
-- if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0))
-- ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
-- ast_poll_channel_del(c0, c1);
-- return AST_BRIDGE_COMPLETE;
-- } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
-- if ((fr->subclass == AST_CONTROL_HOLD) ||
-- (fr->subclass == AST_CONTROL_UNHOLD) ||
-- (fr->subclass == AST_CONTROL_VIDUPDATE) ||
-- (fr->subclass == AST_CONTROL_T38) ||
-- (fr->subclass == AST_CONTROL_SRCUPDATE)) {
-- if (fr->subclass == AST_CONTROL_HOLD) {
-- /* If we someone went on hold we want the other side to reinvite back to us */
-- if (who == c0)
-- pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0);
-- else
-- pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0);
-- } else if (fr->subclass == AST_CONTROL_UNHOLD) {
-- /* If they went off hold they should go back to being direct */
-- if (who == c0)
-- pr1->set_rtp_peer(c1, p0, vp0, tp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE));
-- else
-- pr0->set_rtp_peer(c0, p1, vp1, tp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE));
-- }
-- /* Update local address information */
-- ast_rtp_get_peer(p0, &t0);
-- memcpy(&ac0, &t0, sizeof(ac0));
-- ast_rtp_get_peer(p1, &t1);
-- memcpy(&ac1, &t1, sizeof(ac1));
-- /* Update codec information */
-- if (pr0->get_codec && c0->tech_pvt)
-- oldcodec0 = codec0 = pr0->get_codec(c0);
-- if (pr1->get_codec && c1->tech_pvt)
-- oldcodec1 = codec1 = pr1->get_codec(c1);
-- ast_indicate_data(other, fr->subclass, fr->data.ptr, fr->datalen);
-- ast_frfree(fr);
-- } else {
-- *fo = fr;
-- *rc = who;
-- ast_debug(1, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name);
-- return AST_BRIDGE_COMPLETE;
-- }
-- } else {
-- if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
-- (fr->frametype == AST_FRAME_DTMF_END) ||
-- (fr->frametype == AST_FRAME_VOICE) ||
-- (fr->frametype == AST_FRAME_VIDEO) ||
-- (fr->frametype == AST_FRAME_IMAGE) ||
-- (fr->frametype == AST_FRAME_HTML) ||
-- (fr->frametype == AST_FRAME_MODEM) ||
-- (fr->frametype == AST_FRAME_TEXT)) {
-- ast_write(other, fr);
-- }
-- ast_frfree(fr);
-- }
-- /* Swap priority */
--#ifndef HAVE_EPOLL
-- cs[2] = cs[0];
-- cs[0] = cs[1];
-- cs[1] = cs[2];
--#endif
-- }
--
-- ast_poll_channel_del(c0, c1);
--
-- if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0))
-- ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
-- if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0))
-- ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
--
-- return AST_BRIDGE_FAILED;
--}
--
--/*! \brief P2P RTP Callback */
--#ifdef P2P_INTENSE
--static int p2p_rtp_callback(int *id, int fd, short events, void *cbdata)
--{
-- int res = 0, hdrlen = 12;
-- struct sockaddr_in sin;
-- socklen_t len;
-- unsigned int *header;
-- struct ast_rtp *rtp = cbdata, *bridged = NULL;
--
-- if (!rtp)
-- return 1;
--
-- len = sizeof(sin);
-- if ((res = recvfrom(fd, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 0, (struct sockaddr *)&sin, &len)) < 0)
-- return 1;
--
-- header = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET);
--
-- /* If NAT support is turned on, then see if we need to change their address */
-- if ((rtp->nat) &&
-- ((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
-- (rtp->them.sin_port != sin.sin_port))) {
-- rtp->them = sin;
-- rtp->rxseqno = 0;
-- ast_set_flag(rtp, FLAG_NAT_ACTIVE);
-- if (option_debug || rtpdebug)
-- ast_debug(0, "P2P RTP NAT: Got audio from other end. Now sending to address %s:%d\n", ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port));
-- }
--
-- /* Write directly out to other RTP stream if bridged */
-- if ((bridged = ast_rtp_get_bridged(rtp)))
-- bridge_p2p_rtp_write(rtp, bridged, header, res, hdrlen);
--
-- return 1;
--}
--
--/*! \brief Helper function to switch a channel and RTP stream into callback mode */
--static int p2p_callback_enable(struct ast_channel *chan, struct ast_rtp *rtp, int **iod)
--{
-- /* If we need DTMF, are looking for STUN, or we have no IO structure then we can't do direct callback */
-- if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) || ast_test_flag(rtp, FLAG_HAS_STUN) || !rtp->io)
-- return 0;
--
-- /* If the RTP structure is already in callback mode, remove it temporarily */
-- if (rtp->ioid) {
-- ast_io_remove(rtp->io, rtp->ioid);
-- rtp->ioid = NULL;
-- }
--
-- /* Steal the file descriptors from the channel */
-- chan->fds[0] = -1;
--
-- /* Now, fire up callback mode */
-- iod[0] = ast_io_add(rtp->io, ast_rtp_fd(rtp), p2p_rtp_callback, AST_IO_IN, rtp);
--
-- return 1;
--}
--#else
--static int p2p_callback_enable(struct ast_channel *chan, struct ast_rtp *rtp, int **iod)
--{
-- return 0;
--}
--#endif
--
--/*! \brief Helper function to switch a channel and RTP stream out of callback mode */
--static int p2p_callback_disable(struct ast_channel *chan, struct ast_rtp *rtp, int **iod)
--{
-- ast_channel_lock(chan);
--
-- /* Remove the callback from the IO context */
-- ast_io_remove(rtp->io, iod[0]);
--
-- /* Restore file descriptors */
-- chan->fds[0] = ast_rtp_fd(rtp);
-- ast_channel_unlock(chan);
--
-- /* Restore callback mode if previously used */
-- if (ast_test_flag(rtp, FLAG_CALLBACK_MODE))
-- rtp->ioid = ast_io_add(rtp->io, ast_rtp_fd(rtp), rtpread, AST_IO_IN, rtp);
--
-- return 0;
--}
--
--/*! \brief Helper function that sets what an RTP structure is bridged to */
--static void p2p_set_bridge(struct ast_rtp *rtp0, struct ast_rtp *rtp1)
--{
-- rtp_bridge_lock(rtp0);
-- rtp0->bridged = rtp1;
-- rtp_bridge_unlock(rtp0);
--}
--
--/*! \brief Bridge loop for partial native bridge (packet2packet)
--
-- In p2p mode, Asterisk is a very basic RTP proxy, just forwarding whatever
-- rtp/rtcp we get in to the channel.
-- \note this currently only works for Audio
--*/
--static enum ast_bridge_result bridge_p2p_loop(struct ast_channel *c0, struct ast_channel *c1, struct ast_rtp *p0, struct ast_rtp *p1, int timeoutms, int flags, struct ast_frame **fo, struct ast_channel **rc, void *pvt0, void *pvt1)
--{
-- struct ast_frame *fr = NULL;
-- struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, };
-- int *p0_iod[2] = {NULL, NULL}, *p1_iod[2] = {NULL, NULL};
-- int p0_callback = 0, p1_callback = 0;
-- enum ast_bridge_result res = AST_BRIDGE_FAILED;
--
-- /* Okay, setup each RTP structure to do P2P forwarding */
-- ast_clear_flag(p0, FLAG_P2P_SENT_MARK);
-- p2p_set_bridge(p0, p1);
-- ast_clear_flag(p1, FLAG_P2P_SENT_MARK);
-- p2p_set_bridge(p1, p0);
--
-- /* Activate callback modes if possible */
-- p0_callback = p2p_callback_enable(c0, p0, &p0_iod[0]);
-- p1_callback = p2p_callback_enable(c1, p1, &p1_iod[0]);
--
-- /* Now let go of the channel locks and be on our way */
-- ast_channel_unlock(c0);
-- ast_channel_unlock(c1);
--
-- ast_poll_channel_add(c0, c1);
--
-- /* Go into a loop forwarding frames until we don't need to anymore */
-- cs[0] = c0;
-- cs[1] = c1;
-- cs[2] = NULL;
-- for (;;) {
-- /* If the underlying formats have changed force this bridge to break */
-- if ((c0->rawreadformat != c1->rawwriteformat) || (c1->rawreadformat != c0->rawwriteformat)) {
-- ast_debug(3, "p2p-rtp-bridge: Oooh, formats changed, backing out\n");
-- res = AST_BRIDGE_FAILED_NOWARN;
-- break;
-- }
-- /* Check if anything changed */
-- if ((c0->tech_pvt != pvt0) ||
-- (c1->tech_pvt != pvt1) ||
-- (c0->masq || c0->masqr || c1->masq || c1->masqr) ||
-- (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) {
-- ast_debug(3, "p2p-rtp-bridge: Oooh, something is weird, backing out\n");
-- /* If a masquerade needs to happen we have to try to read in a frame so that it actually happens. Without this we risk being called again and going into a loop */
-- if ((c0->masq || c0->masqr) && (fr = ast_read(c0)))
-- ast_frfree(fr);
-- if ((c1->masq || c1->masqr) && (fr = ast_read(c1)))
-- ast_frfree(fr);
-- res = AST_BRIDGE_RETRY;
-- break;
-- }
-- /* Wait on a channel to feed us a frame */
-- if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
-- if (!timeoutms) {
-- res = AST_BRIDGE_RETRY;
-- break;
-- }
-- if (option_debug > 2)
-- ast_log(LOG_NOTICE, "p2p-rtp-bridge: Ooh, empty read...\n");
-- if (ast_check_hangup(c0) || ast_check_hangup(c1))
-- break;
-- continue;
-- }
-- /* Read in frame from channel */
-- fr = ast_read(who);
-- other = (who == c0) ? c1 : c0;
-- /* Depending on the frame we may need to break out of our bridge */
-- if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) &&
-- ((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) |
-- ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)))) {
-- /* Record received frame and who */
-- *fo = fr;
-- *rc = who;
-- ast_debug(3, "p2p-rtp-bridge: Ooh, got a %s\n", fr ? "digit" : "hangup");
-- res = AST_BRIDGE_COMPLETE;
-- break;
-- } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
-- if ((fr->subclass == AST_CONTROL_HOLD) ||
-- (fr->subclass == AST_CONTROL_UNHOLD) ||
-- (fr->subclass == AST_CONTROL_VIDUPDATE) ||
-- (fr->subclass == AST_CONTROL_T38) ||
-- (fr->subclass == AST_CONTROL_SRCUPDATE)) {
-- /* If we are going on hold, then break callback mode and P2P bridging */
-- if (fr->subclass == AST_CONTROL_HOLD) {
-- if (p0_callback)
-- p0_callback = p2p_callback_disable(c0, p0, &p0_iod[0]);
-- if (p1_callback)
-- p1_callback = p2p_callback_disable(c1, p1, &p1_iod[0]);
-- p2p_set_bridge(p0, NULL);
-- p2p_set_bridge(p1, NULL);
-- } else if (fr->subclass == AST_CONTROL_UNHOLD) {
-- /* If we are off hold, then go back to callback mode and P2P bridging */
-- ast_clear_flag(p0, FLAG_P2P_SENT_MARK);
-- p2p_set_bridge(p0, p1);
-- ast_clear_flag(p1, FLAG_P2P_SENT_MARK);
-- p2p_set_bridge(p1, p0);
-- p0_callback = p2p_callback_enable(c0, p0, &p0_iod[0]);
-- p1_callback = p2p_callback_enable(c1, p1, &p1_iod[0]);
-- }
-- ast_indicate_data(other, fr->subclass, fr->data.ptr, fr->datalen);
-- ast_frfree(fr);
-- } else {
-- *fo = fr;
-- *rc = who;
-- ast_debug(3, "p2p-rtp-bridge: Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name);
-- res = AST_BRIDGE_COMPLETE;
-- break;
-- }
-- } else {
-- if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
-- (fr->frametype == AST_FRAME_DTMF_END) ||
-- (fr->frametype == AST_FRAME_VOICE) ||
-- (fr->frametype == AST_FRAME_VIDEO) ||
-- (fr->frametype == AST_FRAME_IMAGE) ||
-- (fr->frametype == AST_FRAME_HTML) ||
-- (fr->frametype == AST_FRAME_MODEM) ||
-- (fr->frametype == AST_FRAME_TEXT)) {
-- ast_write(other, fr);
-- }
--
-- ast_frfree(fr);
-- }
-- /* Swap priority */
--#ifndef HAVE_EPOLL
-- cs[2] = cs[0];
-- cs[0] = cs[1];
-- cs[1] = cs[2];
--#endif
-- }
--
-- /* If we are totally avoiding the core, then restore our link to it */
-- if (p0_callback)
-- p0_callback = p2p_callback_disable(c0, p0, &p0_iod[0]);
-- if (p1_callback)
-- p1_callback = p2p_callback_disable(c1, p1, &p1_iod[0]);
--
-- /* Break out of the direct bridge */
-- p2p_set_bridge(p0, NULL);
-- p2p_set_bridge(p1, NULL);
--
-- ast_poll_channel_del(c0, c1);
--
-- return res;
--}
--
--/*! \page AstRTPbridge The Asterisk RTP bridge
-- The RTP bridge is called from the channel drivers that are using the RTP
-- subsystem in Asterisk - like SIP, H.323 and Jingle/Google Talk.
--
-- This bridge aims to offload the Asterisk server by setting up
-- the media stream directly between the endpoints, keeping the
-- signalling in Asterisk.
--
-- It checks with the channel driver, using a callback function, if
-- there are possibilities for a remote bridge.
--
-- If this fails, the bridge hands off to the core bridge. Reasons
-- can be NAT support needed, DTMF features in audio needed by
-- the PBX for transfers or spying/monitoring on channels.
--
-- If transcoding is needed - we can't do a remote bridge.
-- If only NAT support is needed, we're using Asterisk in
-- RTP proxy mode with the p2p RTP bridge, basically
-- forwarding incoming audio packets to the outbound
-- stream on a network level.
--
-- References:
-- - ast_rtp_bridge()
-- - ast_channel_early_bridge()
-- - ast_channel_bridge()
-- - rtp.c
-- - rtp.h
--*/
--/*! \brief Bridge calls. If possible and allowed, initiate
-- re-invite so the peers exchange media directly outside
-- of Asterisk.
--*/
--enum ast_bridge_result ast_rtp_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
--{
-- struct ast_rtp *p0 = NULL, *p1 = NULL; /* Audio RTP Channels */
-- struct ast_rtp *vp0 = NULL, *vp1 = NULL; /* Video RTP channels */
-- struct ast_rtp *tp0 = NULL, *tp1 = NULL; /* Text RTP channels */
-- struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL;
-- enum ast_rtp_get_result audio_p0_res = AST_RTP_GET_FAILED, video_p0_res = AST_RTP_GET_FAILED, text_p0_res = AST_RTP_GET_FAILED;
-- enum ast_rtp_get_result audio_p1_res = AST_RTP_GET_FAILED, video_p1_res = AST_RTP_GET_FAILED, text_p1_res = AST_RTP_GET_FAILED;
-- enum ast_bridge_result res = AST_BRIDGE_FAILED;
-- int codec0 = 0, codec1 = 0;
-- void *pvt0 = NULL, *pvt1 = NULL;
--
-- /* Lock channels */
-- ast_channel_lock(c0);
-- while (ast_channel_trylock(c1)) {
-- ast_channel_unlock(c0);
-- usleep(1);
-- ast_channel_lock(c0);
-- }
--
-- /* Ensure neither channel got hungup during lock avoidance */
-- if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
-- ast_log(LOG_WARNING, "Got hangup while attempting to bridge '%s' and '%s'\n", c0->name, c1->name);
-- ast_channel_unlock(c0);
-- ast_channel_unlock(c1);
-- return AST_BRIDGE_FAILED;
-- }
--
-- /* Find channel driver interfaces */
-- if (!(pr0 = get_proto(c0))) {
-- ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name);
-- ast_channel_unlock(c0);
-- ast_channel_unlock(c1);
-- return AST_BRIDGE_FAILED;
-- }
-- if (!(pr1 = get_proto(c1))) {
-- ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name);
-- ast_channel_unlock(c0);
-- ast_channel_unlock(c1);
-- return AST_BRIDGE_FAILED;
-- }
--
-- /* Get channel specific interface structures */
-- pvt0 = c0->tech_pvt;
-- pvt1 = c1->tech_pvt;
--
-- /* Get audio and video interface (if native bridge is possible) */
-- audio_p0_res = pr0->get_rtp_info(c0, &p0);
-- video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED;
-- text_p0_res = pr0->get_trtp_info ? pr0->get_trtp_info(c0, &vp0) : AST_RTP_GET_FAILED;
-- audio_p1_res = pr1->get_rtp_info(c1, &p1);
-- video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED;
-- text_p1_res = pr1->get_trtp_info ? pr1->get_trtp_info(c1, &vp1) : AST_RTP_GET_FAILED;
--
-- /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */
-- if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE))
-- audio_p0_res = AST_RTP_GET_FAILED;
-- if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE))
-- audio_p1_res = AST_RTP_GET_FAILED;
--
-- /* Check if a bridge is possible (partial/native) */
-- if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) {
-- /* Somebody doesn't want to play... */
-- ast_channel_unlock(c0);
-- ast_channel_unlock(c1);
-- return AST_BRIDGE_FAILED_NOWARN;
-- }
--
-- /* If we need to feed DTMF frames into the core then only do a partial native bridge */
-- if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
-- ast_set_flag(p0, FLAG_P2P_NEED_DTMF);
-- audio_p0_res = AST_RTP_TRY_PARTIAL;
-- }
--
-- if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) {
-- ast_set_flag(p1, FLAG_P2P_NEED_DTMF);
-- audio_p1_res = AST_RTP_TRY_PARTIAL;
-- }
--
-- /* If both sides are not using the same method of DTMF transmission
-- * (ie: one is RFC2833, other is INFO... then we can not do direct media.
-- * --------------------------------------------------
-- * | DTMF Mode | HAS_DTMF | Accepts Begin Frames |
-- * |-----------|------------|-----------------------|
-- * | Inband | False | True |
-- * | RFC2833 | True | True |
-- * | SIP INFO | False | False |
-- * --------------------------------------------------
-- * However, if DTMF from both channels is being monitored by the core, then
-- * we can still do packet-to-packet bridging, because passing through the
-- * core will handle DTMF mode translation.
-- */
-- if ((ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) ||
-- (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) {
-- if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) {
-- ast_channel_unlock(c0);
-- ast_channel_unlock(c1);
-- return AST_BRIDGE_FAILED_NOWARN;
-- }
-- audio_p0_res = AST_RTP_TRY_PARTIAL;
-- audio_p1_res = AST_RTP_TRY_PARTIAL;
-- }
--
-- /* If we need to feed frames into the core don't do a P2P bridge */
-- if ((audio_p0_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p0, FLAG_P2P_NEED_DTMF)) ||
-- (audio_p1_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p1, FLAG_P2P_NEED_DTMF))) {
-- ast_channel_unlock(c0);
-- ast_channel_unlock(c1);
-- return AST_BRIDGE_FAILED_NOWARN;
-- }
--
-- /* Get codecs from both sides */
-- codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0;
-- codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0;
-- if (codec0 && codec1 && !(codec0 & codec1)) {
-- /* Hey, we can't do native bridging if both parties speak different codecs */
-- ast_debug(3, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1);
-- ast_channel_unlock(c0);
-- ast_channel_unlock(c1);
-- return AST_BRIDGE_FAILED_NOWARN;
-- }
--
-- /* If either side can only do a partial bridge, then don't try for a true native bridge */
-- if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) {
-- struct ast_format_list fmt0, fmt1;
--
-- /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */
-- if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) {
-- ast_debug(1, "Cannot packet2packet bridge - raw formats are incompatible\n");
-- ast_channel_unlock(c0);
-- ast_channel_unlock(c1);
-- return AST_BRIDGE_FAILED_NOWARN;
-- }
-- /* They must also be using the same packetization */
-- fmt0 = ast_codec_pref_getsize(&p0->pref, c0->rawreadformat);
-- fmt1 = ast_codec_pref_getsize(&p1->pref, c1->rawreadformat);
-- if (fmt0.cur_ms != fmt1.cur_ms) {
-- ast_debug(1, "Cannot packet2packet bridge - packetization settings prevent it\n");
-- ast_channel_unlock(c0);
-- ast_channel_unlock(c1);
-- return AST_BRIDGE_FAILED_NOWARN;
-- }
--
-- ast_verb(3, "Packet2Packet bridging %s and %s\n", c0->name, c1->name);
-- res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1);
-- } else {
-- ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
-- res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, tp0, tp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1);
-- }
--
-- return res;
--}
--
--static char *rtp_do_debug_ip(struct ast_cli_args *a)
--{
-- struct hostent *hp;
-- struct ast_hostent ahp;
-- int port = 0;
-- char *p, *arg;
--
-- arg = a->argv[3];
-- p = strstr(arg, ":");
-- if (p) {
-- *p = '\0';
-- p++;
-- port = atoi(p);
-- }
-- hp = ast_gethostbyname(arg, &ahp);
-- if (hp == NULL) {
-- ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
-- return CLI_FAILURE;
-- }
-- rtpdebugaddr.sin_family = AF_INET;
-- memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr));
-- rtpdebugaddr.sin_port = htons(port);
-- if (port == 0)
-- ast_cli(a->fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtpdebugaddr.sin_addr));
-- else
-- ast_cli(a->fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtpdebugaddr.sin_addr), port);
-- rtpdebug = 1;
-- return CLI_SUCCESS;
--}
--
--static char *rtcp_do_debug_ip(struct ast_cli_args *a)
--{
-- struct hostent *hp;
-- struct ast_hostent ahp;
-- int port = 0;
-- char *p, *arg;
--
-- arg = a->argv[3];
-- p = strstr(arg, ":");
-- if (p) {
-- *p = '\0';
-- p++;
-- port = atoi(p);
-- }
-- hp = ast_gethostbyname(arg, &ahp);
-- if (hp == NULL) {
-- ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
-- return CLI_FAILURE;
-- }
-- rtcpdebugaddr.sin_family = AF_INET;
-- memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr));
-- rtcpdebugaddr.sin_port = htons(port);
-- if (port == 0)
-- ast_cli(a->fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr));
-- else
-- ast_cli(a->fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port);
-- rtcpdebug = 1;
-- return CLI_SUCCESS;
--}
--
--static char *handle_cli_rtp_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
--{
-- switch (cmd) {
-- case CLI_INIT:
-- e->command = "rtp set debug {on|off|ip}";
-- e->usage =
-- "Usage: rtp set debug {on|off|ip host[:port]}\n"
-- " Enable/Disable dumping of all RTP packets. If 'ip' is\n"
-- " specified, limit the dumped packets to those to and from\n"
-- " the specified 'host' with optional port.\n";
-- return NULL;
-- case CLI_GENERATE:
-- return NULL;
-- }
--
-- if (a->argc == e->args) { /* set on or off */
-- if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
-- rtpdebug = 1;
-- memset(&rtpdebugaddr, 0, sizeof(rtpdebugaddr));
-- ast_cli(a->fd, "RTP Debugging Enabled\n");
-- return CLI_SUCCESS;
-- } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
-- rtpdebug = 0;
-- ast_cli(a->fd, "RTP Debugging Disabled\n");
-- return CLI_SUCCESS;
-- }
-- } else if (a->argc == e->args +1) { /* ip */
-- return rtp_do_debug_ip(a);
-- }
--
-- return CLI_SHOWUSAGE; /* default, failure */
--}
--
--static char *handle_cli_rtcp_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
--{
-- switch (cmd) {
-- case CLI_INIT:
-- e->command = "rtcp set debug {on|off|ip}";
-- e->usage =
-- "Usage: rtcp set debug {on|off|ip host[:port]}\n"
-- " Enable/Disable dumping of all RTCP packets. If 'ip' is\n"
-- " specified, limit the dumped packets to those to and from\n"
-- " the specified 'host' with optional port.\n";
-- return NULL;
-- case CLI_GENERATE:
-- return NULL;
-- }
--
-- if (a->argc == e->args) { /* set on or off */
-- if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
-- rtcpdebug = 1;
-- memset(&rtcpdebugaddr, 0, sizeof(rtcpdebugaddr));
-- ast_cli(a->fd, "RTCP Debugging Enabled\n");
-- return CLI_SUCCESS;
-- } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
-- rtcpdebug = 0;
-- ast_cli(a->fd, "RTCP Debugging Disabled\n");
-- return CLI_SUCCESS;
-- }
-- } else if (a->argc == e->args +1) { /* ip */
-- return rtcp_do_debug_ip(a);
-- }
--
-- return CLI_SHOWUSAGE; /* default, failure */
--}
--
--static char *handle_cli_rtcp_set_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
--{
-- switch (cmd) {
-- case CLI_INIT:
-- e->command = "rtcp set stats {on|off}";
-- e->usage =
-- "Usage: rtcp set stats {on|off}\n"
-- " Enable/Disable dumping of RTCP stats.\n";
-- return NULL;
-- case CLI_GENERATE:
-- return NULL;
-- }
--
-- if (a->argc != e->args)
-- return CLI_SHOWUSAGE;
--
-- if (!strncasecmp(a->argv[e->args-1], "on", 2))
-- rtcpstats = 1;
-- else if (!strncasecmp(a->argv[e->args-1], "off", 3))
-- rtcpstats = 0;
-- else
-- return CLI_SHOWUSAGE;
--
-- ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled");
-- return CLI_SUCCESS;
--}
--
--static char *handle_cli_stun_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
--{
-- switch (cmd) {
-- case CLI_INIT:
-- e->command = "stun set debug {on|off}";
-- e->usage =
-- "Usage: stun set debug {on|off}\n"
-- " Enable/Disable STUN (Simple Traversal of UDP through NATs)\n"
-- " debugging\n";
-- return NULL;
-- case CLI_GENERATE:
-- return NULL;
-- }
--
-- if (a->argc != e->args)
-- return CLI_SHOWUSAGE;
--
-- if (!strncasecmp(a->argv[e->args-1], "on", 2))
-- stundebug = 1;
-- else if (!strncasecmp(a->argv[e->args-1], "off", 3))
-- stundebug = 0;
-- else
-- return CLI_SHOWUSAGE;
--
-- ast_cli(a->fd, "STUN Debugging %s\n", stundebug ? "Enabled" : "Disabled");
-- return CLI_SUCCESS;
--}
--
--static struct ast_cli_entry cli_rtp[] = {
-- AST_CLI_DEFINE(handle_cli_rtp_set_debug, "Enable/Disable RTP debugging"),
-- AST_CLI_DEFINE(handle_cli_rtcp_set_debug, "Enable/Disable RTCP debugging"),
-- AST_CLI_DEFINE(handle_cli_rtcp_set_stats, "Enable/Disable RTCP stats"),
-- AST_CLI_DEFINE(handle_cli_stun_set_debug, "Enable/Disable STUN debugging"),
--};
--
--static int __ast_rtp_reload(int reload)
--{
-- struct ast_config *cfg;
-- const char *s;
-- struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
--
-- cfg = ast_config_load2("rtp.conf", "rtp", config_flags);
-- if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
-- return 0;
-- }
--
-- rtpstart = 5000;
-- rtpend = 31000;
-- dtmftimeout = DEFAULT_DTMF_TIMEOUT;
-- strictrtp = STRICT_RTP_OPEN;
-- if (cfg) {
-- if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
-- rtpstart = atoi(s);
-- if (rtpstart < 1024)
-- rtpstart = 1024;
-- if (rtpstart > 65535)
-- rtpstart = 65535;
-- }
-- if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
-- rtpend = atoi(s);
-- if (rtpend < 1024)
-- rtpend = 1024;
-- if (rtpend > 65535)
-- rtpend = 65535;
-- }
-- if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) {
-- rtcpinterval = atoi(s);
-- if (rtcpinterval == 0)
-- rtcpinterval = 0; /* Just so we're clear... it's zero */
-- if (rtcpinterval < RTCP_MIN_INTERVALMS)
-- rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */
-- if (rtcpinterval > RTCP_MAX_INTERVALMS)
-- rtcpinterval = RTCP_MAX_INTERVALMS;
-- }
-- if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
--#ifdef SO_NO_CHECK
-- if (ast_false(s))
-- nochecksums = 1;
-- else
-- nochecksums = 0;
--#else
-- if (ast_false(s))
-- ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
--#endif
-- }
-- if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
-- dtmftimeout = atoi(s);
-- if ((dtmftimeout < 0) || (dtmftimeout > 20000)) {
-- ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
-- dtmftimeout, DEFAULT_DTMF_TIMEOUT);
-- dtmftimeout = DEFAULT_DTMF_TIMEOUT;
-- };
-- }
-- if ((s = ast_variable_retrieve(cfg, "general", "strictrtp"))) {
-- strictrtp = ast_true(s);
-- }
-- ast_config_destroy(cfg);
-- }
-- if (rtpstart >= rtpend) {
-- ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
-- rtpstart = 5000;
-- rtpend = 31000;
-- }
-- ast_verb(2, "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
-- return 0;
--}
--
--int ast_rtp_reload(void)
--{
-- return __ast_rtp_reload(1);
--}
--
--/*! \brief Initialize the RTP system in Asterisk */
--void ast_rtp_init(void)
--{
-- ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry));
-- __ast_rtp_reload(0);
--}
--
--/*! \brief Write t140 redundacy frame
-- * \param data primary data to be buffered
-- */
--static int red_write(const void *data)
--{
-- struct ast_rtp *rtp = (struct ast_rtp*) data;
--
-- ast_rtp_write(rtp, &rtp->red->t140);
--
-- return 1;
--}
--
--/*! \brief Construct a redundant frame
-- * \param red redundant data structure
-- */
--static struct ast_frame *red_t140_to_red(struct rtp_red *red) {
-- unsigned char *data = red->t140red.data.ptr;
-- int len = 0;
-- int i;
--
-- /* replace most aged generation */
-- if (red->len[0]) {
-- for (i = 1; i < red->num_gen+1; i++)
-- len += red->len[i];
--
-- memmove(&data[red->hdrlen], &data[red->hdrlen+red->len[0]], len);
-- }
--
-- /* Store length of each generation and primary data length*/
-- for (i = 0; i < red->num_gen; i++)
-- red->len[i] = red->len[i+1];
-- red->len[i] = red->t140.datalen;
--
-- /* write each generation length in red header */
-- len = red->hdrlen;
-- for (i = 0; i < red->num_gen; i++)
-- len += data[i*4+3] = red->len[i];
--
-- /* add primary data to buffer */
-- memcpy(&data[len], red->t140.data.ptr, red->t140.datalen);
-- red->t140red.datalen = len + red->t140.datalen;
--
-- /* no primary data and no generations to send */
-- if (len == red->hdrlen && !red->t140.datalen)
-- return NULL;
--
-- /* reset t.140 buffer */
-- red->t140.datalen = 0;
--
-- return &red->t140red;
--}
--
--/*! \brief Initialize t140 redundancy
-- * \param rtp
-- * \param ti buffer t140 for ti (msecs) before sending redundant frame
-- * \param red_data_pt Payloadtypes for primary- and generation-data
-- * \param num_gen numbers of generations (primary generation not encounted)
-- *
--*/
--int rtp_red_init(struct ast_rtp *rtp, int ti, int *red_data_pt, int num_gen)
--{
-- struct rtp_red *r;
-- int x;
--
-- if (!(r = ast_calloc(1, sizeof(struct rtp_red))))
-- return -1;
--
-- r->t140.frametype = AST_FRAME_TEXT;
-- r->t140.subclass = AST_FORMAT_T140RED;
-- r->t140.data.ptr = &r->buf_data;
--
-- r->t140.ts = 0;
-- r->t140red = r->t140;
-- r->t140red.data.ptr = &r->t140red_data;
-- r->t140red.datalen = 0;
-- r->ti = ti;
-- r->num_gen = num_gen;
-- r->hdrlen = num_gen * 4 + 1;
-- r->prev_ts = 0;
--
-- for (x = 0; x < num_gen; x++) {
-- r->pt[x] = red_data_pt[x];
-- r->pt[x] |= 1 << 7; /* mark redundant generations pt */
-- r->t140red_data[x*4] = r->pt[x];
-- }
-- r->t140red_data[x*4] = r->pt[x] = red_data_pt[x]; /* primary pt */
-- r->schedid = ast_sched_add(rtp->sched, ti, red_write, rtp);
-- rtp->red = r;
--
-- r->t140.datalen = 0;
--
-- return 0;
--}
--
--/*! \brief Buffer t140 from chan_sip
-- * \param rtp
-- * \param f frame
-- */
--void red_buffer_t140(struct ast_rtp *rtp, struct ast_frame *f)
--{
-- if (f->datalen > -1) {
-- struct rtp_red *red = rtp->red;
-- memcpy(&red->buf_data[red->t140.datalen], f->data.ptr, f->datalen);
-- red->t140.datalen += f->datalen;
-- red->t140.ts = f->ts;
-- }
--}
-Index: main/utils.c
-===================================================================
---- a/main/utils.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/main/utils.c (.../trunk) (revision 186562)
-@@ -1469,8 +1469,33 @@
- * stringfields support routines.
- */
-
--const char __ast_string_field_empty[] = ""; /*!< the empty string */
-+/* this is a little complex... string fields are stored with their
-+ allocated size in the bytes preceding the string; even the
-+ constant 'empty' string has to be this way, so the code that
-+ checks to see if there is enough room for a new string doesn't
-+ have to have any special case checks
-+*/
-
-+static const struct {
-+ ast_string_field_allocation allocation;
-+ char string[1];
-+} __ast_string_field_empty_buffer;
-+
-+ast_string_field __ast_string_field_empty = __ast_string_field_empty_buffer.string;
-+
-+#define ALLOCATOR_OVERHEAD 48
-+
-+static size_t optimal_alloc_size(size_t size)
-+{
-+ unsigned int count;
-+
-+ size += ALLOCATOR_OVERHEAD;
-+
-+ for (count = 1; size; size >>= 1, count++);
-+
-+ return (1 << count) - ALLOCATOR_OVERHEAD;
-+}
-+
- /*! \brief add a new block to the pool.
- * We can only allocate from the topmost pool, so the
- * fields in *mgr reflect the size of that only.
-@@ -1480,14 +1505,15 @@
- size_t size)
- {
- struct ast_string_field_pool *pool;
-+ size_t alloc_size = optimal_alloc_size(sizeof(*pool) + size);
-
-- if (!(pool = ast_calloc(1, sizeof(*pool) + size)))
-+ if (!(pool = ast_calloc(1, alloc_size))) {
- return -1;
--
-+ }
-+
- pool->prev = *pool_head;
-+ pool->size = alloc_size - sizeof(*pool);
- *pool_head = pool;
-- mgr->size = size;
-- mgr->used = 0;
- mgr->last_alloc = NULL;
-
- return 0;
-@@ -1511,13 +1537,16 @@
- struct ast_string_field_pool *cur = *pool_head;
-
- /* clear fields - this is always necessary */
-- while ((struct ast_string_field_mgr *) p != mgr)
-+ while ((struct ast_string_field_mgr *) p != mgr) {
- *p++ = __ast_string_field_empty;
-+ }
-+
- mgr->last_alloc = NULL;
- if (size > 0) { /* allocate the initial pool */
- *pool_head = NULL;
- return add_string_pool(mgr, pool_head, size);
- }
-+
- if (size < 0) { /* reset all pools */
- *pool_head = NULL;
- } else { /* preserve the first pool */
-@@ -1527,7 +1556,7 @@
- }
- cur = cur->prev;
- (*pool_head)->prev = NULL;
-- mgr->used = 0;
-+ (*pool_head)->used = (*pool_head)->active = 0;
- }
-
- while (cur) {
-@@ -1544,34 +1573,37 @@
- struct ast_string_field_pool **pool_head, size_t needed)
- {
- char *result = NULL;
-- size_t space = mgr->size - mgr->used;
-+ size_t space = (*pool_head)->size - (*pool_head)->used;
-+ size_t to_alloc = needed + sizeof(ast_string_field_allocation);
-
-- if (__builtin_expect(needed > space, 0)) {
-- size_t new_size = mgr->size * 2;
-+ if (__builtin_expect(to_alloc > space, 0)) {
-+ size_t new_size = (*pool_head)->size;
-
-- while (new_size < needed)
-+ while (new_size < to_alloc) {
- new_size *= 2;
-+ }
-
- if (add_string_pool(mgr, pool_head, new_size))
- return NULL;
- }
-
-- result = (*pool_head)->base + mgr->used;
-- mgr->used += needed;
-+ result = (*pool_head)->base + (*pool_head)->used;
-+ (*pool_head)->used += to_alloc;
-+ (*pool_head)->active += needed;
-+ result += sizeof(ast_string_field_allocation);
-+ AST_STRING_FIELD_ALLOCATION(result) = needed;
- mgr->last_alloc = result;
-+
- return result;
- }
-
--int __ast_string_field_ptr_grow(struct ast_string_field_mgr *mgr, size_t needed,
-+int __ast_string_field_ptr_grow(struct ast_string_field_mgr *mgr,
-+ struct ast_string_field_pool **pool_head, size_t needed,
- const ast_string_field *ptr)
- {
-- int grow = needed - (strlen(*ptr) + 1);
-- size_t space = mgr->size - mgr->used;
-+ ssize_t grow = needed - AST_STRING_FIELD_ALLOCATION(*ptr);
-+ size_t space = (*pool_head)->size - (*pool_head)->used;
-
-- if (grow <= 0) {
-- return 0;
-- }
--
- if (*ptr != mgr->last_alloc) {
- return 1;
- }
-@@ -1580,30 +1612,57 @@
- return 1;
- }
-
-- mgr->used += grow;
-+ (*pool_head)->used += grow;
-+ (*pool_head)->active += grow;
-+ AST_STRING_FIELD_ALLOCATION(*ptr) += grow;
-
- return 0;
- }
-
-+void __ast_string_field_release_active(struct ast_string_field_pool *pool_head,
-+ const ast_string_field ptr)
-+{
-+ struct ast_string_field_pool *pool, *prev;
-+
-+ if (ptr == __ast_string_field_empty) {
-+ return;
-+ }
-+
-+ for (pool = pool_head, prev = NULL; pool; prev = pool, pool = pool->prev) {
-+ if ((ptr >= pool->base) && (ptr <= (pool->base + pool->size))) {
-+ pool->active -= AST_STRING_FIELD_ALLOCATION(ptr);
-+ if ((pool->active == 0) && prev) {
-+ prev->prev = pool->prev;
-+ ast_free(pool);
-+ }
-+ break;
-+ }
-+ }
-+}
-+
- void __ast_string_field_ptr_build_va(struct ast_string_field_mgr *mgr,
- struct ast_string_field_pool **pool_head,
- ast_string_field *ptr, const char *format, va_list ap1, va_list ap2)
- {
- size_t needed;
- size_t available;
-- size_t space = mgr->size - mgr->used;
-+ size_t space = (*pool_head)->size - (*pool_head)->used;
-+ ssize_t grow;
- char *target;
-
- /* if the field already has space allocated, try to reuse it;
-- otherwise, use the empty space at the end of the current
-+ otherwise, try to use the empty space at the end of the current
- pool
- */
-- if ((*ptr)[0] != '\0') {
-+ if (*ptr != __ast_string_field_empty) {
- target = (char *) *ptr;
-- available = strlen(target) + 1;
-+ available = AST_STRING_FIELD_ALLOCATION(*ptr);
-+ if (*ptr == mgr->last_alloc) {
-+ available += space;
-+ }
- } else {
-- target = (*pool_head)->base + mgr->used;
-- available = space;
-+ target = (*pool_head)->base + (*pool_head)->used + sizeof(ast_string_field_allocation);
-+ available = space - sizeof(ast_string_field_allocation);
- }
-
- needed = vsnprintf(target, available, format, ap1) + 1;
-@@ -1611,28 +1670,32 @@
- va_end(ap1);
-
- if (needed > available) {
-- /* if the space needed can be satisfied by using the current
-- pool (which could only occur if we tried to use the field's
-- allocated space and failed), then use that space; otherwise
-- allocate a new pool
-+ /* the allocation could not be satisfied using the field's current allocation
-+ (if it has one), or the space available in the pool (if it does not). allocate
-+ space for it, adding a new string pool if necessary.
- */
-- if (needed > space) {
-- size_t new_size = mgr->size * 2;
--
-- while (new_size < needed)
-- new_size *= 2;
--
-- if (add_string_pool(mgr, pool_head, new_size))
-- return;
-+ if (!(target = (char *) __ast_string_field_alloc_space(mgr, pool_head, needed))) {
-+ return;
- }
--
-- target = (*pool_head)->base + mgr->used;
- vsprintf(target, format, ap2);
-- }
--
-- if (*ptr != target) {
-+ __ast_string_field_release_active(*pool_head, *ptr);
-+ *ptr = target;
-+ } else if (*ptr != target) {
-+ /* the allocation was satisfied using available space in the pool, but not
-+ using the space already allocated to the field
-+ */
-+ __ast_string_field_release_active(*pool_head, *ptr);
- mgr->last_alloc = *ptr = target;
-- mgr->used += needed;
-+ AST_STRING_FIELD_ALLOCATION(target) = needed;
-+ (*pool_head)->used += needed + sizeof(ast_string_field_allocation);
-+ (*pool_head)->active += needed;
-+ } else if ((grow = (needed - AST_STRING_FIELD_ALLOCATION(*ptr))) > 0) {
-+ /* the allocation was satisfied by using available space in the pool *and*
-+ the field was the last allocated field from the pool, so it grew
-+ */
-+ (*pool_head)->used += grow;
-+ (*pool_head)->active += grow;
-+ AST_STRING_FIELD_ALLOCATION(*ptr) += grow;
- }
- }
-
-Index: main/loader.c
-===================================================================
---- a/main/loader.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/main/loader.c (.../trunk) (revision 186562)
-@@ -43,7 +43,6 @@
- #include "asterisk/manager.h"
- #include "asterisk/cdr.h"
- #include "asterisk/enum.h"
--#include "asterisk/rtp.h"
- #include "asterisk/http.h"
- #include "asterisk/lock.h"
- #include "asterisk/features.h"
-@@ -243,7 +242,6 @@
- { "extconfig", read_config_maps },
- { "enum", ast_enum_reload },
- { "manager", reload_manager },
-- { "rtp", ast_rtp_reload },
- { "http", ast_http_reload },
- { "logger", logger_reload },
- { "features", ast_features_reload },
-@@ -403,18 +401,6 @@
- return NULL;
- }
-
-- /* if the system supports RTLD_NOLOAD, we can just 'promote' the flags
-- on the already-opened library to what we want... if not, we have to
-- close it and start over
-- */
--#if defined(HAVE_RTLD_NOLOAD) && !defined(__Darwin__)
-- if (!dlopen(fn, RTLD_NOLOAD | (wants_global ? RTLD_LAZY | RTLD_GLOBAL : RTLD_NOW | RTLD_LOCAL))) {
-- ast_log(LOG_WARNING, "Unable to promote flags on module '%s': %s\n", resource_in, dlerror());
-- while (!dlclose(lib));
-- ast_free(resource_being_loaded);
-- return NULL;
-- }
--#else
- while (!dlclose(lib));
- resource_being_loaded = NULL;
-
-@@ -435,7 +421,6 @@
- /* since the module was successfully opened, and it registered itself
- the previous time we did that, we're going to assume it worked this
- time too :) */
--#endif
-
- AST_LIST_LAST(&module_list)->lib = lib;
- resource_being_loaded = NULL;
-Index: main/channel.c
-===================================================================
---- a/main/channel.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/main/channel.c (.../trunk) (revision 186562)
-@@ -718,6 +718,8 @@
- AST_FORMAT_ULAW,
- /*! Unless of course, you're a silly European, so then prefer ALAW */
- AST_FORMAT_ALAW,
-+ AST_FORMAT_SIREN14,
-+ AST_FORMAT_SIREN7,
- /*! G.722 is better then all below, but not as common as the above... so give ulaw and alaw priority */
- AST_FORMAT_G722,
- /*! Okay, well, signed linear is easy to translate into other stuff */
-@@ -794,6 +796,13 @@
- return NULL;
- }
-
-+ if (!(tmp->cid.cid_name = ast_strdup(cid_name)) || !(tmp->cid.cid_num = ast_strdup(cid_num))) {
-+ ast_string_field_free_memory(tmp);
-+ sched_context_destroy(tmp->sched);
-+ ast_free(tmp);
-+ return NULL;
-+ }
-+
- #ifdef HAVE_EPOLL
- tmp->epfd = epoll_create(25);
- #endif
-@@ -805,17 +814,19 @@
- #endif
- }
-
-- tmp->timingfd = ast_timer_open();
-- if (tmp->timingfd > -1) {
-+ if ((tmp->timer = ast_timer_open())) {
- needqueue = 0;
-+ tmp->timingfd = ast_timer_fd(tmp->timer);
-+ } else {
-+ tmp->timingfd = -1;
- }
-
- if (needqueue) {
- if (pipe(tmp->alertpipe)) {
- ast_log(LOG_WARNING, "Channel allocation failed: Can't create alert pipe!\n");
- alertpipe_failed:
-- if (tmp->timingfd > -1) {
-- ast_timer_close(tmp->timingfd);
-+ if (tmp->timer) {
-+ ast_timer_close(tmp->timer);
- }
-
- sched_context_destroy(tmp->sched);
-@@ -862,9 +873,6 @@
- ast_string_field_build(tmp, uniqueid, "%s-%li.%d", ast_config_AST_SYSTEM_NAME,
- (long) time(NULL), ast_atomic_fetchadd_int(&uniqueint, 1));
- }
--
-- tmp->cid.cid_name = ast_strdup(cid_name);
-- tmp->cid.cid_num = ast_strdup(cid_num);
-
- if (!ast_strlen_zero(name_fmt)) {
- /* Almost every channel is calling this function, and setting the name via the ast_string_field_build() call.
-@@ -1008,7 +1016,7 @@
- chan->name, f->frametype, f->subclass, qlen, strerror(errno));
- }
- } else if (chan->timingfd > -1) {
-- ast_timer_enable_continuous(chan->timingfd);
-+ ast_timer_enable_continuous(chan->timer);
- } else if (ast_test_flag(chan, AST_FLAG_BLOCKING)) {
- pthread_kill(chan->blocker, SIGURG);
- }
-@@ -1307,6 +1315,279 @@
- cid->cid_dnid = cid->cid_num = cid->cid_name = cid->cid_ani = cid->cid_rdnis = NULL;
- }
-
-+/*!
-+ * \internal
-+ * \brief Initialize the given party id structure.
-+ *
-+ * \param init Party id structure to initialize.
-+ *
-+ * \return Nothing
-+ */
-+static void ast_party_id_init(struct ast_party_id *init)
-+{
-+ init->number = NULL;
-+ init->name = NULL;
-+ init->number_type = 0; /* Unknown */
-+ init->number_presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Copy the source party id information to the destination party id.
-+ *
-+ * \param dest Destination party id
-+ * \param src Source party id
-+ *
-+ * \return Nothing
-+ */
-+static void ast_party_id_copy(struct ast_party_id *dest, const struct ast_party_id *src)
-+{
-+ if (dest == src) {
-+ /* Don't copy to self */
-+ return;
-+ }
-+
-+ if (dest->number) {
-+ ast_free(dest->number);
-+ }
-+ dest->number = ast_strdup(src->number);
-+
-+ if (dest->name) {
-+ ast_free(dest->name);
-+ }
-+ dest->name = ast_strdup(src->name);
-+
-+ dest->number_type = src->number_type;
-+ dest->number_presentation = src->number_presentation;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Initialize the given party id structure using the given guide
-+ * for a set update operation.
-+ *
-+ * \details
-+ * The initialization is needed to allow a set operation to know if a
-+ * value needs to be updated. Simple integers need the guide's original
-+ * value in case the set operation is not trying to set a new value.
-+ * String values are simply set to NULL pointers if they are not going
-+ * to be updated.
-+ *
-+ * \param init Party id structure to initialize.
-+ * \param guide Source party id to use as a guide in initializing.
-+ *
-+ * \return Nothing
-+ */
-+static void ast_party_id_set_init(struct ast_party_id *init, const struct ast_party_id *guide)
-+{
-+ init->number = NULL;
-+ init->name = NULL;
-+ init->number_type = guide->number_type;
-+ init->number_presentation = guide->number_presentation;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Set the source party id information into the destination party id.
-+ *
-+ * \param dest Destination party id
-+ * \param src Source party id
-+ *
-+ * \return Nothing
-+ */
-+static void ast_party_id_set(struct ast_party_id *dest, const struct ast_party_id *src)
-+{
-+ if (dest == src) {
-+ /* Don't set to self */
-+ return;
-+ }
-+
-+ if (src->name && src->name != dest->name) {
-+ if (dest->name) {
-+ ast_free(dest->name);
-+ }
-+ dest->name = ast_strdup(src->name);
-+ }
-+
-+ if (src->number && src->number != dest->number) {
-+ if (dest->number) {
-+ ast_free(dest->number);
-+ }
-+ dest->number = ast_strdup(src->number);
-+ }
-+
-+ dest->number_type = src->number_type;
-+ dest->number_presentation = src->number_presentation;
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Destroy the party id contents
-+ *
-+ * \param doomed The party id to destroy.
-+ *
-+ * \return Nothing
-+ */
-+static void ast_party_id_free(struct ast_party_id *doomed)
-+{
-+ if (doomed->number) {
-+ ast_free(doomed->number);
-+ doomed->number = NULL;
-+ }
-+
-+ if (doomed->name) {
-+ ast_free(doomed->name);
-+ doomed->name = NULL;
-+ }
-+}
-+
-+void ast_party_caller_copy(struct ast_callerid *dest, const struct ast_callerid *src)
-+{
-+ if (dest == src) {
-+ /* Don't copy to self */
-+ return;
-+ }
-+
-+#if 1
-+ /* Copy caller-id specific information ONLY from struct ast_callerid */
-+ if (dest->cid_num)
-+ {
-+ ast_free(dest->cid_num);
-+ }
-+ dest->cid_num = ast_strdup(src->cid_num);
-+
-+ if (dest->cid_name)
-+ {
-+ ast_free(dest->cid_name);
-+ }
-+ dest->cid_name = ast_strdup(src->cid_name);
-+
-+ dest->cid_ton = src->cid_ton;
-+ dest->cid_pres = src->cid_pres;
-+
-+
-+ if (dest->cid_ani)
-+ {
-+ ast_free(dest->cid_ani);
-+ }
-+ dest->cid_ani = ast_strdup(src->cid_ani);
-+
-+ dest->cid_ani2 = src->cid_ani2;
-+
-+#else
-+
-+ /* The src and dest parameter types will become struct ast_party_caller ptrs. */
-+ /* This is future code */
-+
-+ ast_party_id_copy(&dest->id, &src->id);
-+
-+ if (dest->ani) {
-+ ast_free(dest->ani);
-+ }
-+ dest->ani = ast_strdup(src->ani);
-+
-+ dest->ani2 = src->ani2;
-+#endif
-+}
-+
-+void ast_party_connected_line_init(struct ast_party_connected_line *init)
-+{
-+ ast_party_id_init(&init->id);
-+ init->ani = NULL;
-+ init->ani2 = 0;
-+ init->source = AST_CONNECTED_LINE_UPDATE_SOURCE_UNKNOWN;
-+}
-+
-+void ast_party_connected_line_copy(struct ast_party_connected_line *dest, const struct ast_party_connected_line *src)
-+{
-+ if (dest == src) {
-+ /* Don't copy to self */
-+ return;
-+ }
-+
-+ ast_party_id_copy(&dest->id, &src->id);
-+
-+ if (dest->ani) {
-+ ast_free(dest->ani);
-+ }
-+ dest->ani = ast_strdup(src->ani);
-+
-+ dest->ani2 = src->ani2;
-+ dest->source = src->source;
-+}
-+
-+void ast_party_connected_line_set_init(struct ast_party_connected_line *init, const struct ast_party_connected_line *guide)
-+{
-+ ast_party_id_set_init(&init->id, &guide->id);
-+ init->ani = NULL;
-+ init->ani2 = guide->ani2;
-+ init->source = guide->source;
-+}
-+
-+void ast_party_connected_line_set(struct ast_party_connected_line *dest, const struct ast_party_connected_line *src)
-+{
-+ ast_party_id_set(&dest->id, &src->id);
-+
-+ if (src->ani && src->ani != dest->ani) {
-+ if (dest->ani) {
-+ ast_free(dest->ani);
-+ }
-+ dest->ani = ast_strdup(src->ani);
-+ }
-+
-+ dest->ani2 = src->ani2;
-+ dest->source = src->source;
-+}
-+
-+void ast_party_connected_line_collect_caller(struct ast_party_connected_line *connected, struct ast_callerid *cid)
-+{
-+ connected->id.number = cid->cid_num;
-+ connected->id.name = cid->cid_name;
-+ connected->id.number_type = cid->cid_ton;
-+ connected->id.number_presentation = cid->cid_pres;
-+
-+ connected->ani = cid->cid_ani;
-+ connected->ani2 = cid->cid_ani2;
-+ connected->source = AST_CONNECTED_LINE_UPDATE_SOURCE_UNKNOWN;
-+}
-+
-+void ast_party_connected_line_free(struct ast_party_connected_line *doomed)
-+{
-+ ast_party_id_free(&doomed->id);
-+
-+ if (doomed->ani) {
-+ ast_free(doomed->ani);
-+ doomed->ani = NULL;
-+ }
-+}
-+
-+void ast_party_redirecting_copy(struct ast_party_redirecting *dest, const struct ast_party_redirecting *src)
-+{
-+ if (dest == src) {
-+ /* Don't copy to self */
-+ return;
-+ }
-+
-+ ast_party_id_copy(&dest->from, &src->from);
-+ ast_party_id_copy(&dest->to, &src->to);
-+ dest->count = src->count;
-+ dest->reason = src->reason;
-+}
-+
-+void ast_party_redirecting_set_init(struct ast_party_redirecting *init, const struct ast_party_redirecting *guide)
-+{
-+ ast_party_id_set_init(&init->from, &guide->from);
-+ ast_party_id_set_init(&init->to, &guide->to);
-+ init->count = guide->count;
-+ init->reason = guide->reason;
-+}
-+
-+void ast_party_redirecting_free(struct ast_party_redirecting *doomed)
-+{
-+ ast_party_id_free(&doomed->from);
-+ ast_party_id_free(&doomed->to);
-+}
-+
- /*! \brief Free a channel structure */
- void ast_channel_free(struct ast_channel *chan)
- {
-@@ -1370,14 +1651,19 @@
- ast_translator_free_path(chan->writetrans);
- if (chan->pbx)
- ast_log(LOG_WARNING, "PBX may not have been terminated properly on '%s'\n", chan->name);
-+
- free_cid(&chan->cid);
-+ ast_party_connected_line_free(&chan->connected);
-+ ast_party_redirecting_free(&chan->redirecting);
-+
- /* Close pipes if appropriate */
- if ((fd = chan->alertpipe[0]) > -1)
- close(fd);
- if ((fd = chan->alertpipe[1]) > -1)
- close(fd);
-- if ((fd = chan->timingfd) > -1)
-- ast_timer_close(fd);
-+ if (chan->timer) {
-+ ast_timer_close(chan->timer);
-+ }
- #ifdef HAVE_EPOLL
- for (i = 0; i < AST_MAX_FDS; i++) {
- if (chan->epfd_data[i])
-@@ -2323,13 +2609,13 @@
- data = NULL;
- }
-
-- if (rate && rate > (max_rate = ast_timer_get_max_rate(c->timingfd))) {
-+ if (rate && rate > (max_rate = ast_timer_get_max_rate(c->timer))) {
- real_rate = max_rate;
- }
-
- ast_debug(1, "Scheduling timer at (%u requested / %u actual) timer ticks per second\n", rate, real_rate);
-
-- res = ast_timer_set_rate(c->timingfd, real_rate);
-+ res = ast_timer_set_rate(c->timer, real_rate);
-
- c->timingfunc = func;
- c->timingdata = data;
-@@ -2391,6 +2677,8 @@
- case AST_CONTROL_RINGING:
- case AST_CONTROL_ANSWER:
- case AST_CONTROL_SRCUPDATE:
-+ case AST_CONTROL_CONNECTED_LINE:
-+ case AST_CONTROL_REDIRECTING:
- /* Unimportant */
- break;
- default:
-@@ -2582,11 +2870,11 @@
-
- ast_clear_flag(chan, AST_FLAG_EXCEPTION);
-
-- res = ast_timer_get_event(chan->timingfd);
-+ res = ast_timer_get_event(chan->timer);
-
- switch (res) {
- case AST_TIMING_EVENT_EXPIRED:
-- ast_timer_ack(chan->timingfd, 1);
-+ ast_timer_ack(chan->timer, 1);
-
- if (chan->timingfunc) {
- /* save a copy of func/data before unlocking the channel */
-@@ -2596,7 +2884,7 @@
- ast_channel_unlock(chan);
- func(data);
- } else {
-- ast_timer_set_rate(chan->timingfd, 0);
-+ ast_timer_set_rate(chan->timer, 0);
- chan->fdno = -1;
- ast_channel_unlock(chan);
- }
-@@ -2607,7 +2895,7 @@
- case AST_TIMING_EVENT_CONTINUOUS:
- if (AST_LIST_EMPTY(&chan->readq) ||
- !AST_LIST_NEXT(AST_LIST_FIRST(&chan->readq), frame_list)) {
-- ast_timer_disable_continuous(chan->timingfd);
-+ ast_timer_disable_continuous(chan->timer);
- }
- break;
- }
-@@ -2823,6 +3111,13 @@
- ast_clear_flag(chan, AST_FLAG_EMULATE_DTMF);
- chan->emulate_dtmf_digit = 0;
- ast_log(LOG_DTMF, "DTMF end emulation of '%c' queued on %s\n", f->subclass, chan->name);
-+ if (chan->audiohooks) {
-+ struct ast_frame *old_frame = f;
-+ f = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_READ, f);
-+ if (old_frame != f) {
-+ ast_frfree(old_frame);
-+ }
-+ }
- }
- }
- break;
-@@ -2982,7 +3277,10 @@
- case AST_CONTROL_ANSWER:
- case AST_CONTROL_HANGUP:
- case AST_CONTROL_T38:
-- return 0;
-+ case AST_CONTROL_CONNECTED_LINE:
-+ case AST_CONTROL_REDIRECTING:
-+ case AST_CONTROL_TRANSFER:
-+ break;
-
- case AST_CONTROL_CONGESTION:
- case AST_CONTROL_BUSY:
-@@ -3003,7 +3301,7 @@
- * in switch statements. */
- enum ast_control_frame_type condition = _condition;
- struct ast_tone_zone_sound *ts = NULL;
-- int res = -1;
-+ int res;
-
- ast_channel_lock(chan);
-
-@@ -3012,10 +3310,41 @@
- ast_channel_unlock(chan);
- return -1;
- }
-+ switch (condition) {
-+ case AST_CONTROL_CONNECTED_LINE:
-+ {
-+ struct ast_party_connected_line connected;
-
-+ ast_party_connected_line_set_init(&connected, &chan->connected);
-+ res = ast_connected_line_parse_data(data, datalen, &connected);
-+ if (!res) {
-+ ast_channel_set_connected_line(chan, &connected);
-+ }
-+ ast_party_connected_line_free(&connected);
-+ }
-+ break;
-+
-+ case AST_CONTROL_REDIRECTING:
-+ {
-+ struct ast_party_redirecting redirecting;
-+
-+ ast_party_redirecting_set_init(&redirecting, &chan->redirecting);
-+ res = ast_redirecting_parse_data(data, datalen, &redirecting);
-+ if (!res) {
-+ ast_channel_set_redirecting(chan, &redirecting);
-+ }
-+ ast_party_redirecting_free(&redirecting);
-+ }
-+ break;
-+
-+ default:
-+ break;
-+ }
- if (chan->tech->indicate) {
- /* See if the channel driver can handle this condition. */
- res = chan->tech->indicate(chan, condition, data, datalen);
-+ } else {
-+ res = -1;
- }
-
- ast_channel_unlock(chan);
-@@ -3068,6 +3397,9 @@
- case AST_CONTROL_HOLD:
- case AST_CONTROL_UNHOLD:
- case AST_CONTROL_T38:
-+ case AST_CONTROL_TRANSFER:
-+ case AST_CONTROL_CONNECTED_LINE:
-+ case AST_CONTROL_REDIRECTING:
- /* Nothing left to do for these. */
- res = 0;
- break;
-@@ -3530,6 +3862,7 @@
- struct ast_channel *chan;
- int res = 0;
- int last_subclass = 0;
-+ struct ast_party_connected_line connected;
-
- if (outstate)
- *outstate = 0;
-@@ -3560,7 +3893,13 @@
- if (oh->account)
- ast_cdr_setaccount(chan, oh->account);
- }
-+
- ast_set_callerid(chan, cid_num, cid_name, cid_num);
-+ ast_party_connected_line_set_init(&connected, &chan->connected);
-+ connected.id.number = (char *) cid_num;
-+ connected.id.name = (char *) cid_name;
-+ connected.id.number_presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
-+ ast_channel_set_connected_line(chan, &connected);
-
- if (ast_call(chan, data, 0)) { /* ast_call failed... */
- ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
-@@ -3599,6 +3938,8 @@
- case AST_CONTROL_UNHOLD:
- case AST_CONTROL_VIDUPDATE:
- case AST_CONTROL_SRCUPDATE:
-+ case AST_CONTROL_CONNECTED_LINE:
-+ case AST_CONTROL_REDIRECTING:
- case -1: /* Ignore -- just stopping indications */
- break;
-
-@@ -3747,6 +4088,37 @@
- res = 0;
- }
- ast_channel_unlock(chan);
-+
-+ if (res < 0) {
-+ return res;
-+ }
-+
-+ for (;;) {
-+ struct ast_frame *fr;
-+
-+ res = ast_waitfor(chan, -1);
-+
-+ if (res < 0 || !(fr = ast_read(chan))) {
-+ res = -1;
-+ break;
-+ }
-+
-+ if (fr->frametype == AST_FRAME_CONTROL && fr->subclass == AST_CONTROL_TRANSFER) {
-+ enum ast_control_transfer *message = fr->data.ptr;
-+
-+ if (*message == AST_TRANSFER_SUCCESS) {
-+ res = 1;
-+ } else {
-+ res = -1;
-+ }
-+
-+ ast_frfree(fr);
-+ break;
-+ }
-+
-+ ast_frfree(fr);
-+ }
-+
- return res;
- }
-
-@@ -4043,7 +4415,11 @@
- struct ast_frame *current;
- const struct ast_channel_tech *t;
- void *t_pvt;
-- struct ast_callerid tmpcid;
-+ union {
-+ struct ast_callerid cid;
-+ struct ast_party_connected_line connected;
-+ struct ast_party_redirecting redirecting;
-+ } exchange;
- struct ast_channel *clonechan = original->masq;
- struct ast_cdr *cdr;
- int rformat = original->readformat;
-@@ -4224,11 +4600,19 @@
- /* Stream stuff stays the same */
- /* Keep the original state. The fixup code will need to work with it most likely */
-
-- /* Just swap the whole structures, nevermind the allocations, they'll work themselves
-- out. */
-- tmpcid = original->cid;
-+ /*
-+ * Just swap the whole structures, nevermind the allocations,
-+ * they'll work themselves out.
-+ */
-+ exchange.cid = original->cid;
- original->cid = clonechan->cid;
-- clonechan->cid = tmpcid;
-+ clonechan->cid = exchange.cid;
-+ exchange.connected = original->connected;
-+ original->connected = clonechan->connected;
-+ clonechan->connected = exchange.connected;
-+ exchange.redirecting = original->redirecting;
-+ original->redirecting = clonechan->redirecting;
-+ clonechan->redirecting = exchange.redirecting;
-
- /* Restore original timing file descriptor */
- ast_channel_set_fd(original, AST_TIMING_FD, original->timingfd);
-@@ -4521,8 +4905,10 @@
- case AST_CONTROL_HOLD:
- case AST_CONTROL_UNHOLD:
- case AST_CONTROL_VIDUPDATE:
-+ case AST_CONTROL_T38:
- case AST_CONTROL_SRCUPDATE:
-- case AST_CONTROL_T38:
-+ case AST_CONTROL_CONNECTED_LINE:
-+ case AST_CONTROL_REDIRECTING:
- ast_indicate_data(other, f->subclass, f->data.ptr, f->datalen);
- if (jb_in_use) {
- ast_jb_empty_and_reset(c0, c1);
-@@ -5485,3 +5871,576 @@
-
- return ast_say_digit_str_full(chan, buf, ints, lang, audiofd, ctrlfd);
- }
-+
-+void ast_connected_line_copy_from_caller(struct ast_party_connected_line *dest, const struct ast_callerid *src)
-+{
-+#if 1
-+ /* Must manually fill in struct ast_party_id until struct ast_callerid goes away */
-+ if (dest->id.number) {
-+ ast_free(dest->id.number);
-+ }
-+ dest->id.number = ast_strdup(src->cid_num);
-+
-+ if (dest->id.name) {
-+ ast_free(dest->id.name);
-+ }
-+ dest->id.name = ast_strdup(src->cid_name);
-+
-+ dest->id.number_type = src->cid_ton;
-+ dest->id.number_presentation = src->cid_pres;
-+
-+
-+ if (dest->ani) {
-+ ast_free(dest->ani);
-+ }
-+ dest->ani = ast_strdup(src->cid_ani);
-+
-+ dest->ani2 = src->cid_ani2;
-+
-+#else
-+
-+ /* The src parameter type will become a struct ast_party_caller ptr. */
-+ /* This is future code */
-+
-+ ast_party_id_copy(&dest->id, &src->id);
-+
-+ if (dest->ani) {
-+ ast_free(dest->ani);
-+ }
-+ dest->ani = ast_strdup(src->ani);
-+
-+ dest->ani2 = src->ani2;
-+#endif
-+}
-+
-+void ast_connected_line_copy_to_caller(struct ast_callerid *dest, const struct ast_party_connected_line *src)
-+{
-+#if 1
-+ /* Must manually extract from struct ast_party_id until struct ast_callerid goes away */
-+ if (dest->cid_num) {
-+ ast_free(dest->cid_num);
-+ }
-+ dest->cid_num = ast_strdup(src->id.number);
-+
-+ if (dest->cid_name) {
-+ ast_free(dest->cid_name);
-+ }
-+ dest->cid_name = ast_strdup(src->id.name);
-+
-+ dest->cid_ton = src->id.number_type;
-+ dest->cid_pres = src->id.number_presentation;
-+
-+
-+ if (dest->cid_ani) {
-+ ast_free(dest->cid_ani);
-+ }
-+ dest->cid_ani = ast_strdup(src->ani);
-+
-+ dest->cid_ani2 = src->ani2;
-+
-+#else
-+
-+ /* The dest parameter type will become a struct ast_party_caller ptr. */
-+ /* This is future code */
-+
-+ ast_party_id_copy(&dest->id, &src->id);
-+
-+ if (dest->ani) {
-+ ast_free(dest->ani);
-+ }
-+ dest->ani = ast_strdup(src->ani);
-+
-+ dest->ani2 = src->ani2;
-+#endif
-+}
-+
-+void ast_channel_set_connected_line(struct ast_channel *chan, const struct ast_party_connected_line *connected)
-+{
-+ if (&chan->connected == connected) {
-+ /* Don't set to self */
-+ return;
-+ }
-+
-+ ast_channel_lock(chan);
-+ ast_party_connected_line_set(&chan->connected, connected);
-+ ast_channel_unlock(chan);
-+}
-+
-+/*!
-+ * \brief Element identifiers for connected line indication frame data
-+ * \note Only add to the end of this enum.
-+ */
-+enum {
-+ AST_CONNECTED_LINE_NUMBER,
-+ AST_CONNECTED_LINE_NAME,
-+ AST_CONNECTED_LINE_NUMBER_TYPE,
-+ AST_CONNECTED_LINE_NUMBER_PRESENTATION,
-+ AST_CONNECTED_LINE_SOURCE
-+};
-+
-+int ast_connected_line_build_data(unsigned char *data, size_t datalen, const struct ast_party_connected_line *connected)
-+{
-+ int32_t value;
-+ size_t length;
-+ size_t pos = 0;
-+
-+ /*
-+ * The size of integer values must be fixed in case the frame is
-+ * shipped to another machine.
-+ */
-+
-+ /* *************** Connected line party id *************** */
-+ if (connected->id.number) {
-+ length = strlen(connected->id.number);
-+ if (datalen < pos + (sizeof(data[0]) * 2) + length) {
-+ ast_log(LOG_WARNING, "No space left for connected line number\n");
-+ return -1;
-+ }
-+ data[pos++] = AST_CONNECTED_LINE_NUMBER;
-+ data[pos++] = length;
-+ memcpy(data + pos, connected->id.number, length);
-+ pos += length;
-+ }
-+
-+ if (connected->id.name) {
-+ length = strlen(connected->id.name);
-+ if (datalen < pos + (sizeof(data[0]) * 2) + length) {
-+ ast_log(LOG_WARNING, "No space left for connected line name\n");
-+ return -1;
-+ }
-+ data[pos++] = AST_CONNECTED_LINE_NAME;
-+ data[pos++] = length;
-+ memcpy(data + pos, connected->id.name, length);
-+ pos += length;
-+ }
-+
-+ if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
-+ ast_log(LOG_WARNING, "No space left for connected line type of number\n");
-+ return -1;
-+ }
-+ data[pos++] = AST_CONNECTED_LINE_NUMBER_TYPE;
-+ data[pos++] = 1;
-+ data[pos++] = connected->id.number_type;
-+
-+ if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
-+ ast_log(LOG_WARNING, "No space left for connected line presentation\n");
-+ return -1;
-+ }
-+ data[pos++] = AST_CONNECTED_LINE_NUMBER_PRESENTATION;
-+ data[pos++] = 1;
-+ data[pos++] = connected->id.number_presentation;
-+
-+ /* Connected line source */
-+ if (datalen < pos + (sizeof(data[0]) * 2) + sizeof(value)) {
-+ ast_log(LOG_WARNING, "No space left for connected line source\n");
-+ return -1;
-+ }
-+ data[pos++] = AST_CONNECTED_LINE_SOURCE;
-+ data[pos++] = sizeof(value);
-+ value = htonl(connected->source);
-+ memcpy(data + pos, &value, sizeof(value));
-+ pos += sizeof(value);
-+
-+ return pos;
-+}
-+
-+int ast_connected_line_parse_data(const unsigned char *data, size_t datalen, struct ast_party_connected_line *connected)
-+{
-+ size_t pos;
-+ unsigned char ie_len;
-+ unsigned char ie_id;
-+ int32_t value;
-+
-+ for (pos = 0; pos < datalen; pos += ie_len) {
-+ if (datalen < pos + sizeof(ie_id) + sizeof(ie_len)) {
-+ ast_log(LOG_WARNING, "Invalid connected line update\n");
-+ return -1;
-+ }
-+ ie_id = data[pos++];
-+ ie_len = data[pos++];
-+ if (datalen < pos + ie_len) {
-+ ast_log(LOG_WARNING, "Invalid connected line update\n");
-+ return -1;
-+ }
-+
-+ switch (ie_id) {
-+ case AST_CONNECTED_LINE_NUMBER:
-+ if (connected->id.number) {
-+ ast_free(connected->id.number);
-+ }
-+ connected->id.number = ast_malloc(ie_len + 1);
-+ if (connected->id.number) {
-+ memcpy(connected->id.number, data + pos, ie_len);
-+ connected->id.number[ie_len] = 0;
-+ }
-+ break;
-+ case AST_CONNECTED_LINE_NAME:
-+ if (connected->id.name) {
-+ ast_free(connected->id.name);
-+ }
-+ connected->id.name = ast_malloc(ie_len + 1);
-+ if (connected->id.name) {
-+ memcpy(connected->id.name, data + pos, ie_len);
-+ connected->id.name[ie_len] = 0;
-+ }
-+ break;
-+ case AST_CONNECTED_LINE_NUMBER_TYPE:
-+ if (ie_len != 1) {
-+ ast_log(LOG_WARNING, "Invalid connected line type of number (%u)\n", (unsigned) ie_len);
-+ break;
-+ }
-+ connected->id.number_type = data[pos];
-+ break;
-+ case AST_CONNECTED_LINE_NUMBER_PRESENTATION:
-+ if (ie_len != 1) {
-+ ast_log(LOG_WARNING, "Invalid connected line presentation (%u)\n", (unsigned) ie_len);
-+ break;
-+ }
-+ connected->id.number_presentation = data[pos];
-+ break;
-+ case AST_CONNECTED_LINE_SOURCE:
-+ if (ie_len != sizeof(value)) {
-+ ast_log(LOG_WARNING, "Invalid connected line source (%u)\n", (unsigned) ie_len);
-+ break;
-+ }
-+ memcpy(&value, data + pos, sizeof(value));
-+ connected->source = ntohl(value);
-+ break;
-+ default:
-+ ast_log(LOG_DEBUG, "Unknown connected line element: %u (%u)\n", (unsigned) ie_id, (unsigned) ie_len);
-+ break;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+void ast_channel_update_connected_line(struct ast_channel *chan, const struct ast_party_connected_line *connected)
-+{
-+ unsigned char data[1024]; /* This should be large enough */
-+ size_t datalen;
-+
-+ datalen = ast_connected_line_build_data(data, sizeof(data), connected);
-+ if (datalen == (size_t) -1) {
-+ return;
-+ }
-+
-+ ast_indicate_data(chan, AST_CONTROL_CONNECTED_LINE, data, datalen);
-+}
-+
-+void ast_channel_queue_connected_line_update(struct ast_channel *chan, const struct ast_party_connected_line *connected)
-+{
-+ unsigned char data[1024]; /* This should be large enough */
-+ size_t datalen;
-+
-+ datalen = ast_connected_line_build_data(data, sizeof(data), connected);
-+ if (datalen == (size_t) -1) {
-+ return;
-+ }
-+
-+ ast_queue_control_data(chan, AST_CONTROL_CONNECTED_LINE, data, datalen);
-+}
-+
-+void ast_channel_set_redirecting(struct ast_channel *chan, const struct ast_party_redirecting *redirecting)
-+{
-+ if (&chan->redirecting == redirecting) {
-+ /* Don't set to self */
-+ return;
-+ }
-+
-+ ast_channel_lock(chan);
-+
-+ ast_party_id_set(&chan->redirecting.from, &redirecting->from);
-+ if (redirecting->from.number
-+ && redirecting->from.number != chan->redirecting.from.number) {
-+ /*
-+ * Must move string to ast_channel.cid.cid_rdnis until it goes away.
-+ */
-+ if (chan->cid.cid_rdnis) {
-+ ast_free(chan->cid.cid_rdnis);
-+ }
-+ chan->cid.cid_rdnis = chan->redirecting.from.number;
-+ chan->redirecting.from.number = NULL;
-+ }
-+
-+ ast_party_id_set(&chan->redirecting.to, &redirecting->to);
-+ chan->redirecting.reason = redirecting->reason;
-+ chan->redirecting.count = redirecting->count;
-+
-+ ast_channel_unlock(chan);
-+}
-+
-+/*!
-+ * \brief Element identifiers for redirecting indication frame data
-+ * \note Only add to the end of this enum.
-+ */
-+enum {
-+ AST_REDIRECTING_FROM_NUMBER,
-+ AST_REDIRECTING_FROM_NAME,
-+ AST_REDIRECTING_FROM_NUMBER_TYPE,
-+ AST_REDIRECTING_FROM_NUMBER_PRESENTATION,
-+ AST_REDIRECTING_TO_NUMBER,
-+ AST_REDIRECTING_TO_NAME,
-+ AST_REDIRECTING_TO_NUMBER_TYPE,
-+ AST_REDIRECTING_TO_NUMBER_PRESENTATION,
-+ AST_REDIRECTING_REASON,
-+ AST_REDIRECTING_COUNT
-+};
-+
-+int ast_redirecting_build_data(unsigned char *data, size_t datalen, const struct ast_party_redirecting *redirecting)
-+{
-+ int32_t value;
-+ size_t length;
-+ size_t pos = 0;
-+
-+ /*
-+ * The size of integer values must be fixed in case the frame is
-+ * shipped to another machine.
-+ */
-+
-+ /* *************** Redirecting from party id *************** */
-+ if (redirecting->from.number) {
-+ length = strlen(redirecting->from.number);
-+ if (datalen < pos + (sizeof(data[0]) * 2) + length) {
-+ ast_log(LOG_WARNING, "No space left for redirecting from number\n");
-+ return -1;
-+ }
-+ data[pos++] = AST_REDIRECTING_FROM_NUMBER;
-+ data[pos++] = length;
-+ memcpy(data + pos, redirecting->from.number, length);
-+ pos += length;
-+ }
-+
-+ if (redirecting->from.name) {
-+ length = strlen(redirecting->from.name);
-+ if (datalen < pos + (sizeof(data[0]) * 2) + length) {
-+ ast_log(LOG_WARNING, "No space left for redirecting from name\n");
-+ return -1;
-+ }
-+ data[pos++] = AST_REDIRECTING_FROM_NAME;
-+ data[pos++] = length;
-+ memcpy(data + pos, redirecting->from.name, length);
-+ pos += length;
-+ }
-+
-+ if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
-+ ast_log(LOG_WARNING, "No space left for redirecting from type of number\n");
-+ return -1;
-+ }
-+ data[pos++] = AST_REDIRECTING_FROM_NUMBER_TYPE;
-+ data[pos++] = 1;
-+ data[pos++] = redirecting->from.number_type;
-+
-+ if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
-+ ast_log(LOG_WARNING, "No space left for redirecting from presentation\n");
-+ return -1;
-+ }
-+ data[pos++] = AST_REDIRECTING_FROM_NUMBER_PRESENTATION;
-+ data[pos++] = 1;
-+ data[pos++] = redirecting->from.number_presentation;
-+
-+ /* *************** Redirecting to party id *************** */
-+ if (redirecting->to.number) {
-+ length = strlen(redirecting->to.number);
-+ if (datalen < pos + (sizeof(data[0]) * 2) + length) {
-+ ast_log(LOG_WARNING, "No space left for redirecting to number\n");
-+ return -1;
-+ }
-+ data[pos++] = AST_REDIRECTING_TO_NUMBER;
-+ data[pos++] = length;
-+ memcpy(data + pos, redirecting->to.number, length);
-+ pos += length;
-+ }
-+
-+ if (redirecting->to.name) {
-+ length = strlen(redirecting->to.name);
-+ if (datalen < pos + (sizeof(data[0]) * 2) + length) {
-+ ast_log(LOG_WARNING, "No space left for redirecting to name\n");
-+ return -1;
-+ }
-+ data[pos++] = AST_REDIRECTING_TO_NAME;
-+ data[pos++] = length;
-+ memcpy(data + pos, redirecting->to.name, length);
-+ pos += length;
-+ }
-+
-+ if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
-+ ast_log(LOG_WARNING, "No space left for redirecting to type of number\n");
-+ return -1;
-+ }
-+ data[pos++] = AST_REDIRECTING_TO_NUMBER_TYPE;
-+ data[pos++] = 1;
-+ data[pos++] = redirecting->to.number_type;
-+
-+ if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
-+ ast_log(LOG_WARNING, "No space left for redirecting to presentation\n");
-+ return -1;
-+ }
-+ data[pos++] = AST_REDIRECTING_TO_NUMBER_PRESENTATION;
-+ data[pos++] = 1;
-+ data[pos++] = redirecting->to.number_presentation;
-+
-+ /* Redirecting reason */
-+ if (datalen < pos + (sizeof(data[0]) * 2) + sizeof(value)) {
-+ ast_log(LOG_WARNING, "No space left for redirecting reason\n");
-+ return -1;
-+ }
-+ data[pos++] = AST_REDIRECTING_REASON;
-+ data[pos++] = sizeof(value);
-+ value = htonl(redirecting->reason);
-+ memcpy(data + pos, &value, sizeof(value));
-+ pos += sizeof(value);
-+
-+ /* Redirecting count */
-+ if (datalen < pos + (sizeof(data[0]) * 2) + sizeof(value)) {
-+ ast_log(LOG_WARNING, "No space left for redirecting count\n");
-+ return -1;
-+ }
-+ data[pos++] = AST_REDIRECTING_COUNT;
-+ data[pos++] = sizeof(value);
-+ value = htonl(redirecting->count);
-+ memcpy(data + pos, &value, sizeof(value));
-+ pos += sizeof(value);
-+
-+ return pos;
-+}
-+
-+int ast_redirecting_parse_data(const unsigned char *data, size_t datalen, struct ast_party_redirecting *redirecting)
-+{
-+ size_t pos;
-+ unsigned char ie_len;
-+ unsigned char ie_id;
-+ int32_t value;
-+
-+ for (pos = 0; pos < datalen; pos += ie_len) {
-+ if (datalen < pos + sizeof(ie_id) + sizeof(ie_len)) {
-+ ast_log(LOG_WARNING, "Invalid redirecting update\n");
-+ return -1;
-+ }
-+ ie_id = data[pos++];
-+ ie_len = data[pos++];
-+ if (datalen < pos + ie_len) {
-+ ast_log(LOG_WARNING, "Invalid redirecting update\n");
-+ return -1;
-+ }
-+
-+ switch (ie_id) {
-+ case AST_REDIRECTING_FROM_NUMBER:
-+ if (redirecting->from.number) {
-+ ast_free(redirecting->from.number);
-+ }
-+ redirecting->from.number = ast_malloc(ie_len + 1);
-+ if (redirecting->from.number) {
-+ memcpy(redirecting->from.number, data + pos, ie_len);
-+ redirecting->from.number[ie_len] = 0;
-+ }
-+ break;
-+ case AST_REDIRECTING_FROM_NAME:
-+ if (redirecting->from.name) {
-+ ast_free(redirecting->from.name);
-+ }
-+ redirecting->from.name = ast_malloc(ie_len + 1);
-+ if (redirecting->from.name) {
-+ memcpy(redirecting->from.name, data + pos, ie_len);
-+ redirecting->from.name[ie_len] = 0;
-+ }
-+ break;
-+ case AST_REDIRECTING_FROM_NUMBER_TYPE:
-+ if (ie_len != 1) {
-+ ast_log(LOG_WARNING, "Invalid redirecting from type of number (%u)\n", (unsigned) ie_len);
-+ break;
-+ }
-+ redirecting->from.number_type = data[pos];
-+ break;
-+ case AST_REDIRECTING_FROM_NUMBER_PRESENTATION:
-+ if (ie_len != 1) {
-+ ast_log(LOG_WARNING, "Invalid redirecting from presentation (%u)\n", (unsigned) ie_len);
-+ break;
-+ }
-+ redirecting->from.number_presentation = data[pos];
-+ break;
-+ case AST_REDIRECTING_TO_NUMBER:
-+ if (redirecting->to.number) {
-+ ast_free(redirecting->to.number);
-+ }
-+ redirecting->to.number = ast_malloc(ie_len + 1);
-+ if (redirecting->to.number) {
-+ memcpy(redirecting->to.number, data + pos, ie_len);
-+ redirecting->to.number[ie_len] = 0;
-+ }
-+ break;
-+ case AST_REDIRECTING_TO_NAME:
-+ if (redirecting->to.name) {
-+ ast_free(redirecting->to.name);
-+ }
-+ redirecting->to.name = ast_malloc(ie_len + 1);
-+ if (redirecting->to.name) {
-+ memcpy(redirecting->to.name, data + pos, ie_len);
-+ redirecting->to.name[ie_len] = 0;
-+ }
-+ break;
-+ case AST_REDIRECTING_TO_NUMBER_TYPE:
-+ if (ie_len != 1) {
-+ ast_log(LOG_WARNING, "Invalid redirecting to type of number (%u)\n", (unsigned) ie_len);
-+ break;
-+ }
-+ redirecting->to.number_type = data[pos];
-+ break;
-+ case AST_REDIRECTING_TO_NUMBER_PRESENTATION:
-+ if (ie_len != 1) {
-+ ast_log(LOG_WARNING, "Invalid redirecting to presentation (%u)\n", (unsigned) ie_len);
-+ break;
-+ }
-+ redirecting->to.number_presentation = data[pos];
-+ break;
-+ case AST_REDIRECTING_REASON:
-+ if (ie_len != sizeof(value)) {
-+ ast_log(LOG_WARNING, "Invalid redirecting reason (%u)\n", (unsigned) ie_len);
-+ break;
-+ }
-+ memcpy(&value, data + pos, sizeof(value));
-+ redirecting->reason = ntohl(value);
-+ break;
-+ case AST_REDIRECTING_COUNT:
-+ if (ie_len != sizeof(value)) {
-+ ast_log(LOG_WARNING, "Invalid redirecting count (%u)\n", (unsigned) ie_len);
-+ break;
-+ }
-+ memcpy(&value, data + pos, sizeof(value));
-+ redirecting->count = ntohl(value);
-+ break;
-+ default:
-+ ast_log(LOG_DEBUG, "Unknown redirecting element: %u (%u)\n", (unsigned) ie_id, (unsigned) ie_len);
-+ break;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+void ast_channel_update_redirecting(struct ast_channel *chan, const struct ast_party_redirecting *redirecting)
-+{
-+ unsigned char data[1024]; /* This should be large enough */
-+ size_t datalen;
-+
-+ datalen = ast_redirecting_build_data(data, sizeof(data), redirecting);
-+ if (datalen == (size_t) -1) {
-+ return;
-+ }
-+
-+ ast_indicate_data(chan, AST_CONTROL_REDIRECTING, data, datalen);
-+}
-+
-+void ast_channel_queue_redirecting_update(struct ast_channel *chan, const struct ast_party_redirecting *redirecting)
-+{
-+ unsigned char data[1024]; /* This should be large enough */
-+ size_t datalen;
-+
-+ datalen = ast_redirecting_build_data(data, sizeof(data), redirecting);
-+ if (datalen == (size_t) -1) {
-+ return;
-+ }
-+
-+ ast_queue_control_data(chan, AST_CONTROL_REDIRECTING, data, datalen);
-+}
-+
-Index: main/manager.c
-===================================================================
---- a/main/manager.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/main/manager.c (.../trunk) (revision 186562)
-@@ -499,7 +499,7 @@
- }
-
- /*! \brief Get displayconnects config option.
-- * \param s manager session to get parameter from.
-+ * \param session manager session to get parameter from.
- * \return displayconnects config option value.
- */
- static int manager_displayconnects (struct mansession_session *session)
-@@ -1759,22 +1759,39 @@
- static char mandescr_hangup[] =
- "Description: Hangup a channel\n"
- "Variables: \n"
--" Channel: The channel name to be hungup\n";
-+" Channel: The channel name to be hungup\n"
-+" Cause: numeric hangup cause\n";
-
- static int action_hangup(struct mansession *s, const struct message *m)
- {
- struct ast_channel *c = NULL;
-+ int causecode = 0; /* all values <= 0 mean 'do not set hangupcause in channel' */
- const char *name = astman_get_header(m, "Channel");
-+ const char *cause = astman_get_header(m, "Cause");
- if (ast_strlen_zero(name)) {
- astman_send_error(s, m, "No channel specified");
- return 0;
- }
-+ if (!ast_strlen_zero(cause)) {
-+ char *endptr;
-+ causecode = strtol(cause, &endptr, 10);
-+ if (causecode < 0 || causecode > 127 || *endptr != '\0') {
-+ ast_log(LOG_NOTICE, "Invalid 'Cause: %s' in manager action Hangup\n", cause);
-+ /* keep going, better to hangup without cause than to not hang up at all */
-+ causecode = 0; /* do not set channel's hangupcause */
-+ }
-+ }
- c = ast_get_channel_by_name_locked(name);
- if (!c) {
- astman_send_error(s, m, "No such channel");
- return 0;
- }
-- ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
-+ if (causecode > 0) {
-+ ast_debug(1, "Setting hangupcause of channel %s to %d (is %d now)\n",
-+ c->name, causecode, c->hangupcause);
-+ c->hangupcause = causecode;
-+ }
-+ ast_softhangup_nolock(c, AST_SOFTHANGUP_EXPLICIT);
- ast_channel_unlock(c);
- astman_send_ack(s, m, "Channel Hungup");
- return 0;
-@@ -3803,7 +3820,7 @@
- * properties of the rand() function (and the constantcy of s), that
- * won't happen twice in a row.
- */
-- while ((session->managerid = rand() ^ (unsigned long) session) == 0);
-+ while ((session->managerid = ast_random() ^ (unsigned long) session) == 0);
- session->last_ev = grab_last();
- AST_LIST_HEAD_INIT_NOLOCK(&session->datastores);
- AST_LIST_LOCK(&sessions);
-Index: main/tdd.c
-===================================================================
---- a/main/tdd.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/main/tdd.c (.../trunk) (revision 186562)
-@@ -274,7 +274,9 @@
- PUT_TDD_STOP; /* Stop bit */ \
- } while(0);
-
--/*! Generate TDD hold tone */
-+/*! Generate TDD hold tone
-+ * \param buf Result buffer
-+ * \todo How big should this be??? */
- int tdd_gen_holdtone(unsigned char *buf)
- {
- int bytes = 0;
-Index: main/ast_expr2f.c
-===================================================================
---- a/main/ast_expr2f.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/main/ast_expr2f.c (.../trunk) (revision 186562)
-@@ -1962,8 +1962,8 @@
-
- /** Setup the input buffer state to scan the given bytes. The next call to ast_yylex() will
- * scan from a @e copy of @a bytes.
-- * @param bytes the byte buffer to scan
-- * @param len the number of bytes in the buffer pointed to by @a bytes.
-+ * @param yybytes the byte buffer to scan
-+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
- * @param yyscanner The scanner object.
- * @return the newly allocated buffer state object.
- */
-@@ -2124,7 +2124,7 @@
- }
-
- /** Set the current column.
-- * @param line_number
-+ * @param column_no
- * @param yyscanner The scanner object.
- */
- void ast_yyset_column (int column_no , yyscan_t yyscanner)
-@@ -2387,19 +2387,12 @@
-
- int ast_expr(char *expr, char *buf, int length, struct ast_channel *chan)
- {
-- struct parse_io io;
-+ struct parse_io io = { .string = expr, .chan = chan };
- int return_value = 0;
--
-- memset(&io, 0, sizeof(io));
-- io.string = expr; /* to pass to the error routine */
-- io.chan = chan;
--
-+
- ast_yylex_init(&io.scanner);
--
- ast_yy_scan_string(expr, io.scanner);
--
- ast_yyparse ((void *) &io);
--
- ast_yylex_destroy(io.scanner);
-
- if (!io.val) {
-Index: main/features.c
-===================================================================
---- a/main/features.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/main/features.c (.../trunk) (revision 186562)
-@@ -889,9 +889,6 @@
- return masq_park_call(rchan, peer, timeout, extout, 1, NULL);
- }
-
--#define FEATURE_SENSE_CHAN (1 << 0)
--#define FEATURE_SENSE_PEER (1 << 1)
--
- /*!
- * \brief set caller and callee according to the direction
- * \param caller, callee, peer, chan, sense
-@@ -1390,6 +1387,7 @@
- struct ast_bridge_config bconfig;
- struct ast_frame *f;
- int l;
-+ struct ast_party_connected_line connected_line = {{0,},};
- struct ast_datastore *features_datastore;
- struct ast_dial_features *dialfeatures = NULL;
-
-@@ -1481,6 +1479,17 @@
- memset(&bconfig,0,sizeof(struct ast_bridge_config));
- ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
- ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
-+ /* We need to get the transferer's connected line information copied
-+ * at this point because he is likely to hang up during the bridge with
-+ * newchan. This info will be used down below before bridging the
-+ * transferee and newchan
-+ *
-+ * As a result, we need to be sure to free this data before returning
-+ * or overwriting it.
-+ */
-+ ast_channel_lock(transferer);
-+ ast_party_connected_line_copy(&connected_line, &transferer->connected);
-+ ast_channel_unlock(transferer);
- res = ast_bridge_call(transferer, newchan, &bconfig);
- if (ast_check_hangup(newchan) || !ast_check_hangup(transferer)) {
- ast_hangup(newchan);
-@@ -1488,10 +1497,12 @@
- ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
- finishup(transferee);
- transferer->_softhangup = 0;
-+ ast_party_connected_line_free(&connected_line);
- return AST_FEATURE_RETURN_SUCCESS;
- }
- if (check_compat(transferee, newchan)) {
- finishup(transferee);
-+ ast_party_connected_line_free(&connected_line);
- return -1;
- }
- ast_indicate(transferee, AST_CONTROL_UNHOLD);
-@@ -1502,11 +1513,13 @@
- || ast_check_hangup(transferee)
- || ast_check_hangup(newchan)) {
- ast_hangup(newchan);
-+ ast_party_connected_line_free(&connected_line);
- return -1;
- }
- xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
- if (!xferchan) {
- ast_hangup(newchan);
-+ ast_party_connected_line_free(&connected_line);
- return -1;
- }
- /* Make formats okay */
-@@ -1526,6 +1539,7 @@
- if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
- ast_hangup(xferchan);
- ast_hangup(newchan);
-+ ast_party_connected_line_free(&connected_line);
- return -1;
- }
-
-@@ -1560,6 +1574,18 @@
- tobj->bconfig.end_bridge_callback_data_fixup(&tobj->bconfig, tobj->peer, tobj->chan);
- }
-
-+ /* Due to a limitation regarding when callerID is set on a Local channel,
-+ * we use the transferer's connected line information here.
-+ */
-+ connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
-+ ast_channel_update_connected_line(xferchan, &connected_line);
-+ ast_channel_lock(xferchan);
-+ ast_connected_line_copy_from_caller(&connected_line, &xferchan->cid);
-+ ast_channel_unlock(xferchan);
-+ connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
-+ ast_channel_update_connected_line(newchan, &connected_line);
-+ ast_party_connected_line_free(&connected_line);
-+
- if (ast_stream_and_wait(newchan, xfersound, ""))
- ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
- bridge_call_thread_launch(tobj);
-@@ -1656,11 +1682,24 @@
- tobj->chan = newchan;
- tobj->peer = xferchan;
- tobj->bconfig = *config;
--
-+
- if (tobj->bconfig.end_bridge_callback_data_fixup) {
- tobj->bconfig.end_bridge_callback_data_fixup(&tobj->bconfig, tobj->peer, tobj->chan);
- }
-
-+ ast_channel_lock(newchan);
-+ ast_connected_line_copy_from_caller(&connected_line, &newchan->cid);
-+ ast_channel_unlock(newchan);
-+ connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
-+ ast_channel_update_connected_line(xferchan, &connected_line);
-+ ast_channel_lock(xferchan);
-+ ast_connected_line_copy_from_caller(&connected_line, &xferchan->cid);
-+ ast_channel_unlock(xferchan);
-+ connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
-+ ast_channel_update_connected_line(newchan, &connected_line);
-+
-+ ast_party_connected_line_free(&connected_line);
-+
- if (ast_stream_and_wait(newchan, xfersound, ""))
- ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
- bridge_call_thread_launch(tobj);
-@@ -1969,53 +2008,42 @@
- }
-
- /*!
-- * \brief Check the dynamic features
-- * \param chan,peer,config,code,sense
-+ * \brief Helper function for feature_interpret and ast_feature_detect
-+ * \param chan,peer,config,code,sense,dynamic_features char buf,feature flags,operation,feature
- *
- * Lock features list, browse for code, unlock list
-+ * If a feature is found and the operation variable is set, that feature's
-+ * operation is executed. The first feature found is copied to the feature parameter.
- * \retval res on success.
- * \retval -1 on failure.
- */
--static int feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
-+static int feature_interpret_helper(struct ast_channel *chan, struct ast_channel *peer,
-+ struct ast_bridge_config *config, char *code, int sense, char *dynamic_features_buf,
-+ struct ast_flags *features, int operation, struct ast_call_feature *feature)
- {
- int x;
-- struct ast_flags features;
-- struct ast_call_feature *feature;
- struct feature_group *fg = NULL;
- struct feature_group_exten *fge;
-- const char *peer_dynamic_features, *chan_dynamic_features;
-- char dynamic_features_buf[128];
-+ struct ast_call_feature *tmpfeature;
- char *tmp, *tok;
- int res = AST_FEATURE_RETURN_PASSDIGITS;
- int feature_detected = 0;
-
-- if (sense == FEATURE_SENSE_CHAN) {
-- ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
-+ if (!(peer && chan && config) && operation) {
-+ return -1; /* can not run feature operation */
- }
-- else {
-- ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
-- }
-
-- ast_channel_lock(peer);
-- peer_dynamic_features = ast_strdupa(S_OR(pbx_builtin_getvar_helper(peer, "DYNAMIC_FEATURES"),""));
-- ast_channel_unlock(peer);
--
-- ast_channel_lock(chan);
-- chan_dynamic_features = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES"),""));
-- ast_channel_unlock(chan);
--
-- snprintf(dynamic_features_buf, sizeof(dynamic_features_buf), "%s%s%s", S_OR(chan_dynamic_features, ""), chan_dynamic_features && peer_dynamic_features ? "#" : "", S_OR(peer_dynamic_features,""));
--
-- ast_debug(3, "Feature interpret: chan=%s, peer=%s, code=%s, sense=%d, features=%d, dynamic=%s\n", chan->name, peer->name, code, sense, features.flags, dynamic_features_buf);
--
- ast_rwlock_rdlock(&features_lock);
- for (x = 0; x < FEATURES_COUNT; x++) {
-- if ((ast_test_flag(&features, builtin_features[x].feature_mask)) &&
-+ if ((ast_test_flag(features, builtin_features[x].feature_mask)) &&
- !ast_strlen_zero(builtin_features[x].exten)) {
- /* Feature is up for consideration */
- if (!strcmp(builtin_features[x].exten, code)) {
- ast_debug(3, "Feature detected: fname=%s sname=%s exten=%s\n", builtin_features[x].fname, builtin_features[x].sname, builtin_features[x].exten);
-- res = builtin_features[x].operation(chan, peer, config, code, sense, NULL);
-+ if (operation) {
-+ res = builtin_features[x].operation(chan, peer, config, code, sense, NULL);
-+ }
-+ memcpy(feature, &builtin_features[x], sizeof(feature));
- feature_detected = 1;
- break;
- } else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
-@@ -2026,8 +2054,9 @@
- }
- ast_rwlock_unlock(&features_lock);
-
-- if (ast_strlen_zero(dynamic_features_buf) || feature_detected)
-+ if (ast_strlen_zero(dynamic_features_buf) || feature_detected) {
- return res;
-+ }
-
- tmp = dynamic_features_buf;
-
-@@ -2040,8 +2069,10 @@
- AST_LIST_TRAVERSE(&fg->features, fge, entry) {
- if (strcasecmp(fge->exten, code))
- continue;
--
-- res = fge->feature->operation(chan, peer, config, code, sense, fge->feature);
-+ if (operation) {
-+ res = fge->feature->operation(chan, peer, config, code, sense, fge->feature);
-+ }
-+ memcpy(feature, fge->feature, sizeof(feature));
- if (res != AST_FEATURE_RETURN_KEEPTRYING) {
- AST_RWLIST_UNLOCK(&feature_groups);
- break;
-@@ -2056,33 +2087,78 @@
-
- AST_RWLIST_RDLOCK(&feature_list);
-
-- if (!(feature = find_dynamic_feature(tok))) {
-+ if (!(tmpfeature = find_dynamic_feature(tok))) {
- AST_RWLIST_UNLOCK(&feature_list);
- continue;
- }
--
-+
- /* Feature is up for consideration */
-- if (!strcmp(feature->exten, code)) {
-- ast_verb(3, " Feature Found: %s exten: %s\n",feature->sname, tok);
-- res = feature->operation(chan, peer, config, code, sense, feature);
-+ if (!strcmp(tmpfeature->exten, code)) {
-+ ast_verb(3, " Feature Found: %s exten: %s\n",tmpfeature->sname, tok);
-+ if (operation) {
-+ res = tmpfeature->operation(chan, peer, config, code, sense, tmpfeature);
-+ }
-+ memcpy(feature, tmpfeature, sizeof(feature));
- if (res != AST_FEATURE_RETURN_KEEPTRYING) {
- AST_RWLIST_UNLOCK(&feature_list);
- break;
- }
- res = AST_FEATURE_RETURN_PASSDIGITS;
-- } else if (!strncmp(feature->exten, code, strlen(code)))
-+ } else if (!strncmp(tmpfeature->exten, code, strlen(code)))
- res = AST_FEATURE_RETURN_STOREDIGITS;
-
- AST_RWLIST_UNLOCK(&feature_list);
- }
--
-+
- return res;
- }
-
-+/*!
-+ * \brief Check the dynamic features
-+ * \param chan,peer,config,code,sense
-+ *
-+ * \retval res on success.
-+ * \retval -1 on failure.
-+*/
-+
-+static int feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense) {
-+
-+ char dynamic_features_buf[128];
-+ const char *peer_dynamic_features, *chan_dynamic_features;
-+ struct ast_flags features;
-+ struct ast_call_feature feature;
-+ if (sense == FEATURE_SENSE_CHAN) {
-+ ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
-+ }
-+ else {
-+ ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
-+ }
-+
-+ ast_channel_lock(peer);
-+ peer_dynamic_features = ast_strdupa(S_OR(pbx_builtin_getvar_helper(peer, "DYNAMIC_FEATURES"),""));
-+ ast_channel_unlock(peer);
-+
-+ ast_channel_lock(chan);
-+ chan_dynamic_features = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES"),""));
-+ ast_channel_unlock(chan);
-+
-+ snprintf(dynamic_features_buf, sizeof(dynamic_features_buf), "%s%s%s", S_OR(chan_dynamic_features, ""), chan_dynamic_features && peer_dynamic_features ? "#" : "", S_OR(peer_dynamic_features,""));
-+
-+ ast_debug(3, "Feature interpret: chan=%s, peer=%s, code=%s, sense=%d, features=%d, dynamic=%s\n", chan->name, peer->name, code, sense, features.flags, dynamic_features_buf);
-+
-+ return feature_interpret_helper(chan, peer, config, code, sense, dynamic_features_buf, &features, 1, &feature);
-+}
-+
-+
-+int ast_feature_detect(struct ast_channel *chan, struct ast_flags *features, char *code, struct ast_call_feature *feature) {
-+
-+ return feature_interpret_helper(chan, NULL, NULL, code, 0, NULL, features, 0, feature);
-+}
-+
- static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
- {
- int x;
--
-+
- ast_clear_flag(config, AST_FLAGS_ALL);
-
- ast_rwlock_rdlock(&features_lock);
-@@ -2097,7 +2173,7 @@
- ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
- }
- ast_rwlock_unlock(&features_lock);
--
-+
- if (chan && peer && !(ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_0) && ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_1))) {
- const char *dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
-
-@@ -2163,6 +2239,10 @@
- ast_channel_inherit_variables(caller, chan);
- pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", caller->name);
-
-+ ast_channel_lock(chan);
-+ ast_connected_line_copy_from_caller(&chan->connected, &caller->cid);
-+ ast_channel_unlock(chan);
-+
- if (ast_call(chan, data, timeout)) {
- ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
- goto done;
-@@ -2232,6 +2312,8 @@
- f = NULL;
- ready=1;
- break;
-+ } else if (f->subclass == AST_CONTROL_CONNECTED_LINE) {
-+ ast_indicate_data(caller, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen);
- } else if (f->subclass != -1) {
- ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass);
- }
-@@ -4410,8 +4492,19 @@
- struct ast_channel *cur = ast_channel_search_locked(find_channel_by_group, chan);
-
- if (cur) {
-+ struct ast_party_connected_line connected_caller;
-+
- int res = -1;
- ast_debug(1, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name);
-+
-+ connected_caller = cur->connected;
-+ connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
-+ ast_channel_update_connected_line(chan, &connected_caller);
-+
-+ ast_party_connected_line_collect_caller(&connected_caller, &chan->cid);
-+ connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
-+ ast_channel_queue_connected_line_update(chan, &connected_caller);
-+
- res = ast_answer(chan);
- if (res)
- ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
-Index: main/http.c
-===================================================================
---- a/main/http.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/main/http.c (.../trunk) (revision 186562)
-@@ -213,7 +213,7 @@
- "Server: Asterisk/%s\r\n"
- "Date: %s\r\n"
- "Connection: close\r\n"
-- "Cache-Control: no-cache, no-store\r\n"
-+ "Cache-Control: private\r\n"
- "Content-Length: %d\r\n"
- "Content-type: %s\r\n\r\n",
- ast_get_version(), buf, (int) st.st_size, mtype);
-Index: main/app.c
-===================================================================
---- a/main/app.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/main/app.c (.../trunk) (revision 186562)
-@@ -52,7 +52,7 @@
- #include "asterisk/linkedlists.h"
- #include "asterisk/threadstorage.h"
-
--AST_THREADSTORAGE_PUBLIC(global_app_buf);
-+AST_THREADSTORAGE_PUBLIC(ast_str_thread_global_buf);
-
-
- #define MAX_OTHER_FORMATS 10
-Index: main/bridging.c
-===================================================================
---- a/main/bridging.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/main/bridging.c (.../trunk) (revision 186562)
-@@ -319,7 +319,7 @@
- /* Move channels around for priority reasons if we have more than one channel in our array */
- if (bridge->array_num > 1) {
- struct ast_channel *first = bridge->array[0];
-- memmove(bridge->array, bridge->array + 1, sizeof(bridge->array) - 1);
-+ memmove(bridge->array, bridge->array + 1, sizeof(struct ast_channel *) * (bridge->array_num - 1));
- bridge->array[(bridge->array_num - 1)] = first;
- }
-
-Index: main/stdtime/localtime.c
-===================================================================
---- a/main/stdtime/localtime.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/main/stdtime/localtime.c (.../trunk) (revision 186562)
-@@ -310,7 +310,11 @@
- sp->wd[1] = -1;
- }
- /* or if the symlink itself changes (or the real file is here, if path is not a symlink) */
-- sp->wd[0] = inotify_add_watch(inotify_fd, path, IN_ATTRIB | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_CLOSE_WRITE | IN_DONT_FOLLOW);
-+ sp->wd[0] = inotify_add_watch(inotify_fd, path, IN_ATTRIB | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_CLOSE_WRITE
-+#ifdef IN_DONT_FOLLOW /* Only defined in glibc 2.5 and above */
-+ | IN_DONT_FOLLOW
-+#endif
-+ );
- }
- }
- #else
-Index: main/Makefile
-===================================================================
---- a/main/Makefile (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/main/Makefile (.../trunk) (revision 186562)
-@@ -20,7 +20,7 @@
- OBJS= tcptls.o io.o sched.o logger.o frame.o loader.o config.o channel.o \
- translate.o file.o pbx.o cli.o md5.o term.o heap.o \
- ulaw.o alaw.o callerid.o fskmodem.o image.o app.o \
-- cdr.o tdd.o acl.o rtp.o udptl.o manager.o asterisk.o \
-+ cdr.o tdd.o acl.o udptl.o manager.o asterisk.o \
- dsp.o chanvars.o indications.o autoservice.o db.o privacy.o \
- astmm.o enum.o srv.o dns.o aescrypt.o aestab.o aeskey.o \
- utils.o plc.o jitterbuf.o dnsmgr.o devicestate.o \
-@@ -29,7 +29,7 @@
- strcompat.o threadstorage.o dial.o event.o adsistub.o audiohook.o \
- astobj2.o hashtab.o global_datastores.o version.o \
- features.o taskprocessor.o timing.o datastore.o xml.o xmldoc.o \
-- strings.o bridging.o poll.o
-+ strings.o bridging.o poll.o rtp_engine.o stun.o
-
- # we need to link in the objects statically, not as a library, because
- # otherwise modules will not have them available if none of the static
-@@ -103,6 +103,10 @@
- endif
- endif
-
-+ifeq ($(GNU_LD),1)
-+ASTLINK+=-Wl,--version-script,asterisk.exports
-+endif
-+
- CHECK_SUBDIR: # do nothing, just make sure that we recurse in the subdir/
-
- editline/libedit.a: CHECK_SUBDIR
-@@ -163,15 +167,14 @@
- GMIMELDFLAGS+=$(GMIME_LIB)
- endif
-
--$(MAIN_TGT): $(OBJS) editline/libedit.a db1-ast/libdb1.a $(AST_EMBED_LDSCRIPTS)
-+$(MAIN_TGT): $(OBJS) editline/libedit.a db1-ast/libdb1.a $(AST_EMBED_LDSCRIPTS) asterisk.exports
- @$(CC) -c -o buildinfo.o $(ASTCFLAGS) buildinfo.c
-- $(ECHO_PREFIX) echo " [LD] $^ -> $@"
-+ $(ECHO_PREFIX) echo " [LD] $(OBJS) editline/libedit.a db1-ast/libdb1.a $(AST_EMBED_LDSCRIPTS) -> $@"
- ifneq ($(findstring chan_h323,$(MENUSELECT_CHANNELS)),)
-- $(CMD_PREFIX) $(CC) $(STATIC_BUILD) -o $@ $(ASTLINK) $(AST_EMBED_LDFLAGS) $(ASTLDFLAGS) $^ buildinfo.o $(AST_LIBS) $(AST_EMBED_LIBS) $(GMIMELDFLAGS)
-+ $(CMD_PREFIX) $(CC) $(STATIC_BUILD) -o $@ $(ASTLINK) $(AST_EMBED_LDFLAGS) $(ASTLDFLAGS) $(OBJS) editline/libedit.a db1-ast/libdb1.a $(AST_EMBED_LDSCRIPTS) buildinfo.o $(AST_LIBS) $(AST_EMBED_LIBS) $(GMIMELDFLAGS)
- else
-- $(CMD_PREFIX) $(CXX) $(STATIC_BUILD) -o $@ $(ASTLINK) $(AST_EMBED_LDFLAGS) $(ASTLDFLAGS) $(H323LDFLAGS) $^ buildinfo.o $(AST_LIBS) $(AST_EMBED_LIBS) $(H323LDLIBS) $(GMIMELDFLAGS)
-+ $(CMD_PREFIX) $(CXX) $(STATIC_BUILD) -o $@ $(ASTLINK) $(AST_EMBED_LDFLAGS) $(ASTLDFLAGS) $(H323LDFLAGS) $(OBJS) editline/libedit.a db1-ast/libdb1.a $(AST_EMBED_LDSCRIPTS) buildinfo.o $(AST_LIBS) $(AST_EMBED_LIBS) $(H323LDLIBS) $(GMIMELDFLAGS)
- endif
-- $(CMD_PREFIX) $(ASTTOPDIR)/build_tools/strip_nonapi $@ || rm $@
-
- clean::
- rm -f asterisk
-Index: main/event.c
-===================================================================
---- a/main/event.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/main/event.c (.../trunk) (revision 186562)
-@@ -28,6 +28,7 @@
- ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
- #include "asterisk/_private.h"
-+
- #include "asterisk/event.h"
- #include "asterisk/linkedlists.h"
- #include "asterisk/dlinkedlists.h"
-@@ -36,6 +37,7 @@
- #include "asterisk/unaligned.h"
- #include "asterisk/utils.h"
- #include "asterisk/taskprocessor.h"
-+#include "asterisk/astobj2.h"
-
- struct ast_taskprocessor *event_dispatcher;
-
-@@ -55,6 +57,16 @@
- } __attribute__((packed));
-
- /*!
-+ * \brief The payload for a string information element
-+ */
-+struct ast_event_ie_str_payload {
-+ /*! \brief A hash calculated with ast_str_hash(), to speed up comparisons */
-+ uint32_t hash;
-+ /*! \brief The actual string, null terminated */
-+ char str[1];
-+} __attribute__((packed));
-+
-+/*!
- * \brief An event
- *
- * An ast_event consists of an event header (this structure), and zero or
-@@ -74,9 +86,18 @@
- unsigned char payload[0];
- } __attribute__((packed));
-
-+
-+/*!
-+ * \brief A holder for an event
-+ *
-+ * \details This struct used to have more of a purpose than it does now.
-+ * It is used to hold events in the event cache. It can be completely removed
-+ * if one of these two things is done:
-+ * - ast_event gets changed such that it never has to be realloc()d
-+ * - astobj2 is updated so that you can realloc() an astobj2 object
-+ */
- struct ast_event_ref {
- struct ast_event *event;
-- AST_LIST_ENTRY(ast_event_ref) entry;
- };
-
- struct ast_event_ie_val {
-@@ -85,7 +106,10 @@
- enum ast_event_ie_pltype ie_pltype;
- union {
- uint32_t uint;
-- const char *str;
-+ struct {
-+ uint32_t hash;
-+ const char *str;
-+ };
- void *raw;
- } payload;
- size_t raw_datalen;
-@@ -107,13 +131,57 @@
- * The event subscribers are indexed by which event they are subscribed to */
- static AST_RWDLLIST_HEAD(ast_event_sub_list, ast_event_sub) ast_event_subs[AST_EVENT_TOTAL];
-
--/*! \brief Cached events
-- * The event cache is indexed on the event type. The purpose of this is
-- * for events that express some sort of state. So, when someone first
-- * needs to know this state, it can get the last known state from the cache. */
--static AST_RWLIST_HEAD(ast_event_ref_list, ast_event_ref) ast_event_cache[AST_EVENT_TOTAL];
-+static int ast_event_cmp(void *obj, void *arg, int flags);
-+static int ast_event_hash_mwi(const void *obj, const int flags);
-+static int ast_event_hash_devstate(const void *obj, const int flags);
-+static int ast_event_hash_devstate_change(const void *obj, const int flags);
-
-+#ifdef LOW_MEMORY
-+#define NUM_CACHE_BUCKETS 17
-+#else
-+#define NUM_CACHE_BUCKETS 563
-+#endif
-+
-+#define MAX_CACHE_ARGS 8
-+
- /*!
-+ * \brief Event types that are kept in the cache.
-+ */
-+static struct {
-+ /*!
-+ * \brief Container of cached events
-+ *
-+ * \details This gets allocated in ast_event_init() when Asterisk starts
-+ * for the event types declared as using the cache.
-+ */
-+ struct ao2_container *container;
-+ /*! \brief Event type specific hash function */
-+ ao2_hash_fn *hash_fn;
-+ /*!
-+ * \brief Information Elements used for caching
-+ *
-+ * \details This array is the set of information elements that will be unique
-+ * among all events in the cache for this event type. When a new event gets
-+ * cached, a previous event with the same values for these information elements
-+ * will be replaced.
-+ */
-+ enum ast_event_ie_type cache_args[MAX_CACHE_ARGS];
-+} ast_event_cache[AST_EVENT_TOTAL] = {
-+ [AST_EVENT_MWI] = {
-+ .hash_fn = ast_event_hash_mwi,
-+ .cache_args = { AST_EVENT_IE_MAILBOX, AST_EVENT_IE_CONTEXT },
-+ },
-+ [AST_EVENT_DEVICE_STATE] = {
-+ .hash_fn = ast_event_hash_devstate,
-+ .cache_args = { AST_EVENT_IE_DEVICE, },
-+ },
-+ [AST_EVENT_DEVICE_STATE_CHANGE] = {
-+ .hash_fn = ast_event_hash_devstate_change,
-+ .cache_args = { AST_EVENT_IE_DEVICE, AST_EVENT_IE_EID, },
-+ },
-+};
-+
-+/*!
- * The index of each entry _must_ match the event type number!
- */
- static struct event_name {
-@@ -237,6 +305,8 @@
- {
- switch (ie_val->ie_pltype) {
- case AST_EVENT_IE_PLTYPE_STR:
-+ ast_free((char *) ie_val->payload.str);
-+ break;
- case AST_EVENT_IE_PLTYPE_RAW:
- ast_free(ie_val->payload.raw);
- break;
-@@ -328,7 +398,8 @@
- return res;
- }
-
--static int match_ie_val(struct ast_event *event, struct ast_event_ie_val *ie_val, struct ast_event *event2)
-+static int match_ie_val(const struct ast_event *event,
-+ const struct ast_event_ie_val *ie_val, const struct ast_event *event2)
- {
- if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_UINT) {
- uint32_t val = event2 ? ast_event_get_ie_uint(event2, ie_val->ie_type) : ie_val->payload.uint;
-@@ -338,9 +409,19 @@
- }
-
- if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_STR) {
-- const char *str = event2 ? ast_event_get_ie_str(event2, ie_val->ie_type) : ie_val->payload.str;
-- if (str && !strcmp(str, ast_event_get_ie_str(event, ie_val->ie_type)))
-+ const char *str;
-+ uint32_t hash;
-+
-+ hash = event2 ? ast_event_get_ie_str_hash(event2, ie_val->ie_type) : ie_val->payload.hash;
-+ if (hash != ast_event_get_ie_str_hash(event, ie_val->ie_type)) {
-+ return 0;
-+ }
-+
-+ str = event2 ? ast_event_get_ie_str(event2, ie_val->ie_type) : ie_val->payload.str;
-+ if (str && !strcmp(str, ast_event_get_ie_str(event, ie_val->ie_type))) {
- return 1;
-+ }
-+
- return 0;
- }
-
-@@ -360,28 +441,34 @@
- return 0;
- }
-
--/*! \brief Dump the event cache for the subscribed event type */
--void ast_event_dump_cache(const struct ast_event_sub *event_sub)
-+static int dump_cache_cb(void *obj, void *arg, int flags)
- {
-- struct ast_event_ref *event_ref;
-- enum ast_event_type type = event_sub->type;
-+ const struct ast_event_ref *event_ref = obj;
-+ const struct ast_event *event = event_ref->event;
-+ const struct ast_event_sub *event_sub = arg;
-+ struct ast_event_ie_val *ie_val = NULL;
-
-- AST_RWLIST_RDLOCK(&ast_event_cache[type]);
-- AST_RWLIST_TRAVERSE_SAFE_BEGIN(&ast_event_cache[type], event_ref, entry) {
-- struct ast_event_ie_val *ie_val;
-- AST_LIST_TRAVERSE(&event_sub->ie_vals, ie_val, entry) {
-- if (!match_ie_val(event_ref->event, ie_val, NULL))
-- break;
-+ AST_LIST_TRAVERSE(&event_sub->ie_vals, ie_val, entry) {
-+ if (!match_ie_val(event, ie_val, NULL)) {
-+ break;
- }
-- if (!ie_val) {
-- /* All parameters were matched on this cache entry, so dump it */
-- event_sub->cb(event_ref->event, event_sub->userdata);
-- }
- }
-- AST_RWLIST_TRAVERSE_SAFE_END
-- AST_RWLIST_UNLOCK(&ast_event_cache[type]);
-+
-+ if (!ie_val) {
-+ /* All parameters were matched on this cache entry, so dump it */
-+ event_sub->cb(event, event_sub->userdata);
-+ }
-+
-+ return 0;
- }
-
-+/*! \brief Dump the event cache for the subscribed event type */
-+void ast_event_dump_cache(const struct ast_event_sub *event_sub)
-+{
-+ ao2_callback(ast_event_cache[event_sub->type].container, OBJ_NODATA,
-+ dump_cache_cb, (void *) event_sub);
-+}
-+
- static struct ast_event *gen_sub_event(struct ast_event_sub *sub)
- {
- struct ast_event_ie_val *ie_val;
-@@ -536,6 +623,8 @@
- return -1;
- }
-
-+ ie_val->payload.hash = ast_str_hash(str);
-+
- AST_LIST_INSERT_TAIL(&sub->ie_vals, ie_val, entry);
-
- return 0;
-@@ -703,7 +792,11 @@
-
- const char *ast_event_iterator_get_ie_str(struct ast_event_iterator *iterator)
- {
-- return (const char*)iterator->ie->ie_payload;
-+ const struct ast_event_ie_str_payload *str_payload;
-+
-+ str_payload = (struct ast_event_ie_str_payload *) iterator->ie->ie_payload;
-+
-+ return str_payload->str;
- }
-
- void *ast_event_iterator_get_ie_raw(struct ast_event_iterator *iterator)
-@@ -725,9 +818,22 @@
- return ie_val ? ntohl(get_unaligned_uint32(ie_val)) : 0;
- }
-
-+uint32_t ast_event_get_ie_str_hash(const struct ast_event *event, enum ast_event_ie_type ie_type)
-+{
-+ const struct ast_event_ie_str_payload *str_payload;
-+
-+ str_payload = ast_event_get_ie_raw(event, ie_type);
-+
-+ return str_payload->hash;
-+}
-+
- const char *ast_event_get_ie_str(const struct ast_event *event, enum ast_event_ie_type ie_type)
- {
-- return ast_event_get_ie_raw(event, ie_type);
-+ const struct ast_event_ie_str_payload *str_payload;
-+
-+ str_payload = ast_event_get_ie_raw(event, ie_type);
-+
-+ return str_payload->str;
- }
-
- const void *ast_event_get_ie_raw(const struct ast_event *event, enum ast_event_ie_type ie_type)
-@@ -746,7 +852,16 @@
- int ast_event_append_ie_str(struct ast_event **event, enum ast_event_ie_type ie_type,
- const char *str)
- {
-- return ast_event_append_ie_raw(event, ie_type, str, strlen(str) + 1);
-+ struct ast_event_ie_str_payload *str_payload;
-+ size_t payload_len;
-+
-+ payload_len = sizeof(*str_payload) + strlen(str);
-+ str_payload = alloca(payload_len);
-+
-+ strcpy(str_payload->str, str);
-+ str_payload->hash = ast_str_hash(str);
-+
-+ return ast_event_append_ie_raw(event, ie_type, str_payload, payload_len);
- }
-
- int ast_event_append_ie_uint(struct ast_event **event, enum ast_event_ie_type ie_type,
-@@ -839,7 +954,7 @@
- if (!ast_event_get_ie_raw(event, AST_EVENT_IE_EID)) {
- /* If the event is originating on this server, add the server's
- * entity ID to the event. */
-- ast_event_append_ie_raw(&event, AST_EVENT_IE_EID, &g_eid, sizeof(g_eid));
-+ ast_event_append_ie_raw(&event, AST_EVENT_IE_EID, &ast_eid_default, sizeof(ast_eid_default));
- }
-
- return event;
-@@ -850,10 +965,11 @@
- ast_free(event);
- }
-
--static void ast_event_ref_destroy(struct ast_event_ref *event_ref)
-+static void ast_event_ref_destroy(void *obj)
- {
-+ struct ast_event_ref *event_ref = obj;
-+
- ast_event_destroy(event_ref->event);
-- ast_free(event_ref);
- }
-
- static struct ast_event *ast_event_dup(const struct ast_event *event)
-@@ -863,9 +979,10 @@
-
- event_len = ast_event_get_size(event);
-
-- if (!(dup_event = ast_calloc(1, event_len)))
-+ if (!(dup_event = ast_calloc(1, event_len))) {
- return NULL;
--
-+ }
-+
- memcpy(dup_event, event, event_len);
-
- return dup_event;
-@@ -876,139 +993,122 @@
- va_list ap;
- enum ast_event_ie_type ie_type;
- struct ast_event *dup_event = NULL;
-- struct ast_event_ref *event_ref;
-- struct ast_event_ie_val *cache_arg;
-- AST_LIST_HEAD_NOLOCK_STATIC(cache_args, ast_event_ie_val);
-+ struct ast_event_ref *cached_event_ref;
-+ struct ast_event *cache_arg_event;
-+ struct ast_event_ref tmp_event_ref = {
-+ .event = NULL,
-+ };
-+ struct ao2_container *container = NULL;
-
- if (type >= AST_EVENT_TOTAL) {
- ast_log(LOG_ERROR, "%u is an invalid type!\n", type);
- return NULL;
- }
-
-+ if (!(container = ast_event_cache[type].container)) {
-+ ast_log(LOG_ERROR, "%u is not a cached event type\n", type);
-+ return NULL;
-+ }
-+
-+ if (!(cache_arg_event = ast_event_new(type, AST_EVENT_IE_END))) {
-+ return NULL;
-+ }
-+
- va_start(ap, type);
- for (ie_type = va_arg(ap, enum ast_event_type);
- ie_type != AST_EVENT_IE_END;
- ie_type = va_arg(ap, enum ast_event_type))
- {
-- cache_arg = alloca(sizeof(*cache_arg));
-- memset(cache_arg, 0, sizeof(*cache_arg));
-- cache_arg->ie_type = ie_type;
-- cache_arg->ie_pltype = va_arg(ap, enum ast_event_ie_pltype);
-- if (cache_arg->ie_pltype == AST_EVENT_IE_PLTYPE_UINT)
-- cache_arg->payload.uint = va_arg(ap, uint32_t);
-- else if (cache_arg->ie_pltype == AST_EVENT_IE_PLTYPE_STR)
-- cache_arg->payload.str = ast_strdupa(va_arg(ap, const char *));
-- else if (cache_arg->ie_pltype == AST_EVENT_IE_PLTYPE_RAW) {
-+ enum ast_event_ie_pltype ie_pltype;
-+
-+ ie_pltype = va_arg(ap, enum ast_event_ie_pltype);
-+
-+ switch (ie_pltype) {
-+ case AST_EVENT_IE_PLTYPE_UINT:
-+ ast_event_append_ie_uint(&cache_arg_event, ie_type, va_arg(ap, uint32_t));
-+ break;
-+ case AST_EVENT_IE_PLTYPE_STR:
-+ ast_event_append_ie_str(&cache_arg_event, ie_type, va_arg(ap, const char *));
-+ break;
-+ case AST_EVENT_IE_PLTYPE_RAW:
-+ {
- void *data = va_arg(ap, void *);
- size_t datalen = va_arg(ap, size_t);
-- cache_arg->payload.raw = alloca(datalen);
-- memcpy(cache_arg->payload.raw, data, datalen);
-- cache_arg->raw_datalen = datalen;
-+ ast_event_append_ie_raw(&cache_arg_event, ie_type, data, datalen);
- }
-- AST_LIST_INSERT_TAIL(&cache_args, cache_arg, entry);
-+ case AST_EVENT_IE_PLTYPE_EXISTS:
-+ ast_log(LOG_WARNING, "PLTYPE_EXISTS not supported by this function\n");
-+ break;
-+ case AST_EVENT_IE_PLTYPE_UNKNOWN:
-+ break;
-+ }
- }
- va_end(ap);
-
-- if (AST_LIST_EMPTY(&cache_args)) {
-- ast_log(LOG_ERROR, "Events can not be retrieved from the cache without "
-- "specifying at least one IE type!\n");
-- return NULL;
-- }
-+ tmp_event_ref.event = cache_arg_event;
-
-- AST_RWLIST_RDLOCK(&ast_event_cache[type]);
-- AST_RWLIST_TRAVERSE_SAFE_BEGIN(&ast_event_cache[type], event_ref, entry) {
-- AST_LIST_TRAVERSE(&cache_args, cache_arg, entry) {
-- if (!match_ie_val(event_ref->event, cache_arg, NULL))
-- break;
-- }
-- if (!cache_arg) {
-- /* All parameters were matched on this cache entry, so return it */
-- dup_event = ast_event_dup(event_ref->event);
-- break;
-- }
-+ cached_event_ref = ao2_find(container, &tmp_event_ref, OBJ_POINTER);
-+
-+ ast_event_destroy(cache_arg_event);
-+ cache_arg_event = NULL;
-+
-+ if (cached_event_ref) {
-+ dup_event = ast_event_dup(cached_event_ref->event);
-+ ao2_ref(cached_event_ref, -1);
-+ cached_event_ref = NULL;
- }
-- AST_RWLIST_TRAVERSE_SAFE_END
-- AST_RWLIST_UNLOCK(&ast_event_cache[type]);
-
- return dup_event;
- }
-
-+static struct ast_event_ref *alloc_event_ref(void)
-+{
-+ return ao2_alloc(sizeof(struct ast_event_ref), ast_event_ref_destroy);
-+}
-+
- /*! \brief Duplicate an event and add it to the cache
- * \note This assumes this index in to the cache is locked */
--static int ast_event_dup_and_cache(const struct ast_event *event)
-+static int attribute_unused ast_event_dup_and_cache(const struct ast_event *event)
- {
- struct ast_event *dup_event;
- struct ast_event_ref *event_ref;
-
-- if (!(dup_event = ast_event_dup(event)))
-+ if (!(dup_event = ast_event_dup(event))) {
- return -1;
-- if (!(event_ref = ast_calloc(1, sizeof(*event_ref))))
-+ }
-+
-+ if (!(event_ref = alloc_event_ref())) {
-+ ast_event_destroy(dup_event);
- return -1;
--
-+ }
-+
- event_ref->event = dup_event;
-
-- AST_LIST_INSERT_TAIL(&ast_event_cache[ntohs(event->type)], event_ref, entry);
-+ ao2_link(ast_event_cache[ast_event_get_type(event)].container, event_ref);
-
-+ ao2_ref(event_ref, -1);
-+
- return 0;
- }
-
--int ast_event_queue_and_cache(struct ast_event *event, ...)
-+int ast_event_queue_and_cache(struct ast_event *event)
- {
-- va_list ap;
-- enum ast_event_type ie_type;
-- uint16_t host_event_type;
-- struct ast_event_ref *event_ref;
-- int res;
-- struct ast_event_ie_val *cache_arg;
-- AST_LIST_HEAD_NOLOCK_STATIC(cache_args, ast_event_ie_val);
-+ struct ao2_container *container;
-+ struct ast_event_ref tmp_event_ref = {
-+ .event = event,
-+ };
-
-- host_event_type = ntohs(event->type);
--
-- /* Invalid type */
-- if (host_event_type >= AST_EVENT_TOTAL) {
-- ast_log(LOG_WARNING, "Someone tried to queue an event of invalid "
-- "type '%d'!\n", host_event_type);
-- return -1;
-+ if (!(container = ast_event_cache[ast_event_get_type(event)].container)) {
-+ ast_log(LOG_WARNING, "cache requested for non-cached event type\n");
-+ goto queue_event;
- }
-
-- va_start(ap, event);
-- for (ie_type = va_arg(ap, enum ast_event_type);
-- ie_type != AST_EVENT_IE_END;
-- ie_type = va_arg(ap, enum ast_event_type))
-- {
-- cache_arg = alloca(sizeof(*cache_arg));
-- memset(cache_arg, 0, sizeof(*cache_arg));
-- cache_arg->ie_type = ie_type;
-- cache_arg->ie_pltype = va_arg(ap, enum ast_event_ie_pltype);
-- if (cache_arg->ie_pltype == AST_EVENT_IE_PLTYPE_RAW)
-- cache_arg->raw_datalen = va_arg(ap, size_t);
-- AST_LIST_INSERT_TAIL(&cache_args, cache_arg, entry);
-- }
-- va_end(ap);
-+ /* Remove matches from the cache */
-+ ao2_callback(container, OBJ_POINTER | OBJ_UNLINK | OBJ_MULTIPLE | OBJ_NODATA,
-+ ast_event_cmp, &tmp_event_ref);
-
-- if (AST_LIST_EMPTY(&cache_args)) {
-- ast_log(LOG_ERROR, "Events can not be cached without specifying at "
-- "least one IE type!\n");
-- return ast_event_queue(event);
-- }
--
-- AST_RWLIST_WRLOCK(&ast_event_cache[host_event_type]);
-- AST_RWLIST_TRAVERSE_SAFE_BEGIN(&ast_event_cache[host_event_type], event_ref, entry) {
-- AST_LIST_TRAVERSE(&cache_args, cache_arg, entry) {
-- if (!match_ie_val(event_ref->event, cache_arg, event))
-- break;
-- }
-- if (!cache_arg) {
-- /* All parameters were matched on this cache entry, so remove it */
-- AST_LIST_REMOVE_CURRENT(entry);
-- ast_event_ref_destroy(event_ref);
-- }
-- }
-- AST_RWLIST_TRAVERSE_SAFE_END;
-- res = ast_event_dup_and_cache(event);
-- AST_RWLIST_UNLOCK(&ast_event_cache[host_event_type]);
--
-- return (ast_event_queue(event) || res) ? -1 : 0;
-+queue_event:
-+ return ast_event_queue(event);
- }
-
- static int handle_event(void *data)
-@@ -1024,22 +1124,25 @@
- AST_RWDLLIST_TRAVERSE(&ast_event_subs[host_event_type], sub, entry) {
- struct ast_event_ie_val *ie_val;
- AST_LIST_TRAVERSE(&sub->ie_vals, ie_val, entry) {
-- if (!match_ie_val(event_ref->event, ie_val, NULL))
-+ if (!match_ie_val(event_ref->event, ie_val, NULL)) {
- break;
-+ }
- }
-- if (ie_val)
-+ if (ie_val) {
- continue;
-+ }
- sub->cb(event_ref->event, sub->userdata);
- }
- AST_RWDLLIST_UNLOCK(&ast_event_subs[host_event_type]);
-
- /* Now to subscribers to all event types */
- AST_RWDLLIST_RDLOCK(&ast_event_subs[AST_EVENT_ALL]);
-- AST_RWDLLIST_TRAVERSE(&ast_event_subs[AST_EVENT_ALL], sub, entry)
-+ AST_RWDLLIST_TRAVERSE(&ast_event_subs[AST_EVENT_ALL], sub, entry) {
- sub->cb(event_ref->event, sub->userdata);
-+ }
- AST_RWDLLIST_UNLOCK(&ast_event_subs[AST_EVENT_ALL]);
-
-- ast_event_ref_destroy(event_ref);
-+ ao2_ref(event_ref, -1);
-
- return 0;
- }
-@@ -1059,29 +1162,149 @@
- }
-
- /* If nobody has subscribed to this event type, throw it away now */
-- if (ast_event_check_subscriber(host_event_type, AST_EVENT_IE_END)
-- == AST_EVENT_SUB_NONE) {
-+ if (ast_event_check_subscriber(host_event_type, AST_EVENT_IE_END)
-+ == AST_EVENT_SUB_NONE) {
- ast_event_destroy(event);
- return 0;
- }
-
-- if (!(event_ref = ast_calloc(1, sizeof(*event_ref))))
-+ if (!(event_ref = alloc_event_ref())) {
- return -1;
-+ }
-
- event_ref->event = event;
-
- return ast_taskprocessor_push(event_dispatcher, handle_event, event_ref);
- }
-
--void ast_event_init(void)
-+static int ast_event_hash_mwi(const void *obj, const int flags)
- {
-+ const struct ast_event *event = obj;
-+ const char *mailbox = ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX);
-+ const char *context = ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT);
-+
-+ return ast_str_hash_add(context, ast_str_hash(mailbox));
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Hash function for AST_EVENT_DEVICE_STATE
-+ *
-+ * \param[in] obj an ast_event
-+ * \param[in] flags unused
-+ *
-+ * \return hash value
-+ */
-+static int ast_event_hash_devstate(const void *obj, const int flags)
-+{
-+ const struct ast_event *event = obj;
-+
-+ return ast_str_hash(ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE));
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Hash function for AST_EVENT_DEVICE_STATE_CHANGE
-+ *
-+ * \param[in] obj an ast_event
-+ * \param[in] flags unused
-+ *
-+ * \return hash value
-+ */
-+static int ast_event_hash_devstate_change(const void *obj, const int flags)
-+{
-+ const struct ast_event *event = obj;
-+
-+ return ast_str_hash(ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE));
-+}
-+
-+static int ast_event_hash(const void *obj, const int flags)
-+{
-+ const struct ast_event_ref *event_ref;
-+ const struct ast_event *event;
-+ ao2_hash_fn *hash_fn;
-+
-+ event_ref = obj;
-+ event = event_ref->event;
-+
-+ if (!(hash_fn = ast_event_cache[ast_event_get_type(event)].hash_fn)) {
-+ return 0;
-+ }
-+
-+ return hash_fn(event, flags);
-+}
-+
-+/*!
-+ * \internal
-+ * \brief Compare two events
-+ *
-+ * \param[in] obj the first event, as an ast_event_ref
-+ * \param[in] arg the second event, as an ast_event_ref
-+ * \param[in] flags unused
-+ *
-+ * \pre Both events must be the same type.
-+ * \pre The event type must be declared as a cached event type in ast_event_cache
-+ *
-+ * \details This function takes two events, and determines if they are considered
-+ * equivalent. The values of information elements specified in the cache arguments
-+ * for the event type are used to determine if the events are equivalent.
-+ *
-+ * \retval 0 No match
-+ * \retval CMP_MATCH The events are considered equivalent based on the cache arguments
-+ */
-+static int ast_event_cmp(void *obj, void *arg, int flags)
-+{
-+ struct ast_event_ref *event_ref, *event_ref2;
-+ struct ast_event *event, *event2;
-+ int res = CMP_MATCH;
- int i;
-+ enum ast_event_ie_type *cache_args;
-
-- for (i = 0; i < AST_EVENT_TOTAL; i++)
-+ event_ref = obj;
-+ event = event_ref->event;
-+
-+ event_ref2 = arg;
-+ event2 = event_ref2->event;
-+
-+ cache_args = ast_event_cache[ast_event_get_type(event)].cache_args;
-+
-+ for (i = 0; i < ARRAY_LEN(ast_event_cache[0].cache_args) && cache_args[i]; i++) {
-+ struct ast_event_ie_val ie_val = {
-+ .ie_type = cache_args[i],
-+ };
-+
-+ if (!match_ie_val(event, &ie_val, event2)) {
-+ res = 0;
-+ break;
-+ }
-+ }
-+
-+ return res;
-+}
-+
-+int ast_event_init(void)
-+{
-+ int i;
-+
-+ for (i = 0; i < AST_EVENT_TOTAL; i++) {
- AST_RWDLLIST_HEAD_INIT(&ast_event_subs[i]);
-+ }
-
-- for (i = 0; i < AST_EVENT_TOTAL; i++)
-- AST_RWLIST_HEAD_INIT(&ast_event_cache[i]);
-+ for (i = 0; i < AST_EVENT_TOTAL; i++) {
-+ if (!ast_event_cache[i].hash_fn) {
-+ /* This event type is not cached. */
-+ continue;
-+ }
-
-- event_dispatcher = ast_taskprocessor_get("core_event_dispatcher", 0);
-+ if (!(ast_event_cache[i].container = ao2_container_alloc(NUM_CACHE_BUCKETS,
-+ ast_event_hash, ast_event_cmp))) {
-+ return -1;
-+ }
-+ }
-+
-+ if (!(event_dispatcher = ast_taskprocessor_get("core_event_dispatcher", 0))) {
-+ return -1;
-+ }
-+
-+ return 0;
- }
-Index: main/asterisk.c
-===================================================================
---- a/main/asterisk.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/main/asterisk.c (.../trunk) (revision 186562)
-@@ -120,7 +120,6 @@
- #include "asterisk/cdr.h"
- #include "asterisk/pbx.h"
- #include "asterisk/enum.h"
--#include "asterisk/rtp.h"
- #include "asterisk/http.h"
- #include "asterisk/udptl.h"
- #include "asterisk/app.h"
-@@ -182,7 +181,7 @@
-
- /*! @} */
-
--struct ast_eid g_eid;
-+struct ast_eid ast_eid_default;
-
- /* XXX tmpdir is a subdir of the spool directory, and no way to remap it */
- char record_cache_dir[AST_CACHE_DIR_LEN] = DEFAULT_TMP_DIR;
-@@ -427,7 +426,7 @@
- return NULL;
- }
-
-- ast_eid_to_str(eid_str, sizeof(eid_str), &g_eid);
-+ ast_eid_to_str(eid_str, sizeof(eid_str), &ast_eid_default);
-
- ast_cli(a->fd, "\nPBX Core settings\n");
- ast_cli(a->fd, "-----------------\n");
-@@ -2398,11 +2397,12 @@
- int nummatches = 0;
- char **matches;
- int retval = CC_ERROR;
-- char buf[2048];
-+ char buf[2048], savechr;
- int res;
-
- LineInfo *lf = (LineInfo *)el_line(editline);
-
-+ savechr = *(char *)lf->cursor;
- *(char *)lf->cursor = '\0';
- ptr = (char *)lf->cursor;
- if (ptr) {
-@@ -2428,8 +2428,10 @@
- char *mbuf;
- int mlen = 0, maxmbuf = 2048;
- /* Start with a 2048 byte buffer */
-- if (!(mbuf = ast_malloc(maxmbuf)))
-+ if (!(mbuf = ast_malloc(maxmbuf))) {
-+ lf->cursor[0] = savechr;
- return (char *)(CC_ERROR);
-+ }
- snprintf(buf, sizeof(buf), "_COMMAND MATCHESARRAY \"%s\" \"%s\"", lf->buffer, ptr);
- fdsend(ast_consock, buf);
- res = 0;
-@@ -2438,8 +2440,10 @@
- if (mlen + 1024 > maxmbuf) {
- /* Every step increment buffer 1024 bytes */
- maxmbuf += 1024;
-- if (!(mbuf = ast_realloc(mbuf, maxmbuf)))
-+ if (!(mbuf = ast_realloc(mbuf, maxmbuf))) {
-+ lf->cursor[0] = savechr;
- return (char *)(CC_ERROR);
-+ }
- }
- /* Only read 1024 bytes at a time */
- res = read(ast_consock, mbuf + mlen, 1024);
-@@ -2499,6 +2503,8 @@
- ast_free(matches);
- }
-
-+ lf->cursor[0] = savechr;
-+
- return (char *)(long)retval;
- }
-
-@@ -2810,7 +2816,7 @@
- ast_copy_string(cfg_paths.socket_path, DEFAULT_SOCKET, sizeof(cfg_paths.socket_path));
- ast_copy_string(cfg_paths.run_dir, DEFAULT_RUN_DIR, sizeof(cfg_paths.run_dir));
-
-- ast_set_default_eid(&g_eid);
-+ ast_set_default_eid(&ast_eid_default);
-
- /* no asterisk.conf? no problem, use buildtime config! */
- if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
-@@ -2981,7 +2987,7 @@
- struct ast_eid tmp_eid;
- if (!ast_str_to_eid(&tmp_eid, v->value)) {
- ast_verbose("Successfully set global EID to '%s'\n", v->value);
-- g_eid = tmp_eid;
-+ ast_eid_default = tmp_eid;
- } else
- ast_verbose("Invalid Entity ID '%s' provided\n", v->value);
- } else if (!strcasecmp(v->name, "lightbackground")) {
-@@ -3502,7 +3508,10 @@
- }
- #endif
-
-- ast_event_init();
-+ if (ast_event_init()) {
-+ printf("%s", term_quit());
-+ exit(1);
-+ }
-
- ast_makesocket();
- sigemptyset(&sigs);
-@@ -3569,7 +3578,6 @@
- exit(1);
- }
-
-- ast_rtp_init();
- ast_dsp_init();
- ast_udptl_init();
-
-Index: main/timing.c
-===================================================================
---- a/main/timing.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/main/timing.c (.../trunk) (revision 186562)
-@@ -38,6 +38,7 @@
- #include "asterisk/time.h"
- #include "asterisk/heap.h"
- #include "asterisk/module.h"
-+#include "asterisk/poll-compat.h"
-
- struct timing_holder {
- /*! Do _not_ move this from the beginning of the struct. */
-@@ -48,6 +49,11 @@
-
- static struct ast_heap *timing_interfaces;
-
-+struct ast_timer {
-+ int fd;
-+ struct timing_holder *holder;
-+};
-+
- static int timing_holder_cmp(void *_h1, void *_h2)
- {
- struct timing_holder *h1 = _h1;
-@@ -63,16 +69,16 @@
- }
-
- void *_ast_register_timing_interface(struct ast_timing_interface *funcs,
-- struct ast_module *mod)
-+ struct ast_module *mod)
- {
- struct timing_holder *h;
-
- if (!funcs->timer_open ||
- !funcs->timer_close ||
-- !funcs->timer_set_rate ||
-+ !funcs->timer_set_rate ||
- !funcs->timer_ack ||
- !funcs->timer_get_event ||
-- !funcs->timer_get_max_rate ||
-+ !funcs->timer_get_max_rate ||
- !funcs->timer_enable_continuous ||
- !funcs->timer_disable_continuous) {
- return NULL;
-@@ -110,10 +116,11 @@
- return res;
- }
-
--int ast_timer_open(void)
-+struct ast_timer *ast_timer_open(void)
- {
- int fd = -1;
- struct timing_holder *h;
-+ struct ast_timer *t = NULL;
-
- ast_heap_rdlock(timing_interfaces);
-
-@@ -122,124 +129,88 @@
- ast_module_ref(h->mod);
- }
-
-+ if (fd != -1) {
-+ if (!(t = ast_calloc(1, sizeof(*t)))) {
-+ h->iface->timer_close(fd);
-+ } else {
-+ t->fd = fd;
-+ t->holder = h;
-+ }
-+ }
-+
- ast_heap_unlock(timing_interfaces);
-
-- return fd;
-+ return t;
- }
-
--void ast_timer_close(int timer)
-+void ast_timer_close(struct ast_timer *handle)
- {
-- struct timing_holder *h;
-+ handle->holder->iface->timer_close(handle->fd);
-+ ast_module_unref(handle->holder->mod);
-+ ast_free(handle);
-+}
-
-- ast_heap_rdlock(timing_interfaces);
--
-- if ((h = ast_heap_peek(timing_interfaces, 1))) {
-- h->iface->timer_close(timer);
-- ast_module_unref(h->mod);
-- }
--
-- ast_heap_unlock(timing_interfaces);
-+int ast_timer_fd(const struct ast_timer *handle)
-+{
-+ return handle->fd;
- }
-
--int ast_timer_set_rate(int handle, unsigned int rate)
-+int ast_timer_set_rate(const struct ast_timer *handle, unsigned int rate)
- {
-- struct timing_holder *h;
- int res = -1;
-
-- ast_heap_rdlock(timing_interfaces);
-+ res = handle->holder->iface->timer_set_rate(handle->fd, rate);
-
-- if ((h = ast_heap_peek(timing_interfaces, 1))) {
-- res = h->iface->timer_set_rate(handle, rate);
-- }
--
-- ast_heap_unlock(timing_interfaces);
--
- return res;
- }
-
--void ast_timer_ack(int handle, unsigned int quantity)
-+void ast_timer_ack(const struct ast_timer *handle, unsigned int quantity)
- {
-- struct timing_holder *h;
--
-- ast_heap_rdlock(timing_interfaces);
--
-- if ((h = ast_heap_peek(timing_interfaces, 1))) {
-- h->iface->timer_ack(handle, quantity);
-- }
--
-- ast_heap_unlock(timing_interfaces);
-+ handle->holder->iface->timer_ack(handle->fd, quantity);
- }
-
--int ast_timer_enable_continuous(int handle)
-+int ast_timer_enable_continuous(const struct ast_timer *handle)
- {
-- struct timing_holder *h;
- int res = -1;
-
-- ast_heap_rdlock(timing_interfaces);
-+ res = handle->holder->iface->timer_enable_continuous(handle->fd);
-
-- if ((h = ast_heap_peek(timing_interfaces, 1))) {
-- res = h->iface->timer_enable_continuous(handle);
-- }
--
-- ast_heap_unlock(timing_interfaces);
--
- return res;
- }
-
--int ast_timer_disable_continuous(int handle)
-+int ast_timer_disable_continuous(const struct ast_timer *handle)
- {
-- struct timing_holder *h;
- int res = -1;
-
-- ast_heap_rdlock(timing_interfaces);
-+ res = handle->holder->iface->timer_disable_continuous(handle->fd);
-
-- if ((h = ast_heap_peek(timing_interfaces, 1))) {
-- res = h->iface->timer_disable_continuous(handle);
-- }
--
-- ast_heap_unlock(timing_interfaces);
--
- return res;
- }
-
--enum ast_timer_event ast_timer_get_event(int handle)
-+enum ast_timer_event ast_timer_get_event(const struct ast_timer *handle)
- {
-- struct timing_holder *h;
- enum ast_timer_event res = -1;
-
-- ast_heap_rdlock(timing_interfaces);
-+ res = handle->holder->iface->timer_get_event(handle->fd);
-
-- if ((h = ast_heap_peek(timing_interfaces, 1))) {
-- res = h->iface->timer_get_event(handle);
-- }
--
-- ast_heap_unlock(timing_interfaces);
--
- return res;
- }
-
--unsigned int ast_timer_get_max_rate(int handle)
-+unsigned int ast_timer_get_max_rate(const struct ast_timer *handle)
- {
-- struct timing_holder *h;
- unsigned int res = 0;
-
-- ast_heap_rdlock(timing_interfaces);
-+ res = handle->holder->iface->timer_get_max_rate(handle->fd);
-
-- if ((h = ast_heap_peek(timing_interfaces, 1))) {
-- res = h->iface->timer_get_max_rate(handle);
-- }
--
-- ast_heap_unlock(timing_interfaces);
--
- return res;
- }
-
- static char *timing_test(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
- {
-- int fd, count = 0;
-+ struct ast_timer *timer;
-+ int count = 0;
- struct timeval start, end;
- unsigned int test_rate = 50;
-- struct timing_holder *h;
-
- switch (cmd) {
- case CLI_INIT:
-@@ -267,34 +238,29 @@
-
- ast_cli(a->fd, "Attempting to test a timer with %u ticks per second.\n", test_rate);
-
-- if ((fd = ast_timer_open()) == -1) {
-+ if (!(timer = ast_timer_open())) {
- ast_cli(a->fd, "Failed to open timing fd\n");
- return CLI_FAILURE;
- }
-
-- ast_heap_rdlock(timing_interfaces);
-- if ((h = ast_heap_peek(timing_interfaces, 1))) {
-- ast_cli(a->fd, "Using the '%s' timing module for this test.\n", h->iface->name);
-- h = NULL;
-- }
-- ast_heap_unlock(timing_interfaces);
-+ ast_cli(a->fd, "Using the '%s' timing module for this test.\n", timer->holder->iface->name);
-
- start = ast_tvnow();
-
-- ast_timer_set_rate(fd, test_rate);
-+ ast_timer_set_rate(timer, test_rate);
-
- while (ast_tvdiff_ms((end = ast_tvnow()), start) < 1000) {
- int res;
- struct pollfd pfd = {
-- .fd = fd,
-+ .fd = ast_timer_fd(timer),
- .events = POLLIN | POLLPRI,
- };
-
-- res = poll(&pfd, 1, 100);
-+ res = ast_poll(&pfd, 1, 100);
-
- if (res == 1) {
- count++;
-- ast_timer_ack(fd, 1);
-+ ast_timer_ack(timer, 1);
- } else if (!res) {
- ast_cli(a->fd, "poll() timed out! This is bad.\n");
- } else if (errno != EAGAIN && errno != EINTR) {
-@@ -302,7 +268,7 @@
- }
- }
-
-- ast_timer_close(fd);
-+ ast_timer_close(timer);
-
- ast_cli(a->fd, "It has been %d milliseconds, and we got %d timer ticks\n",
- ast_tvdiff_ms(end, start), count);
-Index: main/devicestate.c
-===================================================================
---- a/main/devicestate.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/main/devicestate.c (.../trunk) (revision 186562)
-@@ -196,8 +196,10 @@
- ast_cond_t cond;
- ast_mutex_t lock;
- AST_LIST_HEAD_NOLOCK(, devstate_change) devstate_change_q;
-+ unsigned int enabled:1;
- } devstate_collector = {
- .thread = AST_PTHREADT_NULL,
-+ .enabled = 0,
- };
-
- /* Forward declarations */
-@@ -428,22 +430,26 @@
- static void devstate_event(const char *device, enum ast_device_state state)
- {
- struct ast_event *event;
-+ enum ast_event_type event_type;
-
-+ if (devstate_collector.enabled) {
-+ /* Distributed device state is enabled, so this state change is a change
-+ * for a single server, not the real state. */
-+ event_type = AST_EVENT_DEVICE_STATE_CHANGE;
-+ } else {
-+ event_type = AST_EVENT_DEVICE_STATE;
-+ }
-+
- ast_debug(3, "device '%s' state '%d'\n", device, state);
-
-- if (!(event = ast_event_new(AST_EVENT_DEVICE_STATE_CHANGE,
-+ if (!(event = ast_event_new(event_type,
- AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, device,
- AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_UINT, state,
- AST_EVENT_IE_END))) {
- return;
- }
-
-- /* Cache this event, replacing an event in the cache with the same
-- * device name if it exists. */
-- ast_event_queue_and_cache(event,
-- AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR,
-- AST_EVENT_IE_EID, AST_EVENT_IE_PLTYPE_RAW, sizeof(struct ast_eid),
-- AST_EVENT_IE_END);
-+ ast_event_queue_and_cache(event);
- }
-
- /*! Called by the state change thread to find out what the state is, and then
-@@ -632,13 +638,12 @@
- AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, device,
- AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_UINT, state,
- AST_EVENT_IE_END);
--
-- if (!event)
-+
-+ if (!event) {
- return;
-+ }
-
-- ast_event_queue_and_cache(event,
-- AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR,
-- AST_EVENT_IE_END);
-+ ast_event_queue_and_cache(event);
- }
-
- static void handle_devstate_change(struct devstate_change *sc)
-@@ -719,21 +724,6 @@
- /*! \brief Initialize the device state engine in separate thread */
- int ast_device_state_engine_init(void)
- {
-- devstate_collector.event_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE_CHANGE,
-- devstate_change_collector_cb, NULL, AST_EVENT_IE_END);
--
-- if (!devstate_collector.event_sub) {
-- ast_log(LOG_ERROR, "Failed to create subscription for the device state change collector\n");
-- return -1;
-- }
--
-- ast_mutex_init(&devstate_collector.lock);
-- ast_cond_init(&devstate_collector.cond, NULL);
-- if (ast_pthread_create_background(&devstate_collector.thread, NULL, run_devstate_collector, NULL) < 0) {
-- ast_log(LOG_ERROR, "Unable to start device state collector thread.\n");
-- return -1;
-- }
--
- ast_cond_init(&change_pending, NULL);
- if (ast_pthread_create_background(&change_thread, NULL, do_devstate_changes, NULL) < 0) {
- ast_log(LOG_ERROR, "Unable to start device state change thread.\n");
-@@ -830,3 +820,28 @@
- return AST_DEVICE_NOT_INUSE;
- }
-
-+int ast_enable_distributed_devstate(void)
-+{
-+ if (devstate_collector.enabled) {
-+ return 0;
-+ }
-+
-+ devstate_collector.event_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE_CHANGE,
-+ devstate_change_collector_cb, NULL, AST_EVENT_IE_END);
-+
-+ if (!devstate_collector.event_sub) {
-+ ast_log(LOG_ERROR, "Failed to create subscription for the device state change collector\n");
-+ return -1;
-+ }
-+
-+ ast_mutex_init(&devstate_collector.lock);
-+ ast_cond_init(&devstate_collector.cond, NULL);
-+ if (ast_pthread_create_background(&devstate_collector.thread, NULL, run_devstate_collector, NULL) < 0) {
-+ ast_log(LOG_ERROR, "Unable to start device state collector thread.\n");
-+ return -1;
-+ }
-+
-+ devstate_collector.enabled = 1;
-+
-+ return 0;
-+}
-Index: main/taskprocessor.c
-===================================================================
---- a/main/taskprocessor.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/main/taskprocessor.c (.../trunk) (revision 186562)
-@@ -84,10 +84,10 @@
- /*! \brief tps_singletons is the astobj2 container for taskprocessor singletons */
- static struct ao2_container *tps_singletons;
-
--/*! \brief CLI 'taskprocessor ping <blah>' operation requires a ping condition */
-+/*! \brief CLI <example>taskprocessor ping &lt;blah&gt;</example> operation requires a ping condition */
- static ast_cond_t cli_ping_cond;
-
--/*! \brief CLI 'taskprocessor ping <blah>' operation requires a ping condition lock */
-+/*! \brief CLI <example>taskprocessor ping &lt;blah&gt;</example> operation requires a ping condition lock */
- AST_MUTEX_DEFINE_STATIC(cli_ping_cond_lock);
-
- /*! \brief The astobj2 hash callback for taskprocessors */
-@@ -101,7 +101,7 @@
- /*! \brief Destroy the taskprocessor when its refcount reaches zero */
- static void tps_taskprocessor_destroy(void *tps);
-
--/*! \brief CLI 'taskprocessor ping <blah>' handler function */
-+/*! \brief CLI <example>taskprocessor ping &lt;blah&gt;</example> handler function */
- static int tps_ping_handler(void *datap);
-
- /*! \brief Remove the front task off the taskprocessor queue */
-Index: main/astobj2.c
-===================================================================
---- a/main/astobj2.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/main/astobj2.c (.../trunk) (revision 186562)
-@@ -134,20 +134,20 @@
-
- /* the underlying functions common to debug and non-debug versions */
-
--static int __ao2_ref(void *user_data, const int delta);
--static void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn);
--static struct ao2_container *__ao2_container_alloc(struct ao2_container *c, const uint n_buckets, ao2_hash_fn *hash_fn,
-- ao2_callback_fn *cmp_fn);
--static struct bucket_list *__ao2_link(struct ao2_container *c, void *user_data, const char *file, int line, const char *func);
--static void *__ao2_callback(struct ao2_container *c,
-- const enum search_flags flags, void *cb_fn, void *arg, void *data, enum ao2_callback_type type,
-- char *tag, char *file, int line, const char *funcname);
--static void * __ao2_iterator_next(struct ao2_iterator *a, struct bucket_list **q);
-+static int internal_ao2_ref(void *user_data, const int delta);
-+static void *internal_ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn);
-+static struct ao2_container *internal_ao2_container_alloc(struct ao2_container *c, const uint n_buckets, ao2_hash_fn *hash_fn,
-+ ao2_callback_fn *cmp_fn);
-+static struct bucket_list *internal_ao2_link(struct ao2_container *c, void *user_data, const char *file, int line, const char *func);
-+static void *internal_ao2_callback(struct ao2_container *c,
-+ const enum search_flags flags, void *cb_fn, void *arg, void *data, enum ao2_callback_type type,
-+ char *tag, char *file, int line, const char *funcname);
-+static void *internal_ao2_iterator_next(struct ao2_iterator *a, struct bucket_list **q);
-
- #ifndef DEBUG_THREADS
- int ao2_lock(void *user_data)
- #else
--int _ao2_lock(void *user_data, const char *file, const char *func, int line, const char *var)
-+int __ao2_lock(void *user_data, const char *file, const char *func, int line, const char *var)
- #endif
- {
- struct astobj2 *p = INTERNAL_OBJ(user_data);
-@@ -169,7 +169,7 @@
- #ifndef DEBUG_THREADS
- int ao2_unlock(void *user_data)
- #else
--int _ao2_unlock(void *user_data, const char *file, const char *func, int line, const char *var)
-+int __ao2_unlock(void *user_data, const char *file, const char *func, int line, const char *var)
- #endif
- {
- struct astobj2 *p = INTERNAL_OBJ(user_data);
-@@ -191,7 +191,7 @@
- #ifndef DEBUG_THREADS
- int ao2_trylock(void *user_data)
- #else
--int _ao2_trylock(void *user_data, const char *file, const char *func, int line, const char *var)
-+int __ao2_trylock(void *user_data, const char *file, const char *func, int line, const char *var)
- #endif
- {
- struct astobj2 *p = INTERNAL_OBJ(user_data);
-@@ -227,7 +227,7 @@
- */
-
-
--int _ao2_ref_debug(void *user_data, const int delta, char *tag, char *file, int line, const char *funcname)
-+int __ao2_ref_debug(void *user_data, const int delta, char *tag, char *file, int line, const char *funcname)
- {
- struct astobj2 *obj = INTERNAL_OBJ(user_data);
-
-@@ -244,20 +244,20 @@
- fprintf(refo, "%p **call destructor** %s:%d:%s (%s)\n", user_data, file, line, funcname, tag);
- fclose(refo);
- }
-- return __ao2_ref(user_data, delta);
-+ return internal_ao2_ref(user_data, delta);
- }
-
--int _ao2_ref(void *user_data, const int delta)
-+int __ao2_ref(void *user_data, const int delta)
- {
- struct astobj2 *obj = INTERNAL_OBJ(user_data);
-
- if (obj == NULL)
- return -1;
-
-- return __ao2_ref(user_data, delta);
-+ return internal_ao2_ref(user_data, delta);
- }
-
--static int __ao2_ref(void *user_data, const int delta)
-+static int internal_ao2_ref(void *user_data, const int delta)
- {
- struct astobj2 *obj = INTERNAL_OBJ(user_data);
- int current_value;
-@@ -303,7 +303,7 @@
- * We always alloc at least the size of a void *,
- * for debugging purposes.
- */
--static void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn)
-+static void *internal_ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn)
- {
- /* allocation */
- struct astobj2 *obj;
-@@ -332,13 +332,13 @@
- return EXTERNAL_OBJ(obj);
- }
-
--void *_ao2_alloc_debug(size_t data_size, ao2_destructor_fn destructor_fn, char *tag, char *file, int line, const char *funcname)
-+void *__ao2_alloc_debug(size_t data_size, ao2_destructor_fn destructor_fn, char *tag, char *file, int line, const char *funcname)
- {
- /* allocation */
- void *obj;
- FILE *refo = fopen(REF_FILE,"a");
-
-- obj = __ao2_alloc(data_size, destructor_fn);
-+ obj = internal_ao2_alloc(data_size, destructor_fn);
-
- if (obj == NULL)
- return NULL;
-@@ -352,9 +352,9 @@
- return obj;
- }
-
--void *_ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn)
-+void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn)
- {
-- return __ao2_alloc(data_size, destructor_fn);
-+ return internal_ao2_alloc(data_size, destructor_fn);
- }
-
-
-@@ -418,8 +418,8 @@
- /*
- * A container is just an object, after all!
- */
--static struct ao2_container *__ao2_container_alloc(struct ao2_container *c, const unsigned int n_buckets, ao2_hash_fn *hash_fn,
-- ao2_callback_fn *cmp_fn)
-+static struct ao2_container *internal_ao2_container_alloc(struct ao2_container *c, const unsigned int n_buckets, ao2_hash_fn *hash_fn,
-+ ao2_callback_fn *cmp_fn)
- {
- /* XXX maybe consistency check on arguments ? */
- /* compute the container size */
-@@ -439,28 +439,27 @@
- return c;
- }
-
--struct ao2_container *_ao2_container_alloc_debug(const unsigned int n_buckets, ao2_hash_fn *hash_fn,
-- ao2_callback_fn *cmp_fn, char *tag, char *file, int line, const char *funcname)
-+struct ao2_container *__ao2_container_alloc_debug(const unsigned int n_buckets, ao2_hash_fn *hash_fn,
-+ ao2_callback_fn *cmp_fn, char *tag, char *file, int line, const char *funcname)
- {
- /* XXX maybe consistency check on arguments ? */
- /* compute the container size */
- size_t container_size = sizeof(struct ao2_container) + n_buckets * sizeof(struct bucket);
-- struct ao2_container *c = _ao2_alloc_debug(container_size, container_destruct_debug, tag, file, line, funcname);
-+ struct ao2_container *c = __ao2_alloc_debug(container_size, container_destruct_debug, tag, file, line, funcname);
-
-- return __ao2_container_alloc(c, n_buckets, hash_fn, cmp_fn);
-+ return internal_ao2_container_alloc(c, n_buckets, hash_fn, cmp_fn);
- }
-
--struct ao2_container *
--_ao2_container_alloc(const unsigned int n_buckets, ao2_hash_fn *hash_fn,
-- ao2_callback_fn *cmp_fn)
-+struct ao2_container *__ao2_container_alloc(const unsigned int n_buckets, ao2_hash_fn *hash_fn,
-+ ao2_callback_fn *cmp_fn)
- {
- /* XXX maybe consistency check on arguments ? */
- /* compute the container size */
-
- size_t container_size = sizeof(struct ao2_container) + n_buckets * sizeof(struct bucket);
-- struct ao2_container *c = _ao2_alloc(container_size, container_destruct);
-+ struct ao2_container *c = __ao2_alloc(container_size, container_destruct);
-
-- return __ao2_container_alloc(c, n_buckets, hash_fn, cmp_fn);
-+ return internal_ao2_container_alloc(c, n_buckets, hash_fn, cmp_fn);
- }
-
- /*!
-@@ -486,7 +485,7 @@
- * link an object to a container
- */
-
--static struct bucket_list *__ao2_link(struct ao2_container *c, void *user_data, const char *file, int line, const char *func)
-+static struct bucket_list *internal_ao2_link(struct ao2_container *c, void *user_data, const char *file, int line, const char *func)
- {
- int i;
- /* create a new list entry */
-@@ -516,23 +515,23 @@
- return p;
- }
-
--void *_ao2_link_debug(struct ao2_container *c, void *user_data, char *tag, char *file, int line, const char *funcname)
-+void *__ao2_link_debug(struct ao2_container *c, void *user_data, char *tag, char *file, int line, const char *funcname)
- {
-- struct bucket_list *p = __ao2_link(c, user_data, file, line, funcname);
-+ struct bucket_list *p = internal_ao2_link(c, user_data, file, line, funcname);
-
- if (p) {
-- _ao2_ref_debug(user_data, +1, tag, file, line, funcname);
-+ __ao2_ref_debug(user_data, +1, tag, file, line, funcname);
- ao2_unlock(c);
- }
- return p;
- }
-
--void *_ao2_link(struct ao2_container *c, void *user_data)
-+void *__ao2_link(struct ao2_container *c, void *user_data)
- {
-- struct bucket_list *p = __ao2_link(c, user_data, __FILE__, __LINE__, __PRETTY_FUNCTION__);
-+ struct bucket_list *p = internal_ao2_link(c, user_data, __FILE__, __LINE__, __PRETTY_FUNCTION__);
-
- if (p) {
-- _ao2_ref(user_data, +1);
-+ __ao2_ref(user_data, +1);
- ao2_unlock(c);
- }
- return p;
-@@ -550,23 +549,23 @@
- * Unlink an object from the container
- * and destroy the associated * ao2_bucket_list structure.
- */
--void *_ao2_unlink_debug(struct ao2_container *c, void *user_data, char *tag,
-- char *file, int line, const char *funcname)
-+void *__ao2_unlink_debug(struct ao2_container *c, void *user_data, char *tag,
-+ char *file, int line, const char *funcname)
- {
- if (INTERNAL_OBJ(user_data) == NULL) /* safety check on the argument */
- return NULL;
-
-- _ao2_callback_debug(c, OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA, ao2_match_by_addr, user_data, tag, file, line, funcname);
-+ __ao2_callback_debug(c, OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA, ao2_match_by_addr, user_data, tag, file, line, funcname);
-
- return NULL;
- }
-
--void *_ao2_unlink(struct ao2_container *c, void *user_data)
-+void *__ao2_unlink(struct ao2_container *c, void *user_data)
- {
- if (INTERNAL_OBJ(user_data) == NULL) /* safety check on the argument */
- return NULL;
-
-- _ao2_callback(c, OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA, ao2_match_by_addr, user_data);
-+ __ao2_callback(c, OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA, ao2_match_by_addr, user_data);
-
- return NULL;
- }
-@@ -595,9 +594,9 @@
- * aren't an excessive load to the system, as the callback should not be
- * called as often as, say, the ao2_ref func is called.
- */
--static void *__ao2_callback(struct ao2_container *c,
-- const enum search_flags flags, void *cb_fn, void *arg, void *data, enum ao2_callback_type type,
-- char *tag, char *file, int line, const char *funcname)
-+static void *internal_ao2_callback(struct ao2_container *c,
-+ const enum search_flags flags, void *cb_fn, void *arg, void *data, enum ao2_callback_type type,
-+ char *tag, char *file, int line, const char *funcname)
- {
- int i, last; /* search boundaries */
- void *ret = NULL;
-@@ -675,9 +674,9 @@
- /* it is important to handle this case before the unlink */
- ret = EXTERNAL_OBJ(cur->astobj);
- if (tag)
-- _ao2_ref_debug(ret, 1, tag, file, line, funcname);
-+ __ao2_ref_debug(ret, 1, tag, file, line, funcname);
- else
-- _ao2_ref(ret, 1);
-+ __ao2_ref(ret, 1);
- }
-
- if (flags & OBJ_UNLINK) { /* must unlink */
-@@ -689,9 +688,9 @@
- /* update number of elements and version */
- ast_atomic_fetchadd_int(&c->elements, -1);
- if (tag)
-- _ao2_ref_debug(EXTERNAL_OBJ(x->astobj), -1, tag, file, line, funcname);
-+ __ao2_ref_debug(EXTERNAL_OBJ(x->astobj), -1, tag, file, line, funcname);
- else
-- _ao2_ref(EXTERNAL_OBJ(x->astobj), -1);
-+ __ao2_ref(EXTERNAL_OBJ(x->astobj), -1);
- free(x); /* free the link record */
- }
-
-@@ -715,45 +714,45 @@
- return ret;
- }
-
--void *_ao2_callback_debug(struct ao2_container *c,
-- const enum search_flags flags,
-- ao2_callback_fn *cb_fn, void *arg,
-- char *tag, char *file, int line, const char *funcname)
-+void *__ao2_callback_debug(struct ao2_container *c,
-+ const enum search_flags flags,
-+ ao2_callback_fn *cb_fn, void *arg,
-+ char *tag, char *file, int line, const char *funcname)
- {
-- return __ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, tag, file, line, funcname);
-+ return internal_ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, tag, file, line, funcname);
- }
-
--void *_ao2_callback(struct ao2_container *c, const enum search_flags flags,
-- ao2_callback_fn *cb_fn, void *arg)
-+void *__ao2_callback(struct ao2_container *c, const enum search_flags flags,
-+ ao2_callback_fn *cb_fn, void *arg)
- {
-- return __ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, NULL, NULL, 0, NULL);
-+ return internal_ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, NULL, NULL, 0, NULL);
- }
-
--void *_ao2_callback_data_debug(struct ao2_container *c,
-- const enum search_flags flags,
-- ao2_callback_data_fn *cb_fn, void *arg, void *data,
-- char *tag, char *file, int line, const char *funcname)
-+void *__ao2_callback_data_debug(struct ao2_container *c,
-+ const enum search_flags flags,
-+ ao2_callback_data_fn *cb_fn, void *arg, void *data,
-+ char *tag, char *file, int line, const char *funcname)
- {
-- return __ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, tag, file, line, funcname);
-+ return internal_ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, tag, file, line, funcname);
- }
-
--void *_ao2_callback_data(struct ao2_container *c, const enum search_flags flags,
-- ao2_callback_data_fn *cb_fn, void *arg, void *data)
-+void *__ao2_callback_data(struct ao2_container *c, const enum search_flags flags,
-+ ao2_callback_data_fn *cb_fn, void *arg, void *data)
- {
-- return __ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, NULL, NULL, 0, NULL);
-+ return internal_ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, NULL, NULL, 0, NULL);
- }
-
- /*!
- * the find function just invokes the default callback with some reasonable flags.
- */
--void *_ao2_find_debug(struct ao2_container *c, void *arg, enum search_flags flags, char *tag, char *file, int line, const char *funcname)
-+void *__ao2_find_debug(struct ao2_container *c, void *arg, enum search_flags flags, char *tag, char *file, int line, const char *funcname)
- {
-- return _ao2_callback_debug(c, flags, c->cmp_fn, arg, tag, file, line, funcname);
-+ return __ao2_callback_debug(c, flags, c->cmp_fn, arg, tag, file, line, funcname);
- }
-
--void *_ao2_find(struct ao2_container *c, void *arg, enum search_flags flags)
-+void *__ao2_find(struct ao2_container *c, void *arg, enum search_flags flags)
- {
-- return _ao2_callback(c, flags, c->cmp_fn, arg);
-+ return __ao2_callback(c, flags, c->cmp_fn, arg);
- }
-
- /*!
-@@ -772,7 +771,7 @@
- /*
- * move to the next element in the container.
- */
--static void * __ao2_iterator_next(struct ao2_iterator *a, struct bucket_list **q)
-+static void *internal_ao2_iterator_next(struct ao2_iterator *a, struct bucket_list **q)
- {
- int lim;
- struct bucket_list *p = NULL;
-@@ -827,16 +826,16 @@
- return ret;
- }
-
--void * _ao2_iterator_next_debug(struct ao2_iterator *a, char *tag, char *file, int line, const char *funcname)
-+void *__ao2_iterator_next_debug(struct ao2_iterator *a, char *tag, char *file, int line, const char *funcname)
- {
- struct bucket_list *p;
- void *ret = NULL;
-
-- ret = __ao2_iterator_next(a, &p);
-+ ret = internal_ao2_iterator_next(a, &p);
-
- if (p) {
- /* inc refcount of returned object */
-- _ao2_ref_debug(ret, 1, tag, file, line, funcname);
-+ __ao2_ref_debug(ret, 1, tag, file, line, funcname);
- }
-
- if (!(a->flags & F_AO2I_DONTLOCK))
-@@ -845,16 +844,16 @@
- return ret;
- }
-
--void * _ao2_iterator_next(struct ao2_iterator *a)
-+void *__ao2_iterator_next(struct ao2_iterator *a)
- {
- struct bucket_list *p = NULL;
- void *ret = NULL;
-
-- ret = __ao2_iterator_next(a, &p);
-+ ret = internal_ao2_iterator_next(a, &p);
-
- if (p) {
- /* inc refcount of returned object */
-- _ao2_ref(ret, 1);
-+ __ao2_ref(ret, 1);
- }
-
- if (!(a->flags & F_AO2I_DONTLOCK))
-@@ -868,13 +867,13 @@
- */
- static int cd_cb(void *obj, void *arg, int flag)
- {
-- _ao2_ref(obj, -1);
-+ __ao2_ref(obj, -1);
- return 0;
- }
-
- static int cd_cb_debug(void *obj, void *arg, int flag)
- {
-- _ao2_ref_debug(obj, -1, "deref object via container destroy", __FILE__, __LINE__, __PRETTY_FUNCTION__);
-+ __ao2_ref_debug(obj, -1, "deref object via container destroy", __FILE__, __LINE__, __PRETTY_FUNCTION__);
- return 0;
- }
-
-@@ -883,7 +882,7 @@
- struct ao2_container *c = _c;
- int i;
-
-- _ao2_callback(c, OBJ_UNLINK, cd_cb, NULL);
-+ __ao2_callback(c, OBJ_UNLINK, cd_cb, NULL);
-
- for (i = 0; i < c->n_buckets; i++) {
- struct bucket_list *current;
-@@ -903,7 +902,7 @@
- struct ao2_container *c = _c;
- int i;
-
-- _ao2_callback_debug(c, OBJ_UNLINK, cd_cb_debug, NULL, "container_destruct_debug called", __FILE__, __LINE__, __PRETTY_FUNCTION__);
-+ __ao2_callback_debug(c, OBJ_UNLINK, cd_cb_debug, NULL, "container_destruct_debug called", __FILE__, __LINE__, __PRETTY_FUNCTION__);
-
- for (i = 0; i < c->n_buckets; i++) {
- struct bucket_list *current;
-Index: main/asterisk.exports
-===================================================================
---- a/main/asterisk.exports (.../tags/1.6.2.0-beta1) (revision 0)
-+++ b/main/asterisk.exports (.../trunk) (revision 186562)
-@@ -0,0 +1,33 @@
-+{
-+ global:
-+ ast_*;
-+ _ast_*;
-+ __ast_*;
-+ pbx_*;
-+ astman_*;
-+ ao2_*;
-+ __ao2_*;
-+ option_debug;
-+ option_verbose;
-+ dahdi_chan_name;
-+ dahdi_chan_name_len;
-+ dahdi_chan_mode;
-+ callerid_*;
-+ cid_di;
-+ cid_dr;
-+ clidsb;
-+ MD5*;
-+ sched_*;
-+ io_*;
-+ jb_*;
-+ aes_*;
-+ config_*;
-+ tdd_*;
-+ term_*;
-+ channelreloadreason2txt;
-+ devstate2str;
-+ __manager_event;
-+ dialed_interface_info;
-+ local:
-+ *;
-+};
-
-Property changes on: main/asterisk.exports
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + Author Date Id Revision
-
-Index: main/cli.c
-===================================================================
---- a/main/cli.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/main/cli.c (.../trunk) (revision 186562)
-@@ -1259,7 +1259,7 @@
- {
- struct ast_channel *c=NULL;
- struct timeval now;
-- struct ast_str *out = ast_str_thread_get(&global_app_buf, 16);
-+ struct ast_str *out = ast_str_thread_get(&ast_str_thread_global_buf, 16);
- char cdrtime[256];
- char nf[256], wf[256], rf[256];
- long elapsed_seconds=0;
-Index: main/dial.c
-===================================================================
---- a/main/dial.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/main/dial.c (.../trunk) (revision 186562)
-@@ -274,20 +274,19 @@
- ast_channel_datastore_inherit(chan, channel->owner);
-
- /* Copy over callerid information */
-- S_REPLACE(channel->owner->cid.cid_num, ast_strdup(chan->cid.cid_num));
-- S_REPLACE(channel->owner->cid.cid_name, ast_strdup(chan->cid.cid_name));
-- S_REPLACE(channel->owner->cid.cid_ani, ast_strdup(chan->cid.cid_ani));
- S_REPLACE(channel->owner->cid.cid_rdnis, ast_strdup(chan->cid.cid_rdnis));
-+ ast_party_redirecting_copy(&channel->owner->redirecting, &chan->redirecting);
-
-+ channel->owner->cid.cid_tns = chan->cid.cid_tns;
-+
-+ ast_connected_line_copy_from_caller(&channel->owner->connected, &chan->cid);
-+
- ast_string_field_set(channel->owner, language, chan->language);
- ast_string_field_set(channel->owner, accountcode, chan->accountcode);
- channel->owner->cdrflags = chan->cdrflags;
- if (ast_strlen_zero(channel->owner->musicclass))
- ast_string_field_set(channel->owner, musicclass, chan->musicclass);
-
-- channel->owner->cid.cid_pres = chan->cid.cid_pres;
-- channel->owner->cid.cid_ton = chan->cid.cid_ton;
-- channel->owner->cid.cid_tns = chan->cid.cid_tns;
- channel->owner->adsicpe = chan->adsicpe;
- channel->owner->transfercapability = chan->transfercapability;
- }
-@@ -429,6 +428,14 @@
- ast_verbose (VERBOSE_PREFIX_3 "%s requested a source update, passing it to %s\n", channel->owner->name, chan->name);
- ast_indicate(chan, AST_CONTROL_SRCUPDATE);
- break;
-+ case AST_CONTROL_CONNECTED_LINE:
-+ ast_verb(3, "%s connected line has changed, passing it to %s\n", channel->owner->name, chan->name);
-+ ast_indicate_data(chan, AST_CONTROL_CONNECTED_LINE, fr->data.ptr, fr->datalen);
-+ break;
-+ case AST_CONTROL_REDIRECTING:
-+ ast_verb(3, "%s redirecting info has changed, passing it to %s\n", channel->owner->name, chan->name);
-+ ast_indicate_data(chan, AST_CONTROL_REDIRECTING, fr->data.ptr, fr->datalen);
-+ break;
- case AST_CONTROL_PROCEEDING:
- ast_verb(3, "%s is proceeding, passing it to %s\n", channel->owner->name, chan->name);
- ast_indicate(chan, AST_CONTROL_PROCEEDING);
-Index: main/heap.c
-===================================================================
---- a/main/heap.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/main/heap.c (.../trunk) (revision 186562)
-@@ -302,6 +302,8 @@
- return h->cur_len;
- }
-
-+#ifndef DEBUG_THREADS
-+
- int ast_heap_wrlock(struct ast_heap *h)
- {
- return ast_rwlock_wrlock(&h->lock);
-@@ -317,3 +319,21 @@
- return ast_rwlock_unlock(&h->lock);
- }
-
-+#else /* DEBUG_THREADS */
-+
-+int __ast_heap_wrlock(struct ast_heap *h, const char *file, const char *func, int line)
-+{
-+ return _ast_rwlock_wrlock(&h->lock, "&h->lock", file, line, func);
-+}
-+
-+int __ast_heap_rdlock(struct ast_heap *h, const char *file, const char *func, int line)
-+{
-+ return _ast_rwlock_rdlock(&h->lock, "&h->lock", file, line, func);
-+}
-+
-+int __ast_heap_unlock(struct ast_heap *h, const char *file, const char *func, int line)
-+{
-+ return _ast_rwlock_unlock(&h->lock, "&h->lock", file, line, func);
-+}
-+
-+#endif /* DEBUG_THREADS */
-Index: main/pbx.c
-===================================================================
---- a/main/pbx.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/main/pbx.c (.../trunk) (revision 186562)
-@@ -2924,7 +2924,7 @@
- } else if (!strcmp(var, "SYSTEMNAME")) {
- s = ast_config_AST_SYSTEM_NAME;
- } else if (!strcmp(var, "ENTITYID")) {
-- ast_eid_to_str(workspace, workspacelen, &g_eid);
-+ ast_eid_to_str(workspace, workspacelen, &ast_eid_default);
- s = workspace;
- }
- }
-Index: main/strings.c
-===================================================================
---- a/main/strings.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/main/strings.c (.../trunk) (revision 186562)
-@@ -66,7 +66,7 @@
- }
- /*
- * Ask vsnprintf how much space we need. Remember that vsnprintf
-- * does not count the final '\0' so we must add 1.
-+ * does not count the final <code>'\0'</code> so we must add 1.
- */
- va_copy(aq, ap);
- res = vsnprintf((*buf)->__AST_STR_STR + offset, (*buf)->__AST_STR_LEN - offset, fmt, aq);
-@@ -143,7 +143,8 @@
- maxlen--;
- (*buf)->__AST_STR_USED++;
-
-- if (dynamic && (!maxlen || (escapecommas && !(maxlen - 1)))) {
-+ if ((ptr >= (*buf)->__AST_STR_STR + (*buf)->__AST_STR_LEN - 3) ||
-+ (dynamic && (!maxlen || (escapecommas && !(maxlen - 1))))) {
- char *oldbase = (*buf)->__AST_STR_STR;
- size_t old = (*buf)->__AST_STR_LEN;
- if (ast_str_make_space(buf, (*buf)->__AST_STR_LEN * 2)) {
-@@ -156,11 +157,10 @@
- ptr += (*buf)->__AST_STR_STR - oldbase;
- }
- }
-- if (__builtin_expect(!(maxsrc && maxlen), 0)) {
-+ if (__builtin_expect(!maxlen, 0)) {
- ptr--;
- }
- *ptr = '\0';
-- (*buf)->__AST_STR_USED--;
- return (*buf)->__AST_STR_STR;
- }
-
-Index: main/stun.c
-===================================================================
---- a/main/stun.c (.../tags/1.6.2.0-beta1) (revision 0)
-+++ b/main/stun.c (.../trunk) (revision 186562)
-@@ -0,0 +1,475 @@
-+/*
-+ * Asterisk -- An open source telephony toolkit.
-+ *
-+ * Copyright (C) 1999 - 2008, Digium, Inc.
-+ *
-+ * Mark Spencer <markster@digium.com>
-+ *
-+ * See http://www.asterisk.org for more information about
-+ * the Asterisk project. Please do not directly contact
-+ * any of the maintainers of this project for assistance;
-+ * the project provides a web site, mailing lists and IRC
-+ * channels for your use.
-+ *
-+ * 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.
-+ */
-+
-+/*!
-+ * \file
-+ *
-+ * \brief STUN Support
-+ *
-+ * \author Mark Spencer <markster@digium.com>
-+ *
-+ * \note STUN is defined in RFC 3489.
-+ */
-+
-+#include "asterisk.h"
-+
-+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-+
-+#include "asterisk/_private.h"
-+#include "asterisk/stun.h"
-+#include "asterisk/cli.h"
-+#include "asterisk/utils.h"
-+#include "asterisk/channel.h"
-+
-+static int stundebug; /*!< Are we debugging stun? */
-+
-+/*!
-+ * \brief STUN support code
-+ *
-+ * This code provides some support for doing STUN transactions.
-+ * Eventually it should be moved elsewhere as other protocols
-+ * than RTP can benefit from it - e.g. SIP.
-+ * STUN is described in RFC3489 and it is based on the exchange
-+ * of UDP packets between a client and one or more servers to
-+ * determine the externally visible address (and port) of the client
-+ * once it has gone through the NAT boxes that connect it to the
-+ * outside.
-+ * The simplest request packet is just the header defined in
-+ * struct stun_header, and from the response we may just look at
-+ * one attribute, STUN_MAPPED_ADDRESS, that we find in the response.
-+ * By doing more transactions with different server addresses we
-+ * may determine more about the behaviour of the NAT boxes, of
-+ * course - the details are in the RFC.
-+ *
-+ * All STUN packets start with a simple header made of a type,
-+ * length (excluding the header) and a 16-byte random transaction id.
-+ * Following the header we may have zero or more attributes, each
-+ * structured as a type, length and a value (whose format depends
-+ * on the type, but often contains addresses).
-+ * Of course all fields are in network format.
-+ */
-+
-+typedef struct { unsigned int id[4]; } __attribute__((packed)) stun_trans_id;
-+
-+struct stun_header {
-+ unsigned short msgtype;
-+ unsigned short msglen;
-+ stun_trans_id id;
-+ unsigned char ies[0];
-+} __attribute__((packed));
-+
-+struct stun_attr {
-+ unsigned short attr;
-+ unsigned short len;
-+ unsigned char value[0];
-+} __attribute__((packed));
-+
-+/*
-+ * The format normally used for addresses carried by STUN messages.
-+ */
-+struct stun_addr {
-+ unsigned char unused;
-+ unsigned char family;
-+ unsigned short port;
-+ unsigned int addr;
-+} __attribute__((packed));
-+
-+/*! \brief STUN message types
-+ * 'BIND' refers to transactions used to determine the externally
-+ * visible addresses. 'SEC' refers to transactions used to establish
-+ * a session key for subsequent requests.
-+ * 'SEC' functionality is not supported here.
-+ */
-+
-+#define STUN_BINDREQ 0x0001
-+#define STUN_BINDRESP 0x0101
-+#define STUN_BINDERR 0x0111
-+#define STUN_SECREQ 0x0002
-+#define STUN_SECRESP 0x0102
-+#define STUN_SECERR 0x0112
-+
-+/*! \brief Basic attribute types in stun messages.
-+ * Messages can also contain custom attributes (codes above 0x7fff)
-+ */
-+#define STUN_MAPPED_ADDRESS 0x0001
-+#define STUN_RESPONSE_ADDRESS 0x0002
-+#define STUN_CHANGE_REQUEST 0x0003
-+#define STUN_SOURCE_ADDRESS 0x0004
-+#define STUN_CHANGED_ADDRESS 0x0005
-+#define STUN_USERNAME 0x0006
-+#define STUN_PASSWORD 0x0007
-+#define STUN_MESSAGE_INTEGRITY 0x0008
-+#define STUN_ERROR_CODE 0x0009
-+#define STUN_UNKNOWN_ATTRIBUTES 0x000a
-+#define STUN_REFLECTED_FROM 0x000b
-+
-+/*! \brief helper function to print message names */
-+static const char *stun_msg2str(int msg)
-+{
-+ switch (msg) {
-+ case STUN_BINDREQ:
-+ return "Binding Request";
-+ case STUN_BINDRESP:
-+ return "Binding Response";
-+ case STUN_BINDERR:
-+ return "Binding Error Response";
-+ case STUN_SECREQ:
-+ return "Shared Secret Request";
-+ case STUN_SECRESP:
-+ return "Shared Secret Response";
-+ case STUN_SECERR:
-+ return "Shared Secret Error Response";
-+ }
-+ return "Non-RFC3489 Message";
-+}
-+
-+/*! \brief helper function to print attribute names */
-+static const char *stun_attr2str(int msg)
-+{
-+ switch (msg) {
-+ case STUN_MAPPED_ADDRESS:
-+ return "Mapped Address";
-+ case STUN_RESPONSE_ADDRESS:
-+ return "Response Address";
-+ case STUN_CHANGE_REQUEST:
-+ return "Change Request";
-+ case STUN_SOURCE_ADDRESS:
-+ return "Source Address";
-+ case STUN_CHANGED_ADDRESS:
-+ return "Changed Address";
-+ case STUN_USERNAME:
-+ return "Username";
-+ case STUN_PASSWORD:
-+ return "Password";
-+ case STUN_MESSAGE_INTEGRITY:
-+ return "Message Integrity";
-+ case STUN_ERROR_CODE:
-+ return "Error Code";
-+ case STUN_UNKNOWN_ATTRIBUTES:
-+ return "Unknown Attributes";
-+ case STUN_REFLECTED_FROM:
-+ return "Reflected From";
-+ }
-+ return "Non-RFC3489 Attribute";
-+}
-+
-+/*! \brief here we store credentials extracted from a message */
-+struct stun_state {
-+ const char *username;
-+ const char *password;
-+};
-+
-+static int stun_process_attr(struct stun_state *state, struct stun_attr *attr)
-+{
-+ if (stundebug)
-+ ast_verbose("Found STUN Attribute %s (%04x), length %d\n",
-+ stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len));
-+ switch (ntohs(attr->attr)) {
-+ case STUN_USERNAME:
-+ state->username = (const char *) (attr->value);
-+ break;
-+ case STUN_PASSWORD:
-+ state->password = (const char *) (attr->value);
-+ break;
-+ default:
-+ if (stundebug)
-+ ast_verbose("Ignoring STUN attribute %s (%04x), length %d\n",
-+ stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len));
-+ }
-+ return 0;
-+}
-+
-+/*! \brief append a string to an STUN message */
-+static void append_attr_string(struct stun_attr **attr, int attrval, const char *s, int *len, int *left)
-+{
-+ int size = sizeof(**attr) + strlen(s);
-+ if (*left > size) {
-+ (*attr)->attr = htons(attrval);
-+ (*attr)->len = htons(strlen(s));
-+ memcpy((*attr)->value, s, strlen(s));
-+ (*attr) = (struct stun_attr *)((*attr)->value + strlen(s));
-+ *len += size;
-+ *left -= size;
-+ }
-+}
-+
-+/*! \brief append an address to an STUN message */
-+static void append_attr_address(struct stun_attr **attr, int attrval, struct sockaddr_in *sin, int *len, int *left)
-+{
-+ int size = sizeof(**attr) + 8;
-+ struct stun_addr *addr;
-+ if (*left > size) {
-+ (*attr)->attr = htons(attrval);
-+ (*attr)->len = htons(8);
-+ addr = (struct stun_addr *)((*attr)->value);
-+ addr->unused = 0;
-+ addr->family = 0x01;
-+ addr->port = sin->sin_port;
-+ addr->addr = sin->sin_addr.s_addr;
-+ (*attr) = (struct stun_attr *)((*attr)->value + 8);
-+ *len += size;
-+ *left -= size;
-+ }
-+}
-+
-+/*! \brief wrapper to send an STUN message */
-+static int stun_send(int s, struct sockaddr_in *dst, struct stun_header *resp)
-+{
-+ return sendto(s, resp, ntohs(resp->msglen) + sizeof(*resp), 0,
-+ (struct sockaddr *)dst, sizeof(*dst));
-+}
-+
-+/*! \brief helper function to generate a random request id */
-+static void stun_req_id(struct stun_header *req)
-+{
-+ int x;
-+ for (x = 0; x < 4; x++)
-+ req->id.id[x] = ast_random();
-+}
-+
-+/*! \brief handle an incoming STUN message.
-+ *
-+ * Do some basic sanity checks on packet size and content,
-+ * try to extract a bit of information, and possibly reply.
-+ * At the moment this only processes BIND requests, and returns
-+ * the externally visible address of the request.
-+ * If a callback is specified, invoke it with the attribute.
-+ */
-+int ast_stun_handle_packet(int s, struct sockaddr_in *src, unsigned char *data, size_t len, stun_cb_f *stun_cb, void *arg)
-+{
-+ struct stun_header *hdr = (struct stun_header *)data;
-+ struct stun_attr *attr;
-+ struct stun_state st;
-+ int ret = AST_STUN_IGNORE;
-+ int x;
-+
-+ /* On entry, 'len' is the length of the udp payload. After the
-+ * initial checks it becomes the size of unprocessed options,
-+ * while 'data' is advanced accordingly.
-+ */
-+ if (len < sizeof(struct stun_header)) {
-+ ast_debug(1, "Runt STUN packet (only %d, wanting at least %d)\n", (int) len, (int) sizeof(struct stun_header));
-+ return -1;
-+ }
-+ len -= sizeof(struct stun_header);
-+ data += sizeof(struct stun_header);
-+ x = ntohs(hdr->msglen); /* len as advertised in the message */
-+ if (stundebug)
-+ ast_verbose("STUN Packet, msg %s (%04x), length: %d\n", stun_msg2str(ntohs(hdr->msgtype)), ntohs(hdr->msgtype), x);
-+ if (x > len) {
-+ ast_debug(1, "Scrambled STUN packet length (got %d, expecting %d)\n", x, (int)len);
-+ } else
-+ len = x;
-+ memset(&st, 0, sizeof(st));
-+ while (len) {
-+ if (len < sizeof(struct stun_attr)) {
-+ ast_debug(1, "Runt Attribute (got %d, expecting %d)\n", (int)len, (int) sizeof(struct stun_attr));
-+ break;
-+ }
-+ attr = (struct stun_attr *)data;
-+ /* compute total attribute length */
-+ x = ntohs(attr->len) + sizeof(struct stun_attr);
-+ if (x > len) {
-+ ast_debug(1, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", x, (int)len);
-+ break;
-+ }
-+ if (stun_cb)
-+ stun_cb(attr, arg);
-+ if (stun_process_attr(&st, attr)) {
-+ ast_debug(1, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr));
-+ break;
-+ }
-+ /* Clear attribute id: in case previous entry was a string,
-+ * this will act as the terminator for the string.
-+ */
-+ attr->attr = 0;
-+ data += x;
-+ len -= x;
-+ }
-+ /* Null terminate any string.
-+ * XXX NOTE, we write past the size of the buffer passed by the
-+ * caller, so this is potentially dangerous. The only thing that
-+ * saves us is that usually we read the incoming message in a
-+ * much larger buffer in the struct ast_rtp
-+ */
-+ *data = '\0';
-+
-+ /* Now prepare to generate a reply, which at the moment is done
-+ * only for properly formed (len == 0) STUN_BINDREQ messages.
-+ */
-+ if (len == 0) {
-+ unsigned char respdata[1024];
-+ struct stun_header *resp = (struct stun_header *)respdata;
-+ int resplen = 0; /* len excluding header */
-+ int respleft = sizeof(respdata) - sizeof(struct stun_header);
-+
-+ resp->id = hdr->id;
-+ resp->msgtype = 0;
-+ resp->msglen = 0;
-+ attr = (struct stun_attr *)resp->ies;
-+ switch (ntohs(hdr->msgtype)) {
-+ case STUN_BINDREQ:
-+ if (stundebug)
-+ ast_verbose("STUN Bind Request, username: %s\n",
-+ st.username ? st.username : "<none>");
-+ if (st.username)
-+ append_attr_string(&attr, STUN_USERNAME, st.username, &resplen, &respleft);
-+ append_attr_address(&attr, STUN_MAPPED_ADDRESS, src, &resplen, &respleft);
-+ resp->msglen = htons(resplen);
-+ resp->msgtype = htons(STUN_BINDRESP);
-+ stun_send(s, src, resp);
-+ ret = AST_STUN_ACCEPT;
-+ break;
-+ default:
-+ if (stundebug)
-+ ast_verbose("Dunno what to do with STUN message %04x (%s)\n", ntohs(hdr->msgtype), stun_msg2str(ntohs(hdr->msgtype)));
-+ }
-+ }
-+ return ret;
-+}
-+
-+/*! \brief Extract the STUN_MAPPED_ADDRESS from the stun response.
-+ * This is used as a callback for stun_handle_response
-+ * when called from ast_stun_request.
-+ */
-+static int stun_get_mapped(struct stun_attr *attr, void *arg)
-+{
-+ struct stun_addr *addr = (struct stun_addr *)(attr + 1);
-+ struct sockaddr_in *sa = (struct sockaddr_in *)arg;
-+
-+ if (ntohs(attr->attr) != STUN_MAPPED_ADDRESS || ntohs(attr->len) != 8)
-+ return 1; /* not us. */
-+ sa->sin_port = addr->port;
-+ sa->sin_addr.s_addr = addr->addr;
-+ return 0;
-+}
-+
-+/*! \brief Generic STUN request
-+ * Send a generic stun request to the server specified,
-+ * possibly waiting for a reply and filling the 'reply' field with
-+ * the externally visible address. Note that in this case the request
-+ * will be blocking.
-+ * (Note, the interface may change slightly in the future).
-+ *
-+ * \param s the socket used to send the request
-+ * \param dst the address of the STUN server
-+ * \param username if non null, add the username in the request
-+ * \param answer if non null, the function waits for a response and
-+ * puts here the externally visible address.
-+ * \return 0 on success, other values on error.
-+ */
-+int ast_stun_request(int s, struct sockaddr_in *dst,
-+ const char *username, struct sockaddr_in *answer)
-+{
-+ struct stun_header *req;
-+ unsigned char reqdata[1024];
-+ int reqlen, reqleft;
-+ struct stun_attr *attr;
-+ int res = 0;
-+ int retry;
-+
-+ req = (struct stun_header *)reqdata;
-+ stun_req_id(req);
-+ reqlen = 0;
-+ reqleft = sizeof(reqdata) - sizeof(struct stun_header);
-+ req->msgtype = 0;
-+ req->msglen = 0;
-+ attr = (struct stun_attr *)req->ies;
-+ if (username)
-+ append_attr_string(&attr, STUN_USERNAME, username, &reqlen, &reqleft);
-+ req->msglen = htons(reqlen);
-+ req->msgtype = htons(STUN_BINDREQ);
-+ for (retry = 0; retry < 3; retry++) { /* XXX make retries configurable */
-+ /* send request, possibly wait for reply */
-+ unsigned char reply_buf[1024];
-+ fd_set rfds;
-+ struct timeval to = { 3, 0 }; /* timeout, make it configurable */
-+ struct sockaddr_in src;
-+ socklen_t srclen;
-+
-+ res = stun_send(s, dst, req);
-+ if (res < 0) {
-+ ast_log(LOG_WARNING, "ast_stun_request send #%d failed error %d, retry\n",
-+ retry, res);
-+ continue;
-+ }
-+ if (answer == NULL)
-+ break;
-+ FD_ZERO(&rfds);
-+ FD_SET(s, &rfds);
-+ res = ast_select(s + 1, &rfds, NULL, NULL, &to);
-+ if (res <= 0) /* timeout or error */
-+ continue;
-+ memset(&src, 0, sizeof(src));
-+ srclen = sizeof(src);
-+ /* XXX pass -1 in the size, because stun_handle_packet might
-+ * write past the end of the buffer.
-+ */
-+ res = recvfrom(s, reply_buf, sizeof(reply_buf) - 1,
-+ 0, (struct sockaddr *)&src, &srclen);
-+ if (res < 0) {
-+ ast_log(LOG_WARNING, "ast_stun_request recvfrom #%d failed error %d, retry\n",
-+ retry, res);
-+ continue;
-+ }
-+ memset(answer, 0, sizeof(struct sockaddr_in));
-+ ast_stun_handle_packet(s, &src, reply_buf, res,
-+ stun_get_mapped, answer);
-+ res = 0; /* signal regular exit */
-+ break;
-+ }
-+ return res;
-+}
-+
-+static char *handle_cli_stun_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-+{
-+ switch (cmd) {
-+ case CLI_INIT:
-+ e->command = "stun set debug {on|off}";
-+ e->usage =
-+ "Usage: stun set debug {on|off}\n"
-+ " Enable/Disable STUN (Simple Traversal of UDP through NATs)\n"
-+ " debugging\n";
-+ return NULL;
-+ case CLI_GENERATE:
-+ return NULL;
-+ }
-+
-+ if (a->argc != e->args)
-+ return CLI_SHOWUSAGE;
-+
-+ if (!strncasecmp(a->argv[e->args-1], "on", 2))
-+ stundebug = 1;
-+ else if (!strncasecmp(a->argv[e->args-1], "off", 3))
-+ stundebug = 0;
-+ else
-+ return CLI_SHOWUSAGE;
-+
-+ ast_cli(a->fd, "STUN Debugging %s\n", stundebug ? "Enabled" : "Disabled");
-+ return CLI_SUCCESS;
-+}
-+
-+static struct ast_cli_entry cli_stun[] = {
-+ AST_CLI_DEFINE(handle_cli_stun_set_debug, "Enable/Disable STUN debugging"),
-+};
-+
-+/*! \brief Initialize the STUN system in Asterisk */
-+void ast_stun_init(void)
-+{
-+ ast_cli_register_multiple(cli_stun, sizeof(cli_stun) / sizeof(struct ast_cli_entry));
-+}
-
-Property changes on: main/stun.c
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + Author Date Id Revision
-
-Index: main/file.c
-===================================================================
---- a/main/file.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/main/file.c (.../trunk) (revision 186562)
-@@ -1234,6 +1234,7 @@
- case AST_CONTROL_SRCUPDATE:
- case AST_CONTROL_HOLD:
- case AST_CONTROL_UNHOLD:
-+ case -1:
- /* Unimportant */
- break;
- default:
-Index: main/callerid.c
-===================================================================
---- a/main/callerid.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/main/callerid.c (.../trunk) (revision 186562)
-@@ -791,8 +791,8 @@
-
- }
-
--int vmwi_generate(unsigned char *buf, int active, int type, int codec,
-- const char* name, const char* number, int flags)
-+int ast_callerid_vmwi_generate(unsigned char *buf, int active, int type, int codec,
-+ const char* name, const char* number, int flags)
- {
- char msg[256];
- int len = 0;
-@@ -922,8 +922,10 @@
- return bytes;
- }
-
--/*! \brief Clean up phone string
-- * remove '(', ' ', ')', non-trailing '.', and '-' not in square brackets.
-+/*!
-+ * \brief Clean up phone string
-+ * \details
-+ * Remove '(', ' ', ')', non-trailing '.', and '-' not in square brackets.
- * Basically, remove anything that could be invalid in a pattern.
- */
- void ast_shrink_phone_number(char *n)
-@@ -958,11 +960,13 @@
- n[y] = '\0';
- }
-
--/*! \brief Checks if phone number consists of valid characters
-- \param exten String that needs to be checked
-- \param valid Valid characters in string
-- \return 1 if valid string, 0 if string contains invalid characters
--*/
-+/*!
-+ * \brief Checks if phone number consists of valid characters
-+ * \param exten String that needs to be checked
-+ * \param valid Valid characters in string
-+ * \retval 1 if valid string
-+ * \retval 0 if string contains invalid characters
-+ */
- static int ast_is_valid_string(const char *exten, const char *valid)
- {
- int x;
-@@ -975,34 +979,16 @@
- return 1;
- }
-
--/*! \brief checks if string consists only of digits and * \# and +
-- \return 1 if string is valid AST phone number
-- \return 0 if not
--*/
- int ast_isphonenumber(const char *n)
- {
- return ast_is_valid_string(n, "0123456789*#+");
- }
-
--/*! \brief checks if string consists only of digits and ( ) - * \# and +
-- Pre-qualifies the string for ast_shrink_phone_number()
-- \return 1 if string is valid AST shrinkable phone number
-- \return 0 if not
--*/
- int ast_is_shrinkable_phonenumber(const char *exten)
- {
- return ast_is_valid_string(exten, "0123456789*#+()-.");
- }
-
--/*!
-- * \brief Destructively parse instr for caller id information
-- * \return always returns 0, as the code always returns something.
-- * \note XXX 'name' is not parsed consistently e.g. we have
-- * input location name
-- * " foo bar " <123> 123 ' foo bar ' (with spaces around)
-- * " foo bar " NULL 'foo bar' (without spaces around)
-- * The parsing of leading and trailing space/quotes should be more consistent.
-- */
- int ast_callerid_parse(char *instr, char **name, char **location)
- {
- char *ns, *ne, *ls, *le;
-@@ -1103,68 +1089,191 @@
- return 0;
- }
-
--/*! \brief Translation table for Caller ID Presentation settings */
--static struct {
-- int val;
-+struct ast_value_translation {
-+ int value;
- const char *name;
- const char *description;
--} pres_types[] = {
-- { AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, "allowed_not_screened", "Presentation Allowed, Not Screened"},
-- { AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, "allowed_passed_screen", "Presentation Allowed, Passed Screen"},
-- { AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN, "allowed_failed_screen", "Presentation Allowed, Failed Screen"},
-- { AST_PRES_ALLOWED_NETWORK_NUMBER, "allowed", "Presentation Allowed, Network Number"},
-- { AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED, "prohib_not_screened", "Presentation Prohibited, Not Screened"},
-- { AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN, "prohib_passed_screen", "Presentation Prohibited, Passed Screen"},
-- { AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN, "prohib_failed_screen", "Presentation Prohibited, Failed Screen"},
-- { AST_PRES_PROHIB_NETWORK_NUMBER, "prohib", "Presentation Prohibited, Network Number"},
-- { AST_PRES_NUMBER_NOT_AVAILABLE, "unavailable", "Number Unavailable"},
- };
-
--/*! \brief Convert caller ID text code to value
-- used in config file parsing
-- \param data text string
-- \return value AST_PRES_ from callerid.h
--*/
-+/*! \brief Translation table for Caller ID Presentation settings */
-+static const struct ast_value_translation pres_types[] = {
-+/* *INDENT-OFF* */
-+ { AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_UNSCREENED, "allowed_not_screened", "Presentation Allowed, Not Screened" },
-+ { AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_PASSED_SCREEN, "allowed_passed_screen", "Presentation Allowed, Passed Screen" },
-+ { AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_FAILED_SCREEN, "allowed_failed_screen", "Presentation Allowed, Failed Screen" },
-+ { AST_PRES_ALLOWED | AST_PRES_NETWORK_NUMBER, "allowed", "Presentation Allowed, Network Number" },
-+
-+ { AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_UNSCREENED, "prohib_not_screened", "Presentation Prohibited, Not Screened" },
-+ { AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_PASSED_SCREEN, "prohib_passed_screen", "Presentation Prohibited, Passed Screen" },
-+ { AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_FAILED_SCREEN, "prohib_failed_screen", "Presentation Prohibited, Failed Screen" },
-+ { AST_PRES_RESTRICTED | AST_PRES_NETWORK_NUMBER, "prohib", "Presentation Prohibited, Network Number" },
-+
-+ { AST_PRES_UNAVAILABLE | AST_PRES_NETWORK_NUMBER, "unavailable", "Number Unavailable" }, /* Default name to value conversion. */
-+ { AST_PRES_UNAVAILABLE | AST_PRES_USER_NUMBER_UNSCREENED, "unavailable", "Number Unavailable" },
-+ { AST_PRES_UNAVAILABLE | AST_PRES_USER_NUMBER_FAILED_SCREEN, "unavailable", "Number Unavailable" },
-+ { AST_PRES_UNAVAILABLE | AST_PRES_USER_NUMBER_PASSED_SCREEN, "unavailable", "Number Unavailable" },
-+/* *INDENT-ON* */
-+};
-+
-+/*!
-+ * \brief Convert caller ID text code to value (used in config file parsing)
-+ * \param data text string from config file
-+ * \retval value AST_PRES_ from callerid.h
-+ * \retval -1 if not in table
-+ */
- int ast_parse_caller_presentation(const char *data)
- {
-- int i;
-+ int index;
-
-- for (i = 0; i < ARRAY_LEN(pres_types); i++) {
-- if (!strcasecmp(pres_types[i].name, data))
-- return pres_types[i].val;
-+ for (index = 0; index < ARRAY_LEN(pres_types); ++index) {
-+ if (!strcasecmp(pres_types[index].name, data)) {
-+ return pres_types[index].value;
-+ }
- }
-
- return -1;
- }
-
--/*! \brief Convert caller ID pres value to explanatory string
-- \param data value (see callerid.h AST_PRES_ )
-- \return string for human presentation
--*/
-+/*!
-+ * \brief Convert caller ID pres value to explanatory string
-+ * \param data AST_PRES_ value from callerid.h
-+ * \return string for human presentation
-+ */
- const char *ast_describe_caller_presentation(int data)
- {
-- int i;
-+ int index;
-
-- for (i = 0; i < ARRAY_LEN(pres_types); i++) {
-- if (pres_types[i].val == data)
-- return pres_types[i].description;
-+ for (index = 0; index < ARRAY_LEN(pres_types); ++index) {
-+ if (pres_types[index].value == data) {
-+ return pres_types[index].description;
-+ }
- }
-
- return "unknown";
- }
-
--/*! \brief Convert caller ID pres value to text code
-- \param data text string
-- \return string for config file
--*/
-+/*!
-+ * \brief Convert caller ID pres value to text code
-+ * \param data AST_PRES_ value from callerid.h
-+ * \return string for config file
-+ */
- const char *ast_named_caller_presentation(int data)
- {
-- int i;
-+ int index;
-
-- for (i = 0; i < ARRAY_LEN(pres_types); i++) {
-- if (pres_types[i].val == data)
-- return pres_types[i].name;
-+ for (index = 0; index < ARRAY_LEN(pres_types); ++index) {
-+ if (pres_types[index].value == data) {
-+ return pres_types[index].name;
-+ }
- }
-
- return "unknown";
- }
-+
-+/*! \brief Translation table for redirecting reason settings */
-+static const struct ast_value_translation redirecting_reason_types[] = {
-+/* *INDENT-OFF* */
-+ { AST_REDIRECTING_REASON_UNKNOWN, "unknown", "Unknown" },
-+ { AST_REDIRECTING_REASON_USER_BUSY, "cfb", "Call Forwarding Busy" },
-+ { AST_REDIRECTING_REASON_NO_ANSWER, "cfnr", "Call Forwarding No Reply" },
-+ { AST_REDIRECTING_REASON_UNAVAILABLE, "unavailable", "Callee is Unavailable" },
-+ { AST_REDIRECTING_REASON_UNCONDITIONAL, "cfu", "Call Forwarding Unconditional" },
-+ { AST_REDIRECTING_REASON_TIME_OF_DAY, "time_of_day", "Time of Day" },
-+ { AST_REDIRECTING_REASON_DO_NOT_DISTURB, "dnd", "Do Not Disturb" },
-+ { AST_REDIRECTING_REASON_DEFLECTION, "deflection", "Call Deflection" },
-+ { AST_REDIRECTING_REASON_FOLLOW_ME, "follow_me", "Follow Me" },
-+ { AST_REDIRECTING_REASON_OUT_OF_ORDER, "out_of_order", "Called DTE Out-Of-Order" },
-+ { AST_REDIRECTING_REASON_AWAY, "away", "Callee is Away" },
-+ { AST_REDIRECTING_REASON_CALL_FWD_DTE, "cf_dte", "Call Forwarding By The Called DTE" },
-+/* *INDENT-ON* */
-+};
-+
-+int ast_redirecting_reason_parse(const char *data)
-+{
-+ int index;
-+
-+ for (index = 0; index < ARRAY_LEN(redirecting_reason_types); ++index) {
-+ if (!strcasecmp(redirecting_reason_types[index].name, data)) {
-+ return redirecting_reason_types[index].value;
-+ }
-+ }
-+
-+ return -1;
-+}
-+
-+const char *ast_redirecting_reason_describe(int data)
-+{
-+ int index;
-+
-+ for (index = 0; index < ARRAY_LEN(redirecting_reason_types); ++index) {
-+ if (redirecting_reason_types[index].value == data) {
-+ return redirecting_reason_types[index].description;
-+ }
-+ }
-+
-+ return "not-known";
-+}
-+
-+const char *ast_redirecting_reason_name(int data)
-+{
-+ int index;
-+
-+ for (index = 0; index < ARRAY_LEN(redirecting_reason_types); ++index) {
-+ if (redirecting_reason_types[index].value == data) {
-+ return redirecting_reason_types[index].name;
-+ }
-+ }
-+
-+ return "not-known";
-+}
-+
-+/*! \brief Translation table for connected line update source settings */
-+static const struct ast_value_translation connected_line_source_types[] = {
-+/* *INDENT-OFF* */
-+ { AST_CONNECTED_LINE_UPDATE_SOURCE_UNKNOWN, "unknown", "Unknown" },
-+ { AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER, "answer", "Normal Call Answering" },
-+ { AST_CONNECTED_LINE_UPDATE_SOURCE_DIVERSION, "diversion", "Call Diversion (Deprecated, use REDIRECTING)" },
-+ { AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER, "transfer_active", "Call Transfer(Active)" },
-+ { AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER, "transfer", "Call Transfer(Active)" },/* Old name must come after new name. */
-+ { AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING, "transfer_alerting", "Call Transfer(Alerting)" }
-+/* *INDENT-ON* */
-+};
-+
-+int ast_connected_line_source_parse(const char *data)
-+{
-+ int index;
-+
-+ for (index = 0; index < ARRAY_LEN(connected_line_source_types); ++index) {
-+ if (!strcasecmp(connected_line_source_types[index].name, data)) {
-+ return connected_line_source_types[index].value;
-+ }
-+ }
-+
-+ return -1;
-+}
-+
-+const char *ast_connected_line_source_describe(int data)
-+{
-+ int index;
-+
-+ for (index = 0; index < ARRAY_LEN(connected_line_source_types); ++index) {
-+ if (connected_line_source_types[index].value == data) {
-+ return connected_line_source_types[index].description;
-+ }
-+ }
-+
-+ return "not-known";
-+}
-+
-+const char *ast_connected_line_source_name(int data)
-+{
-+ int index;
-+
-+ for (index = 0; index < ARRAY_LEN(connected_line_source_types); ++index) {
-+ if (connected_line_source_types[index].value == data) {
-+ return connected_line_source_types[index].name;
-+ }
-+ }
-+
-+ return "not-known";
-+}
-Index: main/audiohook.c
-===================================================================
---- a/main/audiohook.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/main/audiohook.c (.../trunk) (revision 186562)
-@@ -441,12 +441,12 @@
-
- void ast_audiohook_move_by_source(struct ast_channel *old_chan, struct ast_channel *new_chan, const char *source)
- {
-- struct ast_audiohook *audiohook = find_audiohook_by_source(old_chan->audiohooks, source);
-+ struct ast_audiohook *audiohook;
-
-- if (!audiohook) {
-+ if (!old_chan->audiohooks || !(audiohook = find_audiohook_by_source(old_chan->audiohooks, source))) {
- return;
- }
--
-+
- /* By locking both channels and the audiohook, we can assure that
- * another thread will not have a chance to read the audiohook's status
- * as done, even though ast_audiohook_remove signals the trigger
-@@ -576,6 +576,7 @@
- }
- if (!(middle_frame = ast_translate(in_translate->trans_pvt, frame, 0)))
- return frame;
-+ samples = middle_frame->samples;
- }
-
- /* Queue up signed linear frame to each spy */
-Index: main/rtp_engine.c
-===================================================================
---- a/main/rtp_engine.c (.../tags/1.6.2.0-beta1) (revision 0)
-+++ b/main/rtp_engine.c (.../trunk) (revision 186562)
-@@ -0,0 +1,1572 @@
-+/*
-+ * Asterisk -- An open source telephony toolkit.
-+ *
-+ * Copyright (C) 1999 - 2008, Digium, Inc.
-+ *
-+ * Joshua Colp <jcolp@digium.com>
-+ *
-+ * See http://www.asterisk.org for more information about
-+ * the Asterisk project. Please do not directly contact
-+ * any of the maintainers of this project for assistance;
-+ * the project provides a web site, mailing lists and IRC
-+ * channels for your use.
-+ *
-+ * 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.
-+ */
-+
-+/*! \file
-+ *
-+ * \brief Pluggable RTP Architecture
-+ *
-+ * \author Joshua Colp <jcolp@digium.com>
-+ */
-+
-+#include "asterisk.h"
-+
-+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-+
-+#include <math.h>
-+
-+#include "asterisk/channel.h"
-+#include "asterisk/frame.h"
-+#include "asterisk/module.h"
-+#include "asterisk/rtp_engine.h"
-+#include "asterisk/manager.h"
-+#include "asterisk/options.h"
-+#include "asterisk/astobj2.h"
-+#include "asterisk/pbx.h"
-+
-+/*! Structure that represents an RTP session (instance) */
-+struct ast_rtp_instance {
-+ /*! Engine that is handling this RTP instance */
-+ struct ast_rtp_engine *engine;
-+ /*! Data unique to the RTP engine */
-+ void *data;
-+ /*! RTP properties that have been set and their value */
-+ int properties[AST_RTP_PROPERTY_MAX];
-+ /*! Address that we are expecting RTP to come in to */
-+ struct sockaddr_in local_address;
-+ /*! Address that we are sending RTP to */
-+ struct sockaddr_in remote_address;
-+ /*! Instance that we are bridged to if doing remote or local bridging */
-+ struct ast_rtp_instance *bridged;
-+ /*! Payload and packetization information */
-+ struct ast_rtp_codecs codecs;
-+ /*! RTP timeout time (negative or zero means disabled, negative value means temporarily disabled) */
-+ int timeout;
-+ /*! RTP timeout when on hold (negative or zero means disabled, negative value means temporarily disabled). */
-+ int holdtimeout;
-+ /*! DTMF mode in use */
-+ enum ast_rtp_dtmf_mode dtmf_mode;
-+};
-+
-+/*! List of RTP engines that are currently registered */
-+static AST_RWLIST_HEAD_STATIC(engines, ast_rtp_engine);
-+
-+/*! List of RTP glues */
-+static AST_RWLIST_HEAD_STATIC(glues, ast_rtp_glue);
-+
-+/*! The following array defines the MIME Media type (and subtype) for each
-+ of our codecs, or RTP-specific data type. */
-+static const struct ast_rtp_mime_type {
-+ struct ast_rtp_payload_type payload_type;
-+ char *type;
-+ char *subtype;
-+ unsigned int sample_rate;
-+} ast_rtp_mime_types[] = {
-+ {{1, AST_FORMAT_G723_1}, "audio", "G723", 8000},
-+ {{1, AST_FORMAT_GSM}, "audio", "GSM", 8000},
-+ {{1, AST_FORMAT_ULAW}, "audio", "PCMU", 8000},
-+ {{1, AST_FORMAT_ULAW}, "audio", "G711U", 8000},
-+ {{1, AST_FORMAT_ALAW}, "audio", "PCMA", 8000},
-+ {{1, AST_FORMAT_ALAW}, "audio", "G711A", 8000},
-+ {{1, AST_FORMAT_G726}, "audio", "G726-32", 8000},
-+ {{1, AST_FORMAT_ADPCM}, "audio", "DVI4", 8000},
-+ {{1, AST_FORMAT_SLINEAR}, "audio", "L16", 8000},
-+ {{1, AST_FORMAT_LPC10}, "audio", "LPC", 8000},
-+ {{1, AST_FORMAT_G729A}, "audio", "G729", 8000},
-+ {{1, AST_FORMAT_G729A}, "audio", "G729A", 8000},
-+ {{1, AST_FORMAT_G729A}, "audio", "G.729", 8000},
-+ {{1, AST_FORMAT_SPEEX}, "audio", "speex", 8000},
-+ {{1, AST_FORMAT_ILBC}, "audio", "iLBC", 8000},
-+ /* this is the sample rate listed in the RTP profile for the G.722
-+ codec, *NOT* the actual sample rate of the media stream
-+ */
-+ {{1, AST_FORMAT_G722}, "audio", "G722", 8000},
-+ {{1, AST_FORMAT_G726_AAL2}, "audio", "AAL2-G726-32", 8000},
-+ {{0, AST_RTP_DTMF}, "audio", "telephone-event", 8000},
-+ {{0, AST_RTP_CISCO_DTMF}, "audio", "cisco-telephone-event", 8000},
-+ {{0, AST_RTP_CN}, "audio", "CN", 8000},
-+ {{1, AST_FORMAT_JPEG}, "video", "JPEG", 90000},
-+ {{1, AST_FORMAT_PNG}, "video", "PNG", 90000},
-+ {{1, AST_FORMAT_H261}, "video", "H261", 90000},
-+ {{1, AST_FORMAT_H263}, "video", "H263", 90000},
-+ {{1, AST_FORMAT_H263_PLUS}, "video", "h263-1998", 90000},
-+ {{1, AST_FORMAT_H264}, "video", "H264", 90000},
-+ {{1, AST_FORMAT_MP4_VIDEO}, "video", "MP4V-ES", 90000},
-+ {{1, AST_FORMAT_T140RED}, "text", "RED", 1000},
-+ {{1, AST_FORMAT_T140}, "text", "T140", 1000},
-+ {{1, AST_FORMAT_SIREN7}, "audio", "G7221", 16000},
-+ {{1, AST_FORMAT_SIREN14}, "audio", "G7221", 32000},
-+};
-+
-+/*!
-+ * \brief Mapping between Asterisk codecs and rtp payload types
-+ *
-+ * Static (i.e., well-known) RTP payload types for our "AST_FORMAT..."s:
-+ * also, our own choices for dynamic payload types. This is our master
-+ * table for transmission
-+ *
-+ * See http://www.iana.org/assignments/rtp-parameters for a list of
-+ * assigned values
-+ */
-+static const struct ast_rtp_payload_type static_RTP_PT[AST_RTP_MAX_PT] = {
-+ [0] = {1, AST_FORMAT_ULAW},
-+ #ifdef USE_DEPRECATED_G726
-+ [2] = {1, AST_FORMAT_G726}, /* Technically this is G.721, but if Cisco can do it, so can we... */
-+ #endif
-+ [3] = {1, AST_FORMAT_GSM},
-+ [4] = {1, AST_FORMAT_G723_1},
-+ [5] = {1, AST_FORMAT_ADPCM}, /* 8 kHz */
-+ [6] = {1, AST_FORMAT_ADPCM}, /* 16 kHz */
-+ [7] = {1, AST_FORMAT_LPC10},
-+ [8] = {1, AST_FORMAT_ALAW},
-+ [9] = {1, AST_FORMAT_G722},
-+ [10] = {1, AST_FORMAT_SLINEAR}, /* 2 channels */
-+ [11] = {1, AST_FORMAT_SLINEAR}, /* 1 channel */
-+ [13] = {0, AST_RTP_CN},
-+ [16] = {1, AST_FORMAT_ADPCM}, /* 11.025 kHz */
-+ [17] = {1, AST_FORMAT_ADPCM}, /* 22.050 kHz */
-+ [18] = {1, AST_FORMAT_G729A},
-+ [19] = {0, AST_RTP_CN}, /* Also used for CN */
-+ [26] = {1, AST_FORMAT_JPEG},
-+ [31] = {1, AST_FORMAT_H261},
-+ [34] = {1, AST_FORMAT_H263},
-+ [97] = {1, AST_FORMAT_ILBC},
-+ [98] = {1, AST_FORMAT_H263_PLUS},
-+ [99] = {1, AST_FORMAT_H264},
-+ [101] = {0, AST_RTP_DTMF},
-+ [102] = {1, AST_FORMAT_SIREN7},
-+ [103] = {1, AST_FORMAT_H263_PLUS},
-+ [104] = {1, AST_FORMAT_MP4_VIDEO},
-+ [105] = {1, AST_FORMAT_T140RED}, /* Real time text chat (with redundancy encoding) */
-+ [106] = {1, AST_FORMAT_T140}, /* Real time text chat */
-+ [110] = {1, AST_FORMAT_SPEEX},
-+ [111] = {1, AST_FORMAT_G726},
-+ [112] = {1, AST_FORMAT_G726_AAL2},
-+ [115] = {1, AST_FORMAT_SIREN14},
-+ [121] = {0, AST_RTP_CISCO_DTMF}, /* Must be type 121 */
-+};
-+
-+int ast_rtp_engine_register2(struct ast_rtp_engine *engine, struct ast_module *module)
-+{
-+ struct ast_rtp_engine *current_engine;
-+
-+ /* Perform a sanity check on the engine structure to make sure it has the basics */
-+ if (ast_strlen_zero(engine->name) || !engine->new || !engine->destroy || !engine->write || !engine->read) {
-+ ast_log(LOG_WARNING, "RTP Engine '%s' failed sanity check so it was not registered.\n", !ast_strlen_zero(engine->name) ? engine->name : "Unknown");
-+ return -1;
-+ }
-+
-+ /* Link owner module to the RTP engine for reference counting purposes */
-+ engine->mod = module;
-+
-+ AST_RWLIST_WRLOCK(&engines);
-+
-+ /* Ensure that no two modules with the same name are registered at the same time */
-+ AST_RWLIST_TRAVERSE(&engines, current_engine, entry) {
-+ if (!strcmp(current_engine->name, engine->name)) {
-+ ast_log(LOG_WARNING, "An RTP engine with the name '%s' has already been registered.\n", engine->name);
-+ AST_RWLIST_UNLOCK(&engines);
-+ return -1;
-+ }
-+ }
-+
-+ /* The engine survived our critique. Off to the list it goes to be used */
-+ AST_RWLIST_INSERT_TAIL(&engines, engine, entry);
-+
-+ AST_RWLIST_UNLOCK(&engines);
-+
-+ ast_verb(2, "Registered RTP engine '%s'\n", engine->name);
-+
-+ return 0;
-+}
-+
-+int ast_rtp_engine_unregister(struct ast_rtp_engine *engine)
-+{
-+ struct ast_rtp_engine *current_engine = NULL;
-+
-+ AST_RWLIST_WRLOCK(&engines);
-+
-+ if ((current_engine = AST_RWLIST_REMOVE(&engines, engine, entry))) {
-+ ast_verb(2, "Unregistered RTP engine '%s'\n", engine->name);
-+ }
-+
-+ AST_RWLIST_UNLOCK(&engines);
-+
-+ return current_engine ? 0 : -1;
-+}
-+
-+int ast_rtp_glue_register2(struct ast_rtp_glue *glue, struct ast_module *module)
-+{
-+ struct ast_rtp_glue *current_glue = NULL;
-+
-+ if (ast_strlen_zero(glue->type)) {
-+ return -1;
-+ }
-+
-+ glue->mod = module;
-+
-+ AST_RWLIST_WRLOCK(&glues);
-+
-+ AST_RWLIST_TRAVERSE(&glues, current_glue, entry) {
-+ if (!strcasecmp(current_glue->type, glue->type)) {
-+ ast_log(LOG_WARNING, "RTP glue with the name '%s' has already been registered.\n", glue->type);
-+ AST_RWLIST_UNLOCK(&glues);
-+ return -1;
-+ }
-+ }
-+
-+ AST_RWLIST_INSERT_TAIL(&glues, glue, entry);
-+
-+ AST_RWLIST_UNLOCK(&glues);
-+
-+ ast_verb(2, "Registered RTP glue '%s'\n", glue->type);
-+
-+ return 0;
-+}
-+
-+int ast_rtp_glue_unregister(struct ast_rtp_glue *glue)
-+{
-+ struct ast_rtp_glue *current_glue = NULL;
-+
-+ AST_RWLIST_WRLOCK(&glues);
-+
-+ if ((current_glue = AST_RWLIST_REMOVE(&glues, glue, entry))) {
-+ ast_verb(2, "Unregistered RTP glue '%s'\n", glue->type);
-+ }
-+
-+ AST_RWLIST_UNLOCK(&glues);
-+
-+ return current_glue ? 0 : -1;
-+}
-+
-+static void instance_destructor(void *obj)
-+{
-+ struct ast_rtp_instance *instance = obj;
-+
-+ /* Pass us off to the engine to destroy */
-+ if (instance->data && instance->engine->destroy(instance)) {
-+ ast_debug(1, "Engine '%s' failed to destroy RTP instance '%p'\n", instance->engine->name, instance);
-+ return;
-+ }
-+
-+ /* Drop our engine reference */
-+ ast_module_unref(instance->engine->mod);
-+
-+ ast_debug(1, "Destroyed RTP instance '%p'\n", instance);
-+}
-+
-+int ast_rtp_instance_destroy(struct ast_rtp_instance *instance)
-+{
-+ ao2_ref(instance, -1);
-+
-+ return 0;
-+}
-+
-+struct ast_rtp_instance *ast_rtp_instance_new(const char *engine_name, struct sched_context *sched, struct sockaddr_in *sin, void *data)
-+{
-+ struct ast_rtp_instance *instance = NULL;
-+ struct ast_rtp_engine *engine = NULL;
-+
-+ AST_RWLIST_RDLOCK(&engines);
-+
-+ /* If an engine name was specified try to use it or otherwise use the first one registered */
-+ if (!ast_strlen_zero(engine_name)) {
-+ AST_RWLIST_TRAVERSE(&engines, engine, entry) {
-+ if (!strcmp(engine->name, engine_name)) {
-+ break;
-+ }
-+ }
-+ } else {
-+ engine = AST_RWLIST_FIRST(&engines);
-+ }
-+
-+ /* If no engine was actually found bail out now */
-+ if (!engine) {
-+ ast_log(LOG_ERROR, "No RTP engine was found. Do you have one loaded?\n");
-+ AST_RWLIST_UNLOCK(&engines);
-+ return NULL;
-+ }
-+
-+ /* Bump up the reference count before we return so the module can not be unloaded */
-+ ast_module_ref(engine->mod);
-+
-+ AST_RWLIST_UNLOCK(&engines);
-+
-+ /* Allocate a new RTP instance */
-+ if (!(instance = ao2_alloc(sizeof(*instance), instance_destructor))) {
-+ ast_module_unref(engine->mod);
-+ return NULL;
-+ }
-+ instance->engine = engine;
-+ memcpy(&instance->local_address, sin, sizeof(instance->local_address));
-+
-+ ast_debug(1, "Using engine '%s' for RTP instance '%p'\n", engine->name, instance);
-+
-+ /* And pass it off to the engine to setup */
-+ if (instance->engine->new(instance, sched, sin, data)) {
-+ ast_debug(1, "Engine '%s' failed to setup RTP instance '%p'\n", engine->name, instance);
-+ ao2_ref(instance, -1);
-+ return NULL;
-+ }
-+
-+ ast_debug(1, "RTP instance '%p' is setup and ready to go\n", instance);
-+
-+ return instance;
-+}
-+
-+void ast_rtp_instance_set_data(struct ast_rtp_instance *instance, void *data)
-+{
-+ instance->data = data;
-+}
-+
-+void *ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
-+{
-+ return instance->data;
-+}
-+
-+int ast_rtp_instance_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
-+{
-+ return instance->engine->write(instance, frame);
-+}
-+
-+struct ast_frame *ast_rtp_instance_read(struct ast_rtp_instance *instance, int rtcp)
-+{
-+ return instance->engine->read(instance, rtcp);
-+}
-+
-+int ast_rtp_instance_set_local_address(struct ast_rtp_instance *instance, struct sockaddr_in *address)
-+{
-+ memcpy(&instance->local_address, address, sizeof(instance->local_address));
-+ return 0;
-+}
-+
-+int ast_rtp_instance_set_remote_address(struct ast_rtp_instance *instance, struct sockaddr_in *address)
-+{
-+ if (&instance->remote_address != address) {
-+ memcpy(&instance->remote_address, address, sizeof(instance->remote_address));
-+ }
-+
-+ /* moo */
-+
-+ if (instance->engine->remote_address_set) {
-+ instance->engine->remote_address_set(instance, address);
-+ }
-+
-+ return 0;
-+}
-+
-+int ast_rtp_instance_get_local_address(struct ast_rtp_instance *instance, struct sockaddr_in *address)
-+{
-+ if ((address->sin_family != AF_INET) ||
-+ (address->sin_port != instance->local_address.sin_port) ||
-+ (address->sin_addr.s_addr != instance->local_address.sin_addr.s_addr)) {
-+ memcpy(address, &instance->local_address, sizeof(address));
-+ return 1;
-+ }
-+
-+ return 0;
-+}
-+
-+int ast_rtp_instance_get_remote_address(struct ast_rtp_instance *instance, struct sockaddr_in *address)
-+{
-+ if ((address->sin_family != AF_INET) ||
-+ (address->sin_port != instance->remote_address.sin_port) ||
-+ (address->sin_addr.s_addr != instance->remote_address.sin_addr.s_addr)) {
-+ memcpy(address, &instance->remote_address, sizeof(address));
-+ return 1;
-+ }
-+
-+ return 0;
-+}
-+
-+void ast_rtp_instance_set_extended_prop(struct ast_rtp_instance *instance, int property, void *value)
-+{
-+ if (instance->engine->extended_prop_set) {
-+ instance->engine->extended_prop_set(instance, property, value);
-+ }
-+}
-+
-+void *ast_rtp_instance_get_extended_prop(struct ast_rtp_instance *instance, int property)
-+{
-+ if (instance->engine->extended_prop_get) {
-+ return instance->engine->extended_prop_get(instance, property);
-+ }
-+
-+ return NULL;
-+}
-+
-+void ast_rtp_instance_set_prop(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value)
-+{
-+ instance->properties[property] = value;
-+
-+ if (instance->engine->prop_set) {
-+ instance->engine->prop_set(instance, property, value);
-+ }
-+}
-+
-+int ast_rtp_instance_get_prop(struct ast_rtp_instance *instance, enum ast_rtp_property property)
-+{
-+ return instance->properties[property];
-+}
-+
-+struct ast_rtp_codecs *ast_rtp_instance_get_codecs(struct ast_rtp_instance *instance)
-+{
-+ return &instance->codecs;
-+}
-+
-+void ast_rtp_codecs_payloads_clear(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance)
-+{
-+ int i;
-+
-+ for (i = 0; i < AST_RTP_MAX_PT; i++) {
-+ ast_debug(2, "Clearing payload %d on %p\n", i, codecs);
-+ codecs->payloads[i].asterisk_format = 0;
-+ codecs->payloads[i].code = 0;
-+ if (instance && instance->engine && instance->engine->payload_set) {
-+ instance->engine->payload_set(instance, i, 0, 0);
-+ }
-+ }
-+}
-+
-+void ast_rtp_codecs_payloads_default(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance)
-+{
-+ int i;
-+
-+ for (i = 0; i < AST_RTP_MAX_PT; i++) {
-+ if (static_RTP_PT[i].code) {
-+ ast_debug(2, "Set default payload %d on %p\n", i, codecs);
-+ codecs->payloads[i].asterisk_format = static_RTP_PT[i].asterisk_format;
-+ codecs->payloads[i].code = static_RTP_PT[i].code;
-+ if (instance && instance->engine && instance->engine->payload_set) {
-+ instance->engine->payload_set(instance, i, codecs->payloads[i].asterisk_format, codecs->payloads[i].code);
-+ }
-+ }
-+ }
-+}
-+
-+void ast_rtp_codecs_payloads_copy(struct ast_rtp_codecs *src, struct ast_rtp_codecs *dest, struct ast_rtp_instance *instance)
-+{
-+ int i;
-+
-+ for (i = 0; i < AST_RTP_MAX_PT; i++) {
-+ if (src->payloads[i].code) {
-+ ast_debug(2, "Copying payload %d from %p to %p\n", i, src, dest);
-+ dest->payloads[i].asterisk_format = src->payloads[i].asterisk_format;
-+ dest->payloads[i].code = src->payloads[i].code;
-+ if (instance && instance->engine && instance->engine->payload_set) {
-+ instance->engine->payload_set(instance, i, dest->payloads[i].asterisk_format, dest->payloads[i].code);
-+ }
-+ }
-+ }
-+}
-+
-+void ast_rtp_codecs_payloads_set_m_type(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload)
-+{
-+ if (payload < 0 || payload > AST_RTP_MAX_PT || !static_RTP_PT[payload].code) {
-+ return;
-+ }
-+
-+ codecs->payloads[payload].asterisk_format = static_RTP_PT[payload].asterisk_format;
-+ codecs->payloads[payload].code = static_RTP_PT[payload].code;
-+
-+ ast_debug(1, "Setting payload %d based on m type on %p\n", payload, codecs);
-+
-+ if (instance && instance->engine && instance->engine->payload_set) {
-+ instance->engine->payload_set(instance, payload, codecs->payloads[payload].asterisk_format, codecs->payloads[payload].code);
-+ }
-+}
-+
-+int ast_rtp_codecs_payloads_set_rtpmap_type_rate(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int pt,
-+ char *mimetype, char *mimesubtype,
-+ enum ast_rtp_options options,
-+ unsigned int sample_rate)
-+{
-+ unsigned int i;
-+ int found = 0;
-+
-+ if (pt < 0 || pt > AST_RTP_MAX_PT)
-+ return -1; /* bogus payload type */
-+
-+ for (i = 0; i < ARRAY_LEN(ast_rtp_mime_types); ++i) {
-+ const struct ast_rtp_mime_type *t = &ast_rtp_mime_types[i];
-+
-+ if (strcasecmp(mimesubtype, t->subtype)) {
-+ continue;
-+ }
-+
-+ if (strcasecmp(mimetype, t->type)) {
-+ continue;
-+ }
-+
-+ /* if both sample rates have been supplied, and they don't match,
-+ then this not a match; if one has not been supplied, then the
-+ rates are not compared */
-+ if (sample_rate && t->sample_rate &&
-+ (sample_rate != t->sample_rate)) {
-+ continue;
-+ }
-+
-+ found = 1;
-+ codecs->payloads[pt] = t->payload_type;
-+
-+ if ((t->payload_type.code == AST_FORMAT_G726) &&
-+ t->payload_type.asterisk_format &&
-+ (options & AST_RTP_OPT_G726_NONSTANDARD)) {
-+ codecs->payloads[pt].code = AST_FORMAT_G726_AAL2;
-+ }
-+
-+ if (instance && instance->engine && instance->engine->payload_set) {
-+ instance->engine->payload_set(instance, pt, codecs->payloads[i].asterisk_format, codecs->payloads[i].code);
-+ }
-+
-+ break;
-+ }
-+
-+ return (found ? 0 : -2);
-+}
-+
-+int ast_rtp_codecs_payloads_set_rtpmap_type(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload, char *mimetype, char *mimesubtype, enum ast_rtp_options options)
-+{
-+ return ast_rtp_codecs_payloads_set_rtpmap_type_rate(codecs, instance, payload, mimetype, mimesubtype, options, 0);
-+}
-+
-+void ast_rtp_codecs_payloads_unset(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload)
-+{
-+ if (payload < 0 || payload > AST_RTP_MAX_PT) {
-+ return;
-+ }
-+
-+ ast_debug(2, "Unsetting payload %d on %p\n", payload, codecs);
-+
-+ codecs->payloads[payload].asterisk_format = 0;
-+ codecs->payloads[payload].code = 0;
-+
-+ if (instance && instance->engine && instance->engine->payload_set) {
-+ instance->engine->payload_set(instance, payload, 0, 0);
-+ }
-+}
-+
-+struct ast_rtp_payload_type ast_rtp_codecs_payload_lookup(struct ast_rtp_codecs *codecs, int payload)
-+{
-+ struct ast_rtp_payload_type result = { .asterisk_format = 0, };
-+
-+ if (payload < 0 || payload > AST_RTP_MAX_PT) {
-+ return result;
-+ }
-+
-+ result.asterisk_format = codecs->payloads[payload].asterisk_format;
-+ result.code = codecs->payloads[payload].code;
-+
-+ if (!result.code) {
-+ result = static_RTP_PT[payload];
-+ }
-+
-+ return result;
-+}
-+
-+void ast_rtp_codecs_payload_formats(struct ast_rtp_codecs *codecs, int *astformats, int *nonastformats)
-+{
-+ int i;
-+
-+ *astformats = *nonastformats = 0;
-+
-+ for (i = 0; i < AST_RTP_MAX_PT; i++) {
-+ if (codecs->payloads[i].code) {
-+ ast_debug(1, "Incorporating payload %d on %p\n", i, codecs);
-+ }
-+ if (codecs->payloads[i].asterisk_format) {
-+ *astformats |= codecs->payloads[i].code;
-+ } else {
-+ *nonastformats |= codecs->payloads[i].code;
-+ }
-+ }
-+}
-+
-+int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, const int asterisk_format, const int code)
-+{
-+ int i;
-+
-+ for (i = 0; i < AST_RTP_MAX_PT; i++) {
-+ if (codecs->payloads[i].asterisk_format == asterisk_format && codecs->payloads[i].code == code) {
-+ ast_debug(2, "Found code %d at payload %d on %p\n", code, i, codecs);
-+ return i;
-+ }
-+ }
-+
-+ for (i = 0; i < AST_RTP_MAX_PT; i++) {
-+ if (static_RTP_PT[i].asterisk_format == asterisk_format && static_RTP_PT[i].code == code) {
-+ return i;
-+ }
-+ }
-+
-+ return -1;
-+}
-+
-+const char *ast_rtp_lookup_mime_subtype2(const int asterisk_format, const int code, enum ast_rtp_options options)
-+{
-+ int i;
-+
-+ for (i = 0; i < ARRAY_LEN(ast_rtp_mime_types); i++) {
-+ if (ast_rtp_mime_types[i].payload_type.code == code && ast_rtp_mime_types[i].payload_type.asterisk_format == asterisk_format) {
-+ if (asterisk_format && (code == AST_FORMAT_G726_AAL2) && (options & AST_RTP_OPT_G726_NONSTANDARD)) {
-+ return "G726-32";
-+ } else {
-+ return ast_rtp_mime_types[i].subtype;
-+ }
-+ }
-+ }
-+
-+ return "";
-+}
-+
-+unsigned int ast_rtp_lookup_sample_rate2(int asterisk_format, int code)
-+{
-+ unsigned int i;
-+
-+ for (i = 0; i < ARRAY_LEN(ast_rtp_mime_types); ++i) {
-+ if ((ast_rtp_mime_types[i].payload_type.code == code) && (ast_rtp_mime_types[i].payload_type.asterisk_format == asterisk_format)) {
-+ return ast_rtp_mime_types[i].sample_rate;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+char *ast_rtp_lookup_mime_multiple2(struct ast_str *buf, const int capability, const int asterisk_format, enum ast_rtp_options options)
-+{
-+ int format, found = 0;
-+
-+ if (!buf) {
-+ return NULL;
-+ }
-+
-+ ast_str_append(&buf, 0, "0x%x (", capability);
-+
-+ for (format = 1; format < AST_RTP_MAX; format <<= 1) {
-+ if (capability & format) {
-+ const char *name = ast_rtp_lookup_mime_subtype2(asterisk_format, format, options);
-+ ast_str_append(&buf, 0, "%s|", name);
-+ found = 1;
-+ }
-+ }
-+
-+ ast_str_append(&buf, 0, "%s", found ? ")" : "nothing)");
-+
-+ return ast_str_buffer(buf);
-+}
-+
-+void ast_rtp_codecs_packetization_set(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, struct ast_codec_pref *prefs)
-+{
-+ codecs->pref = *prefs;
-+
-+ if (instance && instance->engine->packetization_set) {
-+ instance->engine->packetization_set(instance, &instance->codecs.pref);
-+ }
-+}
-+
-+int ast_rtp_instance_dtmf_begin(struct ast_rtp_instance *instance, char digit)
-+{
-+ return instance->engine->dtmf_begin ? instance->engine->dtmf_begin(instance, digit) : -1;
-+}
-+
-+int ast_rtp_instance_dtmf_end(struct ast_rtp_instance *instance, char digit)
-+{
-+ return instance->engine->dtmf_end ? instance->engine->dtmf_end(instance, digit) : -1;
-+}
-+
-+int ast_rtp_instance_dtmf_mode_set(struct ast_rtp_instance *instance, enum ast_rtp_dtmf_mode dtmf_mode)
-+{
-+ if (!instance->engine->dtmf_mode_set || instance->engine->dtmf_mode_set(instance, dtmf_mode)) {
-+ return -1;
-+ }
-+
-+ instance->dtmf_mode = dtmf_mode;
-+
-+ return 0;
-+}
-+
-+enum ast_rtp_dtmf_mode ast_rtp_instance_dtmf_mode_get(struct ast_rtp_instance *instance)
-+{
-+ return instance->dtmf_mode;
-+}
-+
-+void ast_rtp_instance_new_source(struct ast_rtp_instance *instance)
-+{
-+ if (instance->engine->new_source) {
-+ instance->engine->new_source(instance);
-+ }
-+}
-+
-+int ast_rtp_instance_set_qos(struct ast_rtp_instance *instance, int tos, int cos, const char *desc)
-+{
-+ return instance->engine->qos ? instance->engine->qos(instance, tos, cos, desc) : -1;
-+}
-+
-+void ast_rtp_instance_stop(struct ast_rtp_instance *instance)
-+{
-+ if (instance->engine->stop) {
-+ instance->engine->stop(instance);
-+ }
-+}
-+
-+int ast_rtp_instance_fd(struct ast_rtp_instance *instance, int rtcp)
-+{
-+ return instance->engine->fd ? instance->engine->fd(instance, rtcp) : -1;
-+}
-+
-+struct ast_rtp_glue *ast_rtp_instance_get_glue(const char *type)
-+{
-+ struct ast_rtp_glue *glue = NULL;
-+
-+ AST_RWLIST_RDLOCK(&glues);
-+
-+ AST_RWLIST_TRAVERSE(&glues, glue, entry) {
-+ if (!strcasecmp(glue->type, type)) {
-+ break;
-+ }
-+ }
-+
-+ AST_RWLIST_UNLOCK(&glues);
-+
-+ return glue;
-+}
-+
-+static enum ast_bridge_result local_bridge_loop(struct ast_channel *c0, struct ast_channel *c1, struct ast_rtp_instance *instance0, struct ast_rtp_instance *instance1, int timeoutms, int flags, struct ast_frame **fo, struct ast_channel **rc, void *pvt0, void *pvt1)
-+{
-+ enum ast_bridge_result res = AST_BRIDGE_FAILED;
-+ struct ast_channel *who = NULL, *other = NULL, *cs[3] = { NULL, };
-+ struct ast_frame *fr = NULL;
-+
-+ /* Start locally bridging both instances */
-+ if (instance0->engine->local_bridge && instance0->engine->local_bridge(instance0, instance1)) {
-+ ast_debug(1, "Failed to locally bridge %s to %s, backing out.\n", c0->name, c1->name);
-+ ast_channel_unlock(c0);
-+ ast_channel_unlock(c1);
-+ return AST_BRIDGE_FAILED_NOWARN;
-+ }
-+ if (instance1->engine->local_bridge && instance1->engine->local_bridge(instance1, instance0)) {
-+ ast_debug(1, "Failed to locally bridge %s to %s, backing out.\n", c1->name, c0->name);
-+ if (instance0->engine->local_bridge) {
-+ instance0->engine->local_bridge(instance0, NULL);
-+ }
-+ ast_channel_unlock(c0);
-+ ast_channel_unlock(c1);
-+ return AST_BRIDGE_FAILED_NOWARN;
-+ }
-+
-+ ast_channel_unlock(c0);
-+ ast_channel_unlock(c1);
-+
-+ instance0->bridged = instance1;
-+ instance1->bridged = instance0;
-+
-+ ast_poll_channel_add(c0, c1);
-+
-+ /* Hop into a loop waiting for a frame from either channel */
-+ cs[0] = c0;
-+ cs[1] = c1;
-+ cs[2] = NULL;
-+ for (;;) {
-+ /* If the underlying formats have changed force this bridge to break */
-+ if ((c0->rawreadformat != c1->rawwriteformat) || (c1->rawreadformat != c0->rawwriteformat)) {
-+ ast_debug(1, "rtp-engine-local-bridge: Oooh, formats changed, backing out\n");
-+ res = AST_BRIDGE_FAILED_NOWARN;
-+ break;
-+ }
-+ /* Check if anything changed */
-+ if ((c0->tech_pvt != pvt0) ||
-+ (c1->tech_pvt != pvt1) ||
-+ (c0->masq || c0->masqr || c1->masq || c1->masqr) ||
-+ (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) {
-+ ast_debug(1, "rtp-engine-local-bridge: Oooh, something is weird, backing out\n");
-+ /* If a masquerade needs to happen we have to try to read in a frame so that it actually happens. Without this we risk being called again and going into a loop */
-+ if ((c0->masq || c0->masqr) && (fr = ast_read(c0))) {
-+ ast_frfree(fr);
-+ }
-+ if ((c1->masq || c1->masqr) && (fr = ast_read(c1))) {
-+ ast_frfree(fr);
-+ }
-+ res = AST_BRIDGE_RETRY;
-+ break;
-+ }
-+ /* Wait on a channel to feed us a frame */
-+ if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
-+ if (!timeoutms) {
-+ res = AST_BRIDGE_RETRY;
-+ break;
-+ }
-+ ast_debug(2, "rtp-engine-local-bridge: Ooh, empty read...\n");
-+ if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
-+ break;
-+ }
-+ continue;
-+ }
-+ /* Read in frame from channel */
-+ fr = ast_read(who);
-+ other = (who == c0) ? c1 : c0;
-+ /* Depending on the frame we may need to break out of our bridge */
-+ if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) &&
-+ ((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) |
-+ ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)))) {
-+ /* Record received frame and who */
-+ *fo = fr;
-+ *rc = who;
-+ ast_debug(1, "rtp-engine-local-bridge: Ooh, got a %s\n", fr ? "digit" : "hangup");
-+ res = AST_BRIDGE_COMPLETE;
-+ break;
-+ } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
-+ if ((fr->subclass == AST_CONTROL_HOLD) ||
-+ (fr->subclass == AST_CONTROL_UNHOLD) ||
-+ (fr->subclass == AST_CONTROL_VIDUPDATE) ||
-+ (fr->subclass == AST_CONTROL_T38) ||
-+ (fr->subclass == AST_CONTROL_SRCUPDATE)) {
-+ /* If we are going on hold, then break callback mode and P2P bridging */
-+ if (fr->subclass == AST_CONTROL_HOLD) {
-+ if (instance0->engine->local_bridge) {
-+ instance0->engine->local_bridge(instance0, NULL);
-+ }
-+ if (instance1->engine->local_bridge) {
-+ instance1->engine->local_bridge(instance1, NULL);
-+ }
-+ instance0->bridged = NULL;
-+ instance1->bridged = NULL;
-+ } else if (fr->subclass == AST_CONTROL_UNHOLD) {
-+ if (instance0->engine->local_bridge) {
-+ instance0->engine->local_bridge(instance0, instance1);
-+ }
-+ if (instance1->engine->local_bridge) {
-+ instance1->engine->local_bridge(instance1, instance0);
-+ }
-+ instance0->bridged = instance1;
-+ instance1->bridged = instance0;
-+ }
-+ ast_indicate_data(other, fr->subclass, fr->data.ptr, fr->datalen);
-+ ast_frfree(fr);
-+ } else {
-+ *fo = fr;
-+ *rc = who;
-+ ast_debug(1, "rtp-engine-local-bridge: Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name);
-+ res = AST_BRIDGE_COMPLETE;
-+ break;
-+ }
-+ } else {
-+ if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
-+ (fr->frametype == AST_FRAME_DTMF_END) ||
-+ (fr->frametype == AST_FRAME_VOICE) ||
-+ (fr->frametype == AST_FRAME_VIDEO) ||
-+ (fr->frametype == AST_FRAME_IMAGE) ||
-+ (fr->frametype == AST_FRAME_HTML) ||
-+ (fr->frametype == AST_FRAME_MODEM) ||
-+ (fr->frametype == AST_FRAME_TEXT)) {
-+ ast_write(other, fr);
-+ }
-+
-+ ast_frfree(fr);
-+ }
-+ /* Swap priority */
-+ cs[2] = cs[0];
-+ cs[0] = cs[1];
-+ cs[1] = cs[2];
-+ }
-+
-+ /* Stop locally bridging both instances */
-+ if (instance0->engine->local_bridge) {
-+ instance0->engine->local_bridge(instance0, NULL);
-+ }
-+ if (instance1->engine->local_bridge) {
-+ instance1->engine->local_bridge(instance1, NULL);
-+ }
-+
-+ instance0->bridged = NULL;
-+ instance1->bridged = NULL;
-+
-+ ast_poll_channel_del(c0, c1);
-+
-+ return res;
-+}
-+
-+static enum ast_bridge_result remote_bridge_loop(struct ast_channel *c0, struct ast_channel *c1, struct ast_rtp_instance *instance0, struct ast_rtp_instance *instance1,
-+ struct ast_rtp_instance *vinstance0, struct ast_rtp_instance *vinstance1, struct ast_rtp_instance *tinstance0,
-+ struct ast_rtp_instance *tinstance1, struct ast_rtp_glue *glue0, struct ast_rtp_glue *glue1, int codec0, int codec1, int timeoutms,
-+ int flags, struct ast_frame **fo, struct ast_channel **rc, void *pvt0, void *pvt1)
-+{
-+ enum ast_bridge_result res = AST_BRIDGE_FAILED;
-+ struct ast_channel *who = NULL, *other = NULL, *cs[3] = { NULL, };
-+ int oldcodec0 = codec0, oldcodec1 = codec1;
-+ struct sockaddr_in ac1 = {0,}, vac1 = {0,}, tac1 = {0,}, ac0 = {0,}, vac0 = {0,}, tac0 = {0,};
-+ struct sockaddr_in t1 = {0,}, vt1 = {0,}, tt1 = {0,}, t0 = {0,}, vt0 = {0,}, tt0 = {0,};
-+ struct ast_frame *fr = NULL;
-+
-+ /* Test the first channel */
-+ if (!(glue0->update_peer(c0, instance1, vinstance1, tinstance1, codec1, 0))) {
-+ ast_rtp_instance_get_remote_address(instance1, &ac1);
-+ if (vinstance1) {
-+ ast_rtp_instance_get_remote_address(vinstance1, &vac1);
-+ }
-+ if (tinstance1) {
-+ ast_rtp_instance_get_remote_address(tinstance1, &tac1);
-+ }
-+ } else {
-+ ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name);
-+ }
-+
-+ /* Test the second channel */
-+ if (!(glue1->update_peer(c1, instance0, vinstance0, tinstance0, codec0, 0))) {
-+ ast_rtp_instance_get_remote_address(instance0, &ac0);
-+ if (vinstance0) {
-+ ast_rtp_instance_get_remote_address(instance0, &vac0);
-+ }
-+ if (tinstance0) {
-+ ast_rtp_instance_get_remote_address(instance0, &tac0);
-+ }
-+ } else {
-+ ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c1->name, c0->name);
-+ }
-+
-+ ast_channel_unlock(c0);
-+ ast_channel_unlock(c1);
-+
-+ instance0->bridged = instance1;
-+ instance1->bridged = instance0;
-+
-+ ast_poll_channel_add(c0, c1);
-+
-+ /* Go into a loop handling any stray frames that may come in */
-+ cs[0] = c0;
-+ cs[1] = c1;
-+ cs[2] = NULL;
-+ for (;;) {
-+ /* Check if anything changed */
-+ if ((c0->tech_pvt != pvt0) ||
-+ (c1->tech_pvt != pvt1) ||
-+ (c0->masq || c0->masqr || c1->masq || c1->masqr) ||
-+ (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) {
-+ ast_debug(1, "Oooh, something is weird, backing out\n");
-+ res = AST_BRIDGE_RETRY;
-+ break;
-+ }
-+
-+ /* Check if they have changed their address */
-+ ast_rtp_instance_get_remote_address(instance1, &t1);
-+ if (vinstance1) {
-+ ast_rtp_instance_get_remote_address(vinstance1, &vt1);
-+ }
-+ if (tinstance1) {
-+ ast_rtp_instance_get_remote_address(tinstance1, &tt1);
-+ }
-+ if (glue1->get_codec) {
-+ codec1 = glue1->get_codec(c1);
-+ }
-+
-+ ast_rtp_instance_get_remote_address(instance0, &t0);
-+ if (vinstance0) {
-+ ast_rtp_instance_get_remote_address(vinstance0, &vt0);
-+ }
-+ if (tinstance0) {
-+ ast_rtp_instance_get_remote_address(tinstance0, &tt0);
-+ }
-+ if (glue0->get_codec) {
-+ codec0 = glue0->get_codec(c0);
-+ }
-+
-+ if ((inaddrcmp(&t1, &ac1)) ||
-+ (vinstance1 && inaddrcmp(&vt1, &vac1)) ||
-+ (tinstance1 && inaddrcmp(&tt1, &tac1)) ||
-+ (codec1 != oldcodec1)) {
-+ ast_debug(1, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
-+ c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port), codec1);
-+ ast_debug(1, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n",
-+ c1->name, ast_inet_ntoa(vt1.sin_addr), ntohs(vt1.sin_port), codec1);
-+ ast_debug(1, "Oooh, '%s' changed end taddress to %s:%d (format %d)\n",
-+ c1->name, ast_inet_ntoa(tt1.sin_addr), ntohs(tt1.sin_port), codec1);
-+ ast_debug(1, "Oooh, '%s' was %s:%d/(format %d)\n",
-+ c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1);
-+ ast_debug(1, "Oooh, '%s' was %s:%d/(format %d)\n",
-+ c1->name, ast_inet_ntoa(vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1);
-+ ast_debug(1, "Oooh, '%s' was %s:%d/(format %d)\n",
-+ c1->name, ast_inet_ntoa(tac1.sin_addr), ntohs(tac1.sin_port), oldcodec1);
-+ if (glue0->update_peer(c0, t1.sin_addr.s_addr ? instance1 : NULL, vt1.sin_addr.s_addr ? vinstance1 : NULL, tt1.sin_addr.s_addr ? tinstance1 : NULL, codec1, 0)) {
-+ ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name);
-+ }
-+ memcpy(&ac1, &t1, sizeof(ac1));
-+ memcpy(&vac1, &vt1, sizeof(vac1));
-+ memcpy(&tac1, &tt1, sizeof(tac1));
-+ oldcodec1 = codec1;
-+ }
-+ if ((inaddrcmp(&t0, &ac0)) ||
-+ (vinstance0 && inaddrcmp(&vt0, &vac0)) ||
-+ (tinstance0 && inaddrcmp(&tt0, &tac0))) {
-+ ast_debug(1, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
-+ c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port), codec0);
-+ ast_debug(1, "Oooh, '%s' was %s:%d/(format %d)\n",
-+ c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0);
-+ if (glue1->update_peer(c1, t0.sin_addr.s_addr ? instance0 : NULL, vt0.sin_addr.s_addr ? vinstance0 : NULL, tt0.sin_addr.s_addr ? tinstance0 : NULL, codec0, 0)) {
-+ ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name);
-+ }
-+ memcpy(&ac0, &t0, sizeof(ac0));
-+ memcpy(&vac0, &vt0, sizeof(vac0));
-+ memcpy(&tac0, &tt0, sizeof(tac0));
-+ oldcodec0 = codec0;
-+ }
-+
-+ /* Wait for frame to come in on the channels */
-+ if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
-+ if (!timeoutms) {
-+ res = AST_BRIDGE_RETRY;
-+ break;
-+ }
-+ ast_debug(1, "Ooh, empty read...\n");
-+ if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
-+ break;
-+ }
-+ continue;
-+ }
-+ fr = ast_read(who);
-+ other = (who == c0) ? c1 : c0;
-+ if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) &&
-+ (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) ||
-+ ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) {
-+ /* Break out of bridge */
-+ *fo = fr;
-+ *rc = who;
-+ ast_debug(1, "Oooh, got a %s\n", fr ? "digit" : "hangup");
-+ res = AST_BRIDGE_COMPLETE;
-+ break;
-+ } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
-+ if ((fr->subclass == AST_CONTROL_HOLD) ||
-+ (fr->subclass == AST_CONTROL_UNHOLD) ||
-+ (fr->subclass == AST_CONTROL_VIDUPDATE) ||
-+ (fr->subclass == AST_CONTROL_T38) ||
-+ (fr->subclass == AST_CONTROL_SRCUPDATE)) {
-+ if (fr->subclass == AST_CONTROL_HOLD) {
-+ /* If we someone went on hold we want the other side to reinvite back to us */
-+ if (who == c0) {
-+ glue1->update_peer(c1, NULL, NULL, NULL, 0, 0);
-+ } else {
-+ glue0->update_peer(c0, NULL, NULL, NULL, 0, 0);
-+ }
-+ } else if (fr->subclass == AST_CONTROL_UNHOLD) {
-+ /* If they went off hold they should go back to being direct */
-+ if (who == c0) {
-+ glue1->update_peer(c1, instance0, vinstance0, tinstance0, codec0, 0);
-+ } else {
-+ glue0->update_peer(c0, instance1, vinstance1, tinstance1, codec1, 0);
-+ }
-+ }
-+ /* Update local address information */
-+ ast_rtp_instance_get_remote_address(instance0, &t0);
-+ memcpy(&ac0, &t0, sizeof(ac0));
-+ ast_rtp_instance_get_remote_address(instance1, &t1);
-+ memcpy(&ac1, &t1, sizeof(ac1));
-+ /* Update codec information */
-+ if (glue0->get_codec && c0->tech_pvt) {
-+ oldcodec0 = codec0 = glue0->get_codec(c0);
-+ }
-+ if (glue1->get_codec && c1->tech_pvt) {
-+ oldcodec1 = codec1 = glue1->get_codec(c1);
-+ }
-+ ast_indicate_data(other, fr->subclass, fr->data.ptr, fr->datalen);
-+ ast_frfree(fr);
-+ } else {
-+ *fo = fr;
-+ *rc = who;
-+ ast_debug(1, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name);
-+ return AST_BRIDGE_COMPLETE;
-+ }
-+ } else {
-+ if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
-+ (fr->frametype == AST_FRAME_DTMF_END) ||
-+ (fr->frametype == AST_FRAME_VOICE) ||
-+ (fr->frametype == AST_FRAME_VIDEO) ||
-+ (fr->frametype == AST_FRAME_IMAGE) ||
-+ (fr->frametype == AST_FRAME_HTML) ||
-+ (fr->frametype == AST_FRAME_MODEM) ||
-+ (fr->frametype == AST_FRAME_TEXT)) {
-+ ast_write(other, fr);
-+ }
-+ ast_frfree(fr);
-+ }
-+ /* Swap priority */
-+ cs[2] = cs[0];
-+ cs[0] = cs[1];
-+ cs[1] = cs[2];
-+ }
-+
-+ if (glue0->update_peer(c0, NULL, NULL, NULL, 0, 0)) {
-+ ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
-+ }
-+ if (glue1->update_peer(c1, NULL, NULL, NULL, 0, 0)) {
-+ ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
-+ }
-+
-+ instance0->bridged = NULL;
-+ instance1->bridged = NULL;
-+
-+ ast_poll_channel_del(c0, c1);
-+
-+ return res;
-+}
-+
-+/*!
-+ * \brief Conditionally unref an rtp instance
-+ */
-+static void unref_instance_cond(struct ast_rtp_instance **instance)
-+{
-+ if (*instance) {
-+ ao2_ref(*instance, -1);
-+ *instance = NULL;
-+ }
-+}
-+
-+enum ast_bridge_result ast_rtp_instance_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
-+{
-+ struct ast_rtp_instance *instance0 = NULL, *instance1 = NULL,
-+ *vinstance0 = NULL, *vinstance1 = NULL,
-+ *tinstance0 = NULL, *tinstance1 = NULL;
-+ struct ast_rtp_glue *glue0, *glue1;
-+ enum ast_rtp_glue_result audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID, video_glue0_res = AST_RTP_GLUE_RESULT_FORBID, text_glue0_res = AST_RTP_GLUE_RESULT_FORBID;
-+ enum ast_rtp_glue_result audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID, video_glue1_res = AST_RTP_GLUE_RESULT_FORBID, text_glue1_res = AST_RTP_GLUE_RESULT_FORBID;
-+ enum ast_bridge_result res = AST_BRIDGE_FAILED;
-+ int codec0 = 0, codec1 = 0;
-+ int unlock_chans = 1;
-+
-+ /* Lock both channels so we can look for the glue that binds them together */
-+ ast_channel_lock(c0);
-+ while (ast_channel_trylock(c1)) {
-+ ast_channel_unlock(c0);
-+ usleep(1);
-+ ast_channel_lock(c0);
-+ }
-+
-+ /* Ensure neither channel got hungup during lock avoidance */
-+ if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
-+ ast_log(LOG_WARNING, "Got hangup while attempting to bridge '%s' and '%s'\n", c0->name, c1->name);
-+ goto done;
-+ }
-+
-+ /* Grab glue that binds each channel to something using the RTP engine */
-+ if (!(glue0 = ast_rtp_instance_get_glue(c0->tech->type)) || !(glue1 = ast_rtp_instance_get_glue(c1->tech->type))) {
-+ ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", glue0 ? c1->name : c0->name);
-+ goto done;
-+ }
-+
-+ audio_glue0_res = glue0->get_rtp_info(c0, &instance0);
-+ video_glue0_res = glue0->get_vrtp_info ? glue0->get_vrtp_info(c0, &vinstance0) : AST_RTP_GLUE_RESULT_FORBID;
-+ text_glue0_res = glue0->get_trtp_info ? glue0->get_trtp_info(c0, &tinstance0) : AST_RTP_GLUE_RESULT_FORBID;
-+
-+ audio_glue1_res = glue1->get_rtp_info(c1, &instance1);
-+ video_glue1_res = glue1->get_vrtp_info ? glue1->get_vrtp_info(c1, &vinstance1) : AST_RTP_GLUE_RESULT_FORBID;
-+ text_glue1_res = glue1->get_trtp_info ? glue1->get_trtp_info(c1, &tinstance1) : AST_RTP_GLUE_RESULT_FORBID;
-+
-+ /* If we are carrying video, and both sides are not going to remotely bridge... fail the native bridge */
-+ if (video_glue0_res != AST_RTP_GLUE_RESULT_FORBID && (audio_glue0_res != AST_RTP_GLUE_RESULT_REMOTE || video_glue0_res != AST_RTP_GLUE_RESULT_REMOTE)) {
-+ audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID;
-+ }
-+ if (video_glue1_res != AST_RTP_GLUE_RESULT_FORBID && (audio_glue1_res != AST_RTP_GLUE_RESULT_REMOTE || video_glue1_res != AST_RTP_GLUE_RESULT_REMOTE)) {
-+ audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID;
-+ }
-+
-+ /* If any sort of bridge is forbidden just completely bail out and go back to generic bridging */
-+ if (audio_glue0_res == AST_RTP_GLUE_RESULT_FORBID || audio_glue1_res == AST_RTP_GLUE_RESULT_FORBID) {
-+ res = AST_BRIDGE_FAILED_NOWARN;
-+ goto done;
-+ }
-+
-+ /* If we have gotten to a local bridge make sure that both sides have the same local bridge callback and that they are DTMF compatible */
-+ if ((audio_glue0_res == AST_RTP_GLUE_RESULT_LOCAL || audio_glue1_res == AST_RTP_GLUE_RESULT_LOCAL) && ((instance0->engine->local_bridge != instance1->engine->local_bridge) || (instance0->engine->dtmf_compatible && !instance0->engine->dtmf_compatible(c0, instance0, c1, instance1)))) {
-+ res = AST_BRIDGE_FAILED_NOWARN;
-+ goto done;
-+ }
-+
-+ /* Make sure that codecs match */
-+ codec0 = glue0->get_codec ? glue0->get_codec(c0) : 0;
-+ codec1 = glue1->get_codec ? glue1->get_codec(c1) : 0;
-+ if (codec0 && codec1 && !(codec0 & codec1)) {
-+ ast_debug(1, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1);
-+ res = AST_BRIDGE_FAILED_NOWARN;
-+ goto done;
-+ }
-+
-+ /* Depending on the end result for bridging either do a local bridge or remote bridge */
-+ if (audio_glue0_res == AST_RTP_GLUE_RESULT_LOCAL || audio_glue1_res == AST_RTP_GLUE_RESULT_LOCAL) {
-+ ast_verbose(VERBOSE_PREFIX_3 "Locally bridging %s and %s\n", c0->name, c1->name);
-+ res = local_bridge_loop(c0, c1, instance0, instance1, timeoutms, flags, fo, rc, c0->tech_pvt, c1->tech_pvt);
-+ } else {
-+ ast_verbose(VERBOSE_PREFIX_3 "Remotely bridging %s and %s\n", c0->name, c1->name);
-+ res = remote_bridge_loop(c0, c1, instance0, instance1, vinstance0, vinstance1,
-+ tinstance0, tinstance1, glue0, glue1, codec0, codec1, timeoutms, flags,
-+ fo, rc, c0->tech_pvt, c1->tech_pvt);
-+ }
-+
-+ unlock_chans = 0;
-+
-+done:
-+ if (unlock_chans) {
-+ ast_channel_unlock(c0);
-+ ast_channel_unlock(c1);
-+ }
-+
-+ unref_instance_cond(&instance0);
-+ unref_instance_cond(&instance1);
-+ unref_instance_cond(&vinstance0);
-+ unref_instance_cond(&vinstance1);
-+ unref_instance_cond(&tinstance0);
-+ unref_instance_cond(&tinstance1);
-+
-+ return res;
-+}
-+
-+struct ast_rtp_instance *ast_rtp_instance_get_bridged(struct ast_rtp_instance *instance)
-+{
-+ return instance->bridged;
-+}
-+
-+void ast_rtp_instance_early_bridge_make_compatible(struct ast_channel *c0, struct ast_channel *c1)
-+{
-+ struct ast_rtp_instance *instance0 = NULL, *instance1 = NULL,
-+ *vinstance0 = NULL, *vinstance1 = NULL,
-+ *tinstance0 = NULL, *tinstance1 = NULL;
-+ struct ast_rtp_glue *glue0, *glue1;
-+ enum ast_rtp_glue_result audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID, video_glue0_res = AST_RTP_GLUE_RESULT_FORBID, text_glue0_res = AST_RTP_GLUE_RESULT_FORBID;
-+ enum ast_rtp_glue_result audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID, video_glue1_res = AST_RTP_GLUE_RESULT_FORBID, text_glue1_res = AST_RTP_GLUE_RESULT_FORBID;
-+ int codec0 = 0, codec1 = 0;
-+ int res = 0;
-+
-+ /* Lock both channels so we can look for the glue that binds them together */
-+ ast_channel_lock(c0);
-+ while (ast_channel_trylock(c1)) {
-+ ast_channel_unlock(c0);
-+ usleep(1);
-+ ast_channel_lock(c0);
-+ }
-+
-+ /* Grab glue that binds each channel to something using the RTP engine */
-+ if (!(glue0 = ast_rtp_instance_get_glue(c0->tech->type)) || !(glue1 = ast_rtp_instance_get_glue(c1->tech->type))) {
-+ ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", glue0 ? c1->name : c0->name);
-+ goto done;
-+ }
-+
-+ audio_glue0_res = glue0->get_rtp_info(c0, &instance0);
-+ video_glue0_res = glue0->get_vrtp_info ? glue0->get_vrtp_info(c0, &vinstance0) : AST_RTP_GLUE_RESULT_FORBID;
-+ text_glue0_res = glue0->get_trtp_info ? glue0->get_trtp_info(c0, &tinstance0) : AST_RTP_GLUE_RESULT_FORBID;
-+
-+ audio_glue1_res = glue1->get_rtp_info(c1, &instance1);
-+ video_glue1_res = glue1->get_vrtp_info ? glue1->get_vrtp_info(c1, &vinstance1) : AST_RTP_GLUE_RESULT_FORBID;
-+ text_glue1_res = glue1->get_trtp_info ? glue1->get_trtp_info(c1, &tinstance1) : AST_RTP_GLUE_RESULT_FORBID;
-+
-+ /* If we are carrying video, and both sides are not going to remotely bridge... fail the native bridge */
-+ if (video_glue0_res != AST_RTP_GLUE_RESULT_FORBID && (audio_glue0_res != AST_RTP_GLUE_RESULT_REMOTE || video_glue0_res != AST_RTP_GLUE_RESULT_REMOTE)) {
-+ audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID;
-+ }
-+ if (video_glue1_res != AST_RTP_GLUE_RESULT_FORBID && (audio_glue1_res != AST_RTP_GLUE_RESULT_REMOTE || video_glue1_res != AST_RTP_GLUE_RESULT_REMOTE)) {
-+ audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID;
-+ }
-+ if (audio_glue0_res == AST_RTP_GLUE_RESULT_REMOTE && (video_glue0_res == AST_RTP_GLUE_RESULT_FORBID || video_glue0_res == AST_RTP_GLUE_RESULT_REMOTE) && glue0->get_codec(c0)) {
-+ codec0 = glue0->get_codec(c0);
-+ }
-+ if (audio_glue1_res == AST_RTP_GLUE_RESULT_REMOTE && (video_glue1_res == AST_RTP_GLUE_RESULT_FORBID || video_glue1_res == AST_RTP_GLUE_RESULT_REMOTE) && glue1->get_codec(c1)) {
-+ codec1 = glue1->get_codec(c1);
-+ }
-+
-+ /* If any sort of bridge is forbidden just completely bail out and go back to generic bridging */
-+ if (audio_glue0_res != AST_RTP_GLUE_RESULT_REMOTE || audio_glue1_res != AST_RTP_GLUE_RESULT_REMOTE) {
-+ goto done;
-+ }
-+
-+ /* Make sure we have matching codecs */
-+ if (!(codec0 & codec1)) {
-+ goto done;
-+ }
-+
-+ ast_rtp_codecs_payloads_copy(&instance0->codecs, &instance1->codecs, instance1);
-+
-+ if (vinstance0 && vinstance1) {
-+ ast_rtp_codecs_payloads_copy(&vinstance0->codecs, &vinstance1->codecs, vinstance1);
-+ }
-+ if (tinstance0 && tinstance1) {
-+ ast_rtp_codecs_payloads_copy(&tinstance0->codecs, &tinstance1->codecs, tinstance1);
-+ }
-+
-+ res = 0;
-+
-+done:
-+ ast_channel_unlock(c0);
-+ ast_channel_unlock(c1);
-+
-+ unref_instance_cond(&instance0);
-+ unref_instance_cond(&instance1);
-+ unref_instance_cond(&vinstance0);
-+ unref_instance_cond(&vinstance1);
-+ unref_instance_cond(&tinstance0);
-+ unref_instance_cond(&tinstance1);
-+
-+ if (!res) {
-+ ast_debug(1, "Seeded SDP of '%s' with that of '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
-+ }
-+}
-+
-+int ast_rtp_instance_early_bridge(struct ast_channel *c0, struct ast_channel *c1)
-+{
-+ struct ast_rtp_instance *instance0 = NULL, *instance1 = NULL,
-+ *vinstance0 = NULL, *vinstance1 = NULL,
-+ *tinstance0 = NULL, *tinstance1 = NULL;
-+ struct ast_rtp_glue *glue0, *glue1;
-+ enum ast_rtp_glue_result audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID, video_glue0_res = AST_RTP_GLUE_RESULT_FORBID, text_glue0_res = AST_RTP_GLUE_RESULT_FORBID;
-+ enum ast_rtp_glue_result audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID, video_glue1_res = AST_RTP_GLUE_RESULT_FORBID, text_glue1_res = AST_RTP_GLUE_RESULT_FORBID;
-+ int codec0 = 0, codec1 = 0;
-+ int res = 0;
-+
-+ /* If there is no second channel just immediately bail out, we are of no use in that scenario */
-+ if (!c1) {
-+ return -1;
-+ }
-+
-+ /* Lock both channels so we can look for the glue that binds them together */
-+ ast_channel_lock(c0);
-+ while (ast_channel_trylock(c1)) {
-+ ast_channel_unlock(c0);
-+ usleep(1);
-+ ast_channel_lock(c0);
-+ }
-+
-+ /* Grab glue that binds each channel to something using the RTP engine */
-+ if (!(glue0 = ast_rtp_instance_get_glue(c0->tech->type)) || !(glue1 = ast_rtp_instance_get_glue(c1->tech->type))) {
-+ ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", glue0 ? c1->name : c0->name);
-+ goto done;
-+ }
-+
-+ audio_glue0_res = glue0->get_rtp_info(c0, &instance0);
-+ video_glue0_res = glue0->get_vrtp_info ? glue0->get_vrtp_info(c0, &vinstance0) : AST_RTP_GLUE_RESULT_FORBID;
-+ text_glue0_res = glue0->get_trtp_info ? glue0->get_trtp_info(c0, &tinstance0) : AST_RTP_GLUE_RESULT_FORBID;
-+
-+ audio_glue1_res = glue1->get_rtp_info(c1, &instance1);
-+ video_glue1_res = glue1->get_vrtp_info ? glue1->get_vrtp_info(c1, &vinstance1) : AST_RTP_GLUE_RESULT_FORBID;
-+ text_glue1_res = glue1->get_trtp_info ? glue1->get_trtp_info(c1, &tinstance1) : AST_RTP_GLUE_RESULT_FORBID;
-+
-+ /* If we are carrying video, and both sides are not going to remotely bridge... fail the native bridge */
-+ if (video_glue0_res != AST_RTP_GLUE_RESULT_FORBID && (audio_glue0_res != AST_RTP_GLUE_RESULT_REMOTE || video_glue0_res != AST_RTP_GLUE_RESULT_REMOTE)) {
-+ audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID;
-+ }
-+ if (video_glue1_res != AST_RTP_GLUE_RESULT_FORBID && (audio_glue1_res != AST_RTP_GLUE_RESULT_REMOTE || video_glue1_res != AST_RTP_GLUE_RESULT_REMOTE)) {
-+ audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID;
-+ }
-+ if (audio_glue0_res == AST_RTP_GLUE_RESULT_REMOTE && (video_glue0_res == AST_RTP_GLUE_RESULT_FORBID || video_glue0_res == AST_RTP_GLUE_RESULT_REMOTE) && glue0->get_codec(c0)) {
-+ codec0 = glue0->get_codec(c0);
-+ }
-+ if (audio_glue1_res == AST_RTP_GLUE_RESULT_REMOTE && (video_glue1_res == AST_RTP_GLUE_RESULT_FORBID || video_glue1_res == AST_RTP_GLUE_RESULT_REMOTE) && glue1->get_codec(c1)) {
-+ codec1 = glue1->get_codec(c1);
-+ }
-+
-+ /* If any sort of bridge is forbidden just completely bail out and go back to generic bridging */
-+ if (audio_glue0_res != AST_RTP_GLUE_RESULT_REMOTE || audio_glue1_res != AST_RTP_GLUE_RESULT_REMOTE) {
-+ goto done;
-+ }
-+
-+ /* Make sure we have matching codecs */
-+ if (!(codec0 & codec1)) {
-+ goto done;
-+ }
-+
-+ /* Bridge media early */
-+ if (glue0->update_peer(c0, instance1, vinstance1, tinstance1, codec1, 0)) {
-+ ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
-+ }
-+
-+ res = 0;
-+
-+done:
-+ ast_channel_unlock(c0);
-+ ast_channel_unlock(c1);
-+
-+ unref_instance_cond(&instance0);
-+ unref_instance_cond(&instance1);
-+ unref_instance_cond(&vinstance0);
-+ unref_instance_cond(&vinstance1);
-+ unref_instance_cond(&tinstance0);
-+ unref_instance_cond(&tinstance1);
-+
-+ if (!res) {
-+ ast_debug(1, "Setting early bridge SDP of '%s' with that of '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
-+ }
-+
-+ return res;
-+}
-+
-+int ast_rtp_red_init(struct ast_rtp_instance *instance, int buffer_time, int *payloads, int generations)
-+{
-+ return instance->engine->red_init ? instance->engine->red_init(instance, buffer_time, payloads, generations) : -1;
-+}
-+
-+int ast_rtp_red_buffer(struct ast_rtp_instance *instance, struct ast_frame *frame)
-+{
-+ return instance->engine->red_buffer ? instance->engine->red_buffer(instance, frame) : -1;
-+}
-+
-+int ast_rtp_instance_get_stats(struct ast_rtp_instance *instance, struct ast_rtp_instance_stats *stats, enum ast_rtp_instance_stat stat)
-+{
-+ return instance->engine->get_stat ? instance->engine->get_stat(instance, stats, stat) : -1;
-+}
-+
-+char *ast_rtp_instance_get_quality(struct ast_rtp_instance *instance, enum ast_rtp_instance_stat_field field, char *buf, size_t size)
-+{
-+ struct ast_rtp_instance_stats stats;
-+ enum ast_rtp_instance_stat stat;
-+
-+ /* Determine what statistics we will need to retrieve based on field passed in */
-+ if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY) {
-+ stat = AST_RTP_INSTANCE_STAT_ALL;
-+ } else if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY_JITTER) {
-+ stat = AST_RTP_INSTANCE_STAT_COMBINED_JITTER;
-+ } else if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY_LOSS) {
-+ stat = AST_RTP_INSTANCE_STAT_COMBINED_LOSS;
-+ } else if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY_RTT) {
-+ stat = AST_RTP_INSTANCE_STAT_COMBINED_RTT;
-+ } else {
-+ return NULL;
-+ }
-+
-+ /* Attempt to actually retrieve the statistics we need to generate the quality string */
-+ if (ast_rtp_instance_get_stats(instance, &stats, stat)) {
-+ return NULL;
-+ }
-+
-+ /* Now actually fill the buffer with the good information */
-+ if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY) {
-+ snprintf(buf, size, "ssrc=%i;themssrc=%u;lp=%u;rxjitter=%u;rxcount=%u;txjitter=%u;txcount=%u;rlp=%u;rtt=%u",
-+ stats.local_ssrc, stats.remote_ssrc, stats.rxploss, stats.txjitter, stats.rxcount, stats.rxjitter, stats.txcount, stats.txploss, stats.rtt);
-+ } else if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY_JITTER) {
-+ snprintf(buf, size, "minrxjitter=%f;maxrxjitter=%f;avgrxjitter=%f;stdevrxjitter=%f;reported_minjitter=%f;reported_maxjitter=%f;reported_avgjitter=%f;reported_stdevjitter=%f;",
-+ stats.local_minjitter, stats.local_maxjitter, stats.local_normdevjitter, sqrt(stats.local_stdevjitter), stats.remote_minjitter, stats.remote_maxjitter, stats.remote_normdevjitter, sqrt(stats.remote_stdevjitter));
-+ } else if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY_LOSS) {
-+ snprintf(buf, size, "minrxlost=%f;maxrxlost=%f;avgrxlost=%f;stdevrxlost=%f;reported_minlost=%f;reported_maxlost=%f;reported_avglost=%f;reported_stdevlost=%f;",
-+ stats.local_minrxploss, stats.local_maxrxploss, stats.local_normdevrxploss, sqrt(stats.local_stdevrxploss), stats.remote_minrxploss, stats.remote_maxrxploss, stats.remote_normdevrxploss, sqrt(stats.remote_stdevrxploss));
-+ } else if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY_RTT) {
-+ snprintf(buf, size, "minrtt=%f;maxrtt=%f;avgrtt=%f;stdevrtt=%f;", stats.minrtt, stats.maxrtt, stats.normdevrtt, stats.stdevrtt);
-+ }
-+
-+ return buf;
-+}
-+
-+void ast_rtp_instance_set_stats_vars(struct ast_channel *chan, struct ast_rtp_instance *instance)
-+{
-+ char quality_buf[AST_MAX_USER_FIELD], *quality;
-+ struct ast_channel *bridge = ast_bridged_channel(chan);
-+
-+ if ((quality = ast_rtp_instance_get_quality(instance, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, quality_buf, sizeof(quality_buf)))) {
-+ pbx_builtin_setvar_helper(chan, "RTPAUDIOQOS", quality);
-+ if (bridge) {
-+ pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSBRIDGED", quality);
-+ }
-+ }
-+
-+ if ((quality = ast_rtp_instance_get_quality(instance, AST_RTP_INSTANCE_STAT_FIELD_QUALITY_JITTER, quality_buf, sizeof(quality_buf)))) {
-+ pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSJITTER", quality);
-+ if (bridge) {
-+ pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSJITTERBRIDGED", quality);
-+ }
-+ }
-+
-+ if ((quality = ast_rtp_instance_get_quality(instance, AST_RTP_INSTANCE_STAT_FIELD_QUALITY_LOSS, quality_buf, sizeof(quality_buf)))) {
-+ pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSLOSS", quality);
-+ if (bridge) {
-+ pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSLOSSBRIDGED", quality);
-+ }
-+ }
-+
-+ if ((quality = ast_rtp_instance_get_quality(instance, AST_RTP_INSTANCE_STAT_FIELD_QUALITY_RTT, quality_buf, sizeof(quality_buf)))) {
-+ pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSRTT", quality);
-+ if (bridge) {
-+ pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSRTTBRIDGED", quality);
-+ }
-+ }
-+}
-+
-+int ast_rtp_instance_set_read_format(struct ast_rtp_instance *instance, int format)
-+{
-+ return instance->engine->set_read_format ? instance->engine->set_read_format(instance, format) : -1;
-+}
-+
-+int ast_rtp_instance_set_write_format(struct ast_rtp_instance *instance, int format)
-+{
-+ return instance->engine->set_write_format ? instance->engine->set_write_format(instance, format) : -1;
-+}
-+
-+int ast_rtp_instance_make_compatible(struct ast_channel *chan, struct ast_rtp_instance *instance, struct ast_channel *peer)
-+{
-+ struct ast_rtp_glue *glue;
-+ struct ast_rtp_instance *peer_instance = NULL;
-+ int res = -1;
-+
-+ if (!instance->engine->make_compatible) {
-+ return -1;
-+ }
-+
-+ ast_channel_lock(peer);
-+
-+ if (!(glue = ast_rtp_instance_get_glue(peer->tech->type))) {
-+ ast_channel_unlock(peer);
-+ return -1;
-+ }
-+
-+ glue->get_rtp_info(peer, &peer_instance);
-+
-+ if (!peer_instance || peer_instance->engine != instance->engine) {
-+ ast_channel_unlock(peer);
-+ peer_instance = (ao2_ref(peer_instance, -1), NULL);
-+ return -1;
-+ }
-+
-+ res = instance->engine->make_compatible(chan, instance, peer, peer_instance);
-+
-+ ast_channel_unlock(peer);
-+
-+ peer_instance = (ao2_ref(peer_instance, -1), NULL);
-+
-+ return res;
-+}
-+
-+int ast_rtp_instance_activate(struct ast_rtp_instance *instance)
-+{
-+ return instance->engine->activate ? instance->engine->activate(instance) : 0;
-+}
-+
-+void ast_rtp_instance_stun_request(struct ast_rtp_instance *instance, struct sockaddr_in *suggestion, const char *username)
-+{
-+ if (instance->engine->stun_request) {
-+ instance->engine->stun_request(instance, suggestion, username);
-+ }
-+}
-+
-+void ast_rtp_instance_set_timeout(struct ast_rtp_instance *instance, int timeout)
-+{
-+ instance->timeout = timeout;
-+}
-+
-+void ast_rtp_instance_set_hold_timeout(struct ast_rtp_instance *instance, int timeout)
-+{
-+ instance->holdtimeout = timeout;
-+}
-+
-+int ast_rtp_instance_get_timeout(struct ast_rtp_instance *instance)
-+{
-+ return instance->timeout;
-+}
-+
-+int ast_rtp_instance_get_hold_timeout(struct ast_rtp_instance *instance)
-+{
-+ return instance->holdtimeout;
-+}
-
-Property changes on: main/rtp_engine.c
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + Author Date Id Revision
-
-Index: configs/sip.conf.sample
-===================================================================
---- a/configs/sip.conf.sample (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/configs/sip.conf.sample (.../trunk) (revision 186562)
-@@ -182,6 +182,11 @@
- ;vmexten=voicemail ; dialplan extension to reach mailbox sets the
- ; Message-Account in the MWI notify message
- ; defaults to "asterisk"
-+
-+;preferred_codec_only=yes ; Respond to a SIP invite with the single most preferred codec
-+ ; rather than advertising all joint codec capabilities. This
-+ ; limits the other side's codec choice to exactly what we prefer.
-+
- ;disallow=all ; First disallow all codecs
- ;allow=ulaw ; Allow codecs in order of preference
- ;allow=ilbc ; see doc/rtp-packetization for framing options
-@@ -209,6 +214,14 @@
- ;relaxdtmf=yes ; Relax dtmf handling
- ;trustrpid = no ; If Remote-Party-ID should be trusted
- ;sendrpid = yes ; If Remote-Party-ID should be sent
-+;sendrpid = rpid ; Use the "Remote-Party-ID" header
-+ ; to send the identity of the remote party
-+ ; This is identical to sendrpid=yes
-+;sendrpid = pai ; Use the "P-Asserted-Identity" header
-+ ; to send the identity of the remote party
-+;rpid_header = rpid ; Which header should be used when sending Remote Party ID
-+ ; 'rpid' means to send "Remote-Party-ID"
-+ ; 'pai' means to send "P-Asserted-Identity"
- ;progressinband=never ; If we should generate in-band ringing always
- ; use 'never' to never use in-band signalling, even in cases
- ; where some buggy devices might not render it
-@@ -256,9 +269,11 @@
- ;authfailureevents=no ; generate manager "peerstatus" events when peer can't
- ; authenticate with Asterisk. Peerstatus will be "rejected".
- ;alwaysauthreject = yes ; When an incoming INVITE or REGISTER is to be rejected,
-- ; for any reason, always reject with '401 Unauthorized'
-+ ; for any reason, always reject with an identical response
-+ ; equivalent to valid username and invalid password/hash
- ; instead of letting the requester know whether there was
-- ; a matching user or peer for their request
-+ ; a matching user or peer for their request. This reduces
-+ ; the ability of an attacker to scan for valid SIP usernames.
-
- ;g726nonstandard = yes ; If the peer negotiates G726-32 audio, use AAL2 packing
- ; order instead of RFC3551 packing order (this is required
-@@ -285,6 +300,8 @@
- ;contactpermit=172.16.0.0/255.255.0.0 ; restrict at what IPs your users may
- ; register their phones.
-
-+;engine=asterisk ; RTP engine to use when communicating with the device
-+
- ;
- ; If regcontext is specified, Asterisk will dynamically create and destroy a
- ; NoOp priority 1 extension for a given peer who registers or unregisters with
-Index: configs/voicemail.conf.sample
-===================================================================
---- a/configs/voicemail.conf.sample (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/configs/voicemail.conf.sample (.../trunk) (revision 186562)
-@@ -115,6 +115,10 @@
- ; Change the from, body and/or subject, variables:
- ; VM_NAME, VM_DUR, VM_MSGNUM, VM_MAILBOX, VM_CALLERID, VM_CIDNUM,
- ; VM_CIDNAME, VM_DATE
-+; Additionally, on forwarded messages, you have the variables:
-+; ORIG_VM_CALLERID, ORIG_VM_CIDNUM, ORIG_VM_CIDNAME, ORIG_VM_DATE
-+; You can select between two variables by using dialplan functions, e.g.
-+; ${IF(${ISNULL(${ORIG_VM_DATE})}?${VM_DATE}:${ORIG_VM_DATE})}
- ;
- ; Note: The emailbody config row can only be up to 512 characters due to a
- ; limitation in the Asterisk configuration subsystem.
-@@ -124,6 +128,11 @@
- ; caller", if they are both null.
- ;emailbody=Dear ${VM_NAME}:\n\n\tjust wanted to let you know you were just left a ${VM_DUR} long message (number ${VM_MSGNUM})\nin mailbox ${VM_MAILBOX} from ${VM_CALLERID}, on ${VM_DATE}, so you might\nwant to check it when you get a chance. Thanks!\n\n\t\t\t\t--Asterisk\n
- ;
-+; Note: ${IF()} strips spacing at the beginning and end of its true and false
-+; values, so a newline cannot be placed at either location. The word 'so' is
-+; therefore duplicated, in order for the newline to be interpreted correctly.
-+;emailbody=Dear ${VM_NAME}:\n\n\tjust wanted to let you know you were just ${IF($["${VM_CIDNUM}" = "${ORIG_VM_CIDNUM}"]?left:forwarded)} a ${VM_DUR} long message (number ${VM_MSGNUM})\nin mailbox ${VM_MAILBOX} from ${VM_CALLERID}, on ${VM_DATE},\n${IF($["${VM_CIDNUM}" = "${ORIG_VM_CIDNUM}"]?so:(originally sent by ${ORIG_VM_CALLERID} on ${ORIG_VM_DATE})\nso)} you might want to check it when you get a chance. Thanks!\n\n\t\t\t\t--Asterisk\n
-+;
- ; You can also change the Pager From: string, the pager body and/or subject.
- ; The above defined variables also can be used here
- ;pagerfromstring=The Asterisk PBX
-@@ -240,8 +249,10 @@
- ; exitcontext=fromvm ; Context to go to on user exit such as * or 0
- ; The default is the current context.
- ; review=yes ; Allow sender to review/rerecord their message before saving it [OFF by default
--; operator=yes ; Allow sender to hit 0 before/after/during leaving a voicemail to
-- ; reach an operator [OFF by default]
-+; operator=yes ; Allow sender to hit 0 before/after/during leaving a voicemail to
-+ ; reach an operator. This option REQUIRES an 'o' extension in the
-+ ; same context (or in exitcontext, if set), as that is where the
-+ ; 0 key will send you. [OFF by default]
- ; envelope=no ; Turn on/off envelope playback before message playback. [ON by default]
- ; This does NOT affect option 3,3 from the advanced options menu
- ; delete=yes ; After notification, the voicemail is deleted from the server. [per-mailbox only]
-Index: configs/misdn.conf.sample
-===================================================================
---- a/configs/misdn.conf.sample (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/configs/misdn.conf.sample (.../trunk) (revision 186562)
-@@ -7,13 +7,13 @@
- ; for debugging and general setup, things that are not bound to port groups
- ;
-
--[general]
-+[general]
- ;
- ; Sets the Path to the misdn-init.conf (for nt_ptp mode checking)
- ;
- misdn_init=/etc/misdn-init.conf
-
--; set debugging flag:
-+; set debugging flag:
- ; 0 - No Debug
- ; 1 - mISDN Messages and * - Messages, and * - State changes
- ; 2 - Messages + Message specific Informations (e.g. bearer capability)
-@@ -26,8 +26,8 @@
-
-
-
--; set debugging file and flags for mISDNuser (NT-Stack)
--;
-+; set debugging file and flags for mISDNuser (NT-Stack)
-+;
- ; flags can be or'ed with the following values:
- ;
- ; DBGM_NET 0x00000001
-@@ -57,7 +57,7 @@
- ntdebugfile=/var/log/misdn-nt.log
-
-
--; some pbx systems do cut the L1 for some milliseconds, to avoid
-+; some pbx systems do cut the L1 for some milliseconds, to avoid
- ; dropping running calls, we can set this flag to yes and tell
- ; mISDNuser not to drop the calls on L2_RELEASE
- ntkeepcalls=no
-@@ -76,26 +76,13 @@
- bridging=no
-
-
--;
--; watches the L1s of every port. If one l1 is down it tries to
--; get it up. The timeout is given in seconds. with 0 as value it
--; does not watch the l1 at all
--;
--; default value: 0
--;
--; this option is only read at loading time of chan_misdn,
--; which means you need to unload and load chan_misdn to change the
--; value, an asterisk restart should do the trick
--;
--l1watcher_timeout=0
--
- ; stops dialtone after getting first digit on nt Port
- ;
- ; default value: yes
- ;
- stop_tone_after_first_digit=yes
-
--; whether to append overlapdialed Digits to Extension or not
-+; whether to append overlapdialed Digits to Extension or not
- ;
- ; default value: yes
- ;
-@@ -122,19 +109,6 @@
- ;
- crypt_keys=test,muh
-
--; users sections:
--;
--; name your sections as you which but not "general" !
--; the sections are Groups, you can dial out in extensions.conf
--; with Dial(mISDN/g:extern/101) where extern is a section name,
--; chan_misdn tries every port in this section to find a
--; new free channel
--;
--
--; The default section is not a group section, it just contains config elements
--; which are inherited by group sections.
--;
--
- ;------------------------------ JITTER BUFFER CONFIGURATION --------------------------
- ; jbenable = yes ; Enables the use of a jitterbuffer on the receiving side of a
- ; SIP channel. Defaults to "no". An enabled jitterbuffer will
-@@ -161,6 +135,17 @@
- ; jblog = no ; Enables jitterbuffer frame logging. Defaults to "no".
- ;-----------------------------------------------------------------------------------
-
-+; users sections:
-+;
-+; name your sections as you wish but not "general" or "default" !
-+; the sections are Groups, you can dial out in extensions.conf
-+; with Dial(mISDN/g:extern/101) where extern is a section name,
-+; chan_misdn tries every port in this section to find a
-+; new free channel
-+;
-+; The default section is not a group section, it just contains config elements
-+; which are inherited by group sections.
-+;
- [default]
-
- ; define your default context here
-@@ -182,7 +167,7 @@
-
- ;
- ; Either if we should produce DTMF Tones ourselves
--;
-+;
- senddtmf=yes
-
- ;
-@@ -205,14 +190,26 @@
- ;
- allowed_bearers=all
-
--; Prefixes for national and international, those are put before the
--; oad if an according dialplan is set by the other end.
-+; Prefixes for national and international Type-Of-Number. These are
-+; inserted before any number (caller, dialed, connected, redirecting,
-+; redirection) received from the ISDN link if that number has the
-+; correspondng Type-Of-Number.
-+; See the dialplan options.
- ;
--; default values: nationalprefix : 0
--; internationalprefix : 00
-+; default values:
-+; unknownprefix=
-+; internationalprefix=00
-+; nationalprefix=0
-+; netspecificprefix=
-+; subscriberprefix=
-+; abbreviatedprefix=
- ;
-+;unknownprefix=
-+internationalprefix=00
- nationalprefix=0
--internationalprefix=00
-+;netspecificprefix=
-+;subscriberprefix=
-+;abbreviatedprefix=
-
- ; set rx/tx gains between -8 and 8 to change the RX/TX Gain
- ;
-@@ -222,7 +219,7 @@
- rxgain=0
- txgain=0
-
--; some telcos especially in NL seem to need this set to yes, also in
-+; some telcos especially in NL seem to need this set to yes, also in
- ; switzerland this seems to be important
- ;
- ; default value: no
-@@ -232,7 +229,20 @@
-
-
- ;
--; This option defines, if chan_misdn should check the L1 on a PMP
-+; Monitors L1 of the port. If L1 is down it tries
-+; to bring it up. The polling timeout is given in seconds.
-+; Setting the value to 0 disables monitoring L1 of the port.
-+;
-+; default value: 0
-+;
-+; This option is only read at chan_misdn loading time.
-+; You need to unload and load chan_misdn to change the
-+; value. An asterisk restart will also do the trick.
-+;
-+l1watcher_timeout=0
-+
-+;
-+; This option defines, if chan_misdn should check the L1 on a PMP
- ; before making a group call on it. The L1 may go down for PMP Ports
- ; so we might need this.
- ; But be aware! a broken or plugged off cable might be used for a group call
-@@ -245,19 +255,19 @@
-
-
- ;
--; in PMP this option defines which cause should be sent out to
-+; in PMP this option defines which cause should be sent out to
- ; the 3. caller. chan_misdn does not support callwaiting on TE
--; PMP side. This allows to modify the RELEASE_COMPLETE cause
-+; PMP side. This allows to modify the RELEASE_COMPLETE cause
- ; at least.
- ;
- reject_cause=16
-
-
- ;
--; Send Setup_Acknowledge on incoming calls anyway (instead of PROCEEDING),
--; this requests additional Infos, so we can waitfordigits
-+; Send Setup_Acknowledge on incoming calls anyway (instead of PROCEEDING),
-+; this requests additional Infos, so we can waitfordigits
- ; without much issues. This works only for PTP Ports
--;
-+;
- ; default value: no
- ;
- need_more_infos=no
-@@ -269,40 +279,42 @@
- ;
- nttimeout=no
-
--; set the method to use for channel selection:
--; standard - always choose the first free channel with the lowest number
--; round_robin - use the round robin algorithm to select a channel. use this
--; if you want to balance your load.
-+; Set the method to use for channel selection:
-+; standard - Use the first free channel starting from the lowest number.
-+; standard_dec - Use the first free channel starting from the highest number.
-+; round_robin - Use the round robin algorithm to select a channel. Use this
-+; if you want to balance your load.
- ;
- ; default value: standard
- ;
- method=standard
-
-
--; specify if chan_misdn should collect digits before going into the
-+; specify if chan_misdn should collect digits before going into the
- ; dialplan, you can choose yes=4 Seconds, no, or specify the amount
- ; of seconds you need;
--;
-+;
- overlapdial=yes
-
- ;
--; dialplan means Type Of Number in ISDN Terms (for outgoing calls)
-+; dialplan means Type Of Number in ISDN Terms
-+; There are different types of the dialplan:
- ;
--; there are different types of the dialplan:
-+; dialplan -> for outgoing call's dialed number
-+; localdialplan -> for outgoing call's callerid
-+; (if -1 is set use the value from the asterisk channel)
-+; cpndialplan -> for incoming call's connected party number sent to caller
-+; (if -1 is set use the value from the asterisk channel)
- ;
--; dialplan -> outgoing Number
--; localdialplan -> callerid
--; cpndialplan -> connected party number
-+; dialplan options:
- ;
--; dialplan options:
--;
- ; 0 - unknown
- ; 1 - International
- ; 2 - National
-+; 3 - Network-Specific
- ; 4 - Subscriber
-+; 5 - Abbreviated
- ;
--; This setting is used for outgoing calls
--;
- ; default value: 0
- ;
- dialplan=0
-@@ -312,7 +324,7 @@
-
-
- ;
--; turn this to no if you don't mind correct handling of Progress Indicators
-+; turn this to no if you don't mind correct handling of Progress Indicators
- ;
- early_bconnect=yes
-
-@@ -320,16 +332,16 @@
- ;
- ; turn this on if you like to send Tone Indications to a Incoming
- ; isdn channel on a TE Port. Rarely used, only if the Telco allows
--; you to send indications by yourself, normally the Telco sends the
-+; you to send indications by yourself, normally the Telco sends the
- ; indications to the remote party.
--;
-+;
- ; default: no
- ;
- incoming_early_audio=no
-
- ; uncomment the following to get into s extension at extension conf
- ; there you can use DigitTimeout if you can't or don't want to use
--; isdn overlap dial.
-+; isdn overlap dial.
- ; note: This will jump into the s exten for every exten!
- ;
- ; default value: no
-@@ -337,7 +349,7 @@
- ;always_immediate=no
-
- ;
--; set this to yes if you want to generate your own dialtone
-+; set this to yes if you want to generate your own dialtone
- ; with always_immediate=yes, else chan_misdn generates the dialtone
- ;
- ; default value: no
-@@ -345,9 +357,9 @@
- nodialtone=no
-
-
--; uncomment the following if you want callers which called exactly the
-+; uncomment the following if you want callers which called exactly the
- ; base number (so no extension is set) jump to the s extension.
--; if the user dials something more it jumps to the correct extension
-+; if the user dials something more it jumps to the correct extension
- ; instead
- ;
- ; default value: no
-@@ -368,6 +380,8 @@
- ;callgroup=1
- ;pickupgroup=1
-
-+; Set the outgoing caller id to the value.
-+;callerid="name" <number>
-
- ;
- ; these are the exact isdn screening and presentation indicators
-@@ -375,11 +389,31 @@
- ; from asterisks CALLERPRES function.
- ; s=0, p=0 -> callerid presented
- ; s=1, p=1 -> callerid restricted (the remote end does not see it!)
--;
-+;
- ; default values s=-1, p=-1
- presentation=-1
- screen=-1
-
-+; Put a display ie in the CONNECT message containing the following
-+; information if it is available (nt port only):
-+;
-+; 0 - Do not put the connected line information in the display ie.
-+; 1 - Put the available connected line name in the display ie.
-+; 2 - Put the available connected line number in the display ie.
-+; 3 - Put the available connected line name and number in the display ie.
-+;
-+display_connected=0
-+
-+; Put a display ie in the SETUP message containing the following
-+; information if it is available (nt port only):
-+;
-+; 0 - Do not put the caller information in the display ie.
-+; 1 - Put the available caller name in the display ie.
-+; 2 - Put the available caller number in the display ie.
-+; 3 - Put the available caller name and number in the display ie.
-+;
-+display_setup=0
-+
- ; This enables echo cancellation with the given number of taps.
- ; Be aware: Move this setting only to outgoing portgroups!
- ; A value of zero turns echo cancellation off.
-@@ -390,18 +424,9 @@
- ;
- ;echocancel=no
-
--; Set this to no to disable echotraining. You can enter a number > 10
--; the value is a multiple of 0.125 ms.
- ;
--; default value: no
--; yes = 2000
--; no = 0
-+; chan_misdns jitterbuffer, default 4000
- ;
--echotraining=no
--
--;
--; chan_misdns jitterbuffer, default 4000
--;
- jitterbuffer=4000
-
- ;
-@@ -411,7 +436,7 @@
-
-
- ;
--; change this to yes, if you want to bridge a mISDN data channel to
-+; change this to yes, if you want to bridge a mISDN data channel to
- ; another channel type or to an application.
- ;
- hdlc=no
-@@ -419,8 +444,8 @@
-
- ;
- ; defines the maximum amount of incoming calls per port for
--; this group. Calls which exceed the maximum will be marked with
--; the channel variable MAX_OVERFLOW. It will contain the amount of
-+; this group. Calls which exceed the maximum will be marked with
-+; the channel variable MAX_OVERFLOW. It will contain the amount of
- ; overflowed calls
- ;
- max_incoming=-1
-@@ -432,7 +457,7 @@
- max_outgoing=-1
-
- [intern]
--; define your ports, e.g. 1,2 (depends on mISDN-driver loading order)
-+; define your ports, e.g. 1,2 (depends on mISDN-driver loading order)
- ports=1,2
- ; context where to go to when incoming Call on one of the above ports
- context=Intern
-@@ -444,21 +469,21 @@
- ; configs. For backwards compatibility you can still set ptp here.
- ;
- ports=3
--
-+
- [first_extern]
- ; again port defs
- ports=4
- ; again a context for incoming calls
- context=Extern1
--; msns for te ports, listen on those numbers on the above ports, and
-+; msns for te ports, listen on those numbers on the above ports, and
- ; indicate the incoming calls to asterisk
--; here you can give a comma separated list or simply an '*' for
--; any msn.
-+; here you can give a comma separated list or simply an '*' for
-+; any msn.
- msns=*
-
- ; here an example with given msns
- [second_extern]
- ports=5
- context=Extern2
--callerid=15
-+callerid="Asterisk" <1234>
- msns=102,144,101,104
-Index: configs/features.conf.sample
-===================================================================
---- a/configs/features.conf.sample (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/configs/features.conf.sample (.../trunk) (revision 186562)
-@@ -62,7 +62,7 @@
- ;disconnect => *0 ; Disconnect (default is *) -- Make sure to set the H and/or h option in the Dial() or Queue() app call!
- ;automon => *1 ; One Touch Record a.k.a. Touch Monitor -- Make sure to set the W and/or w option in the Dial() or Queue() app call!
- ;atxfer => *2 ; Attended transfer -- Make sure to set the T and/or t option in the Dial() or Queue() app call!
--;parkcall => #72 ; Park call (one step parking) -- Make sure to set the K and/or K option in the Dial() app call!
-+;parkcall => #72 ; Park call (one step parking) -- Make sure to set the K and/or k option in the Dial() app call!
- ;automixmon => *3 ; One Touch Record a.k.a. Touch MixMonitor -- Make sure to set the X and/or x option in the Dial() or Queue() app call!
-
- [applicationmap]
-Index: makeopts.in
-===================================================================
---- a/makeopts.in (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/makeopts.in (.../trunk) (revision 186562)
-@@ -47,6 +47,8 @@
- PTHREAD_CFLAGS=@PTHREAD_CFLAGS@
- PTHREAD_LIBS=@PTHREAD_LIBS@
-
-+GNU_LD=@GNU_LD@
-+
- prefix = @prefix@
- exec_prefix = @exec_prefix@
-
-Index: res/res_config_sqlite.c
-===================================================================
---- a/res/res_config_sqlite.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/res/res_config_sqlite.c (.../trunk) (revision 186562)
-@@ -1862,7 +1862,7 @@
- return 0;
- }
-
--AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Realtime SQLite configuration",
-+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Realtime SQLite configuration",
- .load = load_module,
- .unload = unload_module,
- );
-Index: res/res_speech.exports
-===================================================================
---- a/res/res_speech.exports (.../tags/1.6.2.0-beta1) (revision 0)
-+++ b/res/res_speech.exports (.../trunk) (revision 186562)
-@@ -0,0 +1,21 @@
-+{
-+ global:
-+ ast_speech_change;
-+ ast_speech_change_results_type;
-+ ast_speech_change_state;
-+ ast_speech_destroy;
-+ ast_speech_dtmf;
-+ ast_speech_grammar_activate;
-+ ast_speech_grammar_deactivate;
-+ ast_speech_grammar_load;
-+ ast_speech_grammar_unload;
-+ ast_speech_new;
-+ ast_speech_register;
-+ ast_speech_results_free;
-+ ast_speech_results_get;
-+ ast_speech_start;
-+ ast_speech_unregister;
-+ ast_speech_write;
-+ local:
-+ *;
-+};
-
-Property changes on: res/res_speech.exports
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + Author Date Id Revision
-
-Index: res/res_config_odbc.c
-===================================================================
---- a/res/res_config_odbc.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/res/res_config_odbc.c (.../trunk) (revision 186562)
-@@ -1067,7 +1067,7 @@
- return 0;
- }
-
--AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Realtime ODBC configuration",
-+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Realtime ODBC configuration",
- .load = load_module,
- .unload = unload_module,
- .reload = reload_module,
-Index: res/res_agi.c
-===================================================================
---- a/res/res_agi.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/res/res_agi.c (.../trunk) (revision 186562)
-@@ -737,6 +737,10 @@
- ast_frfree(f);
- }
- }
-+
-+ if (async_agi.speech) {
-+ ast_speech_destroy(async_agi.speech);
-+ }
- quit:
- /* notify manager users this channel cannot be
- controlled anymore by Async AGI */
-@@ -2929,6 +2933,9 @@
- }
- }
- }
-+ if (agi->speech) {
-+ ast_speech_destroy(agi->speech);
-+ }
- /* Notify process */
- if (send_sighup) {
- if (pid > -1) {
-Index: res/res_adsi.exports
-===================================================================
---- a/res/res_adsi.exports (.../tags/1.6.2.0-beta1) (revision 0)
-+++ b/res/res_adsi.exports (.../trunk) (revision 186562)
-@@ -0,0 +1,33 @@
-+{
-+ global:
-+ ast_adsi_available;
-+ ast_adsi_begin_download;
-+ ast_adsi_channel_restore;
-+ ast_adsi_clear_screen;
-+ ast_adsi_clear_soft_keys;
-+ ast_adsi_connect_session;
-+ ast_adsi_data_mode;
-+ ast_adsi_disconnect_session;
-+ ast_adsi_display;
-+ ast_adsi_download_connect;
-+ ast_adsi_download_disconnect;
-+ ast_adsi_end_download;
-+ ast_adsi_get_cpeid;
-+ ast_adsi_get_cpeinfo;
-+ ast_adsi_input_control;
-+ ast_adsi_input_format;
-+ ast_adsi_load_session;
-+ ast_adsi_load_soft_key;
-+ ast_adsi_print;
-+ ast_adsi_query_cpeid;
-+ ast_adsi_query_cpeinfo;
-+ ast_adsi_read_encoded_dtmf;
-+ ast_adsi_set_keys;
-+ ast_adsi_set_line;
-+ ast_adsi_transmit_message;
-+ ast_adsi_transmit_message_full;
-+ ast_adsi_unload_session;
-+ ast_adsi_voice_mode;
-+ local:
-+ *;
-+};
-
-Property changes on: res/res_adsi.exports
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + Author Date Id Revision
-
-Index: res/res_config_ldap.c
-===================================================================
---- a/res/res_config_ldap.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/res/res_config_ldap.c (.../trunk) (revision 186562)
-@@ -1758,7 +1758,7 @@
- return CLI_SUCCESS;
- }
-
--AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "LDAP realtime interface",
-+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "LDAP realtime interface",
- .load = load_module,
- .unload = unload_module,
- .reload = reload,
-Index: res/res_odbc.c
-===================================================================
---- a/res/res_odbc.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/res/res_odbc.c (.../trunk) (revision 186562)
-@@ -133,7 +133,7 @@
- struct ao2_container *obj_container;
- };
-
--struct ao2_container *class_container;
-+static struct ao2_container *class_container;
-
- static AST_RWLIST_HEAD_STATIC(odbc_tables, odbc_cache_tables);
-
-@@ -415,11 +415,12 @@
-
- /*!
- * \brief Find or create an entry describing the table specified.
-- * \param obj An active ODBC handle on which to query the table
-- * \param table Tablename to describe
-+ * \param database Name of an ODBC class on which to query the table
-+ * \param tablename Tablename to describe
- * \retval A structure describing the table layout, or NULL, if the table is not found or another error occurs.
- * When a structure is returned, the contained columns list will be
- * rdlock'ed, to ensure that it will be retained in memory.
-+ * \since 1.6.1
- */
- struct odbc_cache_tables *ast_odbc_find_table(const char *database, const char *tablename)
- {
-Index: res/res_snmp.c
-===================================================================
---- a/res/res_snmp.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/res/res_snmp.c (.../trunk) (revision 186562)
-@@ -115,7 +115,7 @@
- return ((thread != AST_PTHREADT_NULL) ? pthread_join(thread, NULL) : 0);
- }
-
--AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "SNMP [Sub]Agent for Asterisk",
-+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "SNMP [Sub]Agent for Asterisk",
- .load = load_module,
- .unload = unload_module,
- );
-Index: res/ais/evt.c
-===================================================================
---- a/res/ais/evt.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/res/ais/evt.c (.../trunk) (revision 186562)
-@@ -47,6 +47,7 @@
- #include "asterisk/event.h"
- #include "asterisk/config.h"
- #include "asterisk/linkedlists.h"
-+#include "asterisk/devicestate.h"
-
- #ifndef AST_MODULE
- /* XXX HACK */
-@@ -111,34 +112,7 @@
-
- static void queue_event(struct ast_event *ast_event)
- {
-- enum ast_event_type type;
--
-- /*!
-- * \todo This hack macks me sad. I need to come up with a better way to
-- * figure out whether an event should be cached or not, and what
-- * parameters to cache on.
-- *
-- * As long as the types of events that are supported is limited,
-- * this isn't *terrible*, I guess. Perhaps we should just define
-- * caching rules in the core, and make them configurable, and not
-- * have it be the job of the event publishers.
-- */
--
-- type = ast_event_get_type(ast_event);
--
-- if (type == AST_EVENT_MWI) {
-- ast_event_queue_and_cache(ast_event,
-- AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR,
-- AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR,
-- AST_EVENT_IE_END);
-- } else if (type == AST_EVENT_DEVICE_STATE_CHANGE) {
-- ast_event_queue_and_cache(ast_event,
-- AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR,
-- AST_EVENT_IE_EID, AST_EVENT_IE_PLTYPE_RAW, sizeof(struct ast_eid),
-- AST_EVENT_IE_END);
-- } else {
-- ast_event_queue(ast_event);
-- }
-+ ast_event_queue_and_cache(ast_event);
- }
-
- void evt_event_deliver_cb(SaEvtSubscriptionIdT sub_id,
-@@ -167,7 +141,7 @@
- return;
- }
-
-- if (!ast_eid_cmp(&g_eid, ast_event_get_ie_raw(event, AST_EVENT_IE_EID))) {
-+ if (!ast_eid_cmp(&ast_eid_default, ast_event_get_ie_raw(event, AST_EVENT_IE_EID))) {
- /* Don't feed events back in that originated locally. */
- return;
- }
-@@ -209,7 +183,7 @@
-
- ast_log(LOG_DEBUG, "Got an event to forward\n");
-
-- if (ast_eid_cmp(&g_eid, ast_event_get_ie_raw(ast_event, AST_EVENT_IE_EID))) {
-+ if (ast_eid_cmp(&ast_eid_default, ast_event_get_ie_raw(ast_event, AST_EVENT_IE_EID))) {
- /* If the event didn't originate from this server, don't send it back out. */
- ast_log(LOG_DEBUG, "Returning here\n");
- return;
-@@ -341,9 +315,14 @@
- return;
- }
-
-- if (!(publish_event = ast_calloc(1, sizeof(*publish_event))))
-+ if (type == AST_EVENT_DEVICE_STATE_CHANGE && ast_enable_distributed_devstate()) {
- return;
--
-+ }
-+
-+ if (!(publish_event = ast_calloc(1, sizeof(*publish_event)))) {
-+ return;
-+ }
-+
- publish_event->type = type;
- ast_log(LOG_DEBUG, "Subscribing to event type %d\n", type);
- publish_event->sub = ast_event_subscribe(type, ast_event_cb, event_channel,
-@@ -399,9 +378,14 @@
- return;
- }
-
-- if (!(subscribe_event = ast_calloc(1, sizeof(*subscribe_event))))
-+ if (type == AST_EVENT_DEVICE_STATE_CHANGE && ast_enable_distributed_devstate()) {
- return;
--
-+ }
-+
-+ if (!(subscribe_event = ast_calloc(1, sizeof(*subscribe_event)))) {
-+ return;
-+ }
-+
- subscribe_event->type = type;
- subscribe_event->id = ast_atomic_fetchadd_int(&unique_id, +1);
-
-Index: res/res_agi.exports
-===================================================================
---- a/res/res_agi.exports (.../tags/1.6.2.0-beta1) (revision 0)
-+++ b/res/res_agi.exports (.../trunk) (revision 186562)
-@@ -0,0 +1,7 @@
-+{
-+ global:
-+ ast_agi_register;
-+ ast_agi_unregister;
-+ local:
-+ *;
-+};
-
-Property changes on: res/res_agi.exports
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + Author Date Id Revision
-
-Index: res/res_monitor.c
-===================================================================
---- a/res/res_monitor.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/res/res_monitor.c (.../trunk) (revision 186562)
-@@ -587,11 +587,7 @@
-
- if (ast_strlen_zero(fname)) {
- /* No filename base specified, default to channel name as per CLI */
-- if (!(fname = ast_strdup(c->name))) {
-- astman_send_error(s, m, "Could not start monitoring channel");
-- ast_channel_unlock(c);
-- return 0;
-- }
-+ fname = ast_strdupa(c->name);
- /* Channels have the format technology/channel_name - have to replace that / */
- if ((d = strchr(fname, '/')))
- *d = '-';
-Index: res/res_odbc.exports
-===================================================================
---- a/res/res_odbc.exports (.../tags/1.6.2.0-beta1) (revision 0)
-+++ b/res/res_odbc.exports (.../trunk) (revision 186562)
-@@ -0,0 +1,20 @@
-+{
-+ global:
-+ ast_odbc_ast_str_SQLGetData;
-+ ast_odbc_backslash_is_escape;
-+ ast_odbc_clear_cache;
-+ ast_odbc_direct_execute;
-+ ast_odbc_find_column;
-+ ast_odbc_find_table;
-+ ast_odbc_prepare_and_execute;
-+ ast_odbc_release_obj;
-+ ast_odbc_request_obj;
-+ _ast_odbc_request_obj;
-+ ast_odbc_request_obj2;
-+ _ast_odbc_request_obj2;
-+ ast_odbc_retrieve_transaction_obj;
-+ ast_odbc_sanity_check;
-+ ast_odbc_smart_execute;
-+ local:
-+ *;
-+};
-
-Property changes on: res/res_odbc.exports
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + Author Date Id Revision
-
-Index: res/res_features.exports
-===================================================================
---- a/res/res_features.exports (.../tags/1.6.2.0-beta1) (revision 0)
-+++ b/res/res_features.exports (.../trunk) (revision 186562)
-@@ -0,0 +1,13 @@
-+{
-+ global:
-+ ast_bridge_call;
-+ ast_masq_park_call;
-+ ast_park_call;
-+ ast_parking_ext;
-+ ast_pickup_call;
-+ ast_pickup_ext;
-+ ast_register_feature;
-+ ast_unregister_feature;
-+ local:
-+ *;
-+};
-
-Property changes on: res/res_features.exports
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + Author Date Id Revision
-
-Index: res/res_curl.c
-===================================================================
---- a/res/res_curl.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/res/res_curl.c (.../trunk) (revision 186562)
-@@ -71,5 +71,3 @@
- }
-
- AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "cURL Resource Module");
--
--
-Index: res/res_ael_share.exports
-===================================================================
---- a/res/res_ael_share.exports (.../tags/1.6.2.0-beta1) (revision 0)
-+++ b/res/res_ael_share.exports (.../trunk) (revision 186562)
-@@ -0,0 +1,4 @@
-+{
-+ global:
-+ *;
-+};
-
-Property changes on: res/res_ael_share.exports
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + Author Date Id Revision
-
-Index: res/res_jabber.exports
-===================================================================
---- a/res/res_jabber.exports (.../tags/1.6.2.0-beta1) (revision 0)
-+++ b/res/res_jabber.exports (.../trunk) (revision 186562)
-@@ -0,0 +1,14 @@
-+{
-+ global:
-+ ast_aji_create_chat;
-+ ast_aji_disconnect;
-+ ast_aji_get_client;
-+ ast_aji_get_clients;
-+ ast_aji_increment_mid;
-+ ast_aji_invite_chat;
-+ ast_aji_join_chat;
-+ ast_aji_send;
-+ ast_aji_send_chat;
-+ local:
-+ *;
-+};
-
-Property changes on: res/res_jabber.exports
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + Author Date Id Revision
-
-Index: res/res_monitor.exports
-===================================================================
---- a/res/res_monitor.exports (.../tags/1.6.2.0-beta1) (revision 0)
-+++ b/res/res_monitor.exports (.../trunk) (revision 186562)
-@@ -0,0 +1,11 @@
-+{
-+ global:
-+ ast_monitor_change_fname;
-+ ast_monitor_pause;
-+ ast_monitor_setjoinfiles;
-+ ast_monitor_start;
-+ ast_monitor_stop;
-+ ast_monitor_unpause;
-+ local:
-+ *;
-+};
-
-Property changes on: res/res_monitor.exports
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + Author Date Id Revision
-
-Index: res/res_rtp_asterisk.c
-===================================================================
---- a/res/res_rtp_asterisk.c (.../tags/1.6.2.0-beta1) (revision 0)
-+++ b/res/res_rtp_asterisk.c (.../trunk) (revision 186562)
-@@ -0,0 +1,2579 @@
-+/*
-+ * Asterisk -- An open source telephony toolkit.
-+ *
-+ * Copyright (C) 1999 - 2008, Digium, Inc.
-+ *
-+ * Mark Spencer <markster@digium.com>
-+ *
-+ * See http://www.asterisk.org for more information about
-+ * the Asterisk project. Please do not directly contact
-+ * any of the maintainers of this project for assistance;
-+ * the project provides a web site, mailing lists and IRC
-+ * channels for your use.
-+ *
-+ * 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.
-+ */
-+
-+/*!
-+ * \file
-+ *
-+ * \brief Supports RTP and RTCP with Symmetric RTP support for NAT traversal.
-+ *
-+ * \author Mark Spencer <markster@digium.com>
-+ *
-+ * \note RTP is defined in RFC 3550.
-+ */
-+
-+#include "asterisk.h"
-+
-+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-+
-+#include <sys/time.h>
-+#include <signal.h>
-+#include <fcntl.h>
-+#include <math.h>
-+
-+#include "asterisk/stun.h"
-+#include "asterisk/pbx.h"
-+#include "asterisk/frame.h"
-+#include "asterisk/channel.h"
-+#include "asterisk/acl.h"
-+#include "asterisk/config.h"
-+#include "asterisk/lock.h"
-+#include "asterisk/utils.h"
-+#include "asterisk/netsock.h"
-+#include "asterisk/cli.h"
-+#include "asterisk/manager.h"
-+#include "asterisk/unaligned.h"
-+#include "asterisk/module.h"
-+#include "asterisk/rtp_engine.h"
-+
-+#define MAX_TIMESTAMP_SKEW 640
-+
-+#define RTP_SEQ_MOD (1<<16) /*!< A sequence number can't be more than 16 bits */
-+#define RTCP_DEFAULT_INTERVALMS 5000 /*!< Default milli-seconds between RTCP reports we send */
-+#define RTCP_MIN_INTERVALMS 500 /*!< Min milli-seconds between RTCP reports we send */
-+#define RTCP_MAX_INTERVALMS 60000 /*!< Max milli-seconds between RTCP reports we send */
-+
-+#define DEFAULT_RTP_START 5000 /*!< Default port number to start allocating RTP ports from */
-+#define DEFAULT_RTP_END 31000 /*!< Default maximum port number to end allocating RTP ports at */
-+
-+#define MINIMUM_RTP_PORT 1024 /*!< Minimum port number to accept */
-+#define MAXIMUM_RTP_PORT 65535 /*!< Maximum port number to accept */
-+
-+#define RTCP_PT_FUR 192
-+#define RTCP_PT_SR 200
-+#define RTCP_PT_RR 201
-+#define RTCP_PT_SDES 202
-+#define RTCP_PT_BYE 203
-+#define RTCP_PT_APP 204
-+
-+#define RTP_MTU 1200
-+
-+#define DEFAULT_DTMF_TIMEOUT 3000 /*!< samples */
-+
-+#define ZFONE_PROFILE_ID 0x505a
-+
-+static int dtmftimeout = DEFAULT_DTMF_TIMEOUT;
-+
-+static int rtpstart = DEFAULT_RTP_START; /*!< First port for RTP sessions (set in rtp.conf) */
-+static int rtpend = DEFAULT_RTP_END; /*!< Last port for RTP sessions (set in rtp.conf) */
-+static int rtpdebug; /*!< Are we debugging? */
-+static int rtcpdebug; /*!< Are we debugging RTCP? */
-+static int rtcpstats; /*!< Are we debugging RTCP? */
-+static int rtcpinterval = RTCP_DEFAULT_INTERVALMS; /*!< Time between rtcp reports in millisecs */
-+static struct sockaddr_in rtpdebugaddr; /*!< Debug packets to/from this host */
-+static struct sockaddr_in rtcpdebugaddr; /*!< Debug RTCP packets to/from this host */
-+#ifdef SO_NO_CHECK
-+static int nochecksums;
-+#endif
-+static int strictrtp;
-+
-+enum strict_rtp_state {
-+ STRICT_RTP_OPEN = 0, /*! No RTP packets should be dropped, all sources accepted */
-+ STRICT_RTP_LEARN, /*! Accept next packet as source */
-+ STRICT_RTP_CLOSED, /*! Drop all RTP packets not coming from source that was learned */
-+};
-+
-+#define FLAG_3389_WARNING (1 << 0)
-+#define FLAG_NAT_ACTIVE (3 << 1)
-+#define FLAG_NAT_INACTIVE (0 << 1)
-+#define FLAG_NAT_INACTIVE_NOWARN (1 << 1)
-+#define FLAG_NEED_MARKER_BIT (1 << 3)
-+#define FLAG_DTMF_COMPENSATE (1 << 4)
-+
-+/*! \brief RTP session description */
-+struct ast_rtp {
-+ int s;
-+ struct ast_frame f;
-+ unsigned char rawdata[8192 + AST_FRIENDLY_OFFSET];
-+ unsigned int ssrc; /*!< Synchronization source, RFC 3550, page 10. */
-+ unsigned int themssrc; /*!< Their SSRC */
-+ unsigned int rxssrc;
-+ unsigned int lastts;
-+ unsigned int lastrxts;
-+ unsigned int lastividtimestamp;
-+ unsigned int lastovidtimestamp;
-+ unsigned int lastitexttimestamp;
-+ unsigned int lastotexttimestamp;
-+ unsigned int lasteventseqn;
-+ int lastrxseqno; /*!< Last received sequence number */
-+ unsigned short seedrxseqno; /*!< What sequence number did they start with?*/
-+ unsigned int seedrxts; /*!< What RTP timestamp did they start with? */
-+ unsigned int rxcount; /*!< How many packets have we received? */
-+ unsigned int rxoctetcount; /*!< How many octets have we received? should be rxcount *160*/
-+ unsigned int txcount; /*!< How many packets have we sent? */
-+ unsigned int txoctetcount; /*!< How many octets have we sent? (txcount*160)*/
-+ unsigned int cycles; /*!< Shifted count of sequence number cycles */
-+ double rxjitter; /*!< Interarrival jitter at the moment */
-+ double rxtransit; /*!< Relative transit time for previous packet */
-+ int lasttxformat;
-+ int lastrxformat;
-+
-+ int rtptimeout; /*!< RTP timeout time (negative or zero means disabled, negative value means temporarily disabled) */
-+ int rtpholdtimeout; /*!< RTP timeout when on hold (negative or zero means disabled, negative value means temporarily disabled). */
-+ int rtpkeepalive; /*!< Send RTP comfort noice packets for keepalive */
-+
-+ /* DTMF Reception Variables */
-+ char resp;
-+ unsigned int lastevent;
-+ int dtmfcount;
-+ unsigned int dtmfsamples;
-+ /* DTMF Transmission Variables */
-+ unsigned int lastdigitts;
-+ char sending_digit; /*!< boolean - are we sending digits */
-+ char send_digit; /*!< digit we are sending */
-+ int send_payload;
-+ int send_duration;
-+ unsigned int flags;
-+ struct timeval rxcore;
-+ struct timeval txcore;
-+ double drxcore; /*!< The double representation of the first received packet */
-+ struct timeval lastrx; /*!< timeval when we last received a packet */
-+ struct timeval dtmfmute;
-+ struct ast_smoother *smoother;
-+ int *ioid;
-+ unsigned short seqno; /*!< Sequence number, RFC 3550, page 13. */
-+ unsigned short rxseqno;
-+ struct sched_context *sched;
-+ struct io_context *io;
-+ void *data;
-+ struct ast_rtcp *rtcp;
-+ struct ast_rtp *bridged; /*!< Who we are Packet bridged to */
-+
-+ enum strict_rtp_state strict_rtp_state; /*!< Current state that strict RTP protection is in */
-+ struct sockaddr_in strict_rtp_address; /*!< Remote address information for strict RTP purposes */
-+
-+ struct rtp_red *red;
-+};
-+
-+/*!
-+ * \brief Structure defining an RTCP session.
-+ *
-+ * The concept "RTCP session" is not defined in RFC 3550, but since
-+ * this structure is analogous to ast_rtp, which tracks a RTP session,
-+ * it is logical to think of this as a RTCP session.
-+ *
-+ * RTCP packet is defined on page 9 of RFC 3550.
-+ *
-+ */
-+struct ast_rtcp {
-+ int rtcp_info;
-+ int s; /*!< Socket */
-+ struct sockaddr_in us; /*!< Socket representation of the local endpoint. */
-+ struct sockaddr_in them; /*!< Socket representation of the remote endpoint. */
-+ unsigned int soc; /*!< What they told us */
-+ unsigned int spc; /*!< What they told us */
-+ unsigned int themrxlsr; /*!< The middle 32 bits of the NTP timestamp in the last received SR*/
-+ struct timeval rxlsr; /*!< Time when we got their last SR */
-+ struct timeval txlsr; /*!< Time when we sent or last SR*/
-+ unsigned int expected_prior; /*!< no. packets in previous interval */
-+ unsigned int received_prior; /*!< no. packets received in previous interval */
-+ int schedid; /*!< Schedid returned from ast_sched_add() to schedule RTCP-transmissions*/
-+ unsigned int rr_count; /*!< number of RRs we've sent, not including report blocks in SR's */
-+ unsigned int sr_count; /*!< number of SRs we've sent */
-+ unsigned int lastsrtxcount; /*!< Transmit packet count when last SR sent */
-+ double accumulated_transit; /*!< accumulated a-dlsr-lsr */
-+ double rtt; /*!< Last reported rtt */
-+ unsigned int reported_jitter; /*!< The contents of their last jitter entry in the RR */
-+ unsigned int reported_lost; /*!< Reported lost packets in their RR */
-+
-+ double reported_maxjitter;
-+ double reported_minjitter;
-+ double reported_normdev_jitter;
-+ double reported_stdev_jitter;
-+ unsigned int reported_jitter_count;
-+
-+ double reported_maxlost;
-+ double reported_minlost;
-+ double reported_normdev_lost;
-+ double reported_stdev_lost;
-+
-+ double rxlost;
-+ double maxrxlost;
-+ double minrxlost;
-+ double normdev_rxlost;
-+ double stdev_rxlost;
-+ unsigned int rxlost_count;
-+
-+ double maxrxjitter;
-+ double minrxjitter;
-+ double normdev_rxjitter;
-+ double stdev_rxjitter;
-+ unsigned int rxjitter_count;
-+ double maxrtt;
-+ double minrtt;
-+ double normdevrtt;
-+ double stdevrtt;
-+ unsigned int rtt_count;
-+};
-+
-+struct rtp_red {
-+ struct ast_frame t140; /*!< Primary data */
-+ struct ast_frame t140red; /*!< Redundant t140*/
-+ unsigned char pt[AST_RED_MAX_GENERATION]; /*!< Payload types for redundancy data */
-+ unsigned char ts[AST_RED_MAX_GENERATION]; /*!< Time stamps */
-+ unsigned char len[AST_RED_MAX_GENERATION]; /*!< length of each generation */
-+ int num_gen; /*!< Number of generations */
-+ int schedid; /*!< Timer id */
-+ int ti; /*!< How long to buffer data before send */
-+ unsigned char t140red_data[64000];
-+ unsigned char buf_data[64000]; /*!< buffered primary data */
-+ int hdrlen;
-+ long int prev_ts;
-+};
-+
-+/* Forward Declarations */
-+static int ast_rtp_new(struct ast_rtp_instance *instance, struct sched_context *sched, struct sockaddr_in *sin, void *data);
-+static int ast_rtp_destroy(struct ast_rtp_instance *instance);
-+static int ast_rtp_dtmf_begin(struct ast_rtp_instance *instance, char digit);
-+static int ast_rtp_dtmf_end(struct ast_rtp_instance *instance, char digit);
-+static void ast_rtp_new_source(struct ast_rtp_instance *instance);
-+static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *frame);
-+static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtcp);
-+static void ast_rtp_prop_set(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value);
-+static int ast_rtp_fd(struct ast_rtp_instance *instance, int rtcp);
-+static void ast_rtp_remote_address_set(struct ast_rtp_instance *instance, struct sockaddr_in *sin);
-+static int rtp_red_init(struct ast_rtp_instance *instance, int buffer_time, int *payloads, int generations);
-+static int rtp_red_buffer(struct ast_rtp_instance *instance, struct ast_frame *frame);
-+static int ast_rtp_local_bridge(struct ast_rtp_instance *instance0, struct ast_rtp_instance *instance1);
-+static int ast_rtp_get_stat(struct ast_rtp_instance *instance, struct ast_rtp_instance_stats *stats, enum ast_rtp_instance_stat stat);
-+static int ast_rtp_dtmf_compatible(struct ast_channel *chan0, struct ast_rtp_instance *instance0, struct ast_channel *chan1, struct ast_rtp_instance *instance1);
-+static void ast_rtp_stun_request(struct ast_rtp_instance *instance, struct sockaddr_in *suggestion, const char *username);
-+static void ast_rtp_stop(struct ast_rtp_instance *instance);
-+
-+/* RTP Engine Declaration */
-+static struct ast_rtp_engine asterisk_rtp_engine = {
-+ .name = "asterisk",
-+ .new = ast_rtp_new,
-+ .destroy = ast_rtp_destroy,
-+ .dtmf_begin = ast_rtp_dtmf_begin,
-+ .dtmf_end = ast_rtp_dtmf_end,
-+ .new_source = ast_rtp_new_source,
-+ .write = ast_rtp_write,
-+ .read = ast_rtp_read,
-+ .prop_set = ast_rtp_prop_set,
-+ .fd = ast_rtp_fd,
-+ .remote_address_set = ast_rtp_remote_address_set,
-+ .red_init = rtp_red_init,
-+ .red_buffer = rtp_red_buffer,
-+ .local_bridge = ast_rtp_local_bridge,
-+ .get_stat = ast_rtp_get_stat,
-+ .dtmf_compatible = ast_rtp_dtmf_compatible,
-+ .stun_request = ast_rtp_stun_request,
-+ .stop = ast_rtp_stop,
-+};
-+
-+static inline int rtp_debug_test_addr(struct sockaddr_in *addr)
-+{
-+ if (!rtpdebug) {
-+ return 0;
-+ }
-+
-+ if (rtpdebugaddr.sin_addr.s_addr) {
-+ if (((ntohs(rtpdebugaddr.sin_port) != 0)
-+ && (rtpdebugaddr.sin_port != addr->sin_port))
-+ || (rtpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
-+ return 0;
-+ }
-+
-+ return 1;
-+}
-+
-+static inline int rtcp_debug_test_addr(struct sockaddr_in *addr)
-+{
-+ if (!rtcpdebug) {
-+ return 0;
-+ }
-+
-+ if (rtcpdebugaddr.sin_addr.s_addr) {
-+ if (((ntohs(rtcpdebugaddr.sin_port) != 0)
-+ && (rtcpdebugaddr.sin_port != addr->sin_port))
-+ || (rtcpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
-+ return 0;
-+ }
-+
-+ return 1;
-+}
-+
-+static unsigned int ast_rtcp_calc_interval(struct ast_rtp *rtp)
-+{
-+ unsigned int interval;
-+ /*! \todo XXX Do a more reasonable calculation on this one
-+ * Look in RFC 3550 Section A.7 for an example*/
-+ interval = rtcpinterval;
-+ return interval;
-+}
-+
-+/*! \brief Calculate normal deviation */
-+static double normdev_compute(double normdev, double sample, unsigned int sample_count)
-+{
-+ normdev = normdev * sample_count + sample;
-+ sample_count++;
-+
-+ return normdev / sample_count;
-+}
-+
-+static double stddev_compute(double stddev, double sample, double normdev, double normdev_curent, unsigned int sample_count)
-+{
-+/*
-+ for the formula check http://www.cs.umd.edu/~austinjp/constSD.pdf
-+ return sqrt( (sample_count*pow(stddev,2) + sample_count*pow((sample-normdev)/(sample_count+1),2) + pow(sample-normdev_curent,2)) / (sample_count+1));
-+ we can compute the sigma^2 and that way we would have to do the sqrt only 1 time at the end and would save another pow 2 compute
-+ optimized formula
-+*/
-+#define SQUARE(x) ((x) * (x))
-+
-+ stddev = sample_count * stddev;
-+ sample_count++;
-+
-+ return stddev +
-+ ( sample_count * SQUARE( (sample - normdev) / sample_count ) ) +
-+ ( SQUARE(sample - normdev_curent) / sample_count );
-+
-+#undef SQUARE
-+}
-+
-+static int create_new_socket(const char *type)
-+{
-+ int sock = socket(AF_INET, SOCK_DGRAM, 0);
-+
-+ if (sock < 0) {
-+ if (!type) {
-+ type = "RTP/RTCP";
-+ }
-+ ast_log(LOG_WARNING, "Unable to allocate %s socket: %s\n", type, strerror(errno));
-+ } else {
-+ long flags = fcntl(sock, F_GETFL);
-+ fcntl(sock, F_SETFL, flags | O_NONBLOCK);
-+#ifdef SO_NO_CHECK
-+ if (nochecksums) {
-+ setsockopt(sock, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
-+ }
-+#endif
-+ }
-+
-+ return sock;
-+}
-+
-+static int ast_rtp_new(struct ast_rtp_instance *instance, struct sched_context *sched, struct sockaddr_in *sin, void *data)
-+{
-+ struct ast_rtp *rtp = NULL;
-+ int x, startplace;
-+
-+ /* Create a new RTP structure to hold all of our data */
-+ if (!(rtp = ast_calloc(1, sizeof(*rtp)))) {
-+ return -1;
-+ }
-+
-+ /* Set default parameters on the newly created RTP structure */
-+ rtp->ssrc = ast_random();
-+ rtp->seqno = ast_random() & 0xffff;
-+ rtp->strict_rtp_state = (strictrtp ? STRICT_RTP_LEARN : STRICT_RTP_OPEN);
-+
-+ /* Create a new socket for us to listen on and use */
-+ if ((rtp->s = create_new_socket("RTP")) < 0) {
-+ ast_debug(1, "Failed to create a new socket for RTP instance '%p'\n", instance);
-+ ast_free(rtp);
-+ return -1;
-+ }
-+
-+ /* Now actually find a free RTP port to use */
-+ x = (rtpend == rtpstart) ? rtpstart : (ast_random() % (rtpend - rtpstart)) + rtpstart;
-+ x = x & ~1;
-+ startplace = x;
-+
-+ for (;;) {
-+ struct sockaddr_in local_address = { 0, };
-+
-+ local_address.sin_port = htons(x);
-+ /* Try to bind, this will tell us whether the port is available or not */
-+ if (!bind(rtp->s, (struct sockaddr*)&local_address, sizeof(local_address))) {
-+ ast_debug(1, "Allocated port %d for RTP instance '%p'\n", x, instance);
-+ ast_rtp_instance_set_local_address(instance, &local_address);
-+ break;
-+ }
-+
-+ x += 2;
-+ if (x > rtpend) {
-+ x = (rtpstart + 1) & ~1;
-+ }
-+
-+ /* See if we ran out of ports or if the bind actually failed because of something other than the address being in use */
-+ if (x == startplace || errno != EADDRINUSE) {
-+ ast_log(LOG_ERROR, "Oh dear... we couldn't allocate a port for RTP instance '%p'\n", instance);
-+ return -1;
-+ }
-+ }
-+
-+ /* Record any information we may need */
-+ rtp->sched = sched;
-+
-+ /* Associate the RTP structure with the RTP instance and be done */
-+ ast_rtp_instance_set_data(instance, rtp);
-+
-+ return 0;
-+}
-+
-+static int ast_rtp_destroy(struct ast_rtp_instance *instance)
-+{
-+ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
-+
-+ /* Destroy the smoother that was smoothing out audio if present */
-+ if (rtp->smoother) {
-+ ast_smoother_free(rtp->smoother);
-+ }
-+
-+ /* Close our own socket so we no longer get packets */
-+ if (rtp->s > -1) {
-+ close(rtp->s);
-+ }
-+
-+ /* Destroy RTCP if it was being used */
-+ if (rtp->rtcp) {
-+ AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
-+ close(rtp->rtcp->s);
-+ ast_free(rtp->rtcp);
-+ }
-+
-+ /* Destroy RED if it was being used */
-+ if (rtp->red) {
-+ AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
-+ ast_free(rtp->red);
-+ }
-+
-+ /* Finally destroy ourselves */
-+ ast_free(rtp);
-+
-+ return 0;
-+}
-+
-+static int ast_rtp_dtmf_begin(struct ast_rtp_instance *instance, char digit)
-+{
-+ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
-+ struct sockaddr_in remote_address;
-+ int hdrlen = 12, res = 0, i = 0, payload = 101;
-+ char data[256];
-+ unsigned int *rtpheader = (unsigned int*)data;
-+
-+ ast_rtp_instance_get_remote_address(instance, &remote_address);
-+
-+ /* If we have no remote address information bail out now */
-+ if (!remote_address.sin_addr.s_addr || !remote_address.sin_port) {
-+ return -1;
-+ }
-+
-+ /* Convert given digit into what we want to transmit */
-+ if ((digit <= '9') && (digit >= '0')) {
-+ digit -= '0';
-+ } else if (digit == '*') {
-+ digit = 10;
-+ } else if (digit == '#') {
-+ digit = 11;
-+ } else if ((digit >= 'A') && (digit <= 'D')) {
-+ digit = digit - 'A' + 12;
-+ } else if ((digit >= 'a') && (digit <= 'd')) {
-+ digit = digit - 'a' + 12;
-+ } else {
-+ ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
-+ return -1;
-+ }
-+
-+ /* Grab the payload that they expect the RFC2833 packet to be received in */
-+ payload = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 0, AST_RTP_DTMF);
-+
-+ rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
-+ rtp->send_duration = 160;
-+ rtp->lastdigitts = rtp->lastts + rtp->send_duration;
-+
-+ /* Create the actual packet that we will be sending */
-+ rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
-+ rtpheader[1] = htonl(rtp->lastdigitts);
-+ rtpheader[2] = htonl(rtp->ssrc);
-+
-+ /* Actually send the packet */
-+ for (i = 0; i < 2; i++) {
-+ rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
-+ res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &remote_address, sizeof(remote_address));
-+ if (res < 0) {
-+ ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n",
-+ ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port), strerror(errno));
-+ }
-+ if (rtp_debug_test_addr(&remote_address)) {
-+ ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
-+ ast_inet_ntoa(remote_address.sin_addr),
-+ ntohs(remote_address.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
-+ }
-+ rtp->seqno++;
-+ rtp->send_duration += 160;
-+ rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
-+ }
-+
-+ /* Record that we are in the process of sending a digit and information needed to continue doing so */
-+ rtp->sending_digit = 1;
-+ rtp->send_digit = digit;
-+ rtp->send_payload = payload;
-+
-+ return 0;
-+}
-+
-+static int ast_rtp_dtmf_continuation(struct ast_rtp_instance *instance)
-+{
-+ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
-+ struct sockaddr_in remote_address;
-+ int hdrlen = 12, res = 0;
-+ char data[256];
-+ unsigned int *rtpheader = (unsigned int*)data;
-+
-+ ast_rtp_instance_get_remote_address(instance, &remote_address);
-+
-+ /* Make sure we know where the other side is so we can send them the packet */
-+ if (!remote_address.sin_addr.s_addr || !remote_address.sin_port) {
-+ return -1;
-+ }
-+
-+ /* Actually create the packet we will be sending */
-+ rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno));
-+ rtpheader[1] = htonl(rtp->lastdigitts);
-+ rtpheader[2] = htonl(rtp->ssrc);
-+ rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration));
-+ rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
-+
-+ /* Boom, send it on out */
-+ res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &remote_address, sizeof(remote_address));
-+ if (res < 0) {
-+ ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
-+ ast_inet_ntoa(remote_address.sin_addr),
-+ ntohs(remote_address.sin_port), strerror(errno));
-+ }
-+
-+ if (rtp_debug_test_addr(&remote_address)) {
-+ ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
-+ ast_inet_ntoa(remote_address.sin_addr),
-+ ntohs(remote_address.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
-+ }
-+
-+ /* And now we increment some values for the next time we swing by */
-+ rtp->seqno++;
-+ rtp->send_duration += 160;
-+
-+ return 0;
-+}
-+
-+static int ast_rtp_dtmf_end(struct ast_rtp_instance *instance, char digit)
-+{
-+ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
-+ struct sockaddr_in remote_address;
-+ int hdrlen = 12, res = 0, i = 0;
-+ char data[256];
-+ unsigned int *rtpheader = (unsigned int*)data;
-+
-+ ast_rtp_instance_get_remote_address(instance, &remote_address);
-+
-+ /* Make sure we know where the remote side is so we can send them the packet we construct */
-+ if (!remote_address.sin_addr.s_addr || !remote_address.sin_port) {
-+ return -1;
-+ }
-+
-+ /* Convert the given digit to the one we are going to send */
-+ if ((digit <= '9') && (digit >= '0')) {
-+ digit -= '0';
-+ } else if (digit == '*') {
-+ digit = 10;
-+ } else if (digit == '#') {
-+ digit = 11;
-+ } else if ((digit >= 'A') && (digit <= 'D')) {
-+ digit = digit - 'A' + 12;
-+ } else if ((digit >= 'a') && (digit <= 'd')) {
-+ digit = digit - 'a' + 12;
-+ } else {
-+ ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
-+ return -1;
-+ }
-+
-+ rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
-+
-+ /* Construct the packet we are going to send */
-+ rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno));
-+ rtpheader[1] = htonl(rtp->lastdigitts);
-+ rtpheader[2] = htonl(rtp->ssrc);
-+ rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
-+ rtpheader[3] |= htonl((1 << 23));
-+ rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
-+
-+ /* Send it 3 times, that's the magical number */
-+ for (i = 0; i < 3; i++) {
-+ res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &remote_address, sizeof(remote_address));
-+ if (res < 0) {
-+ ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
-+ ast_inet_ntoa(remote_address.sin_addr),
-+ ntohs(remote_address.sin_port), strerror(errno));
-+ }
-+ if (rtp_debug_test_addr(&remote_address)) {
-+ ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
-+ ast_inet_ntoa(remote_address.sin_addr),
-+ ntohs(remote_address.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
-+ }
-+ }
-+
-+ /* Oh and we can't forget to turn off the stuff that says we are sending DTMF */
-+ rtp->lastts += rtp->send_duration;
-+ rtp->sending_digit = 0;
-+ rtp->send_digit = 0;
-+
-+ return 0;
-+}
-+
-+static void ast_rtp_new_source(struct ast_rtp_instance *instance)
-+{
-+ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
-+
-+ /* We simply set this bit so that the next packet sent will have the marker bit turned on */
-+ ast_set_flag(rtp, FLAG_NEED_MARKER_BIT);
-+
-+ return;
-+}
-+
-+static unsigned int calc_txstamp(struct ast_rtp *rtp, struct timeval *delivery)
-+{
-+ struct timeval t;
-+ long ms;
-+
-+ if (ast_tvzero(rtp->txcore)) {
-+ rtp->txcore = ast_tvnow();
-+ rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
-+ }
-+
-+ t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
-+ if ((ms = ast_tvdiff_ms(t, rtp->txcore)) < 0) {
-+ ms = 0;
-+ }
-+ rtp->txcore = t;
-+
-+ return (unsigned int) ms;
-+}
-+
-+static void timeval2ntp(struct timeval tv, unsigned int *msw, unsigned int *lsw)
-+{
-+ unsigned int sec, usec, frac;
-+ sec = tv.tv_sec + 2208988800u; /* Sec between 1900 and 1970 */
-+ usec = tv.tv_usec;
-+ frac = (usec << 12) + (usec << 8) - ((usec * 3650) >> 6);
-+ *msw = sec;
-+ *lsw = frac;
-+}
-+
-+/*! \brief Send RTCP recipient's report */
-+static int ast_rtcp_write_rr(const void *data)
-+{
-+ struct ast_rtp *rtp = (struct ast_rtp *)data;
-+ int res;
-+ int len = 32;
-+ unsigned int lost;
-+ unsigned int extended;
-+ unsigned int expected;
-+ unsigned int expected_interval;
-+ unsigned int received_interval;
-+ int lost_interval;
-+ struct timeval now;
-+ unsigned int *rtcpheader;
-+ char bdata[1024];
-+ struct timeval dlsr;
-+ int fraction;
-+
-+ double rxlost_current;
-+
-+ if (!rtp || !rtp->rtcp || (&rtp->rtcp->them.sin_addr == 0))
-+ return 0;
-+
-+ if (!rtp->rtcp->them.sin_addr.s_addr) {
-+ ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted\n");
-+ AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
-+ return 0;
-+ }
-+
-+ extended = rtp->cycles + rtp->lastrxseqno;
-+ expected = extended - rtp->seedrxseqno + 1;
-+ lost = expected - rtp->rxcount;
-+ expected_interval = expected - rtp->rtcp->expected_prior;
-+ rtp->rtcp->expected_prior = expected;
-+ received_interval = rtp->rxcount - rtp->rtcp->received_prior;
-+ rtp->rtcp->received_prior = rtp->rxcount;
-+ lost_interval = expected_interval - received_interval;
-+
-+ if (lost_interval <= 0)
-+ rtp->rtcp->rxlost = 0;
-+ else rtp->rtcp->rxlost = rtp->rtcp->rxlost;
-+ if (rtp->rtcp->rxlost_count == 0)
-+ rtp->rtcp->minrxlost = rtp->rtcp->rxlost;
-+ if (lost_interval < rtp->rtcp->minrxlost)
-+ rtp->rtcp->minrxlost = rtp->rtcp->rxlost;
-+ if (lost_interval > rtp->rtcp->maxrxlost)
-+ rtp->rtcp->maxrxlost = rtp->rtcp->rxlost;
-+
-+ rxlost_current = normdev_compute(rtp->rtcp->normdev_rxlost, rtp->rtcp->rxlost, rtp->rtcp->rxlost_count);
-+ rtp->rtcp->stdev_rxlost = stddev_compute(rtp->rtcp->stdev_rxlost, rtp->rtcp->rxlost, rtp->rtcp->normdev_rxlost, rxlost_current, rtp->rtcp->rxlost_count);
-+ rtp->rtcp->normdev_rxlost = rxlost_current;
-+ rtp->rtcp->rxlost_count++;
-+
-+ if (expected_interval == 0 || lost_interval <= 0)
-+ fraction = 0;
-+ else
-+ fraction = (lost_interval << 8) / expected_interval;
-+ gettimeofday(&now, NULL);
-+ timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
-+ rtcpheader = (unsigned int *)bdata;
-+ rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_RR << 16) | ((len/4)-1));
-+ rtcpheader[1] = htonl(rtp->ssrc);
-+ rtcpheader[2] = htonl(rtp->themssrc);
-+ rtcpheader[3] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff));
-+ rtcpheader[4] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff)));
-+ rtcpheader[5] = htonl((unsigned int)(rtp->rxjitter * 65536.));
-+ rtcpheader[6] = htonl(rtp->rtcp->themrxlsr);
-+ rtcpheader[7] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
-+
-+ /*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos
-+ it can change mid call, and SDES can't) */
-+ rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
-+ rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */
-+ rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */
-+ len += 12;
-+
-+ res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
-+
-+ if (res < 0) {
-+ ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno));
-+ /* Remove the scheduler */
-+ AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
-+ return 0;
-+ }
-+
-+ rtp->rtcp->rr_count++;
-+ if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
-+ ast_verbose("\n* Sending RTCP RR to %s:%d\n"
-+ " Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n"
-+ " IA jitter: %.4f\n"
-+ " Their last SR: %u\n"
-+ " DLSR: %4.4f (sec)\n\n",
-+ ast_inet_ntoa(rtp->rtcp->them.sin_addr),
-+ ntohs(rtp->rtcp->them.sin_port),
-+ rtp->ssrc, rtp->themssrc, fraction, lost,
-+ rtp->rxjitter,
-+ rtp->rtcp->themrxlsr,
-+ (double)(ntohl(rtcpheader[7])/65536.0));
-+ }
-+
-+ return res;
-+}
-+
-+/*! \brief Send RTCP sender's report */
-+static int ast_rtcp_write_sr(const void *data)
-+{
-+ struct ast_rtp *rtp = (struct ast_rtp *)data;
-+ int res;
-+ int len = 0;
-+ struct timeval now;
-+ unsigned int now_lsw;
-+ unsigned int now_msw;
-+ unsigned int *rtcpheader;
-+ unsigned int lost;
-+ unsigned int extended;
-+ unsigned int expected;
-+ unsigned int expected_interval;
-+ unsigned int received_interval;
-+ int lost_interval;
-+ int fraction;
-+ struct timeval dlsr;
-+ char bdata[512];
-+
-+ /* Commented condition is always not NULL if rtp->rtcp is not NULL */
-+ if (!rtp || !rtp->rtcp/* || (&rtp->rtcp->them.sin_addr == 0)*/)
-+ return 0;
-+
-+ if (!rtp->rtcp->them.sin_addr.s_addr) { /* This'll stop rtcp for this rtp session */
-+ ast_verbose("RTCP SR transmission error, rtcp halted\n");
-+ AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
-+ return 0;
-+ }
-+
-+ gettimeofday(&now, NULL);
-+ timeval2ntp(now, &now_msw, &now_lsw); /* fill thses ones in from utils.c*/
-+ rtcpheader = (unsigned int *)bdata;
-+ rtcpheader[1] = htonl(rtp->ssrc); /* Our SSRC */
-+ rtcpheader[2] = htonl(now_msw); /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970*/
-+ rtcpheader[3] = htonl(now_lsw); /* now, LSW */
-+ rtcpheader[4] = htonl(rtp->lastts); /* FIXME shouldn't be that, it should be now */
-+ rtcpheader[5] = htonl(rtp->txcount); /* No. packets sent */
-+ rtcpheader[6] = htonl(rtp->txoctetcount); /* No. bytes sent */
-+ len += 28;
-+
-+ extended = rtp->cycles + rtp->lastrxseqno;
-+ expected = extended - rtp->seedrxseqno + 1;
-+ if (rtp->rxcount > expected)
-+ expected += rtp->rxcount - expected;
-+ lost = expected - rtp->rxcount;
-+ expected_interval = expected - rtp->rtcp->expected_prior;
-+ rtp->rtcp->expected_prior = expected;
-+ received_interval = rtp->rxcount - rtp->rtcp->received_prior;
-+ rtp->rtcp->received_prior = rtp->rxcount;
-+ lost_interval = expected_interval - received_interval;
-+ if (expected_interval == 0 || lost_interval <= 0)
-+ fraction = 0;
-+ else
-+ fraction = (lost_interval << 8) / expected_interval;
-+ timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
-+ rtcpheader[7] = htonl(rtp->themssrc);
-+ rtcpheader[8] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff));
-+ rtcpheader[9] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff)));
-+ rtcpheader[10] = htonl((unsigned int)(rtp->rxjitter * 65536.));
-+ rtcpheader[11] = htonl(rtp->rtcp->themrxlsr);
-+ rtcpheader[12] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
-+ len += 24;
-+
-+ rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1));
-+
-+ /* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */
-+ /* it can change mid call, and SDES can't) */
-+ rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
-+ rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */
-+ rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */
-+ len += 12;
-+
-+ res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
-+ if (res < 0) {
-+ ast_log(LOG_ERROR, "RTCP SR transmission error to %s:%d, rtcp halted %s\n",ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port), strerror(errno));
-+ AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
-+ return 0;
-+ }
-+
-+ /* FIXME Don't need to get a new one */
-+ gettimeofday(&rtp->rtcp->txlsr, NULL);
-+ rtp->rtcp->sr_count++;
-+
-+ rtp->rtcp->lastsrtxcount = rtp->txcount;
-+
-+ if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
-+ ast_verbose("* Sent RTCP SR to %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
-+ ast_verbose(" Our SSRC: %u\n", rtp->ssrc);
-+ ast_verbose(" Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096);
-+ ast_verbose(" Sent(RTP): %u\n", rtp->lastts);
-+ ast_verbose(" Sent packets: %u\n", rtp->txcount);
-+ ast_verbose(" Sent octets: %u\n", rtp->txoctetcount);
-+ ast_verbose(" Report block:\n");
-+ ast_verbose(" Fraction lost: %u\n", fraction);
-+ ast_verbose(" Cumulative loss: %u\n", lost);
-+ ast_verbose(" IA jitter: %.4f\n", rtp->rxjitter);
-+ ast_verbose(" Their last SR: %u\n", rtp->rtcp->themrxlsr);
-+ ast_verbose(" DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0));
-+ }
-+ manager_event(EVENT_FLAG_REPORTING, "RTCPSent", "To %s:%d\r\n"
-+ "OurSSRC: %u\r\n"
-+ "SentNTP: %u.%010u\r\n"
-+ "SentRTP: %u\r\n"
-+ "SentPackets: %u\r\n"
-+ "SentOctets: %u\r\n"
-+ "ReportBlock:\r\n"
-+ "FractionLost: %u\r\n"
-+ "CumulativeLoss: %u\r\n"
-+ "IAJitter: %.4f\r\n"
-+ "TheirLastSR: %u\r\n"
-+ "DLSR: %4.4f (sec)\r\n",
-+ ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port),
-+ rtp->ssrc,
-+ (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096,
-+ rtp->lastts,
-+ rtp->txcount,
-+ rtp->txoctetcount,
-+ fraction,
-+ lost,
-+ rtp->rxjitter,
-+ rtp->rtcp->themrxlsr,
-+ (double)(ntohl(rtcpheader[12])/65536.0));
-+ return res;
-+}
-+
-+/*! \brief Write and RTCP packet to the far end
-+ * \note Decide if we are going to send an SR (with Reception Block) or RR
-+ * RR is sent if we have not sent any rtp packets in the previous interval */
-+static int ast_rtcp_write(const void *data)
-+{
-+ struct ast_rtp *rtp = (struct ast_rtp *)data;
-+ int res;
-+
-+ if (!rtp || !rtp->rtcp)
-+ return 0;
-+
-+ if (rtp->txcount > rtp->rtcp->lastsrtxcount)
-+ res = ast_rtcp_write_sr(data);
-+ else
-+ res = ast_rtcp_write_rr(data);
-+
-+ return res;
-+}
-+
-+static int ast_rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame *frame, int codec)
-+{
-+ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
-+ int pred, mark = 0;
-+ unsigned int ms = calc_txstamp(rtp, &frame->delivery);
-+ struct sockaddr_in remote_address;
-+
-+ if (rtp->sending_digit) {
-+ return 0;
-+ }
-+
-+ if (frame->frametype == AST_FRAME_VOICE) {
-+ pred = rtp->lastts + frame->samples;
-+
-+ /* Re-calculate last TS */
-+ rtp->lastts = rtp->lastts + ms * 8;
-+ if (ast_tvzero(frame->delivery)) {
-+ /* If this isn't an absolute delivery time, Check if it is close to our prediction,
-+ and if so, go with our prediction */
-+ if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW) {
-+ rtp->lastts = pred;
-+ } else {
-+ ast_debug(3, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms);
-+ mark = 1;
-+ }
-+ }
-+ } else if (frame->frametype == AST_FRAME_VIDEO) {
-+ mark = frame->subclass & 0x1;
-+ pred = rtp->lastovidtimestamp + frame->samples;
-+ /* Re-calculate last TS */
-+ rtp->lastts = rtp->lastts + ms * 90;
-+ /* If it's close to our prediction, go for it */
-+ if (ast_tvzero(frame->delivery)) {
-+ if (abs(rtp->lastts - pred) < 7200) {
-+ rtp->lastts = pred;
-+ rtp->lastovidtimestamp += frame->samples;
-+ } else {
-+ ast_debug(3, "Difference is %d, ms is %d (%d), pred/ts/samples %d/%d/%d\n", abs(rtp->lastts - pred), ms, ms * 90, rtp->lastts, pred, frame->samples);
-+ rtp->lastovidtimestamp = rtp->lastts;
-+ }
-+ }
-+ } else {
-+ pred = rtp->lastotexttimestamp + frame->samples;
-+ /* Re-calculate last TS */
-+ rtp->lastts = rtp->lastts + ms * 90;
-+ /* If it's close to our prediction, go for it */
-+ if (ast_tvzero(frame->delivery)) {
-+ if (abs(rtp->lastts - pred) < 7200) {
-+ rtp->lastts = pred;
-+ rtp->lastotexttimestamp += frame->samples;
-+ } else {
-+ ast_debug(3, "Difference is %d, ms is %d (%d), pred/ts/samples %d/%d/%d\n", abs(rtp->lastts - pred), ms, ms * 90, rtp->lastts, pred, frame->samples);
-+ rtp->lastotexttimestamp = rtp->lastts;
-+ }
-+ }
-+ }
-+
-+ /* If we have been explicitly told to set the marker bit then do so */
-+ if (ast_test_flag(rtp, FLAG_NEED_MARKER_BIT)) {
-+ mark = 1;
-+ ast_clear_flag(rtp, FLAG_NEED_MARKER_BIT);
-+ }
-+
-+ /* If the timestamp for non-digt packets has moved beyond the timestamp for digits, update the digit timestamp */
-+ if (rtp->lastts > rtp->lastdigitts) {
-+ rtp->lastdigitts = rtp->lastts;
-+ }
-+
-+ if (ast_test_flag(frame, AST_FRFLAG_HAS_TIMING_INFO)) {
-+ rtp->lastts = frame->ts * 8;
-+ }
-+
-+ ast_rtp_instance_get_remote_address(instance, &remote_address);
-+
-+ /* If we know the remote address construct a packet and send it out */
-+ if (remote_address.sin_port && remote_address.sin_addr.s_addr) {
-+ int hdrlen = 12, res;
-+ unsigned char *rtpheader = (unsigned char *)(frame->data.ptr - hdrlen);
-+
-+ put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23)));
-+ put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts));
-+ put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc));
-+
-+ if ((res = sendto(rtp->s, (void *)rtpheader, frame->datalen + hdrlen, 0, (struct sockaddr *)&remote_address, sizeof(remote_address))) < 0) {
-+ if (!ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT) || (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT) && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
-+ ast_debug(1, "RTP Transmission error of packet %d to %s:%d: %s\n", rtp->seqno, ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port), strerror(errno));
-+ } else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) {
-+ /* Only give this error message once if we are not RTP debugging */
-+ if (option_debug || rtpdebug)
-+ ast_debug(0, "RTP NAT: Can't write RTP to private address %s:%d, waiting for other end to send audio...\n", ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port));
-+ ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN);
-+ }
-+ } else {
-+ rtp->txcount++;
-+ rtp->txoctetcount += (res - hdrlen);
-+
-+ if (rtp->rtcp && rtp->rtcp->schedid < 1) {
-+ ast_debug(1, "Starting RTCP transmission on RTP instance '%p'\n", instance);
-+ rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
-+ }
-+ }
-+
-+ if (rtp_debug_test_addr(&remote_address)) {
-+ ast_verbose("Sent RTP packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
-+ ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port), codec, rtp->seqno, rtp->lastts, res - hdrlen);
-+ }
-+ }
-+
-+ rtp->seqno++;
-+
-+ return 0;
-+}
-+
-+static struct ast_frame *red_t140_to_red(struct rtp_red *red) {
-+ unsigned char *data = red->t140red.data.ptr;
-+ int len = 0;
-+ int i;
-+
-+ /* replace most aged generation */
-+ if (red->len[0]) {
-+ for (i = 1; i < red->num_gen+1; i++)
-+ len += red->len[i];
-+
-+ memmove(&data[red->hdrlen], &data[red->hdrlen+red->len[0]], len);
-+ }
-+
-+ /* Store length of each generation and primary data length*/
-+ for (i = 0; i < red->num_gen; i++)
-+ red->len[i] = red->len[i+1];
-+ red->len[i] = red->t140.datalen;
-+
-+ /* write each generation length in red header */
-+ len = red->hdrlen;
-+ for (i = 0; i < red->num_gen; i++)
-+ len += data[i*4+3] = red->len[i];
-+
-+ /* add primary data to buffer */
-+ memcpy(&data[len], red->t140.data.ptr, red->t140.datalen);
-+ red->t140red.datalen = len + red->t140.datalen;
-+
-+ /* no primary data and no generations to send */
-+ if (len == red->hdrlen && !red->t140.datalen)
-+ return NULL;
-+
-+ /* reset t.140 buffer */
-+ red->t140.datalen = 0;
-+
-+ return &red->t140red;
-+}
-+
-+static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
-+{
-+ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
-+ struct sockaddr_in remote_address;
-+ int codec, subclass;
-+
-+ ast_rtp_instance_get_remote_address(instance, &remote_address);
-+
-+ /* If we don't actually know the remote address don't even bother doing anything */
-+ if (!remote_address.sin_addr.s_addr) {
-+ ast_debug(1, "No remote address on RTP instance '%p' so dropping frame\n", instance);
-+ return -1;
-+ }
-+
-+ /* If there is no data length we can't very well send the packet */
-+ if (!frame->datalen) {
-+ ast_debug(1, "Received frame with no data for RTP instance '%p' so dropping frame\n", instance);
-+ return -1;
-+ }
-+
-+ /* If the packet is not one our RTP stack supports bail out */
-+ if (frame->frametype != AST_FRAME_VOICE && frame->frametype != AST_FRAME_VIDEO && frame->frametype != AST_FRAME_TEXT) {
-+ ast_log(LOG_WARNING, "RTP can only send voice, video, and text\n");
-+ return -1;
-+ }
-+
-+ if (rtp->red) {
-+ /* return 0; */
-+ /* no primary data or generations to send */
-+ if ((frame = red_t140_to_red(rtp->red)) == NULL)
-+ return 0;
-+ }
-+
-+ /* Grab the subclass and look up the payload we are going to use */
-+ subclass = frame->subclass;
-+ if (frame->frametype == AST_FRAME_VIDEO) {
-+ subclass &= ~0x1;
-+ }
-+ if ((codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 1, subclass)) < 0) {
-+ ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(frame->subclass));
-+ return -1;
-+ }
-+
-+ /* Oh dear, if the format changed we will have to set up a new smoother */
-+ if (rtp->lasttxformat != subclass) {
-+ ast_debug(1, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass));
-+ rtp->lasttxformat = subclass;
-+ if (rtp->smoother) {
-+ ast_smoother_free(rtp->smoother);
-+ rtp->smoother = NULL;
-+ }
-+ }
-+
-+ /* If no smoother is present see if we have to set one up */
-+ if (!rtp->smoother) {
-+ struct ast_format_list fmt = ast_codec_pref_getsize(&ast_rtp_instance_get_codecs(instance)->pref, subclass);
-+
-+ switch (subclass) {
-+ case AST_FORMAT_SPEEX:
-+ case AST_FORMAT_G723_1:
-+ case AST_FORMAT_SIREN7:
-+ case AST_FORMAT_SIREN14:
-+ /* these are all frame-based codecs and cannot be safely run through
-+ a smoother */
-+ break;
-+ default:
-+ if (fmt.inc_ms) {
-+ if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) {
-+ ast_log(LOG_WARNING, "Unable to create smoother: format %d ms: %d len: %d\n", subclass, fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
-+ return -1;
-+ }
-+ if (fmt.flags) {
-+ ast_smoother_set_flags(rtp->smoother, fmt.flags);
-+ }
-+ ast_debug(1, "Created smoother: format: %d ms: %d len: %d\n", subclass, fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
-+ }
-+ }
-+ }
-+
-+ /* Feed audio frames into the actual function that will create a frame and send it */
-+ if (rtp->smoother) {
-+ struct ast_frame *f;
-+
-+ if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) {
-+ ast_smoother_feed_be(rtp->smoother, frame);
-+ } else {
-+ ast_smoother_feed(rtp->smoother, frame);
-+ }
-+
-+ while ((f = ast_smoother_read(rtp->smoother)) && (f->data.ptr)) {
-+ if (f->subclass == AST_FORMAT_G722) {
-+ f->samples /= 2;
-+ }
-+
-+ ast_rtp_raw_write(instance, f, codec);
-+ }
-+ } else {
-+ int hdrlen = 12;
-+ struct ast_frame *f = NULL;
-+
-+ if (frame->offset < hdrlen) {
-+ f = ast_frdup(frame);
-+ } else {
-+ f = frame;
-+ }
-+ if (f->data.ptr) {
-+ ast_rtp_raw_write(instance, f, codec);
-+ }
-+ if (f != frame) {
-+ ast_frfree(f);
-+ }
-+
-+ }
-+
-+ return 0;
-+}
-+
-+static void calc_rxstamp(struct timeval *tv, struct ast_rtp *rtp, unsigned int timestamp, int mark)
-+{
-+ struct timeval now;
-+ double transit;
-+ double current_time;
-+ double d;
-+ double dtv;
-+ double prog;
-+
-+ double normdev_rxjitter_current;
-+ if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) {
-+ gettimeofday(&rtp->rxcore, NULL);
-+ rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000;
-+ /* map timestamp to a real time */
-+ rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */
-+ rtp->rxcore.tv_sec -= timestamp / 8000;
-+ rtp->rxcore.tv_usec -= (timestamp % 8000) * 125;
-+ /* Round to 0.1ms for nice, pretty timestamps */
-+ rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100;
-+ if (rtp->rxcore.tv_usec < 0) {
-+ /* Adjust appropriately if necessary */
-+ rtp->rxcore.tv_usec += 1000000;
-+ rtp->rxcore.tv_sec -= 1;
-+ }
-+ }
-+
-+ gettimeofday(&now,NULL);
-+ /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */
-+ tv->tv_sec = rtp->rxcore.tv_sec + timestamp / 8000;
-+ tv->tv_usec = rtp->rxcore.tv_usec + (timestamp % 8000) * 125;
-+ if (tv->tv_usec >= 1000000) {
-+ tv->tv_usec -= 1000000;
-+ tv->tv_sec += 1;
-+ }
-+ prog = (double)((timestamp-rtp->seedrxts)/8000.);
-+ dtv = (double)rtp->drxcore + (double)(prog);
-+ current_time = (double)now.tv_sec + (double)now.tv_usec/1000000;
-+ transit = current_time - dtv;
-+ d = transit - rtp->rxtransit;
-+ rtp->rxtransit = transit;
-+ if (d<0)
-+ d=-d;
-+ rtp->rxjitter += (1./16.) * (d - rtp->rxjitter);
-+
-+ if (rtp->rtcp) {
-+ if (rtp->rxjitter > rtp->rtcp->maxrxjitter)
-+ rtp->rtcp->maxrxjitter = rtp->rxjitter;
-+ if (rtp->rtcp->rxjitter_count == 1)
-+ rtp->rtcp->minrxjitter = rtp->rxjitter;
-+ if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter)
-+ rtp->rtcp->minrxjitter = rtp->rxjitter;
-+
-+ normdev_rxjitter_current = normdev_compute(rtp->rtcp->normdev_rxjitter,rtp->rxjitter,rtp->rtcp->rxjitter_count);
-+ rtp->rtcp->stdev_rxjitter = stddev_compute(rtp->rtcp->stdev_rxjitter,rtp->rxjitter,rtp->rtcp->normdev_rxjitter,normdev_rxjitter_current,rtp->rtcp->rxjitter_count);
-+
-+ rtp->rtcp->normdev_rxjitter = normdev_rxjitter_current;
-+ rtp->rtcp->rxjitter_count++;
-+ }
-+}
-+
-+static struct ast_frame *send_dtmf(struct ast_rtp_instance *instance, enum ast_frame_type type, int compensate)
-+{
-+ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
-+ struct sockaddr_in remote_address;
-+
-+ ast_rtp_instance_get_remote_address(instance, &remote_address);
-+
-+ if (((compensate && type == AST_FRAME_DTMF_END) || (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) {
-+ ast_debug(1, "Ignore potential DTMF echo from '%s'\n", ast_inet_ntoa(remote_address.sin_addr));
-+ rtp->resp = 0;
-+ rtp->dtmfsamples = 0;
-+ return &ast_null_frame;
-+ }
-+ ast_debug(1, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, ast_inet_ntoa(remote_address.sin_addr));
-+ if (rtp->resp == 'X') {
-+ rtp->f.frametype = AST_FRAME_CONTROL;
-+ rtp->f.subclass = AST_CONTROL_FLASH;
-+ } else {
-+ rtp->f.frametype = type;
-+ rtp->f.subclass = rtp->resp;
-+ }
-+ rtp->f.datalen = 0;
-+ rtp->f.samples = 0;
-+ rtp->f.mallocd = 0;
-+ rtp->f.src = "RTP";
-+
-+ return &rtp->f;
-+}
-+
-+static struct ast_frame *process_dtmf_rfc2833(struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, struct sockaddr_in *sin, int payloadtype, int mark)
-+{
-+ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
-+ struct sockaddr_in remote_address;
-+ unsigned int event, event_end, samples;
-+ char resp = 0;
-+ struct ast_frame *f = NULL;
-+
-+ ast_rtp_instance_get_remote_address(instance, &remote_address);
-+
-+ /* Figure out event, event end, and samples */
-+ event = ntohl(*((unsigned int *)(data)));
-+ event >>= 24;
-+ event_end = ntohl(*((unsigned int *)(data)));
-+ event_end <<= 8;
-+ event_end >>= 24;
-+ samples = ntohl(*((unsigned int *)(data)));
-+ samples &= 0xFFFF;
-+
-+ ast_verbose("Got RTP RFC2833 from %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u, mark %d, event %08x, end %d, duration %-5.5d) \n", ast_inet_ntoa(remote_address.sin_addr),
-+ ntohs(remote_address.sin_port), payloadtype, seqno, timestamp, len, (mark?1:0), event, ((event_end & 0x80)?1:0), samples);
-+
-+ /* Print out debug if turned on */
-+ if (rtpdebug || option_debug > 2)
-+ ast_debug(0, "- RTP 2833 Event: %08x (len = %d)\n", event, len);
-+
-+ /* Figure out what digit was pressed */
-+ if (event < 10) {
-+ resp = '0' + event;
-+ } else if (event < 11) {
-+ resp = '*';
-+ } else if (event < 12) {
-+ resp = '#';
-+ } else if (event < 16) {
-+ resp = 'A' + (event - 12);
-+ } else if (event < 17) { /* Event 16: Hook flash */
-+ resp = 'X';
-+ } else {
-+ /* Not a supported event */
-+ ast_log(LOG_DEBUG, "Ignoring RTP 2833 Event: %08x. Not a DTMF Digit.\n", event);
-+ return &ast_null_frame;
-+ }
-+
-+ if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE)) {
-+ if ((rtp->lastevent != timestamp) || (rtp->resp && rtp->resp != resp)) {
-+ rtp->resp = resp;
-+ rtp->dtmfcount = 0;
-+ f = send_dtmf(instance, AST_FRAME_DTMF_END, ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE));
-+ f->len = 0;
-+ rtp->lastevent = timestamp;
-+ }
-+ } else {
-+ if ((!(rtp->resp) && (!(event_end & 0x80))) || (rtp->resp && rtp->resp != resp)) {
-+ rtp->resp = resp;
-+ f = send_dtmf(instance, AST_FRAME_DTMF_BEGIN, 0);
-+ rtp->dtmfcount = dtmftimeout;
-+ } else if ((event_end & 0x80) && (rtp->lastevent != seqno) && rtp->resp) {
-+ f = send_dtmf(instance, AST_FRAME_DTMF_END, 0);
-+ f->len = ast_tvdiff_ms(ast_samp2tv(samples, 8000), ast_tv(0, 0)); /* XXX hard coded 8kHz */
-+ rtp->resp = 0;
-+ rtp->dtmfcount = 0;
-+ rtp->lastevent = seqno;
-+ }
-+ }
-+
-+ rtp->dtmfsamples = samples;
-+
-+ return f;
-+}
-+
-+static struct ast_frame *process_dtmf_cisco(struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, struct sockaddr_in *sin, int payloadtype, int mark)
-+{
-+ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
-+ unsigned int event, flags, power;
-+ char resp = 0;
-+ unsigned char seq;
-+ struct ast_frame *f = NULL;
-+
-+ if (len < 4) {
-+ return NULL;
-+ }
-+
-+ /* The format of Cisco RTP DTMF packet looks like next:
-+ +0 - sequence number of DTMF RTP packet (begins from 1,
-+ wrapped to 0)
-+ +1 - set of flags
-+ +1 (bit 0) - flaps by different DTMF digits delimited by audio
-+ or repeated digit without audio???
-+ +2 (+4,+6,...) - power level? (rises from 0 to 32 at begin of tone
-+ then falls to 0 at its end)
-+ +3 (+5,+7,...) - detected DTMF digit (0..9,*,#,A-D,...)
-+ Repeated DTMF information (bytes 4/5, 6/7) is history shifted right
-+ by each new packet and thus provides some redudancy.
-+
-+ Sample of Cisco RTP DTMF packet is (all data in hex):
-+ 19 07 00 02 12 02 20 02
-+ showing end of DTMF digit '2'.
-+
-+ The packets
-+ 27 07 00 02 0A 02 20 02
-+ 28 06 20 02 00 02 0A 02
-+ shows begin of new digit '2' with very short pause (20 ms) after
-+ previous digit '2'. Bit +1.0 flips at begin of new digit.
-+
-+ Cisco RTP DTMF packets comes as replacement of audio RTP packets
-+ so its uses the same sequencing and timestamping rules as replaced
-+ audio packets. Repeat interval of DTMF packets is 20 ms and not rely
-+ on audio framing parameters. Marker bit isn't used within stream of
-+ DTMFs nor audio stream coming immediately after DTMF stream. Timestamps
-+ are not sequential at borders between DTMF and audio streams,
-+ */
-+
-+ seq = data[0];
-+ flags = data[1];
-+ power = data[2];
-+ event = data[3] & 0x1f;
-+
-+ if (option_debug > 2 || rtpdebug)
-+ ast_debug(0, "Cisco DTMF Digit: %02x (len=%d, seq=%d, flags=%02x, power=%d, history count=%d)\n", event, len, seq, flags, power, (len - 4) / 2);
-+ if (event < 10) {
-+ resp = '0' + event;
-+ } else if (event < 11) {
-+ resp = '*';
-+ } else if (event < 12) {
-+ resp = '#';
-+ } else if (event < 16) {
-+ resp = 'A' + (event - 12);
-+ } else if (event < 17) {
-+ resp = 'X';
-+ }
-+ if ((!rtp->resp && power) || (rtp->resp && (rtp->resp != resp))) {
-+ rtp->resp = resp;
-+ /* Why we should care on DTMF compensation at reception? */
-+ if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE)) {
-+ f = send_dtmf(instance, AST_FRAME_DTMF_BEGIN, 0);
-+ rtp->dtmfsamples = 0;
-+ }
-+ } else if ((rtp->resp == resp) && !power) {
-+ f = send_dtmf(instance, AST_FRAME_DTMF_END, ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE));
-+ f->samples = rtp->dtmfsamples * 8;
-+ rtp->resp = 0;
-+ } else if (rtp->resp == resp)
-+ rtp->dtmfsamples += 20 * 8;
-+ rtp->dtmfcount = dtmftimeout;
-+
-+ return f;
-+}
-+
-+static struct ast_frame *process_cn_rfc3389(struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, struct sockaddr_in *sin, int payloadtype, int mark)
-+{
-+ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
-+
-+ /* Convert comfort noise into audio with various codecs. Unfortunately this doesn't
-+ totally help us out becuase we don't have an engine to keep it going and we are not
-+ guaranteed to have it every 20ms or anything */
-+ if (rtpdebug)
-+ ast_debug(0, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", rtp->lastrxformat, len);
-+
-+ if (ast_test_flag(rtp, FLAG_3389_WARNING)) {
-+ struct sockaddr_in remote_address;
-+
-+ ast_rtp_instance_get_remote_address(instance, &remote_address);
-+
-+ ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client IP: %s\n",
-+ ast_inet_ntoa(remote_address.sin_addr));
-+ ast_set_flag(rtp, FLAG_3389_WARNING);
-+ }
-+
-+ /* Must have at least one byte */
-+ if (!len)
-+ return NULL;
-+ if (len < 24) {
-+ rtp->f.data.ptr = rtp->rawdata + AST_FRIENDLY_OFFSET;
-+ rtp->f.datalen = len - 1;
-+ rtp->f.offset = AST_FRIENDLY_OFFSET;
-+ memcpy(rtp->f.data.ptr, data + 1, len - 1);
-+ } else {
-+ rtp->f.data.ptr = NULL;
-+ rtp->f.offset = 0;
-+ rtp->f.datalen = 0;
-+ }
-+ rtp->f.frametype = AST_FRAME_CNG;
-+ rtp->f.subclass = data[0] & 0x7f;
-+ rtp->f.datalen = len - 1;
-+ rtp->f.samples = 0;
-+ rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0;
-+
-+ return &rtp->f;
-+}
-+
-+static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
-+{
-+ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
-+ struct sockaddr_in sin;
-+ socklen_t len = sizeof(sin);
-+ unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET];
-+ unsigned int *rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET);
-+ int res, packetwords, position = 0;
-+ struct ast_frame *f = &ast_null_frame;
-+
-+ /* Read in RTCP data from the socket */
-+ if ((res = recvfrom(rtp->rtcp->s, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET, 0, (struct sockaddr *)&sin, &len)) < 0) {
-+ ast_assert(errno != EBADF);
-+ if (errno != EAGAIN) {
-+ ast_log(LOG_WARNING, "RTCP Read error: %s. Hanging up.\n", strerror(errno));
-+ return NULL;
-+ }
-+ return &ast_null_frame;
-+ }
-+
-+ packetwords = res / 4;
-+
-+ if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT)) {
-+ /* Send to whoever sent to us */
-+ if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
-+ (rtp->rtcp->them.sin_port != sin.sin_port)) {
-+ memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them));
-+ if (option_debug || rtpdebug)
-+ ast_debug(0, "RTCP NAT: Got RTCP from other end. Now sending to address %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
-+ }
-+ }
-+
-+ ast_debug(1, "Got RTCP report of %d bytes\n", res);
-+
-+ while (position < packetwords) {
-+ int i, pt, rc;
-+ unsigned int length, dlsr, lsr, msw, lsw, comp;
-+ struct timeval now;
-+ double rttsec, reported_jitter, reported_normdev_jitter_current, normdevrtt_current, reported_lost, reported_normdev_lost_current;
-+ uint64_t rtt = 0;
-+
-+ i = position;
-+ length = ntohl(rtcpheader[i]);
-+ pt = (length & 0xff0000) >> 16;
-+ rc = (length & 0x1f000000) >> 24;
-+ length &= 0xffff;
-+
-+ if ((i + length) > packetwords) {
-+ if (option_debug || rtpdebug)
-+ ast_log(LOG_DEBUG, "RTCP Read too short\n");
-+ return &ast_null_frame;
-+ }
-+
-+ if (rtcp_debug_test_addr(&sin)) {
-+ ast_verbose("\n\nGot RTCP from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
-+ ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown");
-+ ast_verbose("Reception reports: %d\n", rc);
-+ ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]);
-+ }
-+
-+ i += 2; /* Advance past header and ssrc */
-+
-+ switch (pt) {
-+ case RTCP_PT_SR:
-+ gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */
-+ rtp->rtcp->spc = ntohl(rtcpheader[i+3]);
-+ rtp->rtcp->soc = ntohl(rtcpheader[i + 4]);
-+ rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/
-+
-+ if (rtcp_debug_test_addr(&sin)) {
-+ ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096);
-+ ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2]));
-+ ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4]));
-+ }
-+ i += 5;
-+ if (rc < 1)
-+ break;
-+ /* Intentional fall through */
-+ case RTCP_PT_RR:
-+ /* Don't handle multiple reception reports (rc > 1) yet */
-+ /* Calculate RTT per RFC */
-+ gettimeofday(&now, NULL);
-+ timeval2ntp(now, &msw, &lsw);
-+ if (ntohl(rtcpheader[i + 4]) && ntohl(rtcpheader[i + 5])) { /* We must have the LSR && DLSR */
-+ comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16);
-+ lsr = ntohl(rtcpheader[i + 4]);
-+ dlsr = ntohl(rtcpheader[i + 5]);
-+ rtt = comp - lsr - dlsr;
-+
-+ /* Convert end to end delay to usec (keeping the calculation in 64bit space)
-+ sess->ee_delay = (eedelay * 1000) / 65536; */
-+ if (rtt < 4294) {
-+ rtt = (rtt * 1000000) >> 16;
-+ } else {
-+ rtt = (rtt * 1000) >> 16;
-+ rtt *= 1000;
-+ }
-+ rtt = rtt / 1000.;
-+ rttsec = rtt / 1000.;
-+ rtp->rtcp->rtt = rttsec;
-+
-+ if (comp - dlsr >= lsr) {
-+ rtp->rtcp->accumulated_transit += rttsec;
-+
-+ if (rtp->rtcp->rtt_count == 0)
-+ rtp->rtcp->minrtt = rttsec;
-+
-+ if (rtp->rtcp->maxrtt<rttsec)
-+ rtp->rtcp->maxrtt = rttsec;
-+ if (rtp->rtcp->minrtt>rttsec)
-+ rtp->rtcp->minrtt = rttsec;
-+
-+ normdevrtt_current = normdev_compute(rtp->rtcp->normdevrtt, rttsec, rtp->rtcp->rtt_count);
-+
-+ rtp->rtcp->stdevrtt = stddev_compute(rtp->rtcp->stdevrtt, rttsec, rtp->rtcp->normdevrtt, normdevrtt_current, rtp->rtcp->rtt_count);
-+
-+ rtp->rtcp->normdevrtt = normdevrtt_current;
-+
-+ rtp->rtcp->rtt_count++;
-+ } else if (rtcp_debug_test_addr(&sin)) {
-+ ast_verbose("Internal RTCP NTP clock skew detected: "
-+ "lsr=%u, now=%u, dlsr=%u (%d:%03dms), "
-+ "diff=%d\n",
-+ lsr, comp, dlsr, dlsr / 65536,
-+ (dlsr % 65536) * 1000 / 65536,
-+ dlsr - (comp - lsr));
-+ }
-+ }
-+
-+ rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]);
-+ reported_jitter = (double) rtp->rtcp->reported_jitter;
-+
-+ if (rtp->rtcp->reported_jitter_count == 0)
-+ rtp->rtcp->reported_minjitter = reported_jitter;
-+
-+ if (reported_jitter < rtp->rtcp->reported_minjitter)
-+ rtp->rtcp->reported_minjitter = reported_jitter;
-+
-+ if (reported_jitter > rtp->rtcp->reported_maxjitter)
-+ rtp->rtcp->reported_maxjitter = reported_jitter;
-+
-+ reported_normdev_jitter_current = normdev_compute(rtp->rtcp->reported_normdev_jitter, reported_jitter, rtp->rtcp->reported_jitter_count);
-+
-+ rtp->rtcp->reported_stdev_jitter = stddev_compute(rtp->rtcp->reported_stdev_jitter, reported_jitter, rtp->rtcp->reported_normdev_jitter, reported_normdev_jitter_current, rtp->rtcp->reported_jitter_count);
-+
-+ rtp->rtcp->reported_normdev_jitter = reported_normdev_jitter_current;
-+
-+ rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff;
-+
-+ reported_lost = (double) rtp->rtcp->reported_lost;
-+
-+ /* using same counter as for jitter */
-+ if (rtp->rtcp->reported_jitter_count == 0)
-+ rtp->rtcp->reported_minlost = reported_lost;
-+
-+ if (reported_lost < rtp->rtcp->reported_minlost)
-+ rtp->rtcp->reported_minlost = reported_lost;
-+
-+ if (reported_lost > rtp->rtcp->reported_maxlost)
-+ rtp->rtcp->reported_maxlost = reported_lost;
-+ reported_normdev_lost_current = normdev_compute(rtp->rtcp->reported_normdev_lost, reported_lost, rtp->rtcp->reported_jitter_count);
-+
-+ rtp->rtcp->reported_stdev_lost = stddev_compute(rtp->rtcp->reported_stdev_lost, reported_lost, rtp->rtcp->reported_normdev_lost, reported_normdev_lost_current, rtp->rtcp->reported_jitter_count);
-+
-+ rtp->rtcp->reported_normdev_lost = reported_normdev_lost_current;
-+
-+ rtp->rtcp->reported_jitter_count++;
-+
-+ if (rtcp_debug_test_addr(&sin)) {
-+ ast_verbose(" Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24));
-+ ast_verbose(" Packets lost so far: %d\n", rtp->rtcp->reported_lost);
-+ ast_verbose(" Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff));
-+ ast_verbose(" Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16);
-+ ast_verbose(" Interarrival jitter: %u\n", rtp->rtcp->reported_jitter);
-+ ast_verbose(" Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096);
-+ ast_verbose(" DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0);
-+ if (rtt)
-+ ast_verbose(" RTT: %lu(sec)\n", (unsigned long) rtt);
-+ }
-+ if (rtt) {
-+ manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From %s:%d\r\n"
-+ "PT: %d(%s)\r\n"
-+ "ReceptionReports: %d\r\n"
-+ "SenderSSRC: %u\r\n"
-+ "FractionLost: %ld\r\n"
-+ "PacketsLost: %d\r\n"
-+ "HighestSequence: %ld\r\n"
-+ "SequenceNumberCycles: %ld\r\n"
-+ "IAJitter: %u\r\n"
-+ "LastSR: %lu.%010lu\r\n"
-+ "DLSR: %4.4f(sec)\r\n"
-+ "RTT: %llu(sec)\r\n",
-+ ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port),
-+ pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown",
-+ rc,
-+ rtcpheader[i + 1],
-+ (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24),
-+ rtp->rtcp->reported_lost,
-+ (long) (ntohl(rtcpheader[i + 2]) & 0xffff),
-+ (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16,
-+ rtp->rtcp->reported_jitter,
-+ (unsigned long) ntohl(rtcpheader[i + 4]) >> 16, ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096,
-+ ntohl(rtcpheader[i + 5])/65536.0,
-+ (unsigned long long)rtt);
-+ } else {
-+ manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From %s:%d\r\n"
-+ "PT: %d(%s)\r\n"
-+ "ReceptionReports: %d\r\n"
-+ "SenderSSRC: %u\r\n"
-+ "FractionLost: %ld\r\n"
-+ "PacketsLost: %d\r\n"
-+ "HighestSequence: %ld\r\n"
-+ "SequenceNumberCycles: %ld\r\n"
-+ "IAJitter: %u\r\n"
-+ "LastSR: %lu.%010lu\r\n"
-+ "DLSR: %4.4f(sec)\r\n",
-+ ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port),
-+ pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown",
-+ rc,
-+ rtcpheader[i + 1],
-+ (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24),
-+ rtp->rtcp->reported_lost,
-+ (long) (ntohl(rtcpheader[i + 2]) & 0xffff),
-+ (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16,
-+ rtp->rtcp->reported_jitter,
-+ (unsigned long) ntohl(rtcpheader[i + 4]) >> 16,
-+ ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096,
-+ ntohl(rtcpheader[i + 5])/65536.0);
-+ }
-+ break;
-+ case RTCP_PT_FUR:
-+ if (rtcp_debug_test_addr(&sin))
-+ ast_verbose("Received an RTCP Fast Update Request\n");
-+ rtp->f.frametype = AST_FRAME_CONTROL;
-+ rtp->f.subclass = AST_CONTROL_VIDUPDATE;
-+ rtp->f.datalen = 0;
-+ rtp->f.samples = 0;
-+ rtp->f.mallocd = 0;
-+ rtp->f.src = "RTP";
-+ f = &rtp->f;
-+ break;
-+ case RTCP_PT_SDES:
-+ if (rtcp_debug_test_addr(&sin))
-+ ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
-+ break;
-+ case RTCP_PT_BYE:
-+ if (rtcp_debug_test_addr(&sin))
-+ ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
-+ break;
-+ default:
-+ ast_debug(1, "Unknown RTCP packet (pt=%d) received from %s:%d\n", pt, ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
-+ break;
-+ }
-+ position += (length + 1);
-+ }
-+
-+ rtp->rtcp->rtcp_info = 1;
-+
-+ return f;
-+}
-+
-+static int bridge_p2p_rtp_write(struct ast_rtp_instance *instance, unsigned int *rtpheader, int len, int hdrlen)
-+{
-+ struct ast_rtp_instance *instance1 = ast_rtp_instance_get_bridged(instance);
-+ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance), *bridged = ast_rtp_instance_get_data(instance1);
-+ int res = 0, payload = 0, bridged_payload = 0, mark;
-+ struct ast_rtp_payload_type payload_type;
-+ int reconstruct = ntohl(rtpheader[0]);
-+ struct sockaddr_in remote_address;
-+
-+ /* Get fields from packet */
-+ payload = (reconstruct & 0x7f0000) >> 16;
-+ mark = (((reconstruct & 0x800000) >> 23) != 0);
-+
-+ /* Check what the payload value should be */
-+ payload_type = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(instance), payload);
-+
-+ /* Otherwise adjust bridged payload to match */
-+ bridged_payload = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance1), payload_type.asterisk_format, payload_type.code);
-+
-+ /* If the payload coming in is not one of the negotiated ones then send it to the core, this will cause formats to change and the bridge to break */
-+ if (!(ast_rtp_instance_get_codecs(instance1)->payloads[bridged_payload].code)) {
-+ return -1;
-+ }
-+
-+ /* If the marker bit has been explicitly set turn it on */
-+ if (ast_test_flag(rtp, FLAG_NEED_MARKER_BIT)) {
-+ mark = 1;
-+ ast_clear_flag(rtp, FLAG_NEED_MARKER_BIT);
-+ }
-+
-+ /* Reconstruct part of the packet */
-+ reconstruct &= 0xFF80FFFF;
-+ reconstruct |= (bridged_payload << 16);
-+ reconstruct |= (mark << 23);
-+ rtpheader[0] = htonl(reconstruct);
-+
-+ ast_rtp_instance_get_remote_address(instance1, &remote_address);
-+
-+ /* Send the packet back out */
-+ res = sendto(bridged->s, (void *)rtpheader, len, 0, (struct sockaddr *)&remote_address, sizeof(remote_address));
-+ if (res < 0) {
-+ if (!ast_rtp_instance_get_prop(instance1, AST_RTP_PROPERTY_NAT) || (ast_rtp_instance_get_prop(instance1, AST_RTP_PROPERTY_NAT) && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
-+ ast_debug(1, "RTP Transmission error of packet to %s:%d: %s\n", ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port), strerror(errno));
-+ } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) {
-+ if (option_debug || rtpdebug)
-+ ast_debug(0, "RTP NAT: Can't write RTP to private address %s:%d, waiting for other end to send audio...\n", ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port));
-+ ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN);
-+ }
-+ return 0;
-+ } else if (rtp_debug_test_addr(&remote_address)) {
-+ ast_verbose("Sent RTP P2P packet to %s:%u (type %-2.2d, len %-6.6u)\n", ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port), bridged_payload, len - hdrlen);
-+ }
-+
-+ return 0;
-+}
-+
-+static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtcp)
-+{
-+ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
-+ struct sockaddr_in sin;
-+ socklen_t len = sizeof(sin);
-+ int res, hdrlen = 12, version, payloadtype, padding, mark, ext, cc, prev_seqno;
-+ unsigned int *rtpheader = (unsigned int*)(rtp->rawdata + AST_FRIENDLY_OFFSET), seqno, ssrc, timestamp;
-+ struct ast_rtp_payload_type payload;
-+ struct sockaddr_in remote_address;
-+
-+ /* If this is actually RTCP let's hop on over and handle it */
-+ if (rtcp) {
-+ if (rtp->rtcp) {
-+ return ast_rtcp_read(instance);
-+ }
-+ return &ast_null_frame;
-+ }
-+
-+ /* If we are currently sending DTMF to the remote party send a continuation packet */
-+ if (rtp->sending_digit) {
-+ ast_rtp_dtmf_continuation(instance);
-+ }
-+
-+ /* Actually read in the data from the socket */
-+ if ((res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 0, (struct sockaddr*)&sin, &len)) < 0) {
-+ ast_assert(errno != EBADF);
-+ if (errno != EAGAIN) {
-+ ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up.\n", strerror(errno));
-+ return NULL;
-+ }
-+ return &ast_null_frame;
-+ }
-+
-+ /* Make sure the data that was read in is actually enough to make up an RTP packet */
-+ if (res < hdrlen) {
-+ ast_log(LOG_WARNING, "RTP Read too short\n");
-+ return &ast_null_frame;
-+ }
-+
-+ /* If strict RTP protection is enabled see if we need to learn the remote address or if we need to drop the packet */
-+ if (rtp->strict_rtp_state == STRICT_RTP_LEARN) {
-+ memcpy(&rtp->strict_rtp_address, &sin, sizeof(rtp->strict_rtp_address));
-+ rtp->strict_rtp_state = STRICT_RTP_CLOSED;
-+ } else if (rtp->strict_rtp_state == STRICT_RTP_CLOSED) {
-+ if ((rtp->strict_rtp_address.sin_addr.s_addr != sin.sin_addr.s_addr) || (rtp->strict_rtp_address.sin_port != sin.sin_port)) {
-+ ast_debug(1, "Received RTP packet from %s:%d, dropping due to strict RTP protection. Expected it to be from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), ast_inet_ntoa(rtp->strict_rtp_address.sin_addr), ntohs(rtp->strict_rtp_address.sin_port));
-+ return &ast_null_frame;
-+ }
-+ }
-+
-+ /* Get fields and verify this is an RTP packet */
-+ seqno = ntohl(rtpheader[0]);
-+
-+ ast_rtp_instance_get_remote_address(instance, &remote_address);
-+
-+ if (!(version = (seqno & 0xC0000000) >> 30)) {
-+ if ((ast_stun_handle_packet(rtp->s, &sin, rtp->rawdata + AST_FRIENDLY_OFFSET, res, NULL, NULL) == AST_STUN_ACCEPT) &&
-+ (!remote_address.sin_port && !remote_address.sin_addr.s_addr)) {
-+ ast_rtp_instance_set_remote_address(instance, &sin);
-+ }
-+ return &ast_null_frame;
-+ }
-+
-+ /* If symmetric RTP is enabled see if the remote side is not what we expected and change where we are sending audio */
-+ if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT)) {
-+ if ((remote_address.sin_addr.s_addr != sin.sin_addr.s_addr) ||
-+ (remote_address.sin_port != sin.sin_port)) {
-+ ast_rtp_instance_set_remote_address(instance, &sin);
-+ memcpy(&remote_address, &sin, sizeof(remote_address));
-+ if (rtp->rtcp) {
-+ memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them));
-+ rtp->rtcp->them.sin_port = htons(ntohs(sin.sin_port)+1);
-+ }
-+ rtp->rxseqno = 0;
-+ ast_set_flag(rtp, FLAG_NAT_ACTIVE);
-+ if (option_debug || rtpdebug)
-+ ast_debug(0, "RTP NAT: Got audio from other end. Now sending to address %s:%d\n", ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port));
-+ }
-+ }
-+
-+ /* If we are directly bridged to another instance send the audio directly out */
-+ if (ast_rtp_instance_get_bridged(instance) && !bridge_p2p_rtp_write(instance, rtpheader, res, hdrlen)) {
-+ return &ast_null_frame;
-+ }
-+
-+ /* If the version is not what we expected by this point then just drop the packet */
-+ if (version != 2) {
-+ return &ast_null_frame;
-+ }
-+
-+ /* Pull out the various other fields we will need */
-+ payloadtype = (seqno & 0x7f0000) >> 16;
-+ padding = seqno & (1 << 29);
-+ mark = seqno & (1 << 23);
-+ ext = seqno & (1 << 28);
-+ cc = (seqno & 0xF000000) >> 24;
-+ seqno &= 0xffff;
-+ timestamp = ntohl(rtpheader[1]);
-+ ssrc = ntohl(rtpheader[2]);
-+
-+ /* Force a marker bit if the SSRC changes */
-+ if (!mark && rtp->rxssrc && rtp->rxssrc != ssrc) {
-+ if (option_debug || rtpdebug) {
-+ ast_debug(1, "Forcing Marker bit, because SSRC has changed\n");
-+ }
-+ mark = 1;
-+ }
-+
-+ /* Remove any padding bytes that may be present */
-+ if (padding) {
-+ res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1];
-+ }
-+
-+ /* Skip over any CSRC fields */
-+ if (cc) {
-+ hdrlen += cc * 4;
-+ }
-+
-+ /* Look for any RTP extensions, currently we do not support any */
-+ if (ext) {
-+ hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2;
-+ hdrlen += 4;
-+ if (option_debug) {
-+ int profile;
-+ profile = (ntohl(rtpheader[3]) & 0xffff0000) >> 16;
-+ if (profile == 0x505a)
-+ ast_debug(1, "Found Zfone extension in RTP stream - zrtp - not supported.\n");
-+ else
-+ ast_debug(1, "Found unknown RTP Extensions %x\n", profile);
-+ }
-+ }
-+
-+ /* Make sure after we potentially mucked with the header length that it is once again valid */
-+ if (res < hdrlen) {
-+ ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d\n", res, hdrlen);
-+ return &ast_null_frame;
-+ }
-+
-+ rtp->rxcount++;
-+ if (rtp->rxcount == 1) {
-+ rtp->seedrxseqno = seqno;
-+ }
-+
-+ /* Do not schedule RR if RTCP isn't run */
-+ if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) {
-+ /* Schedule transmission of Receiver Report */
-+ rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
-+ }
-+ if ((int)rtp->lastrxseqno - (int)seqno > 100) /* if so it would indicate that the sender cycled; allow for misordering */
-+ rtp->cycles += RTP_SEQ_MOD;
-+
-+ prev_seqno = rtp->lastrxseqno;
-+ rtp->lastrxseqno = seqno;
-+
-+ if (!rtp->themssrc) {
-+ rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */
-+ }
-+
-+ if (rtp_debug_test_addr(&sin)) {
-+ ast_verbose("Got RTP packet from %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
-+ ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen);
-+ }
-+
-+ payload = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(instance), payloadtype);
-+
-+ /* If the payload is not actually an Asterisk one but a special one pass it off to the respective handler */
-+ if (!payload.asterisk_format) {
-+ struct ast_frame *f = NULL;
-+
-+ if (payload.code == AST_RTP_DTMF) {
-+ f = process_dtmf_rfc2833(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &sin, payloadtype, mark);
-+ } else if (payload.code == AST_RTP_CISCO_DTMF) {
-+ f = process_dtmf_cisco(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &sin, payloadtype, mark);
-+ } else if (payload.code == AST_RTP_CN) {
-+ f = process_cn_rfc3389(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &sin, payloadtype, mark);
-+ } else {
-+ ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", payloadtype, ast_inet_ntoa(remote_address.sin_addr));
-+ }
-+
-+ return f ? f : &ast_null_frame;
-+ }
-+
-+ rtp->lastrxformat = rtp->f.subclass = payload.code;
-+ rtp->f.frametype = (rtp->f.subclass & AST_FORMAT_AUDIO_MASK) ? AST_FRAME_VOICE : (rtp->f.subclass & AST_FORMAT_VIDEO_MASK) ? AST_FRAME_VIDEO : AST_FRAME_TEXT;
-+
-+ rtp->rxseqno = seqno;
-+ rtp->lastrxts = timestamp;
-+
-+ rtp->f.src = "RTP";
-+ rtp->f.mallocd = 0;
-+ rtp->f.datalen = res - hdrlen;
-+ rtp->f.data.ptr = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET;
-+ rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
-+ rtp->f.seqno = seqno;
-+
-+ if (rtp->f.subclass == AST_FORMAT_T140 && (int)seqno - (prev_seqno+1) > 0 && (int)seqno - (prev_seqno+1) < 10) {
-+ unsigned char *data = rtp->f.data.ptr;
-+
-+ memmove(rtp->f.data.ptr+3, rtp->f.data.ptr, rtp->f.datalen);
-+ rtp->f.datalen +=3;
-+ *data++ = 0xEF;
-+ *data++ = 0xBF;
-+ *data = 0xBD;
-+ }
-+
-+ if (rtp->f.subclass == AST_FORMAT_T140RED) {
-+ unsigned char *data = rtp->f.data.ptr;
-+ unsigned char *header_end;
-+ int num_generations;
-+ int header_length;
-+ int len;
-+ int diff =(int)seqno - (prev_seqno+1); /* if diff = 0, no drop*/
-+ int x;
-+
-+ rtp->f.subclass = AST_FORMAT_T140;
-+ header_end = memchr(data, ((*data) & 0x7f), rtp->f.datalen);
-+ header_end++;
-+
-+ header_length = header_end - data;
-+ num_generations = header_length / 4;
-+ len = header_length;
-+
-+ if (!diff) {
-+ for (x = 0; x < num_generations; x++)
-+ len += data[x * 4 + 3];
-+
-+ if (!(rtp->f.datalen - len))
-+ return &ast_null_frame;
-+
-+ rtp->f.data.ptr += len;
-+ rtp->f.datalen -= len;
-+ } else if (diff > num_generations && diff < 10) {
-+ len -= 3;
-+ rtp->f.data.ptr += len;
-+ rtp->f.datalen -= len;
-+
-+ data = rtp->f.data.ptr;
-+ *data++ = 0xEF;
-+ *data++ = 0xBF;
-+ *data = 0xBD;
-+ } else {
-+ for ( x = 0; x < num_generations - diff; x++)
-+ len += data[x * 4 + 3];
-+
-+ rtp->f.data.ptr += len;
-+ rtp->f.datalen -= len;
-+ }
-+ }
-+
-+ if (rtp->f.subclass & AST_FORMAT_AUDIO_MASK) {
-+ rtp->f.samples = ast_codec_get_samples(&rtp->f);
-+ if (rtp->f.subclass == AST_FORMAT_SLINEAR)
-+ ast_frame_byteswap_be(&rtp->f);
-+ calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark);
-+ /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */
-+ ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO);
-+ rtp->f.ts = timestamp / 8;
-+ rtp->f.len = rtp->f.samples / ((ast_format_rate(rtp->f.subclass) / 1000));
-+ } else if (rtp->f.subclass & AST_FORMAT_VIDEO_MASK) {
-+ /* Video -- samples is # of samples vs. 90000 */
-+ if (!rtp->lastividtimestamp)
-+ rtp->lastividtimestamp = timestamp;
-+ rtp->f.samples = timestamp - rtp->lastividtimestamp;
-+ rtp->lastividtimestamp = timestamp;
-+ rtp->f.delivery.tv_sec = 0;
-+ rtp->f.delivery.tv_usec = 0;
-+ /* Pass the RTP marker bit as bit 0 in the subclass field.
-+ * This is ok because subclass is actually a bitmask, and
-+ * the low bits represent audio formats, that are not
-+ * involved here since we deal with video.
-+ */
-+ if (mark)
-+ rtp->f.subclass |= 0x1;
-+ } else {
-+ /* TEXT -- samples is # of samples vs. 1000 */
-+ if (!rtp->lastitexttimestamp)
-+ rtp->lastitexttimestamp = timestamp;
-+ rtp->f.samples = timestamp - rtp->lastitexttimestamp;
-+ rtp->lastitexttimestamp = timestamp;
-+ rtp->f.delivery.tv_sec = 0;
-+ rtp->f.delivery.tv_usec = 0;
-+ }
-+
-+ return &rtp->f;
-+}
-+
-+static void ast_rtp_prop_set(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value)
-+{
-+ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
-+
-+ if (property == AST_RTP_PROPERTY_RTCP) {
-+ if (rtp->rtcp) {
-+ ast_debug(1, "Ignoring duplicate RTCP property on RTP instance '%p'\n", instance);
-+ return;
-+ }
-+ if (!(rtp->rtcp = ast_calloc(1, sizeof(*rtp->rtcp)))) {
-+ return;
-+ }
-+ if ((rtp->rtcp->s = create_new_socket("RTCP")) < 0) {
-+ ast_debug(1, "Failed to create a new socket for RTCP on instance '%p'\n", instance);
-+ ast_free(rtp->rtcp);
-+ rtp->rtcp = NULL;
-+ return;
-+ }
-+
-+ /* Grab the IP address and port we are going to use */
-+ ast_rtp_instance_get_local_address(instance, &rtp->rtcp->us);
-+ rtp->rtcp->us.sin_port = htons(ntohs(rtp->rtcp->us.sin_port) + 1);
-+
-+ /* Try to actually bind to the IP address and port we are going to use for RTCP, if this fails we have to bail out */
-+ if (bind(rtp->rtcp->s, (struct sockaddr*)&rtp->rtcp->us, sizeof(rtp->rtcp->us))) {
-+ ast_debug(1, "Failed to setup RTCP on RTP instance '%p'\n", instance);
-+ close(rtp->rtcp->s);
-+ ast_free(rtp->rtcp);
-+ rtp->rtcp = NULL;
-+ return;
-+ }
-+
-+ ast_debug(1, "Setup RTCP on RTP instance '%p'\n", instance);
-+ rtp->rtcp->schedid = -1;
-+
-+ return;
-+ }
-+
-+ return;
-+}
-+
-+static int ast_rtp_fd(struct ast_rtp_instance *instance, int rtcp)
-+{
-+ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
-+
-+ return rtcp ? (rtp->rtcp ? rtp->rtcp->s : -1) : rtp->s;
-+}
-+
-+static void ast_rtp_remote_address_set(struct ast_rtp_instance *instance, struct sockaddr_in *sin)
-+{
-+ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
-+
-+ if (rtp->rtcp) {
-+ ast_debug(1, "Setting RTCP address on RTP instance '%p'\n", instance);
-+ memcpy(&rtp->rtcp->them, sin, sizeof(rtp->rtcp->them));
-+ rtp->rtcp->them.sin_port = htons(ntohs(sin->sin_port) + 1);
-+ }
-+
-+ rtp->rxseqno = 0;
-+
-+ if (strictrtp) {
-+ rtp->strict_rtp_state = STRICT_RTP_LEARN;
-+ }
-+
-+ return;
-+}
-+
-+/*! \brief Write t140 redundacy frame
-+ * \param data primary data to be buffered
-+ */
-+static int red_write(const void *data)
-+{
-+ struct ast_rtp_instance *instance = (struct ast_rtp_instance*) data;
-+ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
-+
-+ ast_rtp_write(instance, &rtp->red->t140);
-+
-+ return 1;
-+}
-+
-+static int rtp_red_init(struct ast_rtp_instance *instance, int buffer_time, int *payloads, int generations)
-+{
-+ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
-+ int x;
-+
-+ if (!(rtp->red = ast_calloc(1, sizeof(*rtp->red)))) {
-+ return -1;
-+ }
-+
-+ rtp->red->t140.frametype = AST_FRAME_TEXT;
-+ rtp->red->t140.subclass = AST_FORMAT_T140RED;
-+ rtp->red->t140.data.ptr = &rtp->red->buf_data;
-+
-+ rtp->red->t140.ts = 0;
-+ rtp->red->t140red = rtp->red->t140;
-+ rtp->red->t140red.data.ptr = &rtp->red->t140red_data;
-+ rtp->red->t140red.datalen = 0;
-+ rtp->red->ti = buffer_time;
-+ rtp->red->num_gen = generations;
-+ rtp->red->hdrlen = generations * 4 + 1;
-+ rtp->red->prev_ts = 0;
-+
-+ for (x = 0; x < generations; x++) {
-+ rtp->red->pt[x] = payloads[x];
-+ rtp->red->pt[x] |= 1 << 7; /* mark redundant generations pt */
-+ rtp->red->t140red_data[x*4] = rtp->red->pt[x];
-+ }
-+ rtp->red->t140red_data[x*4] = rtp->red->pt[x] = payloads[x]; /* primary pt */
-+ rtp->red->schedid = ast_sched_add(rtp->sched, generations, red_write, instance);
-+
-+ rtp->red->t140.datalen = 0;
-+
-+ return 0;
-+}
-+
-+static int rtp_red_buffer(struct ast_rtp_instance *instance, struct ast_frame *frame)
-+{
-+ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
-+
-+ if (frame->datalen > -1) {
-+ struct rtp_red *red = rtp->red;
-+ memcpy(&red->buf_data[red->t140.datalen], frame->data.ptr, frame->datalen);
-+ red->t140.datalen += frame->datalen;
-+ red->t140.ts = frame->ts;
-+ }
-+
-+ return 0;
-+}
-+
-+static int ast_rtp_local_bridge(struct ast_rtp_instance *instance0, struct ast_rtp_instance *instance1)
-+{
-+ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance0);
-+
-+ ast_set_flag(rtp, FLAG_NEED_MARKER_BIT);
-+
-+ return 0;
-+}
-+
-+static int ast_rtp_get_stat(struct ast_rtp_instance *instance, struct ast_rtp_instance_stats *stats, enum ast_rtp_instance_stat stat)
-+{
-+ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
-+
-+ if (!rtp->rtcp) {
-+ return -1;
-+ }
-+
-+ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_TXCOUNT, -1, stats->txcount, rtp->txcount);
-+ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_RXCOUNT, -1, stats->rxcount, rtp->rxcount);
-+
-+ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_TXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->txploss, rtp->rtcp->reported_lost);
-+ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_RXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->rxploss, rtp->rtcp->expected_prior - rtp->rtcp->received_prior);
-+ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_MAXRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->remote_maxrxploss, rtp->rtcp->reported_maxlost);
-+ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_MINRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->remote_minrxploss, rtp->rtcp->reported_minlost);
-+ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->remote_normdevrxploss, rtp->rtcp->reported_normdev_lost);
-+ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_STDEVRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->remote_stdevrxploss, rtp->rtcp->reported_stdev_lost);
-+ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_MAXRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->local_maxrxploss, rtp->rtcp->maxrxlost);
-+ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_MINRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->local_minrxploss, rtp->rtcp->minrxlost);
-+ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->local_normdevrxploss, rtp->rtcp->normdev_rxlost);
-+ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_STDEVRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->local_stdevrxploss, rtp->rtcp->stdev_rxlost);
-+ AST_RTP_STAT_TERMINATOR(AST_RTP_INSTANCE_STAT_COMBINED_LOSS);
-+
-+ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_TXJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->txjitter, rtp->rxjitter);
-+ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_RXJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->rxjitter, rtp->rtcp->reported_jitter / (unsigned int) 65536.0);
-+ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_MAXJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->remote_maxjitter, rtp->rtcp->reported_maxjitter);
-+ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_MINJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->remote_minjitter, rtp->rtcp->reported_minjitter);
-+ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->remote_normdevjitter, rtp->rtcp->reported_normdev_jitter);
-+ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_STDEVJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->remote_stdevjitter, rtp->rtcp->reported_stdev_jitter);
-+ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_MAXJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->local_maxjitter, rtp->rtcp->maxrxjitter);
-+ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_MINJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->local_minjitter, rtp->rtcp->minrxjitter);
-+ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->local_normdevjitter, rtp->rtcp->normdev_rxjitter);
-+ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_STDEVJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->local_stdevjitter, rtp->rtcp->stdev_rxjitter);
-+ AST_RTP_STAT_TERMINATOR(AST_RTP_INSTANCE_STAT_COMBINED_JITTER);
-+
-+ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_RTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->rtt, rtp->rtcp->rtt);
-+ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_MAX_RTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->maxrtt, rtp->rtcp->maxrtt);
-+ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_MIN_RTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->minrtt, rtp->rtcp->minrtt);
-+ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_NORMDEVRTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->normdevrtt, rtp->rtcp->normdevrtt);
-+ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_STDEVRTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->stdevrtt, rtp->rtcp->stdevrtt);
-+ AST_RTP_STAT_TERMINATOR(AST_RTP_INSTANCE_STAT_COMBINED_RTT);
-+
-+ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_SSRC, -1, stats->local_ssrc, rtp->ssrc);
-+ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_SSRC, -1, stats->remote_ssrc, rtp->themssrc);
-+
-+ return 0;
-+}
-+
-+static int ast_rtp_dtmf_compatible(struct ast_channel *chan0, struct ast_rtp_instance *instance0, struct ast_channel *chan1, struct ast_rtp_instance *instance1)
-+{
-+ /* If both sides are not using the same method of DTMF transmission
-+ * (ie: one is RFC2833, other is INFO... then we can not do direct media.
-+ * --------------------------------------------------
-+ * | DTMF Mode | HAS_DTMF | Accepts Begin Frames |
-+ * |-----------|------------|-----------------------|
-+ * | Inband | False | True |
-+ * | RFC2833 | True | True |
-+ * | SIP INFO | False | False |
-+ * --------------------------------------------------
-+ */
-+ return (((ast_rtp_instance_get_prop(instance0, AST_RTP_PROPERTY_DTMF) != ast_rtp_instance_get_prop(instance1, AST_RTP_PROPERTY_DTMF)) ||
-+ (!chan0->tech->send_digit_begin != !chan1->tech->send_digit_begin)) ? 0 : 1);
-+}
-+
-+static void ast_rtp_stun_request(struct ast_rtp_instance *instance, struct sockaddr_in *suggestion, const char *username)
-+{
-+ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
-+
-+ ast_stun_request(rtp->s, suggestion, username, NULL);
-+}
-+
-+static void ast_rtp_stop(struct ast_rtp_instance *instance)
-+{
-+ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
-+ struct sockaddr_in sin = { 0, };
-+
-+ if (rtp->rtcp) {
-+ AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
-+ }
-+ if (rtp->red) {
-+ AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
-+ free(rtp->red);
-+ rtp->red = NULL;
-+ }
-+
-+ ast_rtp_instance_set_remote_address(instance, &sin);
-+ if (rtp->rtcp) {
-+ memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr));
-+ memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port));
-+ }
-+
-+ ast_set_flag(rtp, FLAG_NEED_MARKER_BIT);
-+}
-+
-+static char *rtp_do_debug_ip(struct ast_cli_args *a)
-+{
-+ struct hostent *hp;
-+ struct ast_hostent ahp;
-+ int port = 0;
-+ char *p, *arg;
-+
-+ arg = a->argv[3];
-+ p = strstr(arg, ":");
-+ if (p) {
-+ *p = '\0';
-+ p++;
-+ port = atoi(p);
-+ }
-+ hp = ast_gethostbyname(arg, &ahp);
-+ if (hp == NULL) {
-+ ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
-+ return CLI_FAILURE;
-+ }
-+ rtpdebugaddr.sin_family = AF_INET;
-+ memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr));
-+ rtpdebugaddr.sin_port = htons(port);
-+ if (port == 0)
-+ ast_cli(a->fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtpdebugaddr.sin_addr));
-+ else
-+ ast_cli(a->fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtpdebugaddr.sin_addr), port);
-+ rtpdebug = 1;
-+ return CLI_SUCCESS;
-+}
-+
-+static char *rtcp_do_debug_ip(struct ast_cli_args *a)
-+{
-+ struct hostent *hp;
-+ struct ast_hostent ahp;
-+ int port = 0;
-+ char *p, *arg;
-+
-+ arg = a->argv[3];
-+ p = strstr(arg, ":");
-+ if (p) {
-+ *p = '\0';
-+ p++;
-+ port = atoi(p);
-+ }
-+ hp = ast_gethostbyname(arg, &ahp);
-+ if (hp == NULL) {
-+ ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
-+ return CLI_FAILURE;
-+ }
-+ rtcpdebugaddr.sin_family = AF_INET;
-+ memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr));
-+ rtcpdebugaddr.sin_port = htons(port);
-+ if (port == 0)
-+ ast_cli(a->fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr));
-+ else
-+ ast_cli(a->fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port);
-+ rtcpdebug = 1;
-+ return CLI_SUCCESS;
-+}
-+
-+static char *handle_cli_rtp_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-+{
-+ switch (cmd) {
-+ case CLI_INIT:
-+ e->command = "rtp set debug {on|off|ip}";
-+ e->usage =
-+ "Usage: rtp set debug {on|off|ip host[:port]}\n"
-+ " Enable/Disable dumping of all RTP packets. If 'ip' is\n"
-+ " specified, limit the dumped packets to those to and from\n"
-+ " the specified 'host' with optional port.\n";
-+ return NULL;
-+ case CLI_GENERATE:
-+ return NULL;
-+ }
-+
-+ if (a->argc == e->args) { /* set on or off */
-+ if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
-+ rtpdebug = 1;
-+ memset(&rtpdebugaddr, 0, sizeof(rtpdebugaddr));
-+ ast_cli(a->fd, "RTP Debugging Enabled\n");
-+ return CLI_SUCCESS;
-+ } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
-+ rtpdebug = 0;
-+ ast_cli(a->fd, "RTP Debugging Disabled\n");
-+ return CLI_SUCCESS;
-+ }
-+ } else if (a->argc == e->args +1) { /* ip */
-+ return rtp_do_debug_ip(a);
-+ }
-+
-+ return CLI_SHOWUSAGE; /* default, failure */
-+}
-+
-+static char *handle_cli_rtcp_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-+{
-+ switch (cmd) {
-+ case CLI_INIT:
-+ e->command = "rtcp set debug {on|off|ip}";
-+ e->usage =
-+ "Usage: rtcp set debug {on|off|ip host[:port]}\n"
-+ " Enable/Disable dumping of all RTCP packets. If 'ip' is\n"
-+ " specified, limit the dumped packets to those to and from\n"
-+ " the specified 'host' with optional port.\n";
-+ return NULL;
-+ case CLI_GENERATE:
-+ return NULL;
-+ }
-+
-+ if (a->argc == e->args) { /* set on or off */
-+ if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
-+ rtcpdebug = 1;
-+ memset(&rtcpdebugaddr, 0, sizeof(rtcpdebugaddr));
-+ ast_cli(a->fd, "RTCP Debugging Enabled\n");
-+ return CLI_SUCCESS;
-+ } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
-+ rtcpdebug = 0;
-+ ast_cli(a->fd, "RTCP Debugging Disabled\n");
-+ return CLI_SUCCESS;
-+ }
-+ } else if (a->argc == e->args +1) { /* ip */
-+ return rtcp_do_debug_ip(a);
-+ }
-+
-+ return CLI_SHOWUSAGE; /* default, failure */
-+}
-+
-+static char *handle_cli_rtcp_set_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-+{
-+ switch (cmd) {
-+ case CLI_INIT:
-+ e->command = "rtcp set stats {on|off}";
-+ e->usage =
-+ "Usage: rtcp set stats {on|off}\n"
-+ " Enable/Disable dumping of RTCP stats.\n";
-+ return NULL;
-+ case CLI_GENERATE:
-+ return NULL;
-+ }
-+
-+ if (a->argc != e->args)
-+ return CLI_SHOWUSAGE;
-+
-+ if (!strncasecmp(a->argv[e->args-1], "on", 2))
-+ rtcpstats = 1;
-+ else if (!strncasecmp(a->argv[e->args-1], "off", 3))
-+ rtcpstats = 0;
-+ else
-+ return CLI_SHOWUSAGE;
-+
-+ ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled");
-+ return CLI_SUCCESS;
-+}
-+
-+static struct ast_cli_entry cli_rtp[] = {
-+ AST_CLI_DEFINE(handle_cli_rtp_set_debug, "Enable/Disable RTP debugging"),
-+ AST_CLI_DEFINE(handle_cli_rtcp_set_debug, "Enable/Disable RTCP debugging"),
-+ AST_CLI_DEFINE(handle_cli_rtcp_set_stats, "Enable/Disable RTCP stats"),
-+};
-+
-+static int rtp_reload(int reload)
-+{
-+ struct ast_config *cfg;
-+ const char *s;
-+ struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
-+
-+ cfg = ast_config_load2("rtp.conf", "rtp", config_flags);
-+ if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
-+ return 0;
-+ }
-+
-+ rtpstart = DEFAULT_RTP_START;
-+ rtpend = DEFAULT_RTP_END;
-+ dtmftimeout = DEFAULT_DTMF_TIMEOUT;
-+ strictrtp = STRICT_RTP_OPEN;
-+ if (cfg) {
-+ if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
-+ rtpstart = atoi(s);
-+ if (rtpstart < MINIMUM_RTP_PORT)
-+ rtpstart = MINIMUM_RTP_PORT;
-+ if (rtpstart > MAXIMUM_RTP_PORT)
-+ rtpstart = MAXIMUM_RTP_PORT;
-+ }
-+ if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
-+ rtpend = atoi(s);
-+ if (rtpend < MINIMUM_RTP_PORT)
-+ rtpend = MINIMUM_RTP_PORT;
-+ if (rtpend > MAXIMUM_RTP_PORT)
-+ rtpend = MAXIMUM_RTP_PORT;
-+ }
-+ if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) {
-+ rtcpinterval = atoi(s);
-+ if (rtcpinterval == 0)
-+ rtcpinterval = 0; /* Just so we're clear... it's zero */
-+ if (rtcpinterval < RTCP_MIN_INTERVALMS)
-+ rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */
-+ if (rtcpinterval > RTCP_MAX_INTERVALMS)
-+ rtcpinterval = RTCP_MAX_INTERVALMS;
-+ }
-+ if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
-+#ifdef SO_NO_CHECK
-+ nochecksums = ast_false(s) ? 1 : 0;
-+#else
-+ if (ast_false(s))
-+ ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
-+#endif
-+ }
-+ if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
-+ dtmftimeout = atoi(s);
-+ if ((dtmftimeout < 0) || (dtmftimeout > 20000)) {
-+ ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
-+ dtmftimeout, DEFAULT_DTMF_TIMEOUT);
-+ dtmftimeout = DEFAULT_DTMF_TIMEOUT;
-+ };
-+ }
-+ if ((s = ast_variable_retrieve(cfg, "general", "strictrtp"))) {
-+ strictrtp = ast_true(s);
-+ }
-+ ast_config_destroy(cfg);
-+ }
-+ if (rtpstart >= rtpend) {
-+ ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
-+ rtpstart = DEFAULT_RTP_START;
-+ rtpend = DEFAULT_RTP_END;
-+ }
-+ ast_verb(2, "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
-+ return 0;
-+}
-+
-+static int reload_module(void)
-+{
-+ rtp_reload(1);
-+ return 0;
-+}
-+
-+static int load_module(void)
-+{
-+ if (ast_rtp_engine_register(&asterisk_rtp_engine)) {
-+ return AST_MODULE_LOAD_DECLINE;
-+ }
-+
-+ if (ast_cli_register_multiple(cli_rtp, ARRAY_LEN(cli_rtp))) {
-+ ast_rtp_engine_unregister(&asterisk_rtp_engine);
-+ return AST_MODULE_LOAD_DECLINE;
-+ }
-+
-+ rtp_reload(0);
-+
-+ return AST_MODULE_LOAD_SUCCESS;
-+}
-+
-+static int unload_module(void)
-+{
-+ ast_rtp_engine_unregister(&asterisk_rtp_engine);
-+ ast_cli_unregister_multiple(cli_rtp, ARRAY_LEN(cli_rtp));
-+
-+ return 0;
-+}
-+
-+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Asterisk RTP Stack",
-+ .load = load_module,
-+ .unload = unload_module,
-+ .reload = reload_module,
-+ );
-
-Property changes on: res/res_rtp_asterisk.c
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + Author Date Id Revision
-
-Index: res/res_config_pgsql.c
-===================================================================
---- a/res/res_config_pgsql.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/res/res_config_pgsql.c (.../trunk) (revision 186562)
-@@ -1530,7 +1530,7 @@
- }
-
- /* needs usecount semantics defined */
--AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "PostgreSQL RealTime Configuration Driver",
-+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "PostgreSQL RealTime Configuration Driver",
- .load = load_module,
- .unload = unload_module,
- .reload = reload
-Index: res/res_smdi.exports
-===================================================================
---- a/res/res_smdi.exports (.../tags/1.6.2.0-beta1) (revision 0)
-+++ b/res/res_smdi.exports (.../trunk) (revision 186562)
-@@ -0,0 +1,18 @@
-+{
-+ global:
-+ ast_smdi_interface_find;
-+ ast_smdi_interface_unref;
-+ ast_smdi_md_message_destroy;
-+ ast_smdi_md_message_pop;
-+ ast_smdi_md_message_putback;
-+ ast_smdi_md_message_wait;
-+ ast_smdi_mwi_message_destroy;
-+ ast_smdi_mwi_message_pop;
-+ ast_smdi_mwi_message_putback;
-+ ast_smdi_mwi_message_wait;
-+ ast_smdi_mwi_message_wait_station;
-+ ast_smdi_mwi_set;
-+ ast_smdi_mwi_unset;
-+ local:
-+ *;
-+};
-
-Property changes on: res/res_smdi.exports
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + Author Date Id Revision
-
-Index: res/res_phoneprov.c
-===================================================================
---- a/res/res_phoneprov.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/res/res_phoneprov.c (.../trunk) (revision 186562)
-@@ -1305,7 +1305,7 @@
- return 0;
- }
-
--AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "HTTP Phone Provisioning",
-+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "HTTP Phone Provisioning",
- .load = load_module,
- .unload = unload_module,
- .reload = reload,
-Index: utils/Makefile
-===================================================================
---- a/utils/Makefile (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/utils/Makefile (.../trunk) (revision 186562)
-@@ -163,6 +163,11 @@
- $(CMD_PREFIX) cp "$<" "$@"
- utils.o: ASTCFLAGS+=-DSTANDALONE
-
-+poll.c: $(ASTTOPDIR)/main/poll.c
-+ $(ECHO_PREFIX) echo " [CP] $(subst $(ASTTOPDIR)/,,$<) -> $@"
-+ $(CMD_PREFIX) cp "$<" "$@"
-+poll.o: ASTCFLAGS+=-DSTANDALONE
-+
- strings.c: $(ASTTOPDIR)/main/strings.c
- $(ECHO_PREFIX) echo " [CP] $(subst $(ASTTOPDIR)/,,$<) -> $@"
- $(CMD_PREFIX) cp "$<" "$@"
-@@ -179,12 +184,12 @@
- threadstorage.o: ASTCFLAGS+=-DSTANDALONE
-
- hashtest2.o: ASTCFLAGS+=-O0 -DSTANDALONE
--hashtest2: hashtest2.o md5.o utils.o strings.o astobj2.o sha1.o strcompat.o threadstorage.o clicompat.o
-+hashtest2: hashtest2.o md5.o utils.o strings.o astobj2.o sha1.o strcompat.o threadstorage.o clicompat.o poll.o
-
--hashtest: hashtest.o md5.o hashtab.o utils.o strings.o sha1.o strcompat.o threadstorage.o clicompat.o
-+hashtest: hashtest.o md5.o hashtab.o utils.o strings.o sha1.o strcompat.o threadstorage.o clicompat.o poll.o
- hashtest.o: ASTCFLAGS+=-O0 -DSTANDALONE
-
--refcounter: refcounter.o md5.o hashtab.o utils.o strings.o sha1.o strcompat.o threadstorage.o clicompat.o
-+refcounter: refcounter.o md5.o hashtab.o utils.o strings.o sha1.o strcompat.o threadstorage.o clicompat.o poll.o
- refcounter.o: ASTCFLAGS+=-O0 -DSTANDALONE
-
- extconf.o: extconf.c
-
-Property changes on: utils
-___________________________________________________________________
-Modified: svn:ignore
- - *.d
-*.i
-*.s
-aelbison.c
-aelparse
-aelparse.c
-ast_expr2.c
-ast_expr2f.c
-astman
-astobj2.c
-check_expr
-conf2ael
-hashtab.c
-hashtest
-hashtest2
-md5.c
-muted
-pbx_ael.c
-pval.c
-sha1.c
-smsq
-stereorize
-strcompat.c
-streamplayer
-strings.c
-threadstorage.c
-utils.c
-astcanary
-refcounter
-
- + *.d
-*.i
-*.s
-aelbison.c
-aelparse
-aelparse.c
-ast_expr2.c
-ast_expr2f.c
-astman
-astobj2.c
-check_expr
-conf2ael
-hashtab.c
-hashtest
-hashtest2
-md5.c
-muted
-pbx_ael.c
-pval.c
-poll.c
-sha1.c
-smsq
-stereorize
-strcompat.c
-streamplayer
-strings.c
-threadstorage.c
-utils.c
-astcanary
-refcounter
-
-
-Index: Makefile.rules
-===================================================================
---- a/Makefile.rules (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/Makefile.rules (.../trunk) (revision 186562)
-@@ -51,8 +51,13 @@
- # per-target settings will be applied
- CC_CFLAGS=$(PTHREAD_CFLAGS) $(ASTCFLAGS)
- CXX_CFLAGS=$(PTHREAD_CFLAGS) $(filter-out -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations $(AST_DECLARATION_AFTER_STATEMENT),$(ASTCFLAGS))
--CC_LDFLAGS_SO=$(PTHREAD_CFLAGS) $(ASTLDFLAGS) $(SOLINK)
--CXX_LDFLAGS_SO=$(PTHREAD_CFLAGS) $(ASTLDFLAGS) $(SOLINK)
-+
-+ifeq ($(GNU_LD),1)
-+SO_SUPPRESS_SYMBOLS=-Wl,--version-script,$(if $(wildcard $(subst .so,.exports,$@)),$(subst .so,.exports,$@),$(ASTTOPDIR)/default.exports)
-+endif
-+
-+CC_LDFLAGS_SO=$(PTHREAD_CFLAGS) $(ASTLDFLAGS) $(SOLINK) $(SO_SUPPRESS_SYMBOLS)
-+CXX_LDFLAGS_SO=$(PTHREAD_CFLAGS) $(ASTLDFLAGS) $(SOLINK) $(SO_SUPPRESS_SYMBOLS)
- CC_LIBS=$(PTHREAD_LIBS) $(LIBS)
- CXX_LIBS=$(PTHREAD_LIBS) $(LIBS)
-
-Index: cdr/cdr_radius.c
-===================================================================
---- a/cdr/cdr_radius.c (.../tags/1.6.2.0-beta1) (revision 186562)
-+++ b/cdr/cdr_radius.c (.../trunk) (revision 186562)
-@@ -205,13 +205,19 @@
-
- if (build_radius_record(&tosend, cdr)) {
- ast_debug(1, "Unable to create RADIUS record. CDR not recorded!\n");
-- return result;
-+ goto return_cleanup;
- }
-
- result = rc_acct(rh, 0, tosend);
-- if (result != OK_RC)
-+ if (result != OK_RC) {
- ast_log(LOG_ERROR, "Failed to record Radius CDR record!\n");
-+ }
-
-+return_cleanup:
-+ if (tosend) {
-+ rc_avpair_free(tosend);
-+ }
-+
- return result;
- }
-
-
-Property changes on: .
-___________________________________________________________________
-Deleted: trunk-blocked
- - /trunk:182362,182521,182762,182960,183124,183148
-Deleted: trunk-merged
- - /trunk:1-182359,182408,182450,182525,182530,182553,182722,182847,183028,183057,183108,183117
-Added: branch-1.4-blocked
- + /branches/1.4:43484,43510,43582,43626,43703,43756,44023,44080,44109,44407,44409,44567,44650,44660-44662,44665,44746,44760,44776-44777,44805,44992,45246,45313-45314,45381,45464,46114-46117,46165,46214,46253,46255,46401,46431,46583,46716,46883,47107-47108,47323,47329,47344,47348,47369,47444,47542,47553,47558,47564,47573,47576,47613,47736,47762,47856,47892,48046,48147,48162,48195,48234,48270,48281,48561,48583,48931,49022,49024,49032,49035,49070,49096,49189,49212,49282,49388,49710,50186,50921,51245,51755,51895,52000,52158,52373,52535,52809,52856,53077,53086,53099,53818,53878,54026,56006,56922,57591,58939,58955,59042,59069-59070,59230,60709,61220,62095,62299,62739,62913,63283,63656,64280,64565,64605,65394,65452,66068,66160,66244,66312,66602,66637,67018,67372,72453,72462,72493,72554,72597,72599,72665,73143,74262,74628,74839,75437,75439,75447,75712,75980,76054,76176,76178,76227,76891,77871,78146,78416,78620,78826,78860,80086,80088,80167,80497,80689,80747,81375,81492,82198,82276,82398,83400,83653,84163,84437,84544,85397,85536,85548,85687,85717,85852,86028,86371-86372,86406,87067,87340,87534,88471,89111,89191,89254,89339,89616,89727,89999,90147,90546,90798,91032,91501,92200,92510,93000,93183,93420,93764,94466,94543,94765,94769,94831,96020,96022,96024,97206,98025,98082,98265,98734,98849,98972-98973,98982,99127,99878,100418,100673,100934,101820,102653,103503,103556,103607,103698,103701,103703,103709,103713,103768,103807,104026-104027,104111,104332,104591,105591,107472,107582,109057,109171,109393,110880,112689,112709,113507,114032,114072,114167,114173,114180,114211,114248,114297,114299,114522,114542,114545,114550,114649,115257,115517,117523,117809,118055,119076,120061,120371,120671,120731,121992,122208,122314,122613,122663,124743,124908,125530,125893,126395,126680,127069,127501,127754,128029,128637,129158,129208,129505,130042,130298,130317,130373,131480,132042,132784,132787,132974,133237,133709,134652,134704,134976,136238,136304,136348,136404,136458,136560,137348,137527,137529,137580,137677,137850,138309,138516,138569,138938,138949,139145,139521,139769,140050,140115,141217,141267,141678,143204,143270,143475,143674,143964,144420,144758,145839,146129,146244,147941,148990,149840,150557,150816,151100,151167,151763,154724,158306,158629,159158,159571,160570,160764,162071,162670-162671,163785,164082,164204,164343,165537,165991,166157,166262,166592,168598,169581,169797,171120,171122,171452,172639,173248,173770,173900,174644,174885,175407,175698,177160,177450,177696,178640,178838,180010,181133,182652,182963,182965,184980,185298,185531,186057
-Added: branch-1.4-merged
- + /branches/1.4:1-43376,43383,43386,43388,43392,43396,43405,43410,43422,43441,43445,43450,43454,43456,43464,43466,43469,43477,43482,43486,43489,43492,43518,43524,43553,43564,43616,43635-43702,43704-43755,43757-43800,43802-43846,43852,43861-43862,43864,43873,43877,43893,43898-43899,43913,43915,43918-43919,43933,43944,43952,43978,43993,43996-44012,44022,44034-44043,44053,44055,44057,44068,44078,44090,44111,44125,44135,44166-44167,44169,44186,44199,44215,44283-44286,44298,44312,44322,44378,44390,44393,44433,44436,44450,44476,44486,44502,44559,44561-44563,44581,44605,44628,44631,44684,44759,44764,44786,44788,44806,44808-44809,44819,44888,44911,44921,44942,44945,44956,44971,44982,44994,45026-45027,45031,45040,45049,45051,45066,45079,45088,45104,45106,45125,45196,45213,45262,45280,45327,45378,45408,45410,45439,45441,45452,45517,45595,45622,45646,45678,45692,45694,45741,45775,45817-45818,45916,45928,45999,46065,46067,46078,46080,46082-46113,46118-46141,46143-46154,46200,46216,46237,46249,46252,46276,46298,46329,46347,46351-46353,46358,46363,46367,46370,46377,46382,46389,46398,46403,46407,46433,46474,46506,46511,46526,46554,46558,46561,46563,46606,46628,46631,46714,46744,46775,46778,46780,46822,46845,46847,46857,46901,46930,46937,46965,46992,47015,47051,47053,47192,47195-47196,47199,47239,47250,47268,47279,47284,47287,47309,47327,47331,47333,47352,47366,47372,47375,47377,47380,47391,47398,47405,47414,47418,47432-47433,47436,47454,47457,47463,47466,47474,47476,47492,47494,47497,47507,47509,47511,47513,47523,47526-47527,47540,47551,47572,47581,47584,47597,47617,47621,47625,47628,47632,47635,47639,47641,47645,47656,47684,47690,47693,47698,47701,47707,47709,47712,47733,47744,47748,47751,47755,47758,47764,47777,47782,47823,47843,47845,47850,47852,47860,47864-47865,47897,47944,47959,47989,47992,48002,48015,48017,48031,48038,48049,48054,48088,48095,48101,48105,48107,48113,48115,48129,48135,48143,48152,48155,48158,48166,48168,48177,48179,48186,48190,48193,48199,48219,48223,48228,48230,48248,48252,48254,48264,48279,48317,48323,48326,48349,48357,48363,48372,48375,48377,48379,48381-48382,48391,48396,48399,48401,48427,48461,48472,48478,48481,48487,48502,48504,48506,48513,48521,48525,48528,48548,48554,48564,48571,48577,48586,48592,48596,48637,48783,48870,48888,48906,48944,48948,48956,48960,48964,48966,48975,48977,48980,48982,48985,48987-48988,48993,48995,48997,49006,49009,49024,49028,49046,49061,49063,49066,49073,49098-49099,49102,49145,49165,49237,49259,49313,49355,49413,49457-49461,49465,49523,49536,49551,49553,49581,49600,49636,49680,49705,49712,49714-49715,49742,49831,49834,49866,49890,49925,49945,49983,50006,50032,50073,50098,50124,50151,50228,50266,50298,50346,50377,50405,50433,50466,50468,50562,50602,50647,50674,50727,50754,50782,50820,50867,50895,50957,50994,51030,51057,51087,51146,51148,51150,51159,51162,51165,51167,51170,51172,51176,51182,51186,51195,51198,51204-51205,51211,51213,51233,51236,51241,51243,51251,51256,51262,51265,51272,51274,51311,51326,51328,51331,51339,51341,51343,51348,51350,51407,51409,51513,51558,51615,51683,51716,51750,51781,51788,51829,51848,51931,51989,52016,52049,52052,52107,52160,52163,52208,52210,52265,52335,52370,52416,52462,52494-52506,52523,52572,52611,52645,52647,52679,52688,52695,52717,52763,52807-52808,52904,52952,52997,52999,53001,53035,53037,53040,53042,53046,53050,53052,53057,53062,53064,53070,53072,53075,53079,53081,53085,53088,53093,53097,53104,53109,53114,53118,53120,53131,53136,53138,53143,53150,53152,53246,53294,53324,53355,53358,53399,53429,53434,53464,53497,53530,53532,53601,53715,53749,53779-53781,53783,53810,53850,53879-53881,54002,54066,54103,54204,54218,54235,54290,54375,54481,54623,54714,54772,54787,54884,54886,54888,54898,54924,54969,55002,55006,55050,55052,55086,55129,55154,55217,55219,55278,55397,55435,55483,55553,55555,55590,55634,55670,55688,55717,55741,55758,55799,55834,55869,55914,55947,55949,55951,55954,55957,56008,56011,56055,56094,56125,56231,56277,56341,56372,56407,56457,56505,56569,56685,56740,56783,56785,56805,56839,56847,56856,56888,56975,57049,57053,57055,57089,57093,57139,57144,57146,57203,57207,57318,57364,57396,57426,57473,57477,57556,57649,57768,57770,57798,57826,57870,57872,57914,58023,58053,58119,58121,58165,58240,58243,58320,58351-58352,58354,58389,58436,58474,58479,58510,58512,58584,58604,58638,58669,58705,58779,58783,58825-58826,58843,58845,58848,58902,58906,58923,58931,58933,58935,58937,58941,58946-58947,58953,58957,58992,59035,59037,59040,59049,59064,59076,59078,59081,59087,59089,59145,59180,59182,59188,59195,59200,59202,59206,59213,59215,59217,59223,59225,59228,59254,59256,59259,59261-59262,59273,59275,59278,59281,59284,59289,59302,59304,59341,59358,59361,59363,59452,59486,59522,59573,59654,59688,59724,59774,59804,59853,59887,59936,59939,59963,60069,60088,60112,60137,60214,60265,60268,60323,60325,60361,60399,60459,60485,60521,60565,60603,60661,60712-60713,60762,60798,60847,60850,60936,60984,60989,61183,61342-61443,61477,61641,61644-61645,61648,61651,61656,61658,61674,61676,61678,61681,61683,61686,61690,61694,61697,61705,61707,61763,61765,61772,61774,61779,61787,61799,61805,61863,61870,61914,61959,61961,62005,62038,62137,62171,62174,62218,62331,62369,62371,62414,62419,62497,62545,62548,62624,62689,62692,62738,62789,62797-62807,62842,62883,62912,62942,62986,62989,63047,63099,63152,63254,63286,63329,63360,63403,63445,63448,63478,63532,63534-63535,63566,63608,63611-63612,63698,63749,63804,63830,63872,63886,63905,63982,64044,64086,64114,64157,64193,64240,64276,64278,64306,64324,64353,64426,64515-64516,64543,64578,64602,64686,64720,64754,64756,64759,64761,64820,64868,64904,64974,65039,65076,65123,65200-65201,65250,65342,65408,65501,65541,65589,65677,65679-65680,65683,65685,65768,65836,65839,65841-65842,65853,65863,65866,65965-65967,65978,66026,66029-66030,66070,66074,66076,66157,66159,66363,66398,66404,66414,66437,66474,66503,66538,66671,66768,66770,66775,66821,66879,66881,66897,66916,66919,67020-67021,67026,67061,67064,67066,67068,67071,67073,67119,67121,67156,67158,67162,67210,67270,67304,67308,67329,67334,67360,67420,67457,67492,67526,67558,67594,67597,67626,67631,67650,67716,67804,67862,67872,67924,67941,67993,68027-68028,68030,68071,68157,68192,68198,68211,68249,68280,68313,68326,68354,68370,68401,68450,68527,68595,68644,68683,68733,68781,68814,68922,69010,69012,69014,69016,69069,69071,69128,69144,69181,69183-69184,69221,69259,69358,69392,69434,69470,69518,69558,69579,69625,69660-69661,69668,69689,69702,69708,69744,69775,69794,69796,69805,69847,69895,69944,69987,70003,70062,70084,70164,70198,70360,70397,70445,70494,70552,70554,70560,70612,70656,70677,70726-70727,70808,70841,70866,70883,70899,70949,71003,71063,71096,71106,71118,71120-71123,71214,71230,71289,71291,71362,71371,71412,71422,71430,71519,71522,71576,71657,71751,71796,71877,71915,71953,72006,72042,72112,72125,72148,72257,72260,72272,72328,72331,72335,72381,72383,72556,72705,72766,72806,72850-72852,72888,72926,72933,73005,73053,73208,73253,73316,73319,73355,73398,73400,73467,73512,73548,73551,73555,73598,73629,73675,73679,73696,73727,73769,73849,73930,73980,73985,74043,74045,74047,74082,74120,74122,74159,74162,74211,74265,74314,74317,74323,74374,74379,74388,74428,74476,74515,74572,74642,74722,74767,74815,74864,74866,74888,74922,74955,74997,75053,75067,75078,75108,75253,75306,75401,75403,75405,75441,75445,75450,75529,75583,75619,75621,75623,75658,75707,75711,75732,75749,75759,75807,75928,75969,75978,76067,76087,76132,76139,76174,76211,76485,76519,76561,76618,76620,76654,76656,76708,76801,76803,76937,76983,77071,77154,77176,77191,77318,77348,77350,77380,77410,77424-77429,77460,77490,77536,77540,77571,77768,77771,77778,77780,77783,77785,77788,77794-77795,77824,77827,77831,77844,77852,77854,77863,77865,77867,77869,77883,77886-77887,77890,77894,77939,77943,77945,77947,77949,77993,77996,78028,78063,78095,78101,78103,78242,78275,78371,78375,78415,78437,78450,78488,78569,78575,78646,78717,78749,78778,78859,78891,78907,78936,78951,78955,78995,79044,79049,79142,79174,79207,79214,79255,79397,79436,79470,79523,79527,79553,79642,79665,79690,79748,79756,79778,79792,79833,79857,79902,79904,79906,79912,79947,79998,80044,80047,80049,80130,80132,80166,80183,80255,80257,80302,80304,80330,80360,80362,80390,80424,80426,80469,80499,80501,80539,80547,80573,80661,80717,80722,80750,80789,80820,80849,80895,80932,80974,81010,81012,81042,81065,81074,81120,81158,81189,81226,81291,81331,81340,81342,81346,81349,81367,81369,81373,81379,81381,81383,81392,81395,81397,81401,81403,81405-81406,81410,81412,81415-81416,81418,81426,81433,81435,81437,81439,81442,81448,81453,81455,81520,81523,81525,81569,81599,81650,81682,81713,81743,81776,81778,81826,81832,81886,81923,81952,81997,82028,82091,82155,82236,82238,82240,82243,82245,82250,82252,82261,82263,82265,82267,82274,82278,82280,82285-82286,82291,82296,82309,82326,82335,82337,82339,82344,82346,82358,82376,82385,82394,82396,82435,82444,82514,82590-82592,82594,82644,82676,82751,82802,82834,82865,82867,82929,82961,82992,83023-83024,83070,83074,83121,83175,83177,83179,83230,83232,83246,83316,83348,83432,83558,83589,83637,83695,83773,83879,83910,83941,83943,83974,83976,84018,84049,84078,84133,84146,84158,84160,84166,84170,84206,84236,84239,84271,84274,84291,84370,84410,84474,84511,84581,84637,84690,84692,84742,84783,84818,84851,84890,84902,84957,84990,85023,85057,85093,85158,85195,85242,85276,85280,85316,85356,85515,85517,85523,85532-85533,85540,85543,85545,85552,85556,85559,85561,85571,85604,85647,85649,85684,85686,85720,85818,85850,85896,85921,85958,85994,85997,86032,86063,86066,86117,86149,86202,86237,86296,86328,86330,86405,86469,86471,86502,86598,86630,86661,86663,86694,86726,86750,86754,86756,86787,86836,86880-86881,86902,86936,86982,87069,87120,87168,87262,87294,87342,87373,87396,87460,87567,87571,87650,87686,87739,87775,87849,87852,87906,87908,87970,88026,88078,88116,88210,88283,88328,88366,88539,88585,88624,88671,88709,88719,88765,88768,88805,88826,88862,88931,88994,89032,89036-89037,89042,89045-89046,89053,89079,89088,89090,89093,89095,89097,89099,89101,89103,89105,89115,89119,89125,89169-89173,89184,89194,89205,89239,89241,89246,89248,89260,89275,89280-89281,89286,89288,89296,89298,89301-89302,89323,89325,89416,89419,89450,89457,89491,89493,89495,89527,89534,89536,89540,89545,89559,89571,89577,89580,89586-89587,89592,89594,89599,89610,89618,89622,89624,89630-89631,89634,89701,89709,89790,89837,89839,89844,89886,89893,90059,90098,90101,90142,90145,90154-90155,90160,90163,90166-90545,90547-90753,90876,90967,91070,91074,91192,91237,91273,91292,91366,91439,91450,91637,91675,91677,91693,91737,91777,91780,91783,91826,91828,91830,91890,92158,92202,92204,92323,92363,92443,92463,92617,92696,92803,92807,92809,92815,92875,92933-92934,92937,93180,93182,93250,93291,93336,93377,93381,93625,93668,93949,93955,94077,94122,94251,94256,94418,94420,94464,94468,94538,94540,94660,94763,94767,94789-94790,94793,94797,94801,94808,94824,94828-94829,94905,94924,94977,95024,95095,95191,95470,95577,95890,95946,96102,96198-96199,96318,96394,96449,96525,96573,96575,96644,96884,96932,97077,97093,97152,97192,97194-97195,97304,97308,97350,97410,97448,97450,97489,97491,97529,97575,97618,97622,97640,97645,97697,97734,97753,97847,97849,97889,97925,97973,97976,98164,98219,98315,98317,98325,98372,98390,98467,98733,98774,98894,98934,98943,98946,98951,98955,98958,98960,98964,98966,98991,99004,99079,99081,99187,99301,99341,99426,99540,99592,99594,99643,99652,99718,99775,99777,99923,99975,99977-99978,100138,100164,100264,100378,100465,100581,100624,100626,100629,100672,100675,100740,100793,100835,100882,100922,100930,100932,100973,101035,101080,101152,101216,101219,101222,101413-101414,101433,101480,101482,101531,101601,101649,101693,101772,101818,101822,101894,101942,101989,102090,102142,102214,102323,102378,102450,102453,102576,102651,102725,102807,102858,102968,103070,103120,103197,103315,103324,103385,103683,103688,103690,103722,103726,103728,103741,103763,103770,103780,103786,103790,103795,103801,103812,103821,103823,103845,103904,103953,103956,104015,104037,104082,104084,104086,104092,104094-104095,104102,104106,104119,104132,104135,104139,104141,104334,104536,104593,104596,104598,104625,104665,104704,104783,104787,104841,105059,105113,105116,105261,105326,105409,105557,105560,105563,105565,105568,105570,105572,105674,105676,105932,106015,106038,106235,106237,106328,106437,106552,106606,106635,106704,106788,106842,106895,106945,107016,107099,107102,107158,107161,107173,107230,107290,107352,107405,107408,107461,107464,107637,107646,107713-107714,107826,107877,108031,108083,108086,108135,108227,108288,108469,108530,108583,108682,108737,108792,108796,108961,109012,109107,109226,109309,109386,109575,109648,109713,109763,109838,109908,109973,110019,110035,110083,110163,110336,110395,110474,110614,110628,110635,110779,110962,111014,111020,111024,111049,111121,111126,111129,111245,111280,111341,111391,111442,111605,111658,111720,111856,112068,112125,112138,112204,112209,112393,112468,112599,112711,112766,112820,113012,113065,113117-113118,113296,113348,113399,113402,113454,113504,113596,113681,113784,113874,113927,114021,114029,114035,114045,114051,114063,114083,114100,114103,114106,114112,114117,114120,114133,114138,114148,114184,114191,114195,114198,114204,114207,114226,114230,114242,114257,114275,114278,114284,114322,114537,114558,114571,114579,114584,114587,114591,114594,114597,114600,114603,114608,114621,114624,114628,114632,114662,114673,114689,114695,114708,114823,114829,114848,114875,114880,114890-114891,115017,115102,115196,115276,115279,115282,115285,115304,115308,115312,115320,115327,115333,115341,115415,115418,115422,115512,115545,115551,115554,115557,115561,115565,115568,115579,115884,115944,115990,116038,116088,116230,116296,116352,116409,116463,116466,116799,116978,117081,117086,117135,117462,117479,117507,117514,117519,117574,117582,117899,118048,118052,118163,118251,118358,118365,118465,118509,118551,118558,118646,118858,118953-118954,118956,118961,119009,119012,119071,119156,119238,119301,119354,119404,119478,119530,119533,119585,119636,119687,119742,119838,119926,119929,120001,120168,120173,120226,120282,120285,120425,120513,120675,120863-120885,120908,120959,121078,121229,121280,121442,121495,121596,121751,121804,121861,122046,122127,122130,122137,122259,122311,122713,122869,122919,123110,123113,123271,123274,123333,123391,123485,123710,123769,123869,123883,123909,123930,124112,124182,124315,124372,124395,124450,124540,124910,124965,125132,125218,125276,125327,125384,125585,125587,125740,125793,126056,126516,126573,126735,126789,126844,126899,126902,126999,127068,127133,127244,127560,127663,127892-127895,127973,128639,128737,128795,128812,128856,128912,128950,129047,129149,129343,129436,129567,129741,129803,129907,129966-129967,129970,130039,130102,130169,130173,130236,130514,130573,130634,130735,130792,130889,130959,131012,131242,131299,131357,131369,131421,131491,131790,131915,131921,131970,131985,131988,132107,132112,132311,132571,132641-132642,132645,132704,132712-132713,132826,132872,133038,133101,133104,133169,133295,133488,133572,133578,133649,134161,134254,134352,134475,134480,134536,134540,134595,134649,134758,134883,134915,134983,135055,135058,135473,135479,135482,135536,135597,135747,135799,135841-135850,135899,135915,135949,136062,136190,136241,136484,136488,136726,136946,137138,137405,137530,137679,137731,137847,138023,138027,138119-138238,138258,138360,138886,138942,139015,139074,139213,139347,139387,139456,139466,139553,139621,139635,139764,139869,139909,139927,140051,140056,140060,140421,140488,140605,140670,140690,140747,140751,140816,140850,141028,141094,141156,141366,141503,141565,141741,141806,141809,142063,142079,142218,142354,142358,142416,142474,142575,142675,142740,142744,142807,142865,142927,143140,143337,143404,143534,143736,143903,144066,144238,144356,144677,144924-144925,145479,145751,146026,146448,146643,146711,146799,147193,147517,147681,147997,148257,148611,148736,148912,148916,148987,149061,149130,149200,149204,149207,149266,149452,149683,150124,150304,151240-151241,151905,152059,152215,152286,152368,152463,152535,152538-152539,152811,152922,152958,152992,153114,153337,153651,154060,154066,154263,154266,154365,154685,155011,155398,155553,155803,155861,156164,156167,156178,156229,156289,156294,156297,156386,156688,156755,156816,157104,157162-157163,157305,157365,157859,158053,158071,158126,158483,158539,158600,158603,159025,159246,159269,159316,159476,159808,159897,159900,159976,160003,160207,160297,160480,160551,160558,160703,160770,160943,161013,161287,161426,161725,161948,162013-162014,162136,162188,162204,162264-162265,162273,162286,162341,162348,162413,162463,162653,162659,162663,162738,162804,162874,162926,163080,163084,163088,163092,163253,163316,163383,163448,163511,163761,164201,164350,164416,164422,164605,164634,164672,164736,164806,164876,164881,164977,165317,165591,165661,165767,165796,165889,166093,166297,166380,166509,166568,166772,166953,167095,167179,167260,167299,167432,167541,167545,167554,167566,167714,167840,168128,168191,168198,168267,168480,168507,168516,168546,168551,168561,168593,168603,168608,168614,168622,168628,168716,168721,168745,168828,168975,169210,169364,169485,169722,169867,169943,170050,170147,170158,170239,170392,170504,170568,170588,170648,170671,170719,170836,170979,171187,171264,171527,171621,171837,171963,172030,172169,172438,172962,173066,173070,173211,173392,173396,173559,173592,173692,173696,173917,173967-173968,174082,174148,174218,174282,174369,174583,175029,175124,175187,175294,175311,175590,175777,175792,175825,175921,176029,176216,176249-176252,176254,176354,176426,176661,176701,177096,177225,177383,177536,177540,177701,177786,178141,178205,178373,178445,178508,178804,178956,179395,179461,179468,179532,179536,179608,179671,179741,179807,179840,180006,180194,180372,180380,180464,180532,180567,180941,181029-181031,181295,181328,181340,181423,181436,181655,181659-181660,181664,181768,181898,181990,182208,182281,182449,182808,182810,182882,183115,183123,183126,183145,183238,183241,183291,183319,183342,183386,183559,183700,183913,184078,184188,184388,184447,184565,184842,184947,185031,185120-185121,185196,185362,185468,185599,185771,185845,185952,186059,186081,186174,186229,186320,186415,186445,186458
-Modified: svn:externals
- - menuselect http://svn.digium.com/svn/menuselect/tags/autotag_for_asterisk/1.6.2.0-beta1
-
- + menuselect http://svn.digium.com/svn/menuselect/trunk
-
-
diff --git a/testing/asterisk/asterisk-03-1.6.2.0-beta3-to-svn-r202568.patch b/testing/asterisk/asterisk-03-1.6.2.0-beta3-to-svn-r202568.patch
new file mode 100644
index 000000000..9f8a9cdc6
--- /dev/null
+++ b/testing/asterisk/asterisk-03-1.6.2.0-beta3-to-svn-r202568.patch
@@ -0,0 +1,102239 @@
+Index: .version
+===================================================================
+--- a/.version (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/.version (.../trunk) (revision 202568)
+@@ -1 +1 @@
+-1.6.2.0-beta3
++1.6.3.0-r202568
+Index: build_tools/strip_nonapi
+===================================================================
+--- a/build_tools/strip_nonapi (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/build_tools/strip_nonapi (.../trunk) (revision 202568)
+@@ -1,38 +0,0 @@
+-#!/bin/sh -e
+-
+-# This script is designed to remove all non-API global symbols from an object
+-# file. The only global symbols that should be retained are those that belong
+-# to the official namespace. Unfortunately doing this is platform-specific, as
+-# the object file manipulation tools are not consistent across platforms.
+-#
+-# On platforms where this script does not know what to do, the object file
+-# will retain non-API global symbols, and this may have unpleasant side effects.
+-#
+-# Prefixes that belong to the official namespace are:
+-# ast_
+-# _ast_
+-# __ast_
+-# astman_
+-# pbx_
+-# resample_
+-
+-FILTER="${GREP} -v -e ^ast_ -e ^_ast_ -e ^__ast_ -e ^astman_ -e ^pbx_ -e ^resample_"
+-
+-case "${PROC}" in
+- powerpc64)
+- TEXTSYM=" D "
+- ;;
+- *)
+- TEXTSYM=" T "
+- ;;
+-esac
+-
+-case "${OSARCH}" in
+- linux-gnu|FreeBSD)
+- nm ${1} | ${GREP} -e "$TEXTSYM" | cut -d" " -f3 | ${FILTER} > striplist
+- sed -e "s/^/-N /" striplist | xargs -n 40 ${STRIP} ${1}
+- rm -f striplist
+- ;;
+- *)
+- ;;
+-esac
+Index: build_tools/cflags.xml
+===================================================================
+--- a/build_tools/cflags.xml (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/build_tools/cflags.xml (.../trunk) (revision 202568)
+@@ -32,8 +32,6 @@
+ <member name="TEST_TANDEM_TRANSCODING" displayname="New ulaw/alaw codec, turn on transcoding tests on init">
+ <depend>G711_NEW_ALGORITHM</depend>
+ </member>
+- <member name="DEBUG_CHANNEL_LOCKS" displayname="Debug Channel Locking">
+- </member>
+ <member name="MALLOC_DEBUG" displayname="Keep Track of Memory Allocations">
+ </member>
+ <member name="BUSYDETECT_TONEONLY" displayname="Enable additional comparision of only the tone duration not the silence part">
+Index: build_tools/menuselect-deps.in
+===================================================================
+--- a/build_tools/menuselect-deps.in (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/build_tools/menuselect-deps.in (.../trunk) (revision 202568)
+@@ -11,6 +11,7 @@
+ GTK=@PBX_GTK@
+ H323=@PBX_H323@
+ HOARD=@PBX_HOARD@
++ICAL=@PBX_ICAL@
+ ICONV=@PBX_ICONV@
+ IKSEMEL=@PBX_IKSEMEL@
+ IMAP_TK=@PBX_IMAP_TK@
+@@ -19,12 +20,14 @@
+ IXJUSER=@PBX_IXJUSER@
+ JACK=@PBX_JACK@
+ LDAP=@PBX_LDAP@
++LIBXML2=@PBX_LIBXML2@
+ LTDL=@PBX_LTDL@
+ LUA=@PBX_LUA@
+ MISDN=@PBX_MISDN@
+ NBS=@PBX_NBS@
+ NETSNMP=@PBX_NETSNMP@
+ NEWT=@PBX_NEWT@
++NEON=@PBX_NEON@
+ OGG=@PBX_OGG@
+ OPENH323=@PBX_OPENH323@
+ OSPTK=@PBX_OSPTK@
+@@ -33,6 +36,7 @@
+ POPT=@PBX_POPT@
+ PORTAUDIO=@PBX_PORTAUDIO@
+ PRI=@PBX_PRI@
++OPENR2=@PBX_OPENR2@
+ RESAMPLE=@PBX_RESAMPLE@
+ AIS=@PBX_AIS@
+ RADIUS=@PBX_RADIUS@
+Index: configure
+===================================================================
+Cannot display: file marked as a binary type.
+svn:mime-type = application/octet-stream
+Index: default.exports
+===================================================================
+--- a/default.exports (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/default.exports (.../trunk) (revision 202568)
+@@ -0,0 +1,4 @@
++{
++ local:
++ *;
++};
+
+Property changes on: default.exports
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+
+Index: pbx/pbx_config.c
+===================================================================
+--- a/pbx/pbx_config.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/pbx/pbx_config.c (.../trunk) (revision 202568)
+@@ -328,7 +328,7 @@
+ * Priority input checking ...
+ */
+ if (a->argc == 5) {
+- char *c = a->argv[4];
++ const char *c = a->argv[4];
+
+ /* check for digits in whole parameter for right priority ...
+ * why? because atoi (strtol) returns 0 if any characters in
+@@ -451,8 +451,7 @@
+
+ ast_unlock_contexts();
+ error2:
+- if (exten)
+- free(exten);
++ free(exten);
+ } else if (a->pos == 4) { /* 'dialplan remove extension EXT _X_' (priority) */
+ char *exten = NULL, *context, *cid, *p;
+ struct ast_context *c;
+@@ -509,8 +508,7 @@
+ }
+ ast_unlock_contexts();
+ error3:
+- if (exten)
+- free(exten);
++ free(exten);
+ }
+ return ret;
+ }
+@@ -935,8 +933,7 @@
+ if (strcmp(a->argv[6], "replace"))
+ return CLI_SHOWUSAGE;
+
+- /* XXX overwrite argv[3] */
+- whole_exten = a->argv[3];
++ whole_exten = ast_strdupa(a->argv[3]);
+ exten = strsep(&whole_exten,",");
+ if (strchr(exten, '/')) {
+ cidmatch = exten;
+@@ -1139,8 +1136,7 @@
+ ret = strdup(ast_get_context_name(c));
+ }
+
+- if (ignorepat)
+- free(ignorepat);
++ free(ignorepat);
+ ast_unlock_contexts();
+ return ret;
+ }
+Index: pbx/pbx_spool.c
+===================================================================
+--- a/pbx/pbx_spool.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/pbx/pbx_spool.c (.../trunk) (revision 202568)
+@@ -339,7 +339,7 @@
+ ast_log(LOG_NOTICE, "Call failed to go through, reason (%d) %s\n", reason, ast_channel_reason2str(reason));
+ if (o->retries >= o->maxretries + 1) {
+ /* Max retries exceeded */
+- ast_log(LOG_EVENT, "Queued call to %s/%s expired without completion after %d attempt%s\n", o->tech, o->dest, o->retries - 1, ((o->retries - 1) != 1) ? "s" : "");
++ ast_log(LOG_NOTICE, "Queued call to %s/%s expired without completion after %d attempt%s\n", o->tech, o->dest, o->retries - 1, ((o->retries - 1) != 1) ? "s" : "");
+ remove_from_queue(o, "Expired");
+ } else {
+ /* Notate that the call is still active */
+@@ -347,7 +347,6 @@
+ }
+ } else {
+ ast_log(LOG_NOTICE, "Call completed to %s/%s\n", o->tech, o->dest);
+- ast_log(LOG_EVENT, "Queued call to %s/%s completed\n", o->tech, o->dest);
+ remove_from_queue(o, "Completed");
+ }
+ free_outgoing(o);
+@@ -425,7 +424,7 @@
+ }
+ res = now;
+ } else {
+- ast_log(LOG_EVENT, "Queued call to %s/%s expired without completion after %d attempt%s\n", o->tech, o->dest, o->retries - 1, ((o->retries - 1) != 1) ? "s" : "");
++ ast_log(LOG_NOTICE, "Queued call to %s/%s expired without completion after %d attempt%s\n", o->tech, o->dest, o->retries - 1, ((o->retries - 1) != 1) ? "s" : "");
+ remove_from_queue(o, "Expired");
+ free_outgoing(o);
+ }
+Index: pbx/pbx_ael.c
+===================================================================
+--- a/pbx/pbx_ael.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/pbx/pbx_ael.c (.../trunk) (revision 202568)
+@@ -251,7 +251,7 @@
+ );
+
+ #ifdef AAL_ARGCHECK
+-static char *ael_funclist[] =
++static const char * const ael_funclist[] =
+ {
+ "AGENT",
+ "ARRAY",
+Index: pbx/pbx_lua.c
+===================================================================
+--- a/pbx/pbx_lua.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/pbx/pbx_lua.c (.../trunk) (revision 202568)
+@@ -93,8 +93,8 @@
+ static int exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data);
+
+ AST_MUTEX_DEFINE_STATIC(config_file_lock);
+-char *config_file_data = NULL;
+-long config_file_size = 0;
++static char *config_file_data = NULL;
++static long config_file_size = 0;
+
+ static struct ast_context *local_contexts = NULL;
+ static struct ast_hashtab *local_table = NULL;
+Index: pbx/pbx_realtime.c
+===================================================================
+--- a/pbx/pbx_realtime.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/pbx/pbx_realtime.c (.../trunk) (revision 202568)
+@@ -54,9 +54,9 @@
+
+ #define EXT_DATA_SIZE 256
+
+-enum {
++enum option_flags {
+ OPTION_PATTERNS_DISABLED = (1 << 0),
+-} option_flags;
++};
+
+ AST_APP_OPTIONS(switch_opts, {
+ AST_APP_OPTION('p', OPTION_PATTERNS_DISABLED),
+Index: pbx/pbx_dundi.c
+===================================================================
+--- a/pbx/pbx_dundi.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/pbx/pbx_dundi.c (.../trunk) (revision 202568)
+@@ -3876,7 +3876,7 @@
+ AST_APP_OPTION('b', OPT_BYPASS_CACHE),
+ END_OPTIONS );
+
+-unsigned int dundi_result_id;
++static unsigned int dundi_result_id;
+
+ struct dundi_result_datastore {
+ struct dundi_result results[MAX_RESULTS];
+Index: pbx/dundi-parser.c
+===================================================================
+--- a/pbx/dundi-parser.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/pbx/dundi-parser.c (.../trunk) (revision 202568)
+@@ -155,7 +155,7 @@
+
+ static void dump_cause(char *output, int maxlen, void *value, int len)
+ {
+- static char *causes[] = {
++ static const char * const causes[] = {
+ "SUCCESS",
+ "GENERAL",
+ "DYNAMIC",
+Index: channels/h323/ast_h323.cxx
+===================================================================
+--- a/channels/h323/ast_h323.cxx (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/channels/h323/ast_h323.cxx (.../trunk) (revision 202568)
+@@ -572,8 +572,7 @@
+ {
+ #ifdef H323_H450
+ /* Dispatcher will free out all registered handlers */
+- if (h450dispatcher)
+- delete h450dispatcher;
++ delete h450dispatcher;
+ h450dispatcher = new H450xDispatcher(*this);
+ h4502handler = new H4502Handler(*this, *h450dispatcher);
+ h4504handler = new MyH4504Handler(*this, *h450dispatcher);
+@@ -1988,8 +1987,9 @@
+ if (cap && cap->IsUsable(*this)) {
+ lastcap++;
+ lastcap = localCapabilities.SetCapability(0, lastcap, cap);
+- } else if (cap)
++ } else {
+ delete cap; /* Capability is not usable */
++ }
+
+ dtmfMode = dtmf_mode;
+ if (h323debug) {
+@@ -2001,8 +2001,9 @@
+ cap = new H323_UserInputCapability(H323_UserInputCapability::BasicString);
+ if (cap && cap->IsUsable(*this)) {
+ lastcap = localCapabilities.SetCapability(0, lastcap, cap);
+- } else if (cap)
++ } else {
+ delete cap; /* Capability is not usable */
++ }
+ sendUserInputMode = SendUserInputAsString;
+ } else {
+ if ((dtmfMode & H323_DTMF_RFC2833) != 0) {
+@@ -2011,8 +2012,7 @@
+ lastcap = localCapabilities.SetCapability(0, lastcap, cap);
+ else {
+ dtmfMode |= H323_DTMF_SIGNAL;
+- if (cap)
+- delete cap; /* Capability is not usable */
++ delete cap; /* Capability is not usable */
+ }
+ }
+ if ((dtmfMode & H323_DTMF_CISCO) != 0) {
+@@ -2024,8 +2024,7 @@
+ dtmfMode |= H323_DTMF_SIGNAL;
+ } else {
+ dtmfMode |= H323_DTMF_SIGNAL;
+- if (cap)
+- delete cap; /* Capability is not usable */
++ delete cap; /* Capability is not usable */
+ }
+ }
+ if ((dtmfMode & H323_DTMF_SIGNAL) != 0) {
+@@ -2033,7 +2032,7 @@
+ cap = new H323_UserInputCapability(H323_UserInputCapability::SignalToneH245);
+ if (cap && cap->IsUsable(*this))
+ lastcap = localCapabilities.SetCapability(0, lastcap, cap);
+- else if (cap)
++ else
+ delete cap; /* Capability is not usable */
+ }
+ sendUserInputMode = SendUserInputAsTone; /* RFC2833 transmission handled at Asterisk level */
+Index: channels/h323/README
+===================================================================
+--- a/channels/h323/README (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/channels/h323/README (.../trunk) (revision 202568)
+@@ -137,7 +137,7 @@
+
+ If you are motivated to update/fix this code please submit a
+ disclaimer along with the patch to the Asterisk bug
+-tracker: http://bugs.digium.com/
++tracker: https://issues.asterisk.org/
+
+
+ Jeremy McNamara
+Index: channels/misdn_config.c
+===================================================================
+--- a/channels/misdn_config.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/channels/misdn_config.c (.../trunk) (revision 202568)
+@@ -1,6 +1,6 @@
+ /*
+ * Asterisk -- An open source telephony toolkit.
+- *
++ *
+ * Copyright (C) 2005, Christian Richter
+ *
+ * Christian Richter <crich@beronet.com>
+@@ -132,7 +132,7 @@
+ { "musicclass", MISDN_CFG_MUSICCLASS, MISDN_CTYPE_STR, "default", NONE,
+ "Sets the musiconhold class." },
+ { "callerid", MISDN_CFG_CALLERID, MISDN_CTYPE_STR, "", NONE,
+- "Sets the caller ID." },
++ "Set the outgoing caller id to the value." },
+ { "method", MISDN_CFG_METHOD, MISDN_CTYPE_STR, "standard", NONE,
+ "Set the method to use for channel selection:\n"
+ "\t standard - Use the first free channel starting from the lowest number.\n"
+@@ -140,62 +140,71 @@
+ "\t round_robin - Use the round robin algorithm to select a channel. Use this\n"
+ "\t if you want to balance your load." },
+ { "dialplan", MISDN_CFG_DIALPLAN, MISDN_CTYPE_INT, "0", NONE,
+- "Dialplan means Type Of Number in ISDN Terms (for outgoing calls)\n"
+- "\n"
++ "Dialplan means Type Of Number in ISDN Terms\n"
+ "\tThere are different types of the dialplan:\n"
+ "\n"
+- "\tdialplan -> outgoing Number\n"
+- "\tlocaldialplan -> callerid\n"
+- "\tcpndialplan -> connected party number\n"
++ "\tdialplan -> for outgoing call's dialed number\n"
++ "\tlocaldialplan -> for outgoing call's callerid\n"
++ "\t (if -1 is set use the value from the asterisk channel)\n"
++ "\tcpndialplan -> for incoming call's connected party number sent to caller\n"
++ "\t (if -1 is set use the value from the asterisk channel)\n"
+ "\n"
+ "\tdialplan options:\n"
+ "\n"
+ "\t0 - unknown\n"
+ "\t1 - International\n"
+ "\t2 - National\n"
+- "\t4 - Subscriber\n"
+- "\n"
+- "\tThis setting is used for outgoing calls." },
++ "\t4 - Subscriber" },
+ { "localdialplan", MISDN_CFG_LOCALDIALPLAN, MISDN_CTYPE_INT, "0", NONE,
+- "Dialplan means Type Of Number in ISDN Terms (for outgoing calls)\n"
+- "\n"
++ "Dialplan means Type Of Number in ISDN Terms\n"
+ "\tThere are different types of the dialplan:\n"
+ "\n"
+- "\tdialplan -> outgoing Number\n"
+- "\tlocaldialplan -> callerid\n"
+- "\tcpndialplan -> connected party number\n"
++ "\tdialplan -> for outgoing call's dialed number\n"
++ "\tlocaldialplan -> for outgoing call's callerid\n"
++ "\t (if -1 is set use the value from the asterisk channel)\n"
++ "\tcpndialplan -> for incoming call's connected party number sent to caller\n"
++ "\t (if -1 is set use the value from the asterisk channel)\n"
+ "\n"
+ "\tdialplan options:\n"
+ "\n"
+ "\t0 - unknown\n"
+ "\t1 - International\n"
+ "\t2 - National\n"
+- "\t4 - Subscriber\n"
+- "\n"
+- "\tThis setting is used for outgoing calls." },
++ "\t4 - Subscriber" },
+ { "cpndialplan", MISDN_CFG_CPNDIALPLAN, MISDN_CTYPE_INT, "0", NONE,
+- "Dialplan means Type Of Number in ISDN Terms (for outgoing calls)\n"
+- "\n"
++ "Dialplan means Type Of Number in ISDN Terms\n"
+ "\tThere are different types of the dialplan:\n"
+ "\n"
+- "\tdialplan -> outgoing Number\n"
+- "\tlocaldialplan -> callerid\n"
+- "\tcpndialplan -> connected party number\n"
++ "\tdialplan -> for outgoing call's dialed number\n"
++ "\tlocaldialplan -> for outgoing call's callerid\n"
++ "\t (if -1 is set use the value from the asterisk channel)\n"
++ "\tcpndialplan -> for incoming call's connected party number sent to caller\n"
++ "\t (if -1 is set use the value from the asterisk channel)\n"
+ "\n"
+ "\tdialplan options:\n"
+ "\n"
+ "\t0 - unknown\n"
+ "\t1 - International\n"
+ "\t2 - National\n"
+- "\t4 - Subscriber\n"
+- "\n"
+- "\tThis setting is used for outgoing calls." },
+- { "nationalprefix", MISDN_CFG_NATPREFIX, MISDN_CTYPE_STR, "0", NONE,
+- "Prefix for national, this is put before the\n"
+- "\toad if an according dialplan is set by the other end." },
+- { "internationalprefix", MISDN_CFG_INTERNATPREFIX, MISDN_CTYPE_STR, "00", NONE,
+- "Prefix for international, this is put before the\n"
+- "\toad if an according dialplan is set by the other end." },
++ "\t4 - Subscriber" },
++ { "unknownprefix", MISDN_CFG_TON_PREFIX_UNKNOWN, MISDN_CTYPE_STR, "", NONE,
++ "Prefix for unknown numbers, this is put before an incoming number\n"
++ "\tif its type-of-number is unknown." },
++ { "internationalprefix", MISDN_CFG_TON_PREFIX_INTERNATIONAL, MISDN_CTYPE_STR, "00", NONE,
++ "Prefix for international numbers, this is put before an incoming number\n"
++ "\tif its type-of-number is international." },
++ { "nationalprefix", MISDN_CFG_TON_PREFIX_NATIONAL, MISDN_CTYPE_STR, "0", NONE,
++ "Prefix for national numbers, this is put before an incoming number\n"
++ "\tif its type-of-number is national." },
++ { "netspecificprefix", MISDN_CFG_TON_PREFIX_NETWORK_SPECIFIC, MISDN_CTYPE_STR, "", NONE,
++ "Prefix for network-specific numbers, this is put before an incoming number\n"
++ "\tif its type-of-number is network-specific." },
++ { "subscriberprefix", MISDN_CFG_TON_PREFIX_SUBSCRIBER, MISDN_CTYPE_STR, "", NONE,
++ "Prefix for subscriber numbers, this is put before an incoming number\n"
++ "\tif its type-of-number is subscriber." },
++ { "abbreviatedprefix", MISDN_CFG_TON_PREFIX_ABBREVIATED, MISDN_CTYPE_STR, "", NONE,
++ "Prefix for abbreviated numbers, this is put before an incoming number\n"
++ "\tif its type-of-number is abbreviated." },
+ { "presentation", MISDN_CFG_PRES, MISDN_CTYPE_INT, "-1", NONE,
+ "These (presentation and screen) are the exact isdn screening and presentation\n"
+ "\tindicators.\n"
+@@ -212,6 +221,28 @@
+ "\n"
+ "\tscreen=0, presentation=0 -> callerid presented\n"
+ "\tscreen=1, presentation=1 -> callerid restricted (the remote end doesn't see it!)" },
++ { "outgoing_colp", MISDN_CFG_OUTGOING_COLP, MISDN_CTYPE_INT, "0", NONE,
++ "Select what to do with outgoing COLP information on this port.\n"
++ "\n"
++ "\t0 - Send out COLP information unaltered.\n"
++ "\t1 - Force COLP to restricted on all outgoing COLP information.\n"
++ "\t2 - Do not send COLP information." },
++ { "display_connected", MISDN_CFG_DISPLAY_CONNECTED, MISDN_CTYPE_INT, "0", NONE,
++ "Put a display ie in the CONNECT message containing the following\n"
++ "\tinformation if it is available (nt port only):\n"
++ "\n"
++ "\t0 - Do not put the connected line information in the display ie.\n"
++ "\t1 - Put the available connected line name in the display ie.\n"
++ "\t2 - Put the available connected line number in the display ie.\n"
++ "\t3 - Put the available connected line name and number in the display ie." },
++ { "display_setup", MISDN_CFG_DISPLAY_SETUP, MISDN_CTYPE_INT, "0", NONE,
++ "Put a display ie in the SETUP message containing the following\n"
++ "\tinformation if it is available (nt port only):\n"
++ "\n"
++ "\t0 - Do not put the caller information in the display ie.\n"
++ "\t1 - Put the available caller name in the display ie.\n"
++ "\t2 - Put the available caller number in the display ie.\n"
++ "\t3 - Put the available caller name and number in the display ie." },
+ { "always_immediate", MISDN_CFG_ALWAYS_IMMEDIATE, MISDN_CTYPE_BOOL, "no", NONE,
+ "Enable this to get into the s dialplan-extension.\n"
+ "\tThere you can use DigitTimeout if you can't or don't want to use\n"
+@@ -220,7 +251,7 @@
+ { "nodialtone", MISDN_CFG_NODIALTONE, MISDN_CTYPE_BOOL, "no", NONE,
+ "Enable this to prevent chan_misdn to generate the dialtone\n"
+ "\tThis makes only sense together with the always_immediate=yes option\n"
+- "\tto generate your own dialtone with Playtones or so."},
++ "\tto generate your own dialtone with Playtones or so." },
+ { "immediate", MISDN_CFG_IMMEDIATE, MISDN_CTYPE_BOOL, "no", NONE,
+ "Enable this if you want callers which called exactly the base\n"
+ "\tnumber (so no extension is set) to jump into the s extension.\n"
+@@ -257,17 +288,17 @@
+ #endif
+ #ifdef WITH_BEROEC
+ { "bnechocancel", MISDN_CFG_BNECHOCANCEL, MISDN_CTYPE_BOOLINT, "yes", 64,
+- "echotail in ms (1-200)\n"},
++ "echotail in ms (1-200)" },
+ { "bnec_antihowl", MISDN_CFG_BNEC_ANTIHOWL, MISDN_CTYPE_INT, "0", NONE,
+- "Use antihowl\n"},
++ "Use antihowl" },
+ { "bnec_nlp", MISDN_CFG_BNEC_NLP, MISDN_CTYPE_BOOL, "yes", NONE,
+- "Nonlinear Processing (much faster adaption)"},
++ "Nonlinear Processing (much faster adaption)" },
+ { "bnec_zerocoeff", MISDN_CFG_BNEC_ZEROCOEFF, MISDN_CTYPE_BOOL, "no", NONE,
+- "ZeroCoeffeciens\n"},
++ "ZeroCoeffeciens" },
+ { "bnec_tonedisabler", MISDN_CFG_BNEC_TD, MISDN_CTYPE_BOOL, "no", NONE,
+- "Disable Tone\n"},
++ "Disable Tone" },
+ { "bnec_adaption", MISDN_CFG_BNEC_ADAPT, MISDN_CTYPE_INT, "1", NONE,
+- "Adaption mode (0=no,1=full,2=fast)\n"},
++ "Adaption mode (0=no,1=full,2=fast)" },
+ #endif
+ { "need_more_infos", MISDN_CFG_NEED_MORE_INFOS, MISDN_CTYPE_BOOL, "0", NONE,
+ "Send Setup_Acknowledge on incoming calls anyway (instead of PROCEEDING),\n"
+@@ -311,13 +342,13 @@
+ { "faxdetect_context", MISDN_CFG_FAXDETECT_CONTEXT, MISDN_CTYPE_STR, NO_DEFAULT, NONE,
+ "Context to jump into if we detect a fax. Don't set this if you want to stay in the current context." },
+ { "l1watcher_timeout", MISDN_CFG_L1_TIMEOUT, MISDN_CTYPE_BOOLINT, "0", 4,
+- "Watches the layer 1. If the layer 1 is down, it tries to\n"
+- "\tget it up. The timeout is given in seconds. with 0 as value it\n"
+- "\tdoes not watch the l1 at all\n"
++ "Monitors L1 of the port. If L1 is down it tries\n"
++ "\tto bring it up. The polling timeout is given in seconds.\n"
++ "\tSetting the value to 0 disables monitoring L1 of the port.\n"
+ "\n"
+- "\tThis option is only read at loading time of chan_misdn, which\n"
+- "\tmeans you need to unload and load chan_misdn to change the value,\n"
+- "\tan Asterisk restart should do the trick." },
++ "\tThis option is only read at chan_misdn loading time.\n"
++ "\tYou need to unload and load chan_misdn to change the\n"
++ "\tvalue. An asterisk restart will also do the trick." },
+ { "overlapdial", MISDN_CFG_OVERLAP_DIAL, MISDN_CTYPE_BOOLINT, "0", 4,
+ "Enables overlap dial for the given amount of seconds.\n"
+ "\tPossible values are positive integers or:\n"
+@@ -336,6 +367,8 @@
+ "MSN's for TE ports, listen on those numbers on the above ports, and\n"
+ "\tindicate the incoming calls to Asterisk.\n"
+ "\tHere you can give a comma separated list, or simply an '*' for any msn." },
++ { "cc_request_retention", MISDN_CFG_CC_REQUEST_RETENTION, MISDN_CTYPE_BOOL, "yes", NONE,
++ "Enable/Disable call-completion request retention support (ptp)." },
+ };
+
+ static const struct misdn_cfg_spec gen_spec[] = {
+@@ -365,8 +398,8 @@
+ { "crypt_keys", MISDN_GEN_CRYPT_KEYS, MISDN_CTYPE_STR, NO_DEFAULT, NONE,
+ "Keys for cryption, you reference them in the dialplan\n"
+ "\tLater also in dynamic encr." },
+- { "ntkeepcalls", MISDN_GEN_NTKEEPCALLS, MISDN_CTYPE_BOOL, "no", NONE,
+- "avoid dropping calls if the L2 goes down. some Nortel pbx\n"
++ { "ntkeepcalls", MISDN_GEN_NTKEEPCALLS, MISDN_CTYPE_BOOL, "no", NONE,
++ "avoid dropping calls if the L2 goes down. some Nortel pbx\n"
+ "do put down the L2/L1 for some milliseconds even if there\n"
+ "are running calls. with this option you can avoid dropping them" },
+ { "ntdebugflags", MISDN_GEN_NTDEBUGFLAGS, MISDN_CTYPE_INT, "0", NONE,
+@@ -387,7 +420,7 @@
+ /* maps enum config elements to array positions */
+ static int *map;
+
+-static ast_mutex_t config_mutex;
++static ast_mutex_t config_mutex;
+
+ #define CLI_ERROR(name, value, section) ({ \
+ ast_log(LOG_WARNING, "misdn.conf: \"%s=%s\" (section: %s) invalid or out of range. " \
+@@ -476,7 +509,7 @@
+ int i, j;
+ int gn = map[MISDN_CFG_GROUPNAME];
+ union misdn_cfg_pt* free_list[max_ports + 2];
+-
++
+ memset(free_list, 0, sizeof(free_list));
+ free_list[0] = port_cfg[0];
+ for (i = 1; i <= max_ports; ++i) {
+@@ -508,7 +541,7 @@
+ {
+ int i;
+
+- for (i = 0; i < NUM_GEN_ELEMENTS; i++)
++ for (i = 0; i < NUM_GEN_ELEMENTS; i++)
+ if (general_cfg[i].any)
+ ast_free(general_cfg[i].any);
+ }
+@@ -567,7 +600,7 @@
+ misdn_cfg_unlock();
+ }
+
+-enum misdn_cfg_elements misdn_cfg_get_elem(char *name)
++enum misdn_cfg_elements misdn_cfg_get_elem(const char *name)
+ {
+ int pos;
+
+@@ -580,11 +613,11 @@
+ pos = get_cfg_position(name, PORT_CFG);
+ if (pos >= 0)
+ return port_spec[pos].elem;
+-
++
+ pos = get_cfg_position(name, GEN_CFG);
+ if (pos >= 0)
+ return gen_spec[pos].elem;
+-
++
+ return MISDN_CFG_FIRST;
+ }
+
+@@ -598,7 +631,7 @@
+ memset(buf, 0, 1);
+ return;
+ }
+-
++
+ /* here comes a hack to replace the (not existing) "name" element with the "ports" element */
+ if (elem == MISDN_CFG_GROUPNAME) {
+ if (!snprintf(buf, bufsize, "ports"))
+@@ -631,7 +664,7 @@
+ spec = (struct misdn_cfg_spec *)port_spec;
+ else if ((elem > MISDN_GEN_FIRST) && (elem < MISDN_GEN_LAST))
+ spec = (struct misdn_cfg_spec *)gen_spec;
+-
++
+ if (!spec || !spec[place].desc)
+ memset(buf, 0, 1);
+ else {
+@@ -660,7 +693,7 @@
+ iter = port_cfg[port][map[MISDN_CFG_MSNS]].ml;
+ else
+ iter = port_cfg[0][map[MISDN_CFG_MSNS]].ml;
+- for (; iter; iter = iter->next)
++ for (; iter; iter = iter->next)
+ if (*(iter->msn) == '*' || ast_extension_match(iter->msn, msn)) {
+ re = 1;
+ break;
+@@ -689,7 +722,7 @@
+ for (i = 1; i <= max_ports; i++) {
+ if (port_cfg[i] && port_cfg[i][map[MISDN_CFG_GROUPNAME]].str) {
+ if (!strcasecmp(port_cfg[i][map[MISDN_CFG_GROUPNAME]].str, group))
+- method = (port_cfg[i][map[MISDN_CFG_METHOD]].str ?
++ method = (port_cfg[i][map[MISDN_CFG_METHOD]].str ?
+ port_cfg[i][map[MISDN_CFG_METHOD]].str : port_cfg[0][map[MISDN_CFG_METHOD]].str);
+ }
+ }
+@@ -709,7 +742,7 @@
+ return re;
+ }
+
+-/*!
++/*!
+ * \brief Generate a comma separated list of all active ports
+ */
+ void misdn_cfg_get_ports_string (char *ports)
+@@ -777,10 +810,10 @@
+ break;
+ case MISDN_CTYPE_ASTGROUP:
+ if (port_cfg[port][place].grp)
+- snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name,
++ snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name,
+ ast_print_group(tempbuf, sizeof(tempbuf), *port_cfg[port][place].grp));
+ else if (port_cfg[0][place].grp)
+- snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name,
++ snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name,
+ ast_print_group(tempbuf, sizeof(tempbuf), *port_cfg[0][place].grp));
+ else
+ snprintf(buf, bufsize, " -> %s:", port_spec[place].name);
+@@ -847,7 +880,7 @@
+ {
+ int p = -1;
+ int gn = map[MISDN_CFG_GROUPNAME];
+-
++
+ misdn_cfg_lock();
+ for (port++; port <= max_ports; port++) {
+ if (port_cfg[port][gn].str) {
+@@ -939,7 +972,7 @@
+ for (; v; v = v->next) {
+ if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
+ continue;
+- if (((pos = get_cfg_position(v->name, GEN_CFG)) < 0) ||
++ if (((pos = get_cfg_position(v->name, GEN_CFG)) < 0) ||
+ (_parse(&general_cfg[pos], v->value, gen_spec[pos].type, gen_spec[pos].boolint_def) < 0))
+ CLI_ERROR(v->name, v->value, "general");
+ }
+@@ -961,7 +994,7 @@
+ cfg_for_ports[0] = 1;
+ }
+
+- if (((pos = get_cfg_position("name", PORT_CFG)) < 0) ||
++ if (((pos = get_cfg_position("name", PORT_CFG)) < 0) ||
+ (_parse(&cfg_tmp[pos], cat, port_spec[pos].type, port_spec[pos].boolint_def) < 0)) {
+ CLI_ERROR(v->name, v->value, cat);
+ return;
+@@ -972,7 +1005,7 @@
+ char *token, *tmp = ast_strdupa(v->value);
+ char ptpbuf[BUFFERSIZE] = "";
+ int start, end;
+- for (token = strsep(&tmp, ","); token; token = strsep(&tmp, ","), *ptpbuf = 0) {
++ for (token = strsep(&tmp, ","); token; token = strsep(&tmp, ","), *ptpbuf = 0) {
+ if (!*token)
+ continue;
+ if (sscanf(token, "%d-%d%s", &start, &end, ptpbuf) >= 2) {
+@@ -995,7 +1028,7 @@
+ }
+ }
+ } else {
+- if (((pos = get_cfg_position(v->name, PORT_CFG)) < 0) ||
++ if (((pos = get_cfg_position(v->name, PORT_CFG)) < 0) ||
+ (_parse(&cfg_tmp[pos], v->value, port_spec[pos].type, port_spec[pos].boolint_def) < 0))
+ CLI_ERROR(v->name, v->value, cat);
+ }
+Index: channels/chan_jingle.c
+===================================================================
+--- a/channels/chan_jingle.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/channels/chan_jingle.c (.../trunk) (revision 202568)
+@@ -53,7 +53,7 @@
+ #include "asterisk/pbx.h"
+ #include "asterisk/sched.h"
+ #include "asterisk/io.h"
+-#include "asterisk/rtp.h"
++#include "asterisk/rtp_engine.h"
+ #include "asterisk/acl.h"
+ #include "asterisk/callerid.h"
+ #include "asterisk/file.h"
+@@ -112,9 +112,9 @@
+ char exten[80]; /*!< Called extension */
+ struct ast_channel *owner; /*!< Master Channel */
+ char audio_content_name[100]; /*!< name attribute of content tag */
+- struct ast_rtp *rtp; /*!< RTP audio session */
++ struct ast_rtp_instance *rtp; /*!< RTP audio session */
+ char video_content_name[100]; /*!< name attribute of content tag */
+- struct ast_rtp *vrtp; /*!< RTP video session */
++ struct ast_rtp_instance *vrtp; /*!< RTP video session */
+ int jointcapability; /*!< Supported capability at both ends (codecs ) */
+ int peercapability;
+ struct jingle_pvt *next; /* Next entity */
+@@ -183,11 +183,6 @@
+ static struct jingle_pvt *jingle_alloc(struct jingle *client, const char *from, const char *sid);
+ static char *jingle_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
+ static char *jingle_do_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
+-/*----- RTP interface functions */
+-static int jingle_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp,
+- struct ast_rtp *vrtp, struct ast_rtp *tpeer, int codecs, int nat_active);
+-static enum ast_rtp_get_result jingle_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp);
+-static int jingle_get_codec(struct ast_channel *chan);
+
+ /*! \brief PBX interface structure for channel registration */
+ static const struct ast_channel_tech jingle_tech = {
+@@ -197,7 +192,7 @@
+ .requester = jingle_request,
+ .send_digit_begin = jingle_digit_begin,
+ .send_digit_end = jingle_digit_end,
+- .bridge = ast_rtp_bridge,
++ .bridge = ast_rtp_instance_bridge,
+ .call = jingle_call,
+ .hangup = jingle_hangup,
+ .answer = jingle_answer,
+@@ -216,15 +211,6 @@
+ static struct io_context *io; /*!< The IO context */
+ static struct in_addr __ourip;
+
+-
+-/*! \brief RTP driver interface */
+-static struct ast_rtp_protocol jingle_rtp = {
+- type: "Jingle",
+- get_rtp_info: jingle_get_rtp_peer,
+- set_rtp_peer: jingle_set_rtp_peer,
+- get_codec: jingle_get_codec,
+-};
+-
+ static struct ast_cli_entry jingle_cli[] = {
+ AST_CLI_DEFINE(jingle_do_reload, "Reload Jingle configuration"),
+ AST_CLI_DEFINE(jingle_show_channels, "Show Jingle channels"),
+@@ -304,7 +290,6 @@
+ iks_insert_attrib(payload_g723, "name", "G723");
+ iks_insert_node(dcodecs, payload_g723);
+ }
+- ast_rtp_lookup_code(p->rtp, 1, codec);
+ }
+
+ static int jingle_accept_call(struct jingle *client, struct jingle_pvt *p)
+@@ -398,18 +383,19 @@
+ return res;
+ }
+
+-static enum ast_rtp_get_result jingle_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
++static enum ast_rtp_glue_result jingle_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
+ {
+ struct jingle_pvt *p = chan->tech_pvt;
+- enum ast_rtp_get_result res = AST_RTP_GET_FAILED;
++ enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_FORBID;
+
+ if (!p)
+ return res;
+
+ ast_mutex_lock(&p->lock);
+ if (p->rtp) {
+- *rtp = p->rtp;
+- res = AST_RTP_TRY_PARTIAL;
++ ao2_ref(p->rtp, +1);
++ *instance = p->rtp;
++ res = AST_RTP_GLUE_RESULT_LOCAL;
+ }
+ ast_mutex_unlock(&p->lock);
+
+@@ -422,7 +408,7 @@
+ return p->peercapability;
+ }
+
+-static int jingle_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *tpeer, int codecs, int nat_active)
++static int jingle_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *tpeer, int codecs, int nat_active)
+ {
+ struct jingle_pvt *p;
+
+@@ -442,6 +428,13 @@
+ return 0;
+ }
+
++static struct ast_rtp_glue jingle_rtp_glue = {
++ .type = "Jingle",
++ .get_rtp_info = jingle_get_rtp_peer,
++ .get_codec = jingle_get_codec,
++ .update_peer = jingle_set_rtp_peer,
++};
++
+ static int jingle_response(struct jingle *client, ikspak *pak, const char *reasonstr, const char *reasonstr2)
+ {
+ iks *response = NULL, *error = NULL, *reason = NULL;
+@@ -584,7 +577,7 @@
+ struct jingle_candidate *tmp;
+ struct aji_client *c = client->connection;
+ struct jingle_candidate *ours1 = NULL, *ours2 = NULL;
+- struct sockaddr_in sin;
++ struct sockaddr_in sin = { 0, };
+ struct sockaddr_in dest;
+ struct in_addr us;
+ struct in_addr externaddr;
+@@ -621,7 +614,7 @@
+ goto safeout;
+ }
+
+- ast_rtp_get_us(p->rtp, &sin);
++ ast_rtp_instance_get_local_address(p->rtp, &sin);
+ ast_find_ourip(&us, bindaddr);
+
+ /* Setup our first jingle candidate */
+@@ -779,7 +772,7 @@
+ ast_copy_string(tmp->them, idroster, sizeof(tmp->them));
+ tmp->initiator = 1;
+ }
+- tmp->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
++ tmp->rtp = ast_rtp_instance_new(NULL, sched, &bindaddr, NULL);
+ tmp->parent = client;
+ if (!tmp->rtp) {
+ ast_log(LOG_WARNING, "Out of RTP sessions?\n");
+@@ -825,18 +818,18 @@
+
+ /* Set Frame packetization */
+ if (i->rtp)
+- ast_rtp_codec_setpref(i->rtp, &i->prefs);
++ ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(i->rtp), i->rtp, &i->prefs);
+
+ tmp->nativeformats = ast_codec_choose(&i->prefs, what, 1) | (i->jointcapability & AST_FORMAT_VIDEO_MASK);
+ fmt = ast_best_codec(tmp->nativeformats);
+
+ if (i->rtp) {
+- ast_channel_set_fd(tmp, 0, ast_rtp_fd(i->rtp));
+- ast_channel_set_fd(tmp, 1, ast_rtcp_fd(i->rtp));
++ ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(i->rtp, 0));
++ ast_channel_set_fd(tmp, 1, ast_rtp_instance_fd(i->rtp, 1));
+ }
+ if (i->vrtp) {
+- ast_channel_set_fd(tmp, 2, ast_rtp_fd(i->vrtp));
+- ast_channel_set_fd(tmp, 3, ast_rtcp_fd(i->vrtp));
++ ast_channel_set_fd(tmp, 2, ast_rtp_instance_fd(i->vrtp, 0));
++ ast_channel_set_fd(tmp, 3, ast_rtp_instance_fd(i->vrtp, 1));
+ }
+ if (state == AST_STATE_RING)
+ tmp->rings = 1;
+@@ -942,9 +935,9 @@
+ if (p->owner)
+ ast_log(LOG_WARNING, "Uh oh, there's an owner, this is going to be messy.\n");
+ if (p->rtp)
+- ast_rtp_destroy(p->rtp);
++ ast_rtp_instance_destroy(p->rtp);
+ if (p->vrtp)
+- ast_rtp_destroy(p->vrtp);
++ ast_rtp_instance_destroy(p->vrtp);
+ jingle_free_candidates(p->theircandidates);
+ ast_free(p);
+ }
+@@ -1009,8 +1002,8 @@
+ ast_copy_string(p->audio_content_name, iks_find_attrib(content, "name"), sizeof(p->audio_content_name));
+
+ while (codec) {
+- ast_rtp_set_m_type(p->rtp, atoi(iks_find_attrib(codec, "id")));
+- ast_rtp_set_rtpmap_type(p->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0);
++ ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id")));
++ ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0);
+ codec = iks_next(codec);
+ }
+ }
+@@ -1025,8 +1018,8 @@
+ ast_copy_string(p->video_content_name, iks_find_attrib(content, "name"), sizeof(p->video_content_name));
+
+ while (codec) {
+- ast_rtp_set_m_type(p->rtp, atoi(iks_find_attrib(codec, "id")));
+- ast_rtp_set_rtpmap_type(p->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0);
++ ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id")));
++ ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0);
+ codec = iks_next(codec);
+ }
+ }
+@@ -1079,7 +1072,7 @@
+ sin.sin_port = htons(tmp->port);
+ snprintf(username, sizeof(username), "%s:%s", tmp->ufrag, p->ourcandidates->ufrag);
+
+- ast_rtp_stun_request(p->rtp, &sin, username);
++ ast_rtp_instance_stun_request(p->rtp, &sin, username);
+ tmp = tmp->next;
+ }
+ return 1;
+@@ -1169,7 +1162,7 @@
+
+ if (!p->rtp)
+ return &ast_null_frame;
+- f = ast_rtp_read(p->rtp);
++ f = ast_rtp_instance_read(p->rtp, 0);
+ jingle_update_stun(p->parent, p);
+ if (p->owner) {
+ /* We already hold the channel lock */
+@@ -1220,7 +1213,7 @@
+ if (p) {
+ ast_mutex_lock(&p->lock);
+ if (p->rtp) {
+- res = ast_rtp_write(p->rtp, frame);
++ res = ast_rtp_instance_write(p->rtp, frame);
+ }
+ ast_mutex_unlock(&p->lock);
+ }
+@@ -1229,7 +1222,7 @@
+ if (p) {
+ ast_mutex_lock(&p->lock);
+ if (p->vrtp) {
+- res = ast_rtp_write(p->vrtp, frame);
++ res = ast_rtp_instance_write(p->vrtp, frame);
+ }
+ ast_mutex_unlock(&p->lock);
+ }
+@@ -1879,7 +1872,7 @@
+ return 0;
+ }
+
+- ast_rtp_proto_register(&jingle_rtp);
++ ast_rtp_glue_register(&jingle_rtp_glue);
+ ast_cli_register_multiple(jingle_cli, ARRAY_LEN(jingle_cli));
+ /* Make sure we can register our channel type */
+ if (ast_channel_register(&jingle_tech)) {
+@@ -1902,7 +1895,7 @@
+ ast_cli_unregister_multiple(jingle_cli, ARRAY_LEN(jingle_cli));
+ /* First, take us out of the channel loop */
+ ast_channel_unregister(&jingle_tech);
+- ast_rtp_proto_unregister(&jingle_rtp);
++ ast_rtp_glue_unregister(&jingle_rtp_glue);
+
+ if (!ast_mutex_lock(&jinglelock)) {
+ /* Hangup all interfaces if they have an owner */
+Index: channels/chan_dahdi.c
+===================================================================
+--- a/channels/chan_dahdi.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/channels/chan_dahdi.c (.../trunk) (revision 202568)
+@@ -62,6 +62,7 @@
+
+ #include <dahdi/user.h>
+ #include <dahdi/tonezone.h>
++#include "sig_analog.h"
+
+ #ifdef HAVE_PRI
+ #include <libpri.h>
+@@ -154,11 +155,94 @@
+ <para>This application will Accept the R2 call either with charge or no charge.</para>
+ </description>
+ </application>
++ <manager name="DAHDITransfer" language="en_US">
++ <synopsis>
++ Transfer DAHDI Channel.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="DAHDIChannel" required="true">
++ <para>DAHDI channel name to transfer.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Transfer a DAHDI channel.</para>
++ </description>
++ </manager>
++ <manager name="DAHDIHangup" language="en_US">
++ <synopsis>
++ Hangup DAHDI Channel.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="DAHDIChannel" required="true">
++ <para>DAHDI channel name to hangup.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Hangup a DAHDI channel.</para>
++ </description>
++ </manager>
++ <manager name="DAHDIDialOffhook" language="en_US">
++ <synopsis>
++ Dial over DAHDI channel while offhook.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="DAHDIChannel" required="true" />
++ <parameter name="Number" required="true" />
++ </syntax>
++ <description>
++ </description>
++ </manager>
++ <manager name="DAHDIDNDon" language="en_US">
++ <synopsis>
++ Toggle DAHDI channel Do Not Disturb status ON.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="DAHDIChannel" required="true" />
++ </syntax>
++ <description>
++ </description>
++ </manager>
++ <manager name="DAHDIDNDoff" language="en_US">
++ <synopsis>
++ Toggle DAHDI channel Do Not Disturb status OFF.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="DAHDIChannel" required="true" />
++ </syntax>
++ <description>
++ </description>
++ </manager>
++ <manager name="DAHDIShowChannels" language="en_US">
++ <synopsis>
++ Show status DAHDI channels.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="DAHDIChannel" required="true" />
++ </syntax>
++ <description>
++ </description>
++ </manager>
++ <manager name="DAHDIRestart" language="en_US">
++ <synopsis>
++ Fully Restart DAHDI channels (terminates calls).
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ </syntax>
++ <description>
++ </description>
++ </manager>
+ ***/
+
+ #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
+
+-static const char *lbostr[] = {
++static const char * const lbostr[] = {
+ "0 db (CSU)/0-133 feet (DSX-1)",
+ "133-266 feet (DSX-1)",
+ "266-399 feet (DSX-1)",
+@@ -292,6 +376,28 @@
+ #define CALLPROGRESS_FAX_INCOMING 4
+ #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
+
++#ifdef HAVE_PRI_SERVICE_MESSAGES
++/*! \brief Persistent Service State */
++#define SRVST_DBKEY "service-state"
++/*! \brief The out-of-service SERVICE state */
++#define SRVST_TYPE_OOS "O"
++/*! \brief SRVST_INITIALIZED is used to indicate a channel being out-of-service
++ * The SRVST_INITIALIZED is mostly used maintain backwards compatibility but also may
++ * mean that the channel has not yet received a RESTART message. If a channel is
++ * out-of-service with this reason a RESTART message will result in the channel
++ * being put into service. */
++#define SRVST_INITIALIZED 0
++/*! \brief SRVST_NEAREND is used to indicate that the near end was put out-of-service */
++#define SRVST_NEAREND (1 << 0)
++/*! \brief SRVST_FAREND is used to indicate that the far end was taken out-of-service */
++#define SRVST_FAREND (1 << 1)
++/*! \brief SRVST_BOTH is used to indicate that both sides of the channel are out-of-service */
++#define SRVST_BOTH (SRVST_NEAREND | SRVST_FAREND)
++
++/*! \brief The AstDB family */
++static const char dahdi_db[] = "dahdi/registry";
++#endif
++
+ static char defaultcic[64] = "";
+ static char defaultozz[64] = "";
+
+@@ -363,6 +469,8 @@
+
+ static int dahdi_sendtext(struct ast_channel *c, const char *text);
+
++static int analog_lib_handles(int signalling, int radio, int oprmode);
++
+ static void mwi_event_cb(const struct ast_event *event, void *userdata)
+ {
+ /* This module does not handle MWI in an event-based manner. However, it
+@@ -475,6 +583,9 @@
+ int max_ani;
+ int max_dnis;
+ int get_ani_first:1;
++#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
++ int skip_category_request:1;
++#endif
+ int call_files:1;
+ int allow_collect_calls:1;
+ int charge_calls:1;
+@@ -543,6 +654,9 @@
+ int resetting;
+ /*! \brief Current position during a reset (-1 if not started) */
+ int resetpos;
++#ifdef HAVE_PRI_SERVICE_MESSAGES
++ unsigned int enable_service_message_support:1; /*!< enable SERVICE message support */
++#endif
+ #ifdef HAVE_PRI_INBANDDISCONNECT
+ unsigned int inbanddisconnect:1; /*!< Should we support inband audio after receiving DISCONNECT? */
+ #endif
+@@ -595,7 +709,7 @@
+ struct ringContextData ringContext[3];
+ };
+
+-static char *subnames[] = {
++static const char * const subnames[] = {
+ "Real",
+ "Callwait",
+ "Threeway"
+@@ -645,6 +759,7 @@
+
+ static struct dahdi_pvt {
+ ast_mutex_t lock;
++ struct callerid_state *cs;
+ struct ast_channel *owner; /*!< Our current active owner (if applicable) */
+ /*!< Up to three channels can be associated with this call */
+
+@@ -757,10 +872,10 @@
+ unsigned int echocanon:1;
+ /*! \brief TRUE if a fax tone has already been handled. */
+ unsigned int faxhandled:1;
+- /*! \brief TRUE if dynamic faxbuffers are configured for use, default is OFF */
++ /*! TRUE if dynamic faxbuffers are configured for use, default is OFF */
+ unsigned int usefaxbuffers:1;
+- /*! \brief TRUE while dynamic faxbuffers are in use */
+- unsigned int faxbuffersinuse:1;
++ /*! TRUE while buffer configuration override is in use */
++ unsigned int bufferoverrideinuse:1;
+ /*! \brief TRUE if over a radio and dahdi_read() has been called. */
+ unsigned int firstradio:1;
+ /*!
+@@ -1225,6 +1340,7 @@
+ char begindigit;
+ /*! \brief TRUE if confrence is muted. */
+ int muting;
++ void *sig_pvt;
+ } *iflist = NULL, *ifend = NULL;
+
+ /*! \brief Channel configuration from chan_dahdi.conf .
+@@ -1305,6 +1421,9 @@
+ .max_ani = 10,
+ .max_dnis = 4,
+ .get_ani_first = -1,
++#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
++ .skip_category_request = -1,
++#endif
+ .call_files = 0,
+ .allow_collect_calls = 0,
+ .charge_calls = 1,
+@@ -1356,8 +1475,6 @@
+ .buf_policy = DAHDI_POLICY_IMMEDIATE,
+ .buf_no = numbufs,
+ .usefaxbuffers = 0,
+- .faxbuf_policy = DAHDI_POLICY_IMMEDIATE,
+- .faxbuf_no = numbufs,
+ },
+ .timing = {
+ .prewinktime = -1,
+@@ -1390,8 +1507,10 @@
+ static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
+ static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
+ static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
++static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
+ static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
+ static int handle_init_event(struct dahdi_pvt *i, int event);
++static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
+
+ static const struct ast_channel_tech dahdi_tech = {
+ .type = "DAHDI",
+@@ -1411,7 +1530,9 @@
+ .indicate = dahdi_indicate,
+ .fixup = dahdi_fixup,
+ .setoption = dahdi_setoption,
++ .queryoption = dahdi_queryoption,
+ .func_channel_read = dahdi_func_read,
++ .func_channel_write = dahdi_func_write,
+ };
+
+ #ifdef HAVE_PRI
+@@ -1420,8 +1541,913 @@
+ #define GET_CHANNEL(p) ((p)->channel)
+ #endif
+
+-struct dahdi_pvt *round_robin[32];
++static enum analog_sigtype dahdisig_to_analogsig(int sig)
++{
++ switch (sig) {
++ case SIG_FXOLS:
++ return ANALOG_SIG_FXOLS;
++ case SIG_FXOGS:
++ return ANALOG_SIG_FXOGS;
++ case SIG_FXOKS:
++ return ANALOG_SIG_FXOKS;
++ case SIG_FXSLS:
++ return ANALOG_SIG_FXSLS;
++ case SIG_FXSGS:
++ return ANALOG_SIG_FXSGS;
++ case SIG_FXSKS:
++ return ANALOG_SIG_FXSKS;
++ case SIG_EMWINK:
++ return ANALOG_SIG_EMWINK;
++ case SIG_EM:
++ return ANALOG_SIG_EM;
++ case SIG_EM_E1:
++ return ANALOG_SIG_EM_E1;
++ case SIG_FEATD:
++ return ANALOG_SIG_FEATD;
++ case SIG_FEATDMF:
++ return ANALOG_SIG_FEATDMF;
++ case SIG_E911:
++ return SIG_E911;
++ case SIG_FGC_CAMA:
++ return ANALOG_SIG_FGC_CAMA;
++ case SIG_FGC_CAMAMF:
++ return ANALOG_SIG_FGC_CAMAMF;
++ case SIG_FEATB:
++ return ANALOG_SIG_FEATB;
++ case SIG_SFWINK:
++ return ANALOG_SIG_SFWINK;
++ case SIG_SF:
++ return ANALOG_SIG_SF;
++ case SIG_SF_FEATD:
++ return ANALOG_SIG_SF_FEATD;
++ case SIG_SF_FEATDMF:
++ return ANALOG_SIG_SF_FEATDMF;
++ case SIG_FEATDMF_TA:
++ return ANALOG_SIG_FEATDMF_TA;
++ case SIG_SF_FEATB:
++ return ANALOG_SIG_FEATB;
++ default:
++ return -1;
++ }
++}
+
++
++static int analog_tone_to_dahditone(enum analog_tone tone)
++{
++ switch (tone) {
++ case ANALOG_TONE_RINGTONE:
++ return DAHDI_TONE_RINGTONE;
++ case ANALOG_TONE_STUTTER:
++ return DAHDI_TONE_STUTTER;
++ case ANALOG_TONE_CONGESTION:
++ return DAHDI_TONE_CONGESTION;
++ case ANALOG_TONE_DIALTONE:
++ return DAHDI_TONE_DIALTONE;
++ case ANALOG_TONE_DIALRECALL:
++ return DAHDI_TONE_DIALRECALL;
++ case ANALOG_TONE_INFO:
++ return DAHDI_TONE_INFO;
++ default:
++ return -1;
++ }
++}
++
++static int analogsub_to_dahdisub(enum analog_sub analogsub)
++{
++ int index;
++
++ switch (analogsub) {
++ case ANALOG_SUB_REAL:
++ index = SUB_REAL;
++ break;
++ case ANALOG_SUB_CALLWAIT:
++ index = SUB_CALLWAIT;
++ break;
++ case ANALOG_SUB_THREEWAY:
++ index = SUB_THREEWAY;
++ break;
++ default:
++ ast_log(LOG_ERROR, "Unidentified sub!\n");
++ index = SUB_REAL;
++ }
++
++ return index;
++}
++
++static enum analog_event dahdievent_to_analogevent(int event);
++static int bump_gains(struct dahdi_pvt *p);
++static int dahdi_setlinear(int dfd, int linear);
++
++static int my_start_cid_detect(void *pvt, int cid_signalling)
++{
++ struct dahdi_pvt *p = pvt;
++ int index = SUB_REAL;
++ p->cs = callerid_new(cid_signalling);
++ if (!p->cs) {
++ ast_log(LOG_ERROR, "Unable to alloc callerid\n");
++ return -1;
++ }
++ bump_gains(p);
++ dahdi_setlinear(p->subs[index].dfd, 0);
++
++ return 0;
++}
++
++static int my_stop_cid_detect(void *pvt)
++{
++ struct dahdi_pvt *p = pvt;
++ int index = SUB_REAL;
++ if (p->cs)
++ callerid_free(p->cs);
++ dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
++ return 0;
++}
++
++static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
++{
++ struct dahdi_pvt *p = pvt;
++ struct pollfd poller;
++ char *name, *num;
++ int index = SUB_REAL;
++ int res;
++ unsigned char buf[256];
++ int flags;
++
++ poller.fd = p->subs[SUB_REAL].dfd;
++ poller.events = POLLPRI | POLLIN;
++ poller.revents = 0;
++
++ res = poll(&poller, 1, timeout);
++
++ if (poller.revents & POLLPRI) {
++ *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
++ return 1;
++ }
++
++ if (poller.revents & POLLIN) {
++ /*** NOTES ***/
++ /* Change API: remove cid_signalling from get_callerid, add a new start_cid_detect and stop_cid_detect function
++ * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until
++ * either a timeout occurss or CID is detected (returns 0). returning 1 should be event received, and -1 should be fail
++ * and die */
++ res = read(p->subs[index].dfd, buf, sizeof(buf));
++ if (res < 0) {
++ if (errno != ELAST) {
++ ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
++ callerid_free(p->cs);
++ return -1;
++ }
++ }
++ res = callerid_feed(p->cs, buf, res, AST_LAW(p));
++ if (res < 0) {
++ ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
++ return -1;
++ }
++
++ if (res == 1) {
++ callerid_get(p->cs, &name, &num, &flags);
++ if (name)
++ ast_copy_string(namebuf, name, ANALOG_MAX_CID);
++ if (num)
++ ast_copy_string(numbuf, num, ANALOG_MAX_CID);
++
++ ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
++ return 0;
++ }
++ }
++
++ *ev = ANALOG_EVENT_NONE;
++ return 1;
++}
++
++static int send_callerid(struct dahdi_pvt *p);
++
++static int my_stop_callwait(void *pvt)
++{
++ struct dahdi_pvt *p = pvt;
++ p->callwaitingrepeat = 0;
++ p->cidcwexpire = 0;
++
++ return 0;
++}
++
++static int save_conference(struct dahdi_pvt *p);
++
++static int my_callwait(void *pvt)
++{
++ struct dahdi_pvt *p = pvt;
++ p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
++ if (p->cidspill) {
++ ast_log(LOG_WARNING, "Spill already exists?!?\n");
++ free(p->cidspill);
++ }
++ if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
++ return -1;
++ save_conference(p);
++ /* Silence */
++ memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
++ if (!p->callwaitrings && p->callwaitingcallerid) {
++ ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
++ p->callwaitcas = 1;
++ p->cidlen = 2400 + 680 + READ_SIZE * 4;
++ } else {
++ ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
++ p->callwaitcas = 0;
++ p->cidlen = 2400 + READ_SIZE * 4;
++ }
++ p->cidpos = 0;
++ send_callerid(p);
++
++ return 0;
++}
++
++static int my_send_callerid(void *pvt, int cwcid, struct ast_callerid *cid)
++{
++ struct dahdi_pvt *p = pvt;
++
++ ast_log(LOG_ERROR, "Starting cid spill\n");
++
++ if (p->cidspill) {
++ ast_log(LOG_WARNING, "cidspill already exists??\n");
++ free(p->cidspill);
++ }
++
++ if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
++ if (cwcid == 0) {
++ p->cidlen = ast_callerid_generate(p->cidspill, cid->cid_name, cid->cid_num, AST_LAW(p));
++ } else {
++ p->callwaitcas = 0;
++ p->cidcwexpire = 0;
++ p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, cid->cid_name, cid->cid_num, AST_LAW(p));
++ p->cidlen += READ_SIZE * 4;
++ }
++ p->cidpos = 0;
++ send_callerid(p);
++ }
++ return 0;
++}
++
++static int my_dsp_reset_and_flush_digits(void *pvt)
++{
++ struct dahdi_pvt *p = pvt;
++ if (p->dsp)
++ ast_dsp_digitreset(p->dsp);
++
++ return 0;
++}
++
++static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
++{
++ struct dahdi_pvt *p = pvt;
++
++ if (p->channel == CHAN_PSEUDO)
++ ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
++
++ if (mode == ANALOG_DIGITMODE_DTMF) {
++ /* If we do hardware dtmf, no need for a DSP */
++ if (p->hardwaredtmf) {
++ if (p->dsp) {
++ ast_dsp_free(p->dsp);
++ p->dsp = NULL;
++ }
++ return 0;
++ }
++
++ if (!p->dsp) {
++ p->dsp = ast_dsp_new();
++ if (!p->dsp) {
++ ast_log(LOG_ERROR, "Unable to allocate DSP\n");
++ return -1;
++ }
++ }
++
++ ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
++ } else if (mode == ANALOG_DIGITMODE_MF) {
++ if (!p->dsp) {
++ p->dsp = ast_dsp_new();
++ if (!p->dsp) {
++ ast_log(LOG_ERROR, "Unable to allocate DSP\n");
++ return -1;
++ }
++ }
++ ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
++ }
++ return 0;
++}
++
++static int dahdi_wink(struct dahdi_pvt *p, int index);
++
++static int my_wink(void *pvt, enum analog_sub sub)
++{
++ struct dahdi_pvt *p = pvt;
++ int index = analogsub_to_dahdisub(sub);
++ if (index != SUB_REAL) {
++ ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
++ }
++ return dahdi_wink(p, index);
++}
++
++static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri);
++
++static int reset_conf(struct dahdi_pvt *p);
++
++static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
++
++static void my_handle_dtmfup(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
++{
++ struct ast_frame *f = *dest;
++ struct dahdi_pvt *p = pvt;
++ int idx = analogsub_to_dahdisub(analog_index);
++
++ ast_debug(1, "DTMF digit: %c on %s\n", f->subclass, ast->name);
++
++ if (f->subclass == 'f') {
++ /* Fax tone -- Handle and return NULL */
++ if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
++ /* If faxbuffers are configured, use them for the fax transmission */
++ if (p->usefaxbuffers && !p->bufferoverrideinuse) {
++ struct dahdi_bufferinfo bi = {
++ .txbufpolicy = p->faxbuf_policy,
++ .bufsize = p->bufsize,
++ .numbufs = p->faxbuf_no
++ };
++ int res;
++
++ if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
++ ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
++ } else {
++ p->bufferoverrideinuse = 1;
++ }
++ }
++ p->faxhandled = 1;
++ if (strcmp(ast->exten, "fax")) {
++ const char *target_context = S_OR(ast->macrocontext, ast->context);
++
++ /* We need to unlock 'ast' here because ast_exists_extension has the
++ * potential to start autoservice on the channel. Such action is prone
++ * to deadlock.
++ */
++ ast_mutex_unlock(&p->lock);
++ ast_channel_unlock(ast);
++ if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
++ ast_channel_lock(ast);
++ ast_mutex_lock(&p->lock);
++ ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
++ /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
++ pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
++ if (ast_async_goto(ast, target_context, "fax", 1))
++ ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
++ } else {
++ ast_channel_lock(ast);
++ ast_mutex_lock(&p->lock);
++ ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
++ }
++ } else {
++ ast_debug(1, "Already in a fax extension, not redirecting\n");
++ }
++ } else {
++ ast_debug(1, "Fax already handled\n");
++ }
++ dahdi_confmute(p, 0);
++ p->subs[idx].f.frametype = AST_FRAME_NULL;
++ p->subs[idx].f.subclass = 0;
++ *dest = &p->subs[idx].f;
++ }
++}
++
++static void my_lock_private(void *pvt)
++{
++ struct dahdi_pvt *p = pvt;
++
++ ast_mutex_lock(&p->lock);
++}
++
++static void my_unlock_private(void *pvt)
++{
++ struct dahdi_pvt *p = pvt;
++
++ ast_mutex_unlock(&p->lock);
++}
++
++static void my_increase_ss_count(void)
++{
++ ast_mutex_lock(&ss_thread_lock);
++ ss_thread_count++;
++ ast_mutex_unlock(&ss_thread_lock);
++}
++
++static void my_decrease_ss_count(void)
++{
++ ast_mutex_lock(&ss_thread_lock);
++ ss_thread_count--;
++ ast_cond_signal(&ss_thread_complete);
++ ast_mutex_unlock(&ss_thread_lock);
++}
++
++static void my_all_subchannels_hungup(void *pvt)
++{
++ struct dahdi_pvt *p = pvt;
++ int res, law;
++
++ p->faxhandled = 0;
++ p->didtdd = 0;
++
++ if (p->dsp) {
++ ast_dsp_free(p->dsp);
++ p->dsp = NULL;
++ }
++
++ law = DAHDI_LAW_DEFAULT;
++ res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
++ if (res < 0)
++ ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
++
++ dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
++
++#if 1
++ {
++ int i;
++ p->owner = NULL;
++ /* Cleanup owners here */
++ for (i = 0; i < 3; i++) {
++ p->subs[i].owner = NULL;
++ }
++ }
++#endif
++
++ reset_conf(p);
++ if (num_restart_pending == 0) {
++ restart_monitor();
++ }
++}
++
++static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
++
++static int my_conf_del(void *pvt, enum analog_sub sub)
++{
++ struct dahdi_pvt *p = pvt;
++ int x = analogsub_to_dahdisub(sub);
++
++ return conf_del(p, &p->subs[x], x);
++}
++
++static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
++
++static int my_conf_add(void *pvt, enum analog_sub sub)
++{
++ struct dahdi_pvt *p = pvt;
++ int x = analogsub_to_dahdisub(sub);
++
++ return conf_add(p, &p->subs[x], x, 0);
++}
++
++static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
++
++static int my_complete_conference_update(void *pvt, int needconference)
++{
++ struct dahdi_pvt *p = pvt;
++ int needconf = needconference;
++ int x;
++ int useslavenative;
++ struct dahdi_pvt *slave = NULL;
++
++ useslavenative = isslavenative(p, &slave);
++
++ /* If we have a slave, add him to our conference now. or DAX
++ if this is slave native */
++ for (x = 0; x < MAX_SLAVES; x++) {
++ if (p->slaves[x]) {
++ if (useslavenative)
++ conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
++ else {
++ conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
++ needconf++;
++ }
++ }
++ }
++ /* If we're supposed to be in there, do so now */
++ if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
++ if (useslavenative)
++ conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
++ else {
++ conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
++ needconf++;
++ }
++ }
++ /* If we have a master, add ourselves to his conference */
++ if (p->master) {
++ if (isslavenative(p->master, NULL)) {
++ conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
++ } else {
++ conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
++ }
++ }
++ if (!needconf) {
++ /* Nobody is left (or should be left) in our conference.
++ Kill it. */
++ p->confno = -1;
++ }
++
++ return 0;
++}
++
++static int check_for_conference(struct dahdi_pvt *p);
++
++static int my_check_for_conference(void *pvt)
++{
++ struct dahdi_pvt *p = pvt;
++ return check_for_conference(p);
++}
++
++static void my_swap_subchannels(void *pvt, enum analog_sub a, struct ast_channel *ast_a, enum analog_sub b, struct ast_channel *ast_b)
++{
++ struct dahdi_pvt *p = pvt;
++ int da, db;
++ int tchan;
++
++ da = analogsub_to_dahdisub(a);
++ db = analogsub_to_dahdisub(b);
++
++ tchan = p->subs[da].chan;
++
++ p->subs[da].chan = p->subs[db].chan;
++
++ p->subs[db].chan = tchan;
++
++ if (ast_a)
++ ast_a->fds[0] = p->subs[da].dfd;
++ if (ast_b)
++ ast_b->fds[0] = p->subs[db].dfd;
++
++ p->subs[da].owner = ast_a;
++ p->subs[db].owner = ast_b;
++
++ wakeup_sub(p, a, NULL);
++ wakeup_sub(p, b, NULL);
++
++ return;
++}
++
++static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
++
++static struct ast_channel * my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub)
++{
++ struct dahdi_pvt *p = pvt;
++ int dsub = analogsub_to_dahdisub(sub);
++
++ return dahdi_new(p, state, startpbx, dsub, 0, 0);
++}
++
++static int unalloc_sub(struct dahdi_pvt *p, int x);
++
++static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
++{
++ struct dahdi_pvt *p = pvt;
++
++ return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
++}
++
++static int alloc_sub(struct dahdi_pvt *p, int x);
++
++static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
++{
++ struct dahdi_pvt *p = pvt;
++
++ return alloc_sub(p, analogsub_to_dahdisub(analogsub));
++}
++
++static int has_voicemail(struct dahdi_pvt *p);
++
++static int my_has_voicemail(void *pvt)
++{
++ struct dahdi_pvt *p = pvt;
++
++ return has_voicemail(p);
++}
++
++static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
++{
++ struct dahdi_pvt *p = pvt;
++ int index;
++
++ index = analogsub_to_dahdisub(sub);
++
++ return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
++}
++
++static enum analog_event dahdievent_to_analogevent(int event)
++{
++ enum analog_event res = ANALOG_EVENT_ERROR;
++
++ switch (event) {
++ case DAHDI_EVENT_DIALCOMPLETE:
++ res = ANALOG_EVENT_DIALCOMPLETE;
++ break;
++ case DAHDI_EVENT_WINKFLASH:
++ res = ANALOG_EVENT_WINKFLASH;
++ break;
++ case DAHDI_EVENT_ONHOOK:
++ res = ANALOG_EVENT_ONHOOK;
++ break;
++ case DAHDI_EVENT_RINGOFFHOOK:
++ res = ANALOG_EVENT_RINGOFFHOOK;
++ break;
++ case DAHDI_EVENT_ALARM:
++ res = ANALOG_EVENT_ALARM;
++ break;
++ case DAHDI_EVENT_NOALARM:
++ res = ANALOG_EVENT_NOALARM;
++ break;
++ case DAHDI_EVENT_HOOKCOMPLETE:
++ res = ANALOG_EVENT_HOOKCOMPLETE;
++ break;
++ case DAHDI_EVENT_POLARITY:
++ res = ANALOG_EVENT_POLARITY;
++ break;
++ case DAHDI_EVENT_RINGERON:
++ res = ANALOG_EVENT_RINGERON;
++ break;
++ case DAHDI_EVENT_RINGEROFF:
++ res = ANALOG_EVENT_RINGEROFF;
++ break;
++ case DAHDI_EVENT_RINGBEGIN:
++ res = ANALOG_EVENT_RINGBEGIN;
++ break;
++ case DAHDI_EVENT_PULSE_START:
++ res = ANALOG_EVENT_PULSE_START;
++ break;
++ case DAHDI_EVENT_NEONMWI_ACTIVE:
++ res = ANALOG_EVENT_NEONMWI_ACTIVE;
++ break;
++ case DAHDI_EVENT_NEONMWI_INACTIVE:
++ res = ANALOG_EVENT_NEONMWI_INACTIVE;
++ break;
++ }
++
++ return res;
++}
++
++static inline int dahdi_wait_event(int fd);
++
++static int my_wait_event(void *pvt)
++{
++ struct dahdi_pvt *p = pvt;
++
++ return dahdi_wait_event(p->subs[SUB_REAL].dfd);
++}
++
++static int my_get_event(void *pvt)
++{
++ struct dahdi_pvt *p = pvt;
++ int res;
++
++ if (p->fake_event) {
++ res = p->fake_event;
++ p->fake_event = 0;
++ } else
++ res = dahdi_get_event(p->subs[SUB_REAL].dfd);
++
++ return dahdievent_to_analogevent(res);
++}
++
++static int my_is_off_hook(void *pvt)
++{
++ struct dahdi_pvt *p = pvt;
++ int res;
++ struct dahdi_params par;
++
++ if (p->subs[SUB_REAL].dfd > -1)
++ res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
++ else {
++ /* Assume not off hook on CVRS */
++ res = 0;
++ par.rxisoffhook = 0;
++ }
++ if (res) {
++ ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
++ }
++
++ return (par.rxbits > -1) || par.rxisoffhook;
++}
++
++static void dahdi_enable_ec(struct dahdi_pvt *p);
++static void dahdi_disable_ec(struct dahdi_pvt *p);
++
++static int my_set_echocanceller(void *pvt, int enable)
++{
++ struct dahdi_pvt *p = pvt;
++
++ if (enable)
++ dahdi_enable_ec(p);
++ else
++ dahdi_disable_ec(p);
++
++ return 0;
++}
++
++static int dahdi_ring_phone(struct dahdi_pvt *p);
++
++static int my_ring(void *pvt)
++{
++ struct dahdi_pvt *p = pvt;
++
++ return dahdi_ring_phone(p);
++}
++
++static inline int dahdi_set_hook(int fd, int hs);
++
++static int my_off_hook(void *pvt)
++{
++ struct dahdi_pvt *p = pvt;
++ return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
++}
++
++static int my_start(void *pvt)
++{
++ struct dahdi_pvt *p = pvt;
++ int x = DAHDI_START;
++
++ return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
++}
++
++static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
++{
++ int index = analogsub_to_dahdisub(sub);
++ int res;
++ struct dahdi_pvt *p = pvt;
++ struct dahdi_dialoperation ddop;
++
++ if (dop->op != ANALOG_DIAL_OP_REPLACE) {
++ ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
++ return -1;
++ }
++
++ if (sub != ANALOG_SUB_REAL)
++ printf("Trying to dial digits on sub %d\n", sub);
++
++ ddop.op = DAHDI_DIAL_OP_REPLACE;
++ strncpy(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
++
++ printf("Dialing %s on %d\n", ddop.dialstr, p->channel);
++
++ res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
++
++ if (res == -1)
++ ast_log(LOG_DEBUG, "DAHDI_DIAL ioctl failed on %s: %s\n", p->owner->name, strerror(errno));
++
++ return res;
++}
++
++static void dahdi_train_ec(struct dahdi_pvt *p);
++
++static int my_train_echocanceller(void *pvt)
++{
++ struct dahdi_pvt *p = pvt;
++
++ dahdi_train_ec(p);
++
++ return 0;
++}
++
++static int my_is_dialing(void *pvt, enum analog_sub sub)
++{
++ struct dahdi_pvt *p = pvt;
++ int index;
++ int x;
++
++ index = analogsub_to_dahdisub(sub);
++
++ if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
++ ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed!\n");
++ return -1;
++ }
++
++ return x;
++}
++
++static int my_on_hook(void *pvt)
++{
++ struct dahdi_pvt *p = pvt;
++ int x = DAHDI_ONHOOK;
++
++ return ioctl(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_HOOK, &x);
++}
++
++/*!
++ * \brief Send MWI state change
++ *
++ * \arg mailbox_full This is the mailbox associated with the FXO line that the
++ * MWI state has changed on.
++ * \arg thereornot This argument should simply be set to 1 or 0, to indicate
++ * whether there are messages waiting or not.
++ *
++ * \return nothing
++ *
++ * This function does two things:
++ *
++ * 1) It generates an internal Asterisk event notifying any other module that
++ * cares about MWI that the state of a mailbox has changed.
++ *
++ * 2) It runs the script specified by the mwimonitornotify option to allow
++ * some custom handling of the state change.
++ */
++static void notify_message(char *mailbox_full, int thereornot)
++{
++ char s[sizeof(mwimonitornotify) + 80];
++ struct ast_event *event;
++ char *mailbox, *context;
++
++ /* Strip off @default */
++ context = mailbox = ast_strdupa(mailbox_full);
++ strsep(&context, "@");
++ if (ast_strlen_zero(context))
++ context = "default";
++
++ if (!(event = ast_event_new(AST_EVENT_MWI,
++ AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
++ AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
++ AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
++ AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
++ AST_EVENT_IE_END))) {
++ return;
++ }
++
++ ast_event_queue_and_cache(event);
++
++ if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
++ snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
++ ast_safe_system(s);
++ }
++}
++
++static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
++{
++ struct dahdi_pvt *p = pvt;
++
++ if (neon_mwievent > -1 && !p->mwimonitor_neon)
++ return;
++
++ if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
++ ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
++ notify_message(p->mailbox, 1);
++ } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
++ ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
++ notify_message(p->mailbox, 0);
++ }
++ /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
++ /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
++ if (neon_mwievent == -1 && p->mwimonitor_rpas) {
++ ast_hangup(chan);
++ return;
++ }
++}
++
++
++static const char *event2str(int event);
++
++static struct analog_callback dahdi_analog_callbacks =
++{
++ .play_tone = my_play_tone,
++ .get_event = my_get_event,
++ .wait_event = my_wait_event,
++ .is_off_hook = my_is_off_hook,
++ .set_echocanceller = my_set_echocanceller,
++ .ring = my_ring,
++ .off_hook = my_off_hook,
++ .dial_digits = my_dial_digits,
++ .train_echocanceller = my_train_echocanceller,
++ .on_hook = my_on_hook,
++ .is_dialing = my_is_dialing,
++ .allocate_sub = my_allocate_sub,
++ .unallocate_sub = my_unallocate_sub,
++ .swap_subs = my_swap_subchannels,
++ .has_voicemail = my_has_voicemail,
++ .check_for_conference = my_check_for_conference,
++ .conf_add = my_conf_add,
++ .conf_del = my_conf_del,
++ .complete_conference_update = my_complete_conference_update,
++ .start = my_start,
++ .all_subchannels_hungup = my_all_subchannels_hungup,
++ .lock_private = my_lock_private,
++ .unlock_private = my_unlock_private,
++ .handle_dtmfup = my_handle_dtmfup,
++ .wink = my_wink,
++ .new_ast_channel = my_new_analog_ast_channel,
++ .dsp_set_digitmode = my_dsp_set_digitmode,
++ .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
++ .send_callerid = my_send_callerid,
++ .callwait = my_callwait,
++ .stop_callwait = my_stop_callwait,
++ .get_callerid = my_get_callerid,
++ .start_cid_detect = my_start_cid_detect,
++ .stop_cid_detect = my_stop_cid_detect,
++ .handle_notify_message = my_handle_notify_message,
++ .increase_ss_count = my_increase_ss_count,
++ .decrease_ss_count = my_decrease_ss_count,
++};
++
++static struct dahdi_pvt *round_robin[32];
++
+ #if defined(HAVE_PRI)
+ static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
+ {
+@@ -2339,7 +3365,7 @@
+ return res;
+ }
+
+-static char *events[] = {
++static const char * const events[] = {
+ "No event",
+ "On hook",
+ "Ring/Answered",
+@@ -2384,7 +3410,7 @@
+ return alm ? "Unknown Alarm" : "No Alarm";
+ }
+
+-static char *event2str(int event)
++static const char *event2str(int event)
+ {
+ static char buf[256];
+ if ((event < (ARRAY_LEN(events))) && (event > -1))
+@@ -2471,6 +3497,45 @@
+ }
+ }
+
++int analog_lib_handles(int signalling, int radio, int oprmode)
++{
++ switch (signalling) {
++ case SIG_FXOLS:
++ case SIG_FXOGS:
++ case SIG_FXOKS:
++ case SIG_FXSLS:
++ case SIG_FXSGS:
++ case SIG_FXSKS:
++ case SIG_EMWINK:
++ case SIG_EM:
++ case SIG_EM_E1:
++ case SIG_FEATD:
++ case SIG_FEATDMF:
++ case SIG_E911:
++ case SIG_FGC_CAMA:
++ case SIG_FGC_CAMAMF:
++ case SIG_FEATB:
++ case SIG_SFWINK:
++ case SIG_SF:
++ case SIG_SF_FEATD:
++ case SIG_SF_FEATDMF:
++ case SIG_FEATDMF_TA:
++ case SIG_SF_FEATB:
++ break;
++ default:
++ /* The rest of the function should cover the remainder of signalling types */
++ return 0;
++ }
++
++ if (radio)
++ return 0;
++
++ if (oprmode)
++ return 0;
++
++ return 1;
++}
++
+ #define sig2str dahdi_sig2str
+
+ static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
+@@ -2917,53 +3982,6 @@
+ return 0;
+ }
+
+-/*!
+- * \brief Send MWI state change
+- *
+- * \arg mailbox_full This is the mailbox associated with the FXO line that the
+- * MWI state has changed on.
+- * \arg thereornot This argument should simply be set to 1 or 0, to indicate
+- * whether there are messages waiting or not.
+- *
+- * \return nothing
+- *
+- * This function does two things:
+- *
+- * 1) It generates an internal Asterisk event notifying any other module that
+- * cares about MWI that the state of a mailbox has changed.
+- *
+- * 2) It runs the script specified by the mwimonitornotify option to allow
+- * some custom handling of the state change.
+- */
+-static void notify_message(char *mailbox_full, int thereornot)
+-{
+- char s[sizeof(mwimonitornotify) + 80];
+- struct ast_event *event;
+- char *mailbox, *context;
+-
+- /* Strip off @default */
+- context = mailbox = ast_strdupa(mailbox_full);
+- strsep(&context, "@");
+- if (ast_strlen_zero(context))
+- context = "default";
+-
+- if (!(event = ast_event_new(AST_EVENT_MWI,
+- AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
+- AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
+- AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
+- AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
+- AST_EVENT_IE_END))) {
+- return;
+- }
+-
+- ast_event_queue_and_cache(event);
+-
+- if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
+- snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
+- ast_safe_system(s);
+- }
+-}
+-
+ static int restore_conference(struct dahdi_pvt *p)
+ {
+ int res;
+@@ -3021,6 +4039,8 @@
+ return new_msgs;
+ }
+
++
++
+ static int send_callerid(struct dahdi_pvt *p)
+ {
+ /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
+@@ -3135,6 +4155,14 @@
+
+ set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
+
++ /* If this is analog signalling we can exit here */
++ if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
++ p->callwaitrings = 0;
++ res = analog_call(p->sig_pvt, ast, rdest, timeout);
++ ast_mutex_unlock(&p->lock);
++ return res;
++ }
++
+ mysig = p->sig;
+ if (p->outsigmod > -1)
+ mysig = p->outsigmod;
+@@ -3156,7 +4184,7 @@
+ }
+ p->callwaitcas = 0;
+ if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
+- p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
++ p->cidlen = ast_callerid_generate(p->cidspill, ast->connected.id.name, ast->connected.id.number, AST_LAW(p));
+ p->cidpos = 0;
+ send_callerid(p);
+ }
+@@ -3197,12 +4225,12 @@
+ } else {
+ /* Call waiting call */
+ p->callwaitrings = 0;
+- if (ast->cid.cid_num)
+- ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
++ if (ast->connected.id.number)
++ ast_copy_string(p->callwait_num, ast->connected.id.number, sizeof(p->callwait_num));
+ else
+ p->callwait_num[0] = '\0';
+- if (ast->cid.cid_name)
+- ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
++ if (ast->connected.id.name)
++ ast_copy_string(p->callwait_name, ast->connected.id.name, sizeof(p->callwait_name));
+ else
+ p->callwait_name[0] = '\0';
+ /* Call waiting tone instead */
+@@ -3214,8 +4242,8 @@
+ if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
+ ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
+ }
+- n = ast->cid.cid_name;
+- l = ast->cid.cid_num;
++ n = ast->connected.id.name;
++ l = ast->connected.id.number;
+ if (l)
+ ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
+ else
+@@ -3281,14 +4309,14 @@
+
+ switch (mysig) {
+ case SIG_FEATD:
+- l = ast->cid.cid_num;
++ l = ast->connected.id.number;
+ if (l)
+ snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
+ else
+ snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
+ break;
+ case SIG_FEATDMF:
+- l = ast->cid.cid_num;
++ l = ast->connected.id.number;
+ if (l)
+ snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
+ else
+@@ -3423,7 +4451,7 @@
+ }
+
+ if (!p->hidecallerid) {
+- l = ast->cid.cid_num;
++ l = ast->connected.id.number;
+ } else {
+ l = NULL;
+ }
+@@ -3472,10 +4500,10 @@
+ }
+ }
+ isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
+- p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
+- p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED );
++ p->use_callingpres ? cid_pres2ss7pres(ast->connected.id.number_presentation) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
++ p->use_callingpres ? cid_pres2ss7screen(ast->connected.id.number_presentation) : SS7_SCREENING_USER_PROVIDED );
+
+- isup_set_oli(p->ss7call, ast->cid.cid_ani2);
++ isup_set_oli(p->ss7call, ast->connected.ani2);
+ isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
+
+ ast_channel_lock(ast);
+@@ -3587,9 +4615,9 @@
+ l = NULL;
+ n = NULL;
+ if (!p->hidecallerid) {
+- l = ast->cid.cid_num;
++ l = ast->connected.id.number;
+ if (!p->hidecalleridname) {
+- n = ast->cid.cid_name;
++ n = ast->connected.id.name;
+ }
+ }
+
+@@ -3803,7 +4831,7 @@
+ }
+ }
+ pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
+- p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
++ p->use_callingpres ? ast->connected.id.number_presentation : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
+ if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
+ if (!strcasecmp(rr_str, "UNKNOWN"))
+ redirect_reason = 0;
+@@ -3934,11 +4962,25 @@
+ pl = p;
+ p = p->next;
+ x = pl->channel;
++#ifdef HAVE_PRI_SERVICE_MESSAGES
++ {
++ char db_chan_name[20], db_answer[5], state;
++ int why = -1;
++
++ snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, pl->span, x);
++ if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
++ sscanf(db_answer, "%c:%d", &state, &why);
++ }
++ if (!why) {
++ /* SRVST persistence is not required */
++ ast_db_del(db_chan_name, SRVST_DBKEY);
++ }
++ }
++#endif
+ /* Free associated memory */
+ if (pl)
+ destroy_dahdi_pvt(&pl);
+- if (option_verbose > 2)
+- ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
++ ast_verb(3, "Unregistered channel %d\n", x);
+ }
+ iflist = NULL;
+ ifcount = 0;
+@@ -3948,11 +4990,11 @@
+ #if defined(HAVE_PRI)
+ static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
+
+-static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
++static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *data)
+ {
+ /* Data will be our digit string */
+ struct dahdi_pvt *p;
+- char *digits = (char *) data;
++ const char *digits = data;
+
+ if (ast_strlen_zero(digits)) {
+ ast_debug(1, "No digit string sent to application!\n");
+@@ -3993,7 +5035,7 @@
+ #if defined(HAVE_PRI_PROG_W_CAUSE)
+ static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
+
+-static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, void *data)
++static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
+ {
+ /* Data will be our digit string */
+ struct dahdi_pvt *p;
+@@ -4157,9 +5199,9 @@
+ #endif /* defined(HAVE_PRI) */
+
+ #if defined(HAVE_OPENR2)
+-static const char *dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
++static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
+
+-static int dahdi_accept_r2_call_exec(struct ast_channel *chan, void *data)
++static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
+ {
+ /* data is whether to accept with charge or no charge */
+ openr2_call_mode_t accept_mode;
+@@ -4293,8 +5335,8 @@
+ r2cause = OR2_CAUSE_NORMAL_CLEARING;
+ break;
+ }
+- ast_log(LOG_DEBUG, "dahdi_ast_cause_to_r2_cause returned %d/%s for ast cause %d\n",
+- r2cause, openr2_proto_get_disconnect_string(r2cause), cause);
++ ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
++ cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
+ return r2cause;
+ }
+ #endif
+@@ -4315,6 +5357,34 @@
+ return 0;
+ }
+
++ if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
++ ast_mutex_lock(&p->lock);
++
++ dahdi_confmute(p, 0);
++ restore_gains(p);
++ p->ignoredtmf = 0;
++
++ if (p->bufferoverrideinuse) {
++ /* faxbuffers are in use, revert them */
++ struct dahdi_bufferinfo bi = {
++ .txbufpolicy = p->buf_policy,
++ .rxbufpolicy = p->buf_policy,
++ .bufsize = p->bufsize,
++ .numbufs = p->buf_no
++ };
++ int bpres;
++
++ if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
++ ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno));
++ }
++ p->bufferoverrideinuse = 0;
++ }
++
++ res = analog_hangup(p->sig_pvt, ast);
++
++ goto hangup_out;
++ }
++
+ ast_mutex_lock(&p->lock);
+
+ idx = dahdi_get_index(ast, p, 1);
+@@ -4470,7 +5540,7 @@
+ p->dsp = NULL;
+ }
+
+- if (p->faxbuffersinuse) {
++ if (p->bufferoverrideinuse) {
+ /* faxbuffers are in use, revert them */
+ struct dahdi_bufferinfo bi = {
+ .txbufpolicy = p->buf_policy,
+@@ -4481,9 +5551,9 @@
+ int bpres;
+
+ if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
+- ast_log(LOG_WARNING, "Channel '%s' unable to revert faxbuffer policy: %s\n", ast->name, strerror(errno));
++ ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno));
+ }
+- p->faxbuffersinuse = 0;
++ p->bufferoverrideinuse = 0;
+ }
+
+ law = DAHDI_LAW_DEFAULT;
+@@ -4623,15 +5693,12 @@
+ default:
+ tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
+ }
+- if (p->cidspill)
+- ast_free(p->cidspill);
+ if (p->sig)
+ dahdi_disable_ec(p);
+ x = 0;
+ ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
+ ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
+ p->didtdd = 0;
+- p->cidspill = NULL;
+ p->callwaitcas = 0;
+ p->callwaiting = p->permcallwaiting;
+ p->hidecallerid = p->permhidecallerid;
+@@ -4667,6 +5734,11 @@
+ p->cidcwexpire = 0;
+ p->oprmode = 0;
+ ast->tech_pvt = NULL;
++hangup_out:
++ if (p->cidspill)
++ ast_free(p->cidspill);
++ p->cidspill = NULL;
++
+ ast_mutex_unlock(&p->lock);
+ ast_module_unref(ast_module_info->self);
+ ast_verb(3, "Hungup '%s'\n", ast->name);
+@@ -4710,6 +5782,13 @@
+ ast_mutex_unlock(&p->lock);
+ return 0;
+ }
++
++ if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
++ res = analog_answer(p->sig_pvt, ast);
++ ast_mutex_unlock(&p->lock);
++ return res;
++ }
++
+ switch (p->sig) {
+ case SIG_FXSLS:
+ case SIG_FXSGS:
+@@ -4813,6 +5892,66 @@
+ return res;
+ }
+
++static void disable_dtmf_detect(struct dahdi_pvt *p)
++{
++ int val = 0;
++
++ p->ignoredtmf = 1;
++
++ ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
++
++ if (!p->hardwaredtmf && p->dsp) {
++ p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
++ ast_dsp_set_features(p->dsp, p->dsp_features);
++ }
++}
++
++static void enable_dtmf_detect(struct dahdi_pvt *p)
++{
++ int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
++
++ if (p->channel == CHAN_PSEUDO)
++ return;
++
++ p->ignoredtmf = 0;
++
++ ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
++
++ if (!p->hardwaredtmf && p->dsp) {
++ p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
++ ast_dsp_set_features(p->dsp, p->dsp_features);
++ }
++}
++
++static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
++{
++ char *cp;
++ struct dahdi_pvt *p = chan->tech_pvt;
++
++ /* all supported options require data */
++ if (!data || (*datalen < 1)) {
++ errno = EINVAL;
++ return -1;
++ }
++
++ switch (option) {
++ case AST_OPTION_DIGIT_DETECT:
++ cp = (char *) data;
++ *cp = p->ignoredtmf ? 0 : 1;
++ ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
++ break;
++ case AST_OPTION_FAX_DETECT:
++ cp = (char *) data;
++ *cp = (p->callprogress & CALLPROGRESS_FAX) ? 0 : 1;
++ ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
++ break;
++ }
++
++ errno = 0;
++
++ return 0;
++}
++
+ static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
+ {
+ char *cp;
+@@ -4995,6 +6134,31 @@
+ dahdi_disable_ec(p);
+ }
+ break;
++ case AST_OPTION_DIGIT_DETECT:
++ cp = (char *) data;
++ ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
++ if (*cp) {
++ enable_dtmf_detect(p);
++ } else {
++ disable_dtmf_detect(p);
++ }
++ break;
++ case AST_OPTION_FAX_DETECT:
++ cp = (char *) data;
++ if (p->dsp) {
++ ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name);
++ if (*cp) {
++ p->callprogress |= CALLPROGRESS_FAX;
++ p->dsp_features |= DSP_FEATURE_FAX_DETECT;
++ } else {
++ p->callprogress &= ~CALLPROGRESS_FAX;
++ p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
++ }
++ ast_dsp_set_features(p->dsp, p->dsp_features);
++ }
++ break;
++ default:
++ return -1;
+ }
+ errno = 0;
+
+@@ -5004,7 +6168,8 @@
+ static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
+ {
+ struct dahdi_pvt *p = chan->tech_pvt;
+-
++ int res = 0;
++
+ if (!strcasecmp(data, "rxgain")) {
+ ast_mutex_lock(&p->lock);
+ snprintf(buf, len, "%f", p->rxgain);
+@@ -5015,11 +6180,111 @@
+ ast_mutex_unlock(&p->lock);
+ } else {
+ ast_copy_string(buf, "", len);
++ res = -1;
+ }
++
++ return res;
++}
++
++
++static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
++{
++ int res;
++ char policy_str[21] = "";
++
++ if ((res = sscanf(parse, "%d,%20s", num_buffers, policy_str)) != 2) {
++ ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
++ return 1;
++ }
++ if (*num_buffers < 0) {
++ ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
++ return -1;
++ }
++ if (!strcasecmp(policy_str, "full")) {
++ *policy = DAHDI_POLICY_WHEN_FULL;
++ } else if (!strcasecmp(policy_str, "immediate")) {
++ *policy = DAHDI_POLICY_IMMEDIATE;
++#if defined(HAVE_DAHDI_HALF_FULL)
++ } else if (!strcasecmp(policy_str, "half")) {
++ *policy = DAHDI_POLICY_HALF_FULL;
++#endif
++ } else {
++ ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
++ return -1;
++ }
++
+ return 0;
+ }
+
++static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
++{
++ struct dahdi_pvt *p = chan->tech_pvt;
++ int res = 0;
++
++ if (!strcasecmp(data, "buffers")) {
++ int num_bufs, policy;
+
++ if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
++ struct dahdi_bufferinfo bi = {
++ .txbufpolicy = policy,
++ .rxbufpolicy = policy,
++ .bufsize = p->bufsize,
++ .numbufs = num_bufs,
++ };
++ int bpres;
++
++ if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
++ ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
++ } else {
++ p->bufferoverrideinuse = 1;
++ }
++ } else {
++ res = -1;
++ }
++ } else if (!strcasecmp(data, "echocan_mode")) {
++ if (!strcasecmp(value, "on")) {
++ ast_mutex_lock(&p->lock);
++ dahdi_enable_ec(p);
++ ast_mutex_unlock(&p->lock);
++ } else if (!strcasecmp(value, "off")) {
++ ast_mutex_lock(&p->lock);
++ dahdi_disable_ec(p);
++ ast_mutex_unlock(&p->lock);
++#ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
++ } else if (!strcasecmp(value, "fax")) {
++ int blah = 1;
++
++ ast_mutex_lock(&p->lock);
++ if (!p->echocanon) {
++ dahdi_enable_ec(p);
++ }
++ if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
++ ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
++ }
++ ast_mutex_unlock(&p->lock);
++ } else if (!strcasecmp(value, "voice")) {
++ int blah = 0;
++
++ ast_mutex_lock(&p->lock);
++ if (!p->echocanon) {
++ dahdi_enable_ec(p);
++ }
++ if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
++ ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
++ }
++ ast_mutex_unlock(&p->lock);
++#endif
++ } else {
++ ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
++ res = -1;
++ }
++ } else {
++ res = -1;
++ }
++
++ return res;
++}
++
+ static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
+ {
+ /* Unlink a specific slave or all slaves/masters from a given master */
+@@ -5099,39 +6364,6 @@
+ ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
+ }
+
+-static void disable_dtmf_detect(struct dahdi_pvt *p)
+-{
+- int val;
+-
+- p->ignoredtmf = 1;
+-
+- val = 0;
+- ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
+-
+- if (!p->hardwaredtmf && p->dsp) {
+- p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
+- ast_dsp_set_features(p->dsp, p->dsp_features);
+- }
+-}
+-
+-static void enable_dtmf_detect(struct dahdi_pvt *p)
+-{
+- int val;
+-
+- if (p->channel == CHAN_PSEUDO)
+- return;
+-
+- p->ignoredtmf = 0;
+-
+- val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
+- ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
+-
+- if (!p->hardwaredtmf && p->dsp) {
+- p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
+- ast_dsp_set_features(p->dsp, p->dsp_features);
+- }
+-}
+-
+ static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
+ {
+ struct ast_channel *who;
+@@ -5441,6 +6673,11 @@
+ }
+ if (newchan->_state == AST_STATE_RINGING)
+ dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
++
++ if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
++ analog_fixup(oldchan, newchan, p->sig_pvt);
++ }
++
+ update_conf(p);
+ ast_mutex_unlock(&p->lock);
+ return 0;
+@@ -5476,7 +6713,7 @@
+ return res;
+ }
+
+-static void *ss_thread(void *data);
++static void *analog_ss_thread(void *data);
+
+ static int attempt_transfer(struct dahdi_pvt *p)
+ {
+@@ -5614,7 +6851,7 @@
+ /* Fax tone -- Handle and return NULL */
+ if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
+ /* If faxbuffers are configured, use them for the fax transmission */
+- if (p->usefaxbuffers && !p->faxbuffersinuse) {
++ if (p->usefaxbuffers && !p->bufferoverrideinuse) {
+ struct dahdi_bufferinfo bi = {
+ .txbufpolicy = p->faxbuf_policy,
+ .bufsize = p->bufsize,
+@@ -5623,12 +6860,16 @@
+ int res;
+
+ if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
+- ast_log(LOG_WARNING, "Channel '%s' unable to set faxbuffer policy, reason: %s\n", ast->name, strerror(errno));
++ ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
+ } else {
+- p->faxbuffersinuse = 1;
++ p->bufferoverrideinuse = 1;
+ }
+ }
+ p->faxhandled = 1;
++ p->callprogress &= ~CALLPROGRESS_FAX;
++ p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
++ ast_dsp_set_features(p->dsp, p->dsp_features);
++ ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
+ if (strcmp(ast->exten, "fax")) {
+ const char *target_context = S_OR(ast->macrocontext, ast->context);
+
+@@ -5736,806 +6977,818 @@
+ }
+
+ switch (res) {
+- case DAHDI_EVENT_EC_DISABLED:
+- ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel);
+- p->echocanon = 0;
+- break;
+- case DAHDI_EVENT_BITSCHANGED:
++ case DAHDI_EVENT_EC_DISABLED:
++ ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
++ p->echocanon = 0;
++ break;
++#ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
++ case DAHDI_EVENT_TX_CED_DETECTED:
++ ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
++ break;
++ case DAHDI_EVENT_RX_CED_DETECTED:
++ ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
++ break;
++ case DAHDI_EVENT_EC_NLP_DISABLED:
++ ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
++ break;
++ case DAHDI_EVENT_EC_NLP_ENABLED:
++ ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
++ break;
++#endif
++ case DAHDI_EVENT_BITSCHANGED:
+ #ifdef HAVE_OPENR2
+- if (p->sig != SIG_MFCR2) {
+- ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
+- } else {
+- ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
+- openr2_chan_handle_cas(p->r2chan);
+- }
++ if (p->sig != SIG_MFCR2) {
++ ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
++ } else {
++ ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
++ openr2_chan_handle_cas(p->r2chan);
++ }
+ #else
+- ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
++ ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
+ #endif
+- case DAHDI_EVENT_PULSE_START:
+- /* Stop tone if there's a pulse start and the PBX isn't started */
+- if (!ast->pbx)
+- tone_zone_play_tone(p->subs[idx].dfd, -1);
++ case DAHDI_EVENT_PULSE_START:
++ /* Stop tone if there's a pulse start and the PBX isn't started */
++ if (!ast->pbx)
++ tone_zone_play_tone(p->subs[idx].dfd, -1);
++ break;
++ case DAHDI_EVENT_DIALCOMPLETE:
++#ifdef HAVE_OPENR2
++ if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
++ /* we don't need to do anything for this event for R2 signaling
++ if the call is being setup */
+ break;
+- case DAHDI_EVENT_DIALCOMPLETE:
+-#ifdef HAVE_OPENR2
+- if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
+- /* we don't need to do anything for this event for R2 signaling
+- if the call is being setup */
+- break;
+- }
++ }
+ #endif
+- if (p->inalarm) break;
+- if ((p->radio || (p->oprmode < 0))) break;
+- if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
+- ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
+- return NULL;
+- }
+- if (!x) { /* if not still dialing in driver */
+- dahdi_enable_ec(p);
+- if (p->echobreak) {
+- dahdi_train_ec(p);
+- ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
+- p->dop.op = DAHDI_DIAL_OP_REPLACE;
+- res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
+- p->echobreak = 0;
+- } else {
+- p->dialing = 0;
+- if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
+- /* if thru with dialing after offhook */
+- if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
+- ast_setstate(ast, AST_STATE_UP);
+- p->subs[idx].f.frametype = AST_FRAME_CONTROL;
+- p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
+- break;
+- } else { /* if to state wait for offhook to dial rest */
+- /* we now wait for off hook */
+- ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
+- }
++ if (p->inalarm) break;
++ if ((p->radio || (p->oprmode < 0))) break;
++ if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
++ ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
++ return NULL;
++ }
++ if (!x) { /* if not still dialing in driver */
++ dahdi_enable_ec(p);
++ if (p->echobreak) {
++ dahdi_train_ec(p);
++ ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
++ p->dop.op = DAHDI_DIAL_OP_REPLACE;
++ res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
++ p->echobreak = 0;
++ } else {
++ p->dialing = 0;
++ if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
++ /* if thru with dialing after offhook */
++ if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
++ ast_setstate(ast, AST_STATE_UP);
++ p->subs[idx].f.frametype = AST_FRAME_CONTROL;
++ p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
++ break;
++ } else { /* if to state wait for offhook to dial rest */
++ /* we now wait for off hook */
++ ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
+ }
+- if (ast->_state == AST_STATE_DIALING) {
+- if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
+- ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
+- } else if (p->confirmanswer || (!p->dialednone
+- && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
+- || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
+- || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
+- || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
+- || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
+- || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
+- || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
+- || (mysig == SIG_SF_FEATB)))) {
+- ast_setstate(ast, AST_STATE_RINGING);
+- } else if (!p->answeronpolarityswitch) {
+- ast_setstate(ast, AST_STATE_UP);
+- p->subs[idx].f.frametype = AST_FRAME_CONTROL;
+- p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
+- /* If aops=0 and hops=1, this is necessary */
+- p->polarity = POLARITY_REV;
+- } else {
+- /* Start clean, so we can catch the change to REV polarity when party answers */
+- p->polarity = POLARITY_IDLE;
+- }
++ }
++ if (ast->_state == AST_STATE_DIALING) {
++ if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
++ ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
++ } else if (p->confirmanswer || (!p->dialednone
++ && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
++ || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
++ || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
++ || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
++ || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
++ || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
++ || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
++ || (mysig == SIG_SF_FEATB)))) {
++ ast_setstate(ast, AST_STATE_RINGING);
++ } else if (!p->answeronpolarityswitch) {
++ ast_setstate(ast, AST_STATE_UP);
++ p->subs[idx].f.frametype = AST_FRAME_CONTROL;
++ p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
++ /* If aops=0 and hops=1, this is necessary */
++ p->polarity = POLARITY_REV;
++ } else {
++ /* Start clean, so we can catch the change to REV polarity when party answers */
++ p->polarity = POLARITY_IDLE;
+ }
+ }
+ }
+- break;
+- case DAHDI_EVENT_ALARM:
++ }
++ break;
++ case DAHDI_EVENT_ALARM:
+ #ifdef HAVE_PRI
+- if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
+- if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
+- /* T309 is not enabled : hangup calls when alarm occurs */
+- if (p->call) {
+- if (p->pri && p->pri->pri) {
+- if (!pri_grab(p, p->pri)) {
+- pri_hangup(p->pri->pri, p->call, -1);
+- pri_destroycall(p->pri->pri, p->call);
+- p->call = NULL;
+- pri_rel(p->pri);
+- } else
+- ast_log(LOG_WARNING, "Failed to grab PRI!\n");
++ if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
++ if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
++ /* T309 is not enabled : hangup calls when alarm occurs */
++ if (p->call) {
++ if (p->pri && p->pri->pri) {
++ if (!pri_grab(p, p->pri)) {
++ pri_hangup(p->pri->pri, p->call, -1);
++ pri_destroycall(p->pri->pri, p->call);
++ p->call = NULL;
++ pri_rel(p->pri);
+ } else
+- ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
+- }
+- if (p->owner)
+- p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
++ ast_log(LOG_WARNING, "Failed to grab PRI!\n");
++ } else
++ ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
+ }
++ if (p->owner)
++ p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+ }
+- if (p->bearer)
+- p->bearer->inalarm = 1;
+- else
++ }
++ if (p->bearer)
++ p->bearer->inalarm = 1;
++ else
+ #endif
+- p->inalarm = 1;
+- res = get_alarms(p);
+- handle_alarms(p, res);
++ p->inalarm = 1;
++ res = get_alarms(p);
++ handle_alarms(p, res);
+ #ifdef HAVE_PRI
+- if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
+- /* fall through intentionally */
+- } else {
+- break;
+- }
++ if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
++ /* fall through intentionally */
++ } else {
++ break;
++ }
+ #endif
+ #ifdef HAVE_SS7
+- if (p->sig == SIG_SS7)
+- break;
++ if (p->sig == SIG_SS7)
++ break;
+ #endif
+ #ifdef HAVE_OPENR2
+- if (p->sig == SIG_MFCR2)
+- break;
++ if (p->sig == SIG_MFCR2)
++ break;
+ #endif
+- case DAHDI_EVENT_ONHOOK:
+- if (p->radio) {
+- p->subs[idx].f.frametype = AST_FRAME_CONTROL;
+- p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
+- break;
+- }
+- if (p->oprmode < 0)
++ case DAHDI_EVENT_ONHOOK:
++ if (p->radio) {
++ p->subs[idx].f.frametype = AST_FRAME_CONTROL;
++ p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
++ break;
++ }
++ if (p->oprmode < 0)
++ {
++ if (p->oprmode != -1) break;
++ if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
+ {
+- if (p->oprmode != -1) break;
+- if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
+- {
+- /* Make sure it starts ringing */
+- dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
+- dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
+- save_conference(p->oprpeer);
+- tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
+- }
+- break;
++ /* Make sure it starts ringing */
++ dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
++ dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
++ save_conference(p->oprpeer);
++ tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
+ }
+- switch (p->sig) {
+- case SIG_FXOLS:
+- case SIG_FXOGS:
+- case SIG_FXOKS:
+- p->onhooktime = time(NULL);
+- p->fxsoffhookstate = 0;
+- p->msgstate = -1;
+- /* Check for some special conditions regarding call waiting */
+- if (idx == SUB_REAL) {
+- /* The normal line was hung up */
+- if (p->subs[SUB_CALLWAIT].owner) {
+- /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
+- swap_subs(p, SUB_CALLWAIT, SUB_REAL);
+- ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
+- unalloc_sub(p, SUB_CALLWAIT);
++ break;
++ }
++ switch (p->sig) {
++ case SIG_FXOLS:
++ case SIG_FXOGS:
++ case SIG_FXOKS:
++ p->onhooktime = time(NULL);
++ p->fxsoffhookstate = 0;
++ p->msgstate = -1;
++ /* Check for some special conditions regarding call waiting */
++ if (idx == SUB_REAL) {
++ /* The normal line was hung up */
++ if (p->subs[SUB_CALLWAIT].owner) {
++ /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
++ swap_subs(p, SUB_CALLWAIT, SUB_REAL);
++ ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
++ unalloc_sub(p, SUB_CALLWAIT);
+ #if 0
+- p->subs[idx].needanswer = 0;
+- p->subs[idx].needringing = 0;
++ p->subs[idx].needanswer = 0;
++ p->subs[idx].needringing = 0;
+ #endif
+- p->callwaitingrepeat = 0;
+- p->cidcwexpire = 0;
+- p->owner = NULL;
+- /* Don't start streaming audio yet if the incoming call isn't up yet */
+- if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
+- p->dialing = 1;
+- dahdi_ring_phone(p);
+- } else if (p->subs[SUB_THREEWAY].owner) {
+- unsigned int mssinceflash;
+- /* Here we have to retain the lock on both the main channel, the 3-way channel, and
+- the private structure -- not especially easy or clean */
+- while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
+- /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
+- DLA_UNLOCK(&p->lock);
+- CHANNEL_DEADLOCK_AVOIDANCE(ast);
+- /* We can grab ast and p in that order, without worry. We should make sure
+- nothing seriously bad has happened though like some sort of bizarre double
+- masquerade! */
+- DLA_LOCK(&p->lock);
+- if (p->owner != ast) {
+- ast_log(LOG_WARNING, "This isn't good...\n");
+- return NULL;
+- }
+- }
+- if (!p->subs[SUB_THREEWAY].owner) {
+- ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
++ p->callwaitingrepeat = 0;
++ p->cidcwexpire = 0;
++ p->owner = NULL;
++ /* Don't start streaming audio yet if the incoming call isn't up yet */
++ if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
++ p->dialing = 1;
++ dahdi_ring_phone(p);
++ } else if (p->subs[SUB_THREEWAY].owner) {
++ unsigned int mssinceflash;
++ /* Here we have to retain the lock on both the main channel, the 3-way channel, and
++ the private structure -- not especially easy or clean */
++ while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
++ /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
++ DLA_UNLOCK(&p->lock);
++ CHANNEL_DEADLOCK_AVOIDANCE(ast);
++ /* We can grab ast and p in that order, without worry. We should make sure
++ nothing seriously bad has happened though like some sort of bizarre double
++ masquerade! */
++ DLA_LOCK(&p->lock);
++ if (p->owner != ast) {
++ ast_log(LOG_WARNING, "This isn't good...\n");
+ return NULL;
+ }
+- mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
+- ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
+- if (mssinceflash < MIN_MS_SINCE_FLASH) {
+- /* It hasn't been long enough since the last flashook. This is probably a bounce on
+- hanging up. Hangup both channels now */
+- if (p->subs[SUB_THREEWAY].owner)
+- ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
+- p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
+- ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
+- ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
+- } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
+- if (p->transfer) {
+- /* In any case this isn't a threeway call anymore */
+- p->subs[SUB_REAL].inthreeway = 0;
+- p->subs[SUB_THREEWAY].inthreeway = 0;
+- /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
+- if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
+- ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
+- /* Swap subs and dis-own channel */
+- swap_subs(p, SUB_THREEWAY, SUB_REAL);
+- p->owner = NULL;
+- /* Ring the phone */
+- dahdi_ring_phone(p);
+- } else {
+- if ((res = attempt_transfer(p)) < 0) {
+- p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
+- if (p->subs[SUB_THREEWAY].owner)
+- ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
+- } else if (res) {
+- /* Don't actually hang up at this point */
+- if (p->subs[SUB_THREEWAY].owner)
+- ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
+- break;
+- }
++ }
++ if (!p->subs[SUB_THREEWAY].owner) {
++ ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
++ return NULL;
++ }
++ mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
++ ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
++ if (mssinceflash < MIN_MS_SINCE_FLASH) {
++ /* It hasn't been long enough since the last flashook. This is probably a bounce on
++ hanging up. Hangup both channels now */
++ if (p->subs[SUB_THREEWAY].owner)
++ ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
++ p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
++ ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
++ ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
++ } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
++ if (p->transfer) {
++ /* In any case this isn't a threeway call anymore */
++ p->subs[SUB_REAL].inthreeway = 0;
++ p->subs[SUB_THREEWAY].inthreeway = 0;
++ /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
++ if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
++ ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
++ /* Swap subs and dis-own channel */
++ swap_subs(p, SUB_THREEWAY, SUB_REAL);
++ p->owner = NULL;
++ /* Ring the phone */
++ dahdi_ring_phone(p);
++ } else {
++ if ((res = attempt_transfer(p)) < 0) {
++ p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
++ if (p->subs[SUB_THREEWAY].owner)
++ ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
++ } else if (res) {
++ /* Don't actually hang up at this point */
++ if (p->subs[SUB_THREEWAY].owner)
++ ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
++ break;
+ }
+- } else {
+- p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
+- if (p->subs[SUB_THREEWAY].owner)
+- ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
+ }
+ } else {
+- ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
+- /* Swap subs and dis-own channel */
+- swap_subs(p, SUB_THREEWAY, SUB_REAL);
+- p->owner = NULL;
+- /* Ring the phone */
+- dahdi_ring_phone(p);
++ p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
++ if (p->subs[SUB_THREEWAY].owner)
++ ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
+ }
++ } else {
++ ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
++ /* Swap subs and dis-own channel */
++ swap_subs(p, SUB_THREEWAY, SUB_REAL);
++ p->owner = NULL;
++ /* Ring the phone */
++ dahdi_ring_phone(p);
+ }
+- } else {
+- ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
+ }
+- /* Fall through */
+- default:
+- dahdi_disable_ec(p);
+- return NULL;
++ } else {
++ ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
+ }
+- break;
+- case DAHDI_EVENT_RINGOFFHOOK:
+- if (p->inalarm) break;
+- if (p->oprmode < 0)
++ /* Fall through */
++ default:
++ dahdi_disable_ec(p);
++ return NULL;
++ }
++ break;
++ case DAHDI_EVENT_RINGOFFHOOK:
++ if (p->inalarm) break;
++ if (p->oprmode < 0)
++ {
++ if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
+ {
+- if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
+- {
+- /* Make sure it stops ringing */
+- dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
+- tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
+- restore_conference(p->oprpeer);
+- }
+- break;
++ /* Make sure it stops ringing */
++ dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
++ tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
++ restore_conference(p->oprpeer);
+ }
+- if (p->radio)
+- {
+- p->subs[idx].f.frametype = AST_FRAME_CONTROL;
+- p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
+- break;
+- }
+- /* for E911, its supposed to wait for offhook then dial
+- the second half of the dial string */
+- if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
+- c = strchr(p->dialdest, '/');
+- if (c)
+- c++;
+- else
+- c = p->dialdest;
+- if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
+- else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
+- if (strlen(p->dop.dialstr) > 4) {
+- memset(p->echorest, 'w', sizeof(p->echorest) - 1);
+- strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
+- p->echorest[sizeof(p->echorest) - 1] = '\0';
+- p->echobreak = 1;
+- p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
+- } else
+- p->echobreak = 0;
+- if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
+- int saveerr = errno;
++ break;
++ }
++ if (p->radio)
++ {
++ p->subs[idx].f.frametype = AST_FRAME_CONTROL;
++ p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
++ break;
++ }
++ /* for E911, its supposed to wait for offhook then dial
++ the second half of the dial string */
++ if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
++ c = strchr(p->dialdest, '/');
++ if (c)
++ c++;
++ else
++ c = p->dialdest;
++ if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
++ else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
++ if (strlen(p->dop.dialstr) > 4) {
++ memset(p->echorest, 'w', sizeof(p->echorest) - 1);
++ strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
++ p->echorest[sizeof(p->echorest) - 1] = '\0';
++ p->echobreak = 1;
++ p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
++ } else
++ p->echobreak = 0;
++ if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
++ int saveerr = errno;
+
+- x = DAHDI_ONHOOK;
+- ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
+- ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
+- return NULL;
+- }
+- p->dialing = 1;
+- return &p->subs[idx].f;
+- }
+- switch (p->sig) {
+- case SIG_FXOLS:
+- case SIG_FXOGS:
+- case SIG_FXOKS:
+- p->fxsoffhookstate = 1;
+- switch (ast->_state) {
+- case AST_STATE_RINGING:
+- dahdi_enable_ec(p);
+- dahdi_train_ec(p);
+- p->subs[idx].f.frametype = AST_FRAME_CONTROL;
+- p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
+- /* Make sure it stops ringing */
+- dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
+- ast_debug(1, "channel %d answered\n", p->channel);
+- if (p->cidspill) {
+- /* Cancel any running CallerID spill */
+- ast_free(p->cidspill);
+- p->cidspill = NULL;
+- }
+- p->dialing = 0;
+- p->callwaitcas = 0;
+- if (p->confirmanswer) {
+- /* Ignore answer if "confirm answer" is enabled */
+- p->subs[idx].f.frametype = AST_FRAME_NULL;
+- p->subs[idx].f.subclass = 0;
+- } else if (!ast_strlen_zero(p->dop.dialstr)) {
+- /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
+- res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
+- if (res < 0) {
+- ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
+- p->dop.dialstr[0] = '\0';
+- return NULL;
+- } else {
+- ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
+- p->subs[idx].f.frametype = AST_FRAME_NULL;
+- p->subs[idx].f.subclass = 0;
+- p->dialing = 1;
+- }
+- p->dop.dialstr[0] = '\0';
+- ast_setstate(ast, AST_STATE_DIALING);
+- } else
+- ast_setstate(ast, AST_STATE_UP);
+- return &p->subs[idx].f;
+- case AST_STATE_DOWN:
+- ast_setstate(ast, AST_STATE_RING);
+- ast->rings = 1;
+- p->subs[idx].f.frametype = AST_FRAME_CONTROL;
+- p->subs[idx].f.subclass = AST_CONTROL_OFFHOOK;
+- ast_debug(1, "channel %d picked up\n", p->channel);
+- return &p->subs[idx].f;
+- case AST_STATE_UP:
+- /* Make sure it stops ringing */
+- dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
+- /* Okay -- probably call waiting*/
+- if (ast_bridged_channel(p->owner))
+- ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
+- p->subs[idx].needunhold = 1;
+- break;
+- case AST_STATE_RESERVED:
+- /* Start up dialtone */
+- if (has_voicemail(p))
+- res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
+- else
+- res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
+- break;
+- default:
+- ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
++ x = DAHDI_ONHOOK;
++ ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
++ ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
++ return NULL;
+ }
+- break;
+- case SIG_FXSLS:
+- case SIG_FXSGS:
+- case SIG_FXSKS:
+- if (ast->_state == AST_STATE_RING) {
+- p->ringt = p->ringt_base;
++ p->dialing = 1;
++ return &p->subs[idx].f;
++ }
++ switch (p->sig) {
++ case SIG_FXOLS:
++ case SIG_FXOGS:
++ case SIG_FXOKS:
++ p->fxsoffhookstate = 1;
++ switch (ast->_state) {
++ case AST_STATE_RINGING:
++ dahdi_enable_ec(p);
++ dahdi_train_ec(p);
++ p->subs[idx].f.frametype = AST_FRAME_CONTROL;
++ p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
++ /* Make sure it stops ringing */
++ dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
++ ast_debug(1, "channel %d answered\n", p->channel);
++ if (p->cidspill) {
++ /* Cancel any running CallerID spill */
++ ast_free(p->cidspill);
++ p->cidspill = NULL;
+ }
+-
+- /* If we get a ring then we cannot be in
+- * reversed polarity. So we reset to idle */
+- ast_debug(1, "Setting IDLE polarity due "
+- "to ring. Old polarity was %d\n",
+- p->polarity);
+- p->polarity = POLARITY_IDLE;
+-
+- /* Fall through */
+- case SIG_EM:
+- case SIG_EM_E1:
+- case SIG_EMWINK:
+- case SIG_FEATD:
+- case SIG_FEATDMF:
+- case SIG_FEATDMF_TA:
+- case SIG_E911:
+- case SIG_FGC_CAMA:
+- case SIG_FGC_CAMAMF:
+- case SIG_FEATB:
+- case SIG_SF:
+- case SIG_SFWINK:
+- case SIG_SF_FEATD:
+- case SIG_SF_FEATDMF:
+- case SIG_SF_FEATB:
+- if (ast->_state == AST_STATE_PRERING)
+- ast_setstate(ast, AST_STATE_RING);
+- if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
+- ast_debug(1, "Ring detected\n");
+- p->subs[idx].f.frametype = AST_FRAME_CONTROL;
+- p->subs[idx].f.subclass = AST_CONTROL_RING;
+- } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
+- ast_debug(1, "Line answered\n");
+- if (p->confirmanswer) {
++ p->dialing = 0;
++ p->callwaitcas = 0;
++ if (p->confirmanswer) {
++ /* Ignore answer if "confirm answer" is enabled */
++ p->subs[idx].f.frametype = AST_FRAME_NULL;
++ p->subs[idx].f.subclass = 0;
++ } else if (!ast_strlen_zero(p->dop.dialstr)) {
++ /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
++ res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
++ if (res < 0) {
++ ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
++ p->dop.dialstr[0] = '\0';
++ return NULL;
++ } else {
++ ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
+ p->subs[idx].f.frametype = AST_FRAME_NULL;
+ p->subs[idx].f.subclass = 0;
+- } else {
+- p->subs[idx].f.frametype = AST_FRAME_CONTROL;
+- p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
+- ast_setstate(ast, AST_STATE_UP);
++ p->dialing = 1;
+ }
+- } else if (ast->_state != AST_STATE_RING)
+- ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
++ p->dop.dialstr[0] = '\0';
++ ast_setstate(ast, AST_STATE_DIALING);
++ } else
++ ast_setstate(ast, AST_STATE_UP);
++ return &p->subs[idx].f;
++ case AST_STATE_DOWN:
++ ast_setstate(ast, AST_STATE_RING);
++ ast->rings = 1;
++ p->subs[idx].f.frametype = AST_FRAME_CONTROL;
++ p->subs[idx].f.subclass = AST_CONTROL_OFFHOOK;
++ ast_debug(1, "channel %d picked up\n", p->channel);
++ return &p->subs[idx].f;
++ case AST_STATE_UP:
++ /* Make sure it stops ringing */
++ dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
++ /* Okay -- probably call waiting*/
++ if (ast_bridged_channel(p->owner))
++ ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
++ p->subs[idx].needunhold = 1;
+ break;
++ case AST_STATE_RESERVED:
++ /* Start up dialtone */
++ if (has_voicemail(p))
++ res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
++ else
++ res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
++ break;
+ default:
+- ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
++ ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
+ }
+ break;
+- case DAHDI_EVENT_RINGBEGIN:
+- switch (p->sig) {
+- case SIG_FXSLS:
+- case SIG_FXSGS:
+- case SIG_FXSKS:
+- if (ast->_state == AST_STATE_RING) {
+- p->ringt = p->ringt_base;
++ case SIG_FXSLS:
++ case SIG_FXSGS:
++ case SIG_FXSKS:
++ if (ast->_state == AST_STATE_RING) {
++ p->ringt = p->ringt_base;
++ }
++
++ /* If we get a ring then we cannot be in
++ * reversed polarity. So we reset to idle */
++ ast_debug(1, "Setting IDLE polarity due "
++ "to ring. Old polarity was %d\n",
++ p->polarity);
++ p->polarity = POLARITY_IDLE;
++
++ /* Fall through */
++ case SIG_EM:
++ case SIG_EM_E1:
++ case SIG_EMWINK:
++ case SIG_FEATD:
++ case SIG_FEATDMF:
++ case SIG_FEATDMF_TA:
++ case SIG_E911:
++ case SIG_FGC_CAMA:
++ case SIG_FGC_CAMAMF:
++ case SIG_FEATB:
++ case SIG_SF:
++ case SIG_SFWINK:
++ case SIG_SF_FEATD:
++ case SIG_SF_FEATDMF:
++ case SIG_SF_FEATB:
++ if (ast->_state == AST_STATE_PRERING)
++ ast_setstate(ast, AST_STATE_RING);
++ if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
++ ast_debug(1, "Ring detected\n");
++ p->subs[idx].f.frametype = AST_FRAME_CONTROL;
++ p->subs[idx].f.subclass = AST_CONTROL_RING;
++ } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
++ ast_debug(1, "Line answered\n");
++ if (p->confirmanswer) {
++ p->subs[idx].f.frametype = AST_FRAME_NULL;
++ p->subs[idx].f.subclass = 0;
++ } else {
++ p->subs[idx].f.frametype = AST_FRAME_CONTROL;
++ p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
++ ast_setstate(ast, AST_STATE_UP);
+ }
+- break;
+- }
++ } else if (ast->_state != AST_STATE_RING)
++ ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
+ break;
+- case DAHDI_EVENT_RINGEROFF:
+- if (p->inalarm) break;
+- if ((p->radio || (p->oprmode < 0))) break;
+- ast->rings++;
+- if ((ast->rings > p->cidrings) && (p->cidspill)) {
+- ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
+- ast_free(p->cidspill);
+- p->cidspill = NULL;
+- p->callwaitcas = 0;
++ default:
++ ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
++ }
++ break;
++ case DAHDI_EVENT_RINGBEGIN:
++ switch (p->sig) {
++ case SIG_FXSLS:
++ case SIG_FXSGS:
++ case SIG_FXSKS:
++ if (ast->_state == AST_STATE_RING) {
++ p->ringt = p->ringt_base;
+ }
+- p->subs[idx].f.frametype = AST_FRAME_CONTROL;
+- p->subs[idx].f.subclass = AST_CONTROL_RINGING;
+ break;
+- case DAHDI_EVENT_RINGERON:
+- break;
+- case DAHDI_EVENT_NOALARM:
+- p->inalarm = 0;
++ }
++ break;
++ case DAHDI_EVENT_RINGEROFF:
++ if (p->inalarm) break;
++ if ((p->radio || (p->oprmode < 0))) break;
++ ast->rings++;
++ if ((ast->rings > p->cidrings) && (p->cidspill)) {
++ ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
++ ast_free(p->cidspill);
++ p->cidspill = NULL;
++ p->callwaitcas = 0;
++ }
++ p->subs[idx].f.frametype = AST_FRAME_CONTROL;
++ p->subs[idx].f.subclass = AST_CONTROL_RINGING;
++ break;
++ case DAHDI_EVENT_RINGERON:
++ break;
++ case DAHDI_EVENT_NOALARM:
++ p->inalarm = 0;
+ #ifdef HAVE_PRI
+- /* Extremely unlikely but just in case */
+- if (p->bearer)
+- p->bearer->inalarm = 0;
++ /* Extremely unlikely but just in case */
++ if (p->bearer)
++ p->bearer->inalarm = 0;
+ #endif
+- ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
+- manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
+- "Channel: %d\r\n", p->channel);
+- break;
+- case DAHDI_EVENT_WINKFLASH:
+- if (p->inalarm) break;
+- if (p->radio) break;
+- if (p->oprmode < 0) break;
+- if (p->oprmode > 1)
++ ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
++ manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
++ "Channel: %d\r\n", p->channel);
++ break;
++ case DAHDI_EVENT_WINKFLASH:
++ if (p->inalarm) break;
++ if (p->radio) break;
++ if (p->oprmode < 0) break;
++ if (p->oprmode > 1)
++ {
++ struct dahdi_params par;
++
++ memset(&par, 0, sizeof(par));
++ if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
+ {
+- struct dahdi_params par;
+-
+- memset(&par, 0, sizeof(par));
+- if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
++ if (!par.rxisoffhook)
+ {
+- if (!par.rxisoffhook)
+- {
+- /* Make sure it stops ringing */
+- dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
+- dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
+- save_conference(p);
+- tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
+- }
++ /* Make sure it stops ringing */
++ dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
++ dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
++ save_conference(p);
++ tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
+ }
+- break;
+ }
+- /* Remember last time we got a flash-hook */
+- p->flashtime = ast_tvnow();
+- switch (mysig) {
+- case SIG_FXOLS:
+- case SIG_FXOGS:
+- case SIG_FXOKS:
+- ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
+- idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
+- p->callwaitcas = 0;
++ break;
++ }
++ /* Remember last time we got a flash-hook */
++ p->flashtime = ast_tvnow();
++ switch (mysig) {
++ case SIG_FXOLS:
++ case SIG_FXOGS:
++ case SIG_FXOKS:
++ ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
++ idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
++ p->callwaitcas = 0;
+
+- if (idx != SUB_REAL) {
+- ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
++ if (idx != SUB_REAL) {
++ ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
++ goto winkflashdone;
++ }
++
++ if (p->subs[SUB_CALLWAIT].owner) {
++ /* Swap to call-wait */
++ swap_subs(p, SUB_REAL, SUB_CALLWAIT);
++ tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
++ p->owner = p->subs[SUB_REAL].owner;
++ ast_debug(1, "Making %s the new owner\n", p->owner->name);
++ if (p->owner->_state == AST_STATE_RINGING) {
++ ast_setstate(p->owner, AST_STATE_UP);
++ p->subs[SUB_REAL].needanswer = 1;
++ }
++ p->callwaitingrepeat = 0;
++ p->cidcwexpire = 0;
++ /* Start music on hold if appropriate */
++ if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
++ ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
++ S_OR(p->mohsuggest, NULL),
++ !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
++ }
++ p->subs[SUB_CALLWAIT].needhold = 1;
++ if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
++ ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
++ S_OR(p->mohsuggest, NULL),
++ !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
++ }
++ p->subs[SUB_REAL].needunhold = 1;
++ } else if (!p->subs[SUB_THREEWAY].owner) {
++ if (!p->threewaycalling) {
++ /* Just send a flash if no 3-way calling */
++ p->subs[SUB_REAL].needflash = 1;
+ goto winkflashdone;
+- }
++ } else if (!check_for_conference(p)) {
++ char cid_num[256];
++ char cid_name[256];
+
+- if (p->subs[SUB_CALLWAIT].owner) {
+- /* Swap to call-wait */
+- swap_subs(p, SUB_REAL, SUB_CALLWAIT);
+- tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
+- p->owner = p->subs[SUB_REAL].owner;
+- ast_debug(1, "Making %s the new owner\n", p->owner->name);
+- if (p->owner->_state == AST_STATE_RINGING) {
+- ast_setstate(p->owner, AST_STATE_UP);
+- p->subs[SUB_REAL].needanswer = 1;
++ cid_num[0] = 0;
++ cid_name[0] = 0;
++ if (p->dahditrcallerid && p->owner) {
++ if (p->owner->cid.cid_num)
++ ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
++ if (p->owner->cid.cid_name)
++ ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
+ }
+- p->callwaitingrepeat = 0;
+- p->cidcwexpire = 0;
+- /* Start music on hold if appropriate */
+- if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
+- ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
+- S_OR(p->mohsuggest, NULL),
+- !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
++ /* XXX This section needs much more error checking!!! XXX */
++ /* Start a 3-way call if feasible */
++ if (!((ast->pbx) ||
++ (ast->_state == AST_STATE_UP) ||
++ (ast->_state == AST_STATE_RING))) {
++ ast_debug(1, "Flash when call not up or ringing\n");
++ goto winkflashdone;
+ }
+- p->subs[SUB_CALLWAIT].needhold = 1;
+- if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
+- ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
+- S_OR(p->mohsuggest, NULL),
+- !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
++ if (alloc_sub(p, SUB_THREEWAY)) {
++ ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
++ goto winkflashdone;
+ }
+- p->subs[SUB_REAL].needunhold = 1;
+- } else if (!p->subs[SUB_THREEWAY].owner) {
+- if (!p->threewaycalling) {
+- /* Just send a flash if no 3-way calling */
+- p->subs[SUB_REAL].needflash = 1;
+- goto winkflashdone;
+- } else if (!check_for_conference(p)) {
+- char cid_num[256];
+- char cid_name[256];
++ /* Make new channel */
++ chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
++ if (p->dahditrcallerid) {
++ if (!p->origcid_num)
++ p->origcid_num = ast_strdup(p->cid_num);
++ if (!p->origcid_name)
++ p->origcid_name = ast_strdup(p->cid_name);
++ ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
++ ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
++ }
++ /* Swap things around between the three-way and real call */
++ swap_subs(p, SUB_THREEWAY, SUB_REAL);
++ /* Disable echo canceller for better dialing */
++ dahdi_disable_ec(p);
++ res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
++ if (res)
++ ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
++ p->owner = chan;
++ if (!chan) {
++ ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
++ } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
++ ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
++ res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
++ dahdi_enable_ec(p);
++ ast_hangup(chan);
++ } else {
++ struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
++ int way3bridge = 0, cdr3way = 0;
+
+- cid_num[0] = 0;
+- cid_name[0] = 0;
+- if (p->dahditrcallerid && p->owner) {
+- if (p->owner->cid.cid_num)
+- ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
+- if (p->owner->cid.cid_name)
+- ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
+- }
+- /* XXX This section needs much more error checking!!! XXX */
+- /* Start a 3-way call if feasible */
+- if (!((ast->pbx) ||
+- (ast->_state == AST_STATE_UP) ||
+- (ast->_state == AST_STATE_RING))) {
+- ast_debug(1, "Flash when call not up or ringing\n");
+- goto winkflashdone;
+- }
+- if (alloc_sub(p, SUB_THREEWAY)) {
+- ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
+- goto winkflashdone;
+- }
+- /* Make new channel */
+- chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
+- if (p->dahditrcallerid) {
+- if (!p->origcid_num)
+- p->origcid_num = ast_strdup(p->cid_num);
+- if (!p->origcid_name)
+- p->origcid_name = ast_strdup(p->cid_name);
+- ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
+- ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
+- }
+- /* Swap things around between the three-way and real call */
+- swap_subs(p, SUB_THREEWAY, SUB_REAL);
+- /* Disable echo canceller for better dialing */
+- dahdi_disable_ec(p);
+- res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
+- if (res)
+- ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
+- p->owner = chan;
+- if (!chan) {
+- ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
+- } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
+- ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
+- res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
+- dahdi_enable_ec(p);
+- ast_hangup(chan);
+- } else {
+- struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
+- int way3bridge = 0, cdr3way = 0;
++ if (!other) {
++ other = ast_bridged_channel(p->subs[SUB_REAL].owner);
++ } else
++ way3bridge = 1;
+
+- if (!other) {
+- other = ast_bridged_channel(p->subs[SUB_REAL].owner);
+- } else
+- way3bridge = 1;
++ if (p->subs[SUB_THREEWAY].owner->cdr)
++ cdr3way = 1;
+
+- if (p->subs[SUB_THREEWAY].owner->cdr)
+- cdr3way = 1;
++ ast_verb(3, "Started three way call on channel %d\n", p->channel);
+
+- ast_verb(3, "Started three way call on channel %d\n", p->channel);
+-
+- /* Start music on hold if appropriate */
+- if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
+- ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
+- S_OR(p->mohsuggest, NULL),
+- !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
+- }
+- p->subs[SUB_THREEWAY].needhold = 1;
++ /* Start music on hold if appropriate */
++ if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
++ ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
++ S_OR(p->mohsuggest, NULL),
++ !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
+ }
++ p->subs[SUB_THREEWAY].needhold = 1;
+ }
++ }
++ } else {
++ /* Already have a 3 way call */
++ if (p->subs[SUB_THREEWAY].inthreeway) {
++ /* Call is already up, drop the last person */
++ ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
++ /* If the primary call isn't answered yet, use it */
++ if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
++ /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
++ swap_subs(p, SUB_THREEWAY, SUB_REAL);
++ p->owner = p->subs[SUB_REAL].owner;
++ }
++ /* Drop the last call and stop the conference */
++ ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
++ p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
++ p->subs[SUB_REAL].inthreeway = 0;
++ p->subs[SUB_THREEWAY].inthreeway = 0;
+ } else {
+- /* Already have a 3 way call */
+- if (p->subs[SUB_THREEWAY].inthreeway) {
+- /* Call is already up, drop the last person */
+- ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
+- /* If the primary call isn't answered yet, use it */
+- if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
+- /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
+- swap_subs(p, SUB_THREEWAY, SUB_REAL);
+- p->owner = p->subs[SUB_REAL].owner;
+- }
+- /* Drop the last call and stop the conference */
+- ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
+- p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
+- p->subs[SUB_REAL].inthreeway = 0;
+- p->subs[SUB_THREEWAY].inthreeway = 0;
+- } else {
+- /* Lets see what we're up to */
+- if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
+- (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
+- int otherindex = SUB_THREEWAY;
+- struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
+- int way3bridge = 0, cdr3way = 0;
++ /* Lets see what we're up to */
++ if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
++ (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
++ int otherindex = SUB_THREEWAY;
++ struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
++ int way3bridge = 0, cdr3way = 0;
+
+- if (!other) {
+- other = ast_bridged_channel(p->subs[SUB_REAL].owner);
+- } else
+- way3bridge = 1;
++ if (!other) {
++ other = ast_bridged_channel(p->subs[SUB_REAL].owner);
++ } else
++ way3bridge = 1;
+
+- if (p->subs[SUB_THREEWAY].owner->cdr)
+- cdr3way = 1;
++ if (p->subs[SUB_THREEWAY].owner->cdr)
++ cdr3way = 1;
+
+- ast_verb(3, "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
+- /* Put them in the threeway, and flip */
+- p->subs[SUB_THREEWAY].inthreeway = 1;
+- p->subs[SUB_REAL].inthreeway = 1;
+- if (ast->_state == AST_STATE_UP) {
+- swap_subs(p, SUB_THREEWAY, SUB_REAL);
+- otherindex = SUB_REAL;
+- }
+- if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
+- ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
+- p->subs[otherindex].needunhold = 1;
+- p->owner = p->subs[SUB_REAL].owner;
+- if (ast->_state == AST_STATE_RINGING) {
+- ast_debug(1, "Enabling ringtone on real and threeway\n");
+- res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
+- res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
+- }
+- } else {
+- ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
++ ast_verb(3, "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
++ /* Put them in the threeway, and flip */
++ p->subs[SUB_THREEWAY].inthreeway = 1;
++ p->subs[SUB_REAL].inthreeway = 1;
++ if (ast->_state == AST_STATE_UP) {
+ swap_subs(p, SUB_THREEWAY, SUB_REAL);
+- p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
+- p->owner = p->subs[SUB_REAL].owner;
+- if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
+- ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
+- p->subs[SUB_REAL].needunhold = 1;
+- dahdi_enable_ec(p);
++ otherindex = SUB_REAL;
+ }
++ if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
++ ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
++ p->subs[otherindex].needunhold = 1;
++ p->owner = p->subs[SUB_REAL].owner;
++ if (ast->_state == AST_STATE_RINGING) {
++ ast_debug(1, "Enabling ringtone on real and threeway\n");
++ res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
++ res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
++ }
++ } else {
++ ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
++ swap_subs(p, SUB_THREEWAY, SUB_REAL);
++ p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
++ p->owner = p->subs[SUB_REAL].owner;
++ if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
++ ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
++ p->subs[SUB_REAL].needunhold = 1;
++ dahdi_enable_ec(p);
+ }
+ }
++ }
+ winkflashdone:
+- update_conf(p);
+- break;
+- case SIG_EM:
+- case SIG_EM_E1:
+- case SIG_EMWINK:
+- case SIG_FEATD:
+- case SIG_SF:
+- case SIG_SFWINK:
+- case SIG_SF_FEATD:
+- case SIG_FXSLS:
+- case SIG_FXSGS:
+- if (option_debug) {
+- if (p->dialing)
+- ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
+- else
+- ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
+- }
+- break;
+- case SIG_FEATDMF_TA:
+- switch (p->whichwink) {
+- case 0:
+- ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
+- snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
+- break;
+- case 1:
+- ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
+- break;
+- case 2:
+- ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
+- return NULL;
+- }
+- p->whichwink++;
+- /* Fall through */
+- case SIG_FEATDMF:
+- case SIG_E911:
+- case SIG_FGC_CAMAMF:
+- case SIG_FGC_CAMA:
+- case SIG_FEATB:
+- case SIG_SF_FEATDMF:
+- case SIG_SF_FEATB:
+- /* FGD MF *Must* wait for wink */
+- if (!ast_strlen_zero(p->dop.dialstr)) {
+- res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
+- if (res < 0) {
+- ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
+- p->dop.dialstr[0] = '\0';
+- return NULL;
+- } else
+- ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
+- }
+- p->dop.dialstr[0] = '\0';
+- break;
+- default:
+- ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
+- }
++ update_conf(p);
+ break;
+- case DAHDI_EVENT_HOOKCOMPLETE:
+- if (p->inalarm) break;
+- if ((p->radio || (p->oprmode < 0))) break;
+- if (p->waitingfordt.tv_sec) break;
+- switch (mysig) {
+- case SIG_FXSLS: /* only interesting for FXS */
+- case SIG_FXSGS:
+- case SIG_FXSKS:
+- case SIG_EM:
+- case SIG_EM_E1:
+- case SIG_EMWINK:
+- case SIG_FEATD:
+- case SIG_SF:
+- case SIG_SFWINK:
+- case SIG_SF_FEATD:
+- if (!ast_strlen_zero(p->dop.dialstr)) {
+- res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
+- if (res < 0) {
+- ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
+- p->dop.dialstr[0] = '\0';
+- return NULL;
+- } else
+- ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
+- }
+- p->dop.dialstr[0] = '\0';
+- p->dop.op = DAHDI_DIAL_OP_REPLACE;
++ case SIG_EM:
++ case SIG_EM_E1:
++ case SIG_EMWINK:
++ case SIG_FEATD:
++ case SIG_SF:
++ case SIG_SFWINK:
++ case SIG_SF_FEATD:
++ case SIG_FXSLS:
++ case SIG_FXSGS:
++ if (p->dialing)
++ ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
++ else
++ ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
++ break;
++ case SIG_FEATDMF_TA:
++ switch (p->whichwink) {
++ case 0:
++ ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
++ snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
+ break;
+- case SIG_FEATDMF:
+- case SIG_FEATDMF_TA:
+- case SIG_E911:
+- case SIG_FGC_CAMA:
+- case SIG_FGC_CAMAMF:
+- case SIG_FEATB:
+- case SIG_SF_FEATDMF:
+- case SIG_SF_FEATB:
+- ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
++ case 1:
++ ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
+ break;
+- default:
+- break;
++ case 2:
++ ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
++ return NULL;
+ }
+- break;
+- case DAHDI_EVENT_POLARITY:
+- /*
+- * If we get a Polarity Switch event, check to see
+- * if we should change the polarity state and
+- * mark the channel as UP or if this is an indication
+- * of remote end disconnect.
+- */
+- if (p->polarity == POLARITY_IDLE) {
+- p->polarity = POLARITY_REV;
+- if (p->answeronpolarityswitch &&
+- ((ast->_state == AST_STATE_DIALING) ||
+- (ast->_state == AST_STATE_RINGING))) {
+- ast_debug(1, "Answering on polarity switch!\n");
+- ast_setstate(p->owner, AST_STATE_UP);
+- if (p->hanguponpolarityswitch) {
+- p->polaritydelaytv = ast_tvnow();
+- }
++ p->whichwink++;
++ /* Fall through */
++ case SIG_FEATDMF:
++ case SIG_E911:
++ case SIG_FGC_CAMAMF:
++ case SIG_FGC_CAMA:
++ case SIG_FEATB:
++ case SIG_SF_FEATDMF:
++ case SIG_SF_FEATB:
++ /* FGD MF *Must* wait for wink */
++ if (!ast_strlen_zero(p->dop.dialstr)) {
++ res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
++ if (res < 0) {
++ ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
++ p->dop.dialstr[0] = '\0';
++ return NULL;
+ } else
+- ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
++ ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
+ }
+- /* Removed else statement from here as it was preventing hangups from ever happening*/
+- /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
+- if (p->hanguponpolarityswitch &&
+- (p->polarityonanswerdelay > 0) &&
+- (p->polarity == POLARITY_REV) &&
+- ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
+- /* Added log_debug information below to provide a better indication of what is going on */
+- ast_debug(1, "Polarity Reversal event occured - DEBUG 1: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
+-
+- if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
+- ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
+- ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
+- p->polarity = POLARITY_IDLE;
++ p->dop.dialstr[0] = '\0';
++ break;
++ default:
++ ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
++ }
++ break;
++ case DAHDI_EVENT_HOOKCOMPLETE:
++ if (p->inalarm) break;
++ if ((p->radio || (p->oprmode < 0))) break;
++ if (p->waitingfordt.tv_sec) break;
++ switch (mysig) {
++ case SIG_FXSLS: /* only interesting for FXS */
++ case SIG_FXSGS:
++ case SIG_FXSKS:
++ case SIG_EM:
++ case SIG_EM_E1:
++ case SIG_EMWINK:
++ case SIG_FEATD:
++ case SIG_SF:
++ case SIG_SFWINK:
++ case SIG_SF_FEATD:
++ if (!ast_strlen_zero(p->dop.dialstr)) {
++ res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
++ if (res < 0) {
++ ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
++ p->dop.dialstr[0] = '\0';
++ return NULL;
+ } else
+- ast_debug(1, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast->_state);
+-
+- } else {
+- p->polarity = POLARITY_IDLE;
+- ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
++ ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
+ }
+- /* Added more log_debug information below to provide a better indication of what is going on */
+- ast_debug(1, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
++ p->dop.dialstr[0] = '\0';
++ p->dop.op = DAHDI_DIAL_OP_REPLACE;
+ break;
++ case SIG_FEATDMF:
++ case SIG_FEATDMF_TA:
++ case SIG_E911:
++ case SIG_FGC_CAMA:
++ case SIG_FGC_CAMAMF:
++ case SIG_FEATB:
++ case SIG_SF_FEATDMF:
++ case SIG_SF_FEATB:
++ ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
++ break;
+ default:
+- ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
++ break;
++ }
++ break;
++ case DAHDI_EVENT_POLARITY:
++ /*
++ * If we get a Polarity Switch event, check to see
++ * if we should change the polarity state and
++ * mark the channel as UP or if this is an indication
++ * of remote end disconnect.
++ */
++ if (p->polarity == POLARITY_IDLE) {
++ p->polarity = POLARITY_REV;
++ if (p->answeronpolarityswitch &&
++ ((ast->_state == AST_STATE_DIALING) ||
++ (ast->_state == AST_STATE_RINGING))) {
++ ast_debug(1, "Answering on polarity switch!\n");
++ ast_setstate(p->owner, AST_STATE_UP);
++ if (p->hanguponpolarityswitch) {
++ p->polaritydelaytv = ast_tvnow();
++ }
++ } else
++ ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
++ }
++ /* Removed else statement from here as it was preventing hangups from ever happening*/
++ /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
++ if (p->hanguponpolarityswitch &&
++ (p->polarityonanswerdelay > 0) &&
++ (p->polarity == POLARITY_REV) &&
++ ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
++ /* Added log_debug information below to provide a better indication of what is going on */
++ ast_debug(1, "Polarity Reversal event occured - DEBUG 1: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
++
++ if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
++ ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
++ ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
++ p->polarity = POLARITY_IDLE;
++ } else
++ ast_debug(1, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast->_state);
++
++ } else {
++ p->polarity = POLARITY_IDLE;
++ ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
++ }
++ /* Added more log_debug information below to provide a better indication of what is going on */
++ ast_debug(1, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
++ break;
++ default:
++ ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
+ }
+ return &p->subs[idx].f;
+ }
+@@ -6651,7 +7904,12 @@
+ struct dahdi_pvt *p = ast->tech_pvt;
+ struct ast_frame *f;
+ ast_mutex_lock(&p->lock);
+- f = __dahdi_exception(ast);
++ if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
++ struct analog_pvt *analog_p = p->sig_pvt;
++ f = analog_exception(analog_p, ast);
++ } else {
++ f = __dahdi_exception(ast);
++ }
+ ast_mutex_unlock(&p->lock);
+ return f;
+ }
+@@ -6899,7 +8157,7 @@
+ p->subs[idx].f.datalen = READ_SIZE;
+
+ /* Handle CallerID Transmission */
+- if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
++ if ((p->owner == ast) && p->cidspill) {
+ send_callerid(p);
+ }
+
+@@ -6912,7 +8170,9 @@
+ #if 0
+ ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
+ #endif
+- if (p->dialing || /* Transmitting something */
++ {
++ struct analog_pvt *ap = p->sig_pvt;
++ if ((analog_lib_handles(p->sig ,p->radio, p->oprmode) && ap->dialing) || p->dialing || p->radio || /* Transmitting something */
+ (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
+ ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
+ ) {
+@@ -6926,6 +8186,7 @@
+ p->subs[idx].f.data.ptr = NULL;
+ p->subs[idx].f.datalen= 0;
+ }
++ }
+ if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
+ /* Perform busy detection etc on the dahdi line */
+ int mute;
+@@ -6992,8 +8253,12 @@
+ } else
+ f = &p->subs[idx].f;
+
+- if (f && (f->frametype == AST_FRAME_DTMF))
+- dahdi_handle_dtmfup(ast, idx, &f);
++ if (f && (f->frametype == AST_FRAME_DTMF)) {
++ if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
++ analog_handle_dtmfup(p->sig_pvt, ast, idx, &f);
++ } else
++ dahdi_handle_dtmfup(ast, idx, &f);
++ }
+
+ /* If we have a fake_event, trigger exception to handle it */
+ if (p->fake_event)
+@@ -7064,6 +8329,12 @@
+ ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
+ return -1;
+ }
++ if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
++ struct analog_pvt *ap = p->sig_pvt;
++
++ if (ap->dialing)
++ return 0;
++ }
+ if (p->dialing) {
+ ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
+ return 0;
+@@ -7610,7 +8881,7 @@
+ on? "enabled" : "disabled");
+ }
+
+-static void *ss_thread(void *data)
++static void *analog_ss_thread(void *data)
+ {
+ struct ast_channel *chan = data;
+ struct dahdi_pvt *p = chan->tech_pvt;
+@@ -8769,25 +10040,9 @@
+
+ if (cs)
+ callerid_free(cs);
+- /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
+- if (flags & CID_MSGWAITING) {
+- ast_log(LOG_NOTICE, "MWI: Channel %d message waiting!\n", p->channel);
+- notify_message(p->mailbox, 1);
+- /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
+- if (p->mwimonitor_rpas) {
+- ast_hangup(chan);
+- return NULL;
+- }
+- } else if (flags & CID_NOMSGWAITING) {
+- ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting!\n", p->channel);
+- notify_message(p->mailbox, 0);
+- /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
+- if (p->mwimonitor_rpas) {
+- ast_hangup(chan);
+- return NULL;
+- }
+- }
+
++ my_handle_notify_message(chan, p, flags, -1);
++
+ ast_setstate(chan, AST_STATE_RING);
+ chan->rings = 1;
+ p->ringt = p->ringt_base;
+@@ -8890,14 +10145,20 @@
+ handle_alarms(mtd->pvt, res);
+ break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
+ default:
+- ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to ss_thread\n", res, event2str(res));
++ ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to analog_ss_thread\n", res, event2str(res));
+ callerid_free(cs);
+
+ restore_gains(mtd->pvt);
+ mtd->pvt->ringt = mtd->pvt->ringt_base;
+
+ if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, 0))) {
+- if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
++ int result;
++ if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
++ result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
++ } else {
++ result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
++ }
++ if (result) {
+ ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
+ res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
+ if (res < 0)
+@@ -9017,8 +10278,8 @@
+ #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
+ if (pvt->mwisend_fsk) {
+ #endif
+- pvt->cidlen = vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
+- AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
++ pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
++ AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
+ pvt->cidpos = 0;
+ #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
+ }
+@@ -9168,7 +10429,7 @@
+ while (tmp) {
+ if (tmp->channel == channel) {
+ int x = DAHDI_FLASH;
+- ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); /* important to create an event for dahdi_wait_event to register so that all ss_threads terminate */
++ ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
+ destroy_channel(prev, tmp, 1);
+ ast_module_unref(ast_module_info->self);
+ return RESULT_SUCCESS;
+@@ -9232,7 +10493,7 @@
+ res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
+ if (res < 0)
+ ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
+- if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
++ if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
+ ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
+ res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
+ if (res < 0)
+@@ -9274,7 +10535,7 @@
+
+ if (!chan) {
+ ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
+- } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
++ } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
+ ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
+ res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
+ if (res < 0) {
+@@ -9380,7 +10641,7 @@
+ chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
+ if (!chan) {
+ ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
+- } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
++ } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
+ ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
+ } else {
+ thread_spawned = 1;
+@@ -9458,19 +10719,39 @@
+ count = 0;
+ i = iflist;
+ while (i) {
++ ast_mutex_lock(&i->lock);
+ if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
+- if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
+- /* This needs to be watched, as it lacks an owner */
+- pfds[count].fd = i->subs[SUB_REAL].dfd;
+- pfds[count].events = POLLPRI;
+- pfds[count].revents = 0;
+- /* If we are monitoring for VMWI or sending CID, we need to
+- read from the channel as well */
+- if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk)
+- pfds[count].events |= POLLIN;
+- count++;
++ if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
++ struct analog_pvt *p = i->sig_pvt;
++
++ if (!p)
++ ast_log(LOG_ERROR, "No sig_pvt?\n");
++
++ if (!p->owner && !p->subs[SUB_REAL].owner) {
++ /* This needs to be watched, as it lacks an owner */
++ pfds[count].fd = i->subs[SUB_REAL].dfd;
++ pfds[count].events = POLLPRI;
++ pfds[count].revents = 0;
++ /* Message waiting or r2 channels also get watched for reading */
++ if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk)
++ pfds[count].events |= POLLIN;
++ count++;
++ }
++ } else {
++ if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
++ /* This needs to be watched, as it lacks an owner */
++ pfds[count].fd = i->subs[SUB_REAL].dfd;
++ pfds[count].events = POLLPRI;
++ pfds[count].revents = 0;
++ /* If we are monitoring for VMWI or sending CID, we need to
++ read from the channel as well */
++ if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk)
++ pfds[count].events |= POLLIN;
++ count++;
++ }
+ }
+ }
++ ast_mutex_unlock(&i->lock);
+ i = i->next;
+ }
+ /* Okay, now that we know what to do, release the interface lock */
+@@ -9535,7 +10816,10 @@
+ ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
+ /* Don't hold iflock while handling init events */
+ ast_mutex_unlock(&iflock);
+- handle_init_event(i, res);
++ if (analog_lib_handles(i->sig, i->radio, i->oprmode))
++ analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
++ else
++ handle_init_event(i, res);
+ ast_mutex_lock(&iflock);
+ }
+ i = i->next;
+@@ -9601,7 +10885,10 @@
+ /* Don't hold iflock while handling init events */
+ ast_mutex_unlock(&iflock);
+ if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
+- handle_init_event(i, res);
++ if (analog_lib_handles(i->sig, i->radio, i->oprmode))
++ analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
++ else
++ handle_init_event(i, res);
+ }
+ ast_mutex_lock(&iflock);
+ }
+@@ -9855,6 +11142,9 @@
+ }
+ openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
+ openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
++#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
++ openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
++#endif
+ openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
+ openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
+ openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
+@@ -9912,6 +11202,7 @@
+ int x;
+ struct dahdi_pvt **wlist;
+ struct dahdi_pvt **wend;
++ struct analog_pvt *analog_p = NULL;
+ struct dahdi_params p;
+
+ wlist = &iflist;
+@@ -9944,8 +11235,6 @@
+
+ if (!here && reloading != 1) {
+ if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
+- if (tmp)
+- free(tmp);
+ return NULL;
+ }
+ ast_mutex_init(&tmp->lock);
+@@ -9999,6 +11288,20 @@
+ return NULL;
+ }
+ }
++
++ if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
++ if (tmp->sig_pvt) {
++ ast_log(LOG_WARNING, "Private already exists!\n");
++ analog_p = tmp->sig_pvt;
++ } else
++ analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp);
++ if (!analog_p) {
++ destroy_dahdi_pvt(&tmp);
++ return NULL;
++ }
++ tmp->sig_pvt = analog_p;
++
++ }
+ #ifdef HAVE_SS7
+ if (chan_sig == SIG_SS7) {
+ struct dahdi_ss7 *ss7;
+@@ -10063,7 +11366,8 @@
+ tmp->subs[SUB_REAL].dfd,
+ NULL, NULL);
+ if (!tmp->r2chan) {
+- ast_log(LOG_ERROR, "Cannot create OpenR2 channel.\n");
++ openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
++ ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
+ destroy_dahdi_pvt(&tmp);
+ return NULL;
+ }
+@@ -10135,7 +11439,6 @@
+ }
+ }
+ }
+- offset = p.chanpos;
+ if (!matchesdchan) {
+ if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
+ ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
+@@ -10191,6 +11494,9 @@
+ pris[span].overlapdial = conf->pri.overlapdial;
+ pris[span].qsigchannelmapping = conf->pri.qsigchannelmapping;
+ pris[span].discardremoteholdretrieval = conf->pri.discardremoteholdretrieval;
++#ifdef HAVE_PRI_SERVICE_MESSAGES
++ pris[span].enable_service_message_support = conf->pri.enable_service_message_support;
++#endif
+ #ifdef HAVE_PRI_INBANDDISCONNECT
+ pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
+ #endif
+@@ -10205,7 +11511,11 @@
+ pris[span].resetinterval = conf->pri.resetinterval;
+
+ tmp->pri = &pris[span];
+- tmp->prioffset = offset;
++ if (si.spanno != span + 1) { /* in another trunkgroup */
++ tmp->prioffset = pris[span].numchans;
++ } else {
++ tmp->prioffset = p.chanpos;
++ }
+ tmp->call = NULL;
+ } else {
+ ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
+@@ -10484,11 +11794,57 @@
+ tmp->sendcalleridafter = conf->chan.sendcalleridafter;
+ if (!here) {
+ tmp->locallyblocked = tmp->remotelyblocked = 0;
+- if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7))
++ if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7)) {
+ tmp->inservice = 0;
+- else /* We default to in service on protocols that don't have a reset */
++#ifdef HAVE_PRI_SERVICE_MESSAGES
++ if (chan_sig == SIG_PRI) {
++ char db_chan_name[20], db_answer[5];
++
++ snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
++ if (ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
++ snprintf(db_answer, sizeof(db_answer), "%s:%d", SRVST_TYPE_OOS, SRVST_INITIALIZED);
++ ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
++ }
++ }
++#endif
++ } else {
++ /* We default to in service on protocols that don't have a reset */
+ tmp->inservice = 1;
++ }
+ }
++
++ analog_p = tmp->sig_pvt;
++ if (analog_p) {
++ analog_p->channel = tmp->channel;
++ analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
++ analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
++ analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
++ analog_p->sendcalleridafter = conf->chan.sendcalleridafter;
++ analog_p->permcallwaiting = 1;
++ analog_p->callreturn = conf->chan.callreturn;
++ analog_p->cancallforward = conf->chan.cancallforward;
++ analog_p->canpark = conf->chan.canpark;
++ analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
++ analog_p->immediate = conf->chan.immediate;
++ analog_p->permhidecallerid = conf->chan.permhidecallerid;
++ analog_p->pulse = conf->chan.pulse;
++ analog_p->threewaycalling = conf->chan.threewaycalling;
++ analog_p->transfer = conf->chan.transfer;
++ analog_p->transfertobusy = conf->chan.transfertobusy;
++ analog_p->use_callerid = conf->chan.use_callerid;
++ analog_p->outsigmod = ANALOG_SIG_NONE;
++ analog_p->echotraining = conf->chan.echotraining;
++ analog_p->cid_signalling = conf->chan.cid_signalling;
++ analog_p->stripmsd = conf->chan.stripmsd;
++ analog_p->cid_start = ANALOG_CID_START_RING;
++ tmp->callwaitingcallerid = analog_p->callwaitingcallerid = 1;
++
++ ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
++ ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
++ ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
++
++ analog_config_complete(analog_p);
++ }
+ }
+ if (tmp && !here) {
+ /* nothing on the iflist */
+@@ -10537,7 +11893,7 @@
+ return tmp;
+ }
+
+-static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
++static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *reason, int *channelmatched, int *groupmatched)
+ {
+ int res;
+ struct dahdi_params par;
+@@ -10554,10 +11910,14 @@
+ return 0;
+ *channelmatched = 1;
+ }
++
++ if (analog_lib_handles(p->sig, p->radio, p->oprmode))
++ return analog_available(p->sig_pvt, channelmatch, groupmatch, reason, channelmatched, groupmatched);
++
+ /* We're at least busy at this point */
+- if (busy) {
++ if (reason) {
+ if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
+- *busy = 1;
++ *reason = AST_CAUSE_BUSY;
+ }
+ /* If do not disturb, definitely not */
+ if (p->dnd)
+@@ -10574,10 +11934,25 @@
+ #ifdef HAVE_PRI
+ /* Trust PRI */
+ if (p->pri) {
+- if (p->resetting || p->call)
++#ifdef HAVE_PRI_SERVICE_MESSAGES
++ char db_chan_name[20], db_answer[5], state;
++ int why = 0;
++
++ snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, p->channel);
++ if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
++ sscanf(db_answer, "%c:%d", &state, &why);
++ }
++ if ((p->resetting || p->call) || (why)) {
++ if (why) {
++ *reason = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
++ }
++#else
++ if (p->resetting || p->call) {
++#endif
+ return 0;
+- else
++ } else {
+ return 1;
++ }
+ }
+ #endif
+ #ifdef HAVE_SS7
+@@ -10737,7 +12112,7 @@
+ int channelmatch = -1;
+ int roundrobin = 0;
+ int callwait = 0;
+- int busy = 0;
++ int unavailreason = 0;
+ struct dahdi_pvt *p;
+ struct ast_channel *tmp = NULL;
+ char *dest=NULL;
+@@ -10866,7 +12241,7 @@
+ ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
+ #endif
+
+- if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
++ if (p && available(p, channelmatch, groupmatch, &unavailreason, &channelmatched, &groupmatched)) {
+ ast_debug(1, "Using channel %d\n", p->channel);
+ if (p->inalarm)
+ goto next;
+@@ -10922,7 +12297,10 @@
+ }
+ }
+ p->outgoing = 1;
+- tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
++ if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
++ tmp = analog_request(p->sig_pvt, &callwait);
++ } else
++ tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
+ #ifdef HAVE_PRI
+ if (p->bearer) {
+ /* Log owner to bearer channel, too */
+@@ -10974,10 +12352,10 @@
+ *cause = AST_CAUSE_BUSY;
+ else if (!tmp) {
+ if (channelmatched) {
+- if (busy)
++ if (unavailreason)
+ *cause = AST_CAUSE_BUSY;
+ } else if (groupmatched) {
+- *cause = AST_CAUSE_CONGESTION;
++ *cause = (unavailreason) ? unavailreason : AST_CAUSE_CONGESTION;
+ }
+ }
+
+@@ -10987,7 +12365,11 @@
+ #if defined(HAVE_PRI) || defined(HAVE_SS7)
+ static int dahdi_setlaw(int dfd, int law)
+ {
+- return ioctl(dfd, DAHDI_SETLAW, &law);
++ int res;
++ res = ioctl(dfd, DAHDI_SETLAW, &law);
++ if (res)
++ return res;
++ return 0;
+ }
+ #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
+
+@@ -12002,9 +13384,13 @@
+ new->owner = old->owner;
+ old->owner = NULL;
+ if (new->owner) {
+- ast_string_field_build(new->owner, name,
+- "DAHDI/%d:%d-%d", pri->trunkgroup,
+- new->channel, 1);
++ char newname[AST_CHANNEL_NAME];
++
++ snprintf(newname, sizeof(newname),
++ "DAHDI/%d:%d-%d", pri->trunkgroup, new->channel, 1);
++
++ ast_change_name(new->owner, newname);
++
+ new->owner->tech_pvt = new;
+ ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].dfd);
+ new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
+@@ -12190,6 +13576,9 @@
+ #if defined(HAVE_PRI)
+ static int pri_check_restart(struct dahdi_pri *pri)
+ {
++#ifdef HAVE_PRI_SERVICE_MESSAGES
++tryanotherpos:
++#endif
+ do {
+ pri->resetpos++;
+ } while ((pri->resetpos < pri->numchans) &&
+@@ -12197,6 +13586,26 @@
+ pri->pvts[pri->resetpos]->call ||
+ pri->pvts[pri->resetpos]->resetting));
+ if (pri->resetpos < pri->numchans) {
++#ifdef HAVE_PRI_SERVICE_MESSAGES
++ char db_chan_name[20], db_answer[5], state;
++ int why;
++
++ /* check if the channel is out of service */
++ ast_mutex_lock(&pri->pvts[pri->resetpos]->lock);
++ snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, pri->pvts[pri->resetpos]->span, pri->pvts[pri->resetpos]->channel);
++ ast_mutex_unlock(&pri->pvts[pri->resetpos]->lock);
++
++ /* if so, try next channel */
++ if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
++ sscanf(db_answer, "%c:%d", &state, &why);
++ if (why) {
++ ast_log(LOG_NOTICE, "span '%d' channel '%d' out-of-service (reason: %s), not sending RESTART\n", pri->span,
++ pri->pvts[pri->resetpos]->channel, (why & SRVST_FAREND) ? (why & SRVST_NEAREND) ? "both ends" : "far end" : "near end");
++ goto tryanotherpos;
++ }
++ }
++#endif
++
+ /* Mark the channel as resetting and restart it */
+ pri->pvts[pri->resetpos]->resetting = 1;
+ pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
+@@ -12581,13 +13990,36 @@
+ ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
+ PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
+ else {
+- ast_verb(3, "B-channel %d/%d restarted on span %d\n",
+- PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
++#ifdef HAVE_PRI_SERVICE_MESSAGES
++ char db_chan_name[20], db_answer[5], state;
++ int why, skipit = 0;
++
+ ast_mutex_lock(&pri->pvts[chanpos]->lock);
+- if (pri->pvts[chanpos]->call) {
+- pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
+- pri->pvts[chanpos]->call = NULL;
++ snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, pri->pvts[chanpos]->span, pri->pvts[chanpos]->channel);
++ ast_mutex_unlock(&pri->pvts[chanpos]->lock);
++
++ if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
++ sscanf(db_answer, "%c:%d", &state, &why);
++ if (why) {
++ ast_log(LOG_NOTICE, "span '%d' channel '%d' out-of-service (reason: %s), ignoring RESTART\n", pri->span,
++ e->restart.channel, (why & SRVST_FAREND) ? (why & SRVST_NEAREND) ? "both ends" : "far end" : "near end");
++ skipit = 1;
++ } else {
++ ast_db_del(db_chan_name, SRVST_DBKEY);
++ }
+ }
++ if (!skipit) {
++#endif
++ ast_verb(3, "B-channel %d/%d restarted on span %d\n",
++ PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
++ ast_mutex_lock(&pri->pvts[chanpos]->lock);
++ if (pri->pvts[chanpos]->call) {
++ pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
++ pri->pvts[chanpos]->call = NULL;
++ }
++#ifdef HAVE_PRI_SERVICE_MESSAGES
++ }
++#endif
+ /* Force soft hangup if appropriate */
+ if (pri->pvts[chanpos]->realcall)
+ pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
+@@ -12667,6 +14099,62 @@
+ }
+ }
+ break;
++#ifdef HAVE_PRI_SERVICE_MESSAGES
++ case PRI_EVENT_SERVICE:
++ chanpos = pri_find_principle(pri, e->service.channel);
++ if (chanpos < 0) {
++ ast_log(LOG_WARNING, "Received service change status %d on unconfigured channel %d/%d span %d\n",
++ e->service_ack.changestatus, PRI_SPAN(e->service_ack.channel), PRI_CHANNEL(e->service_ack.channel), pri->span);
++ } else {
++ char db_chan_name[20], db_answer[5], state;
++ int ch, why = -1;
++
++ ast_mutex_lock(&pri->pvts[chanpos]->lock);
++ ch = pri->pvts[chanpos]->channel;
++ ast_mutex_unlock(&pri->pvts[chanpos]->lock);
++
++ snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, pri->pvts[chanpos]->span, ch);
++ if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
++ sscanf(db_answer, "%c:%d", &state, &why);
++ ast_db_del(db_chan_name, SRVST_DBKEY);
++ }
++ switch (e->service.changestatus) {
++ case 0: /* in-service */
++ if (why > -1) {
++ if (why & SRVST_NEAREND) {
++ snprintf(db_answer, sizeof(db_answer), "%s:%d", SRVST_TYPE_OOS, SRVST_NEAREND);
++ ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
++ ast_debug(2, "channel '%d' service state { near: out-of-service, far: in-service }\n", ch);
++ }
++ }
++ break;
++ case 2: /* out-of-service */
++ if (why == -1) {
++ why = SRVST_FAREND;
++ } else {
++ why |= SRVST_FAREND;
++ }
++ snprintf(db_answer, sizeof(db_answer), "%s:%d", SRVST_TYPE_OOS, why);
++ ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
++ break;
++ default:
++ ast_log(LOG_ERROR, "Huh? changestatus is: %d\n", e->service.changestatus);
++ }
++ ast_log(LOG_NOTICE, "Channel %d/%d span %d (logical: %d) received a change of service message, status '%d'\n",
++ PRI_SPAN(e->service.channel), PRI_CHANNEL(e->service.channel), pri->span, ch, e->service.changestatus);
++ }
++ break;
++ case PRI_EVENT_SERVICE_ACK:
++ chanpos = pri_find_principle(pri, e->service_ack.channel);
++ if (chanpos < 0) {
++ ast_log(LOG_WARNING, "Received service acknowledge change status '%d' on unconfigured channel %d/%d span %d\n",
++ e->service_ack.changestatus, PRI_SPAN(e->service_ack.channel), PRI_CHANNEL(e->service_ack.channel), pri->span);
++ } else {
++ ast_debug(2, "Channel %d/%d span %d received a change os service acknowledgement message, status '%d'\n",
++ PRI_SPAN(e->service_ack.channel), PRI_CHANNEL(e->service_ack.channel), pri->span, e->service_ack.changestatus);
++ }
++ break;
++#endif
+ case PRI_EVENT_RING:
+ crv = NULL;
+ if (e->ring.channel == -1)
+@@ -12842,7 +14330,7 @@
+
+ ast_mutex_lock(&pri->pvts[chanpos]->lock);
+ ast_mutex_lock(&pri->lock);
+- if (c && !ast_pthread_create_detached(&threadid, NULL, ss_thread, c)) {
++ if (c && !ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, c)) {
+ ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
+ plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
+ pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
+@@ -13464,6 +14952,11 @@
+ break;
+ default:
+ pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
++#ifdef HAVE_PRI_SERVICE_MESSAGES
++ if (pri->enable_service_message_support) {
++ pri_set_service_message_support(pri->dchans[i], 1);
++ }
++#endif
+ break;
+ }
+ /* Force overlap dial if we're doing GR-303! */
+@@ -13638,6 +15131,149 @@
+ }
+ #endif /* defined(HAVE_PRI) */
+
++#ifdef HAVE_PRI_SERVICE_MESSAGES
++static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
++{
++ int why;
++ int channel;
++ int trunkgroup;
++ int x, y, fd = a->fd;
++ int interfaceid = 0;
++ char *c;
++ char state;
++ char db_chan_name[20], db_answer[5];
++ struct dahdi_pvt *start, *tmp = NULL;
++ struct dahdi_pri *pri = NULL;
++ ast_mutex_t *lock;
++
++ lock = &iflock;
++ start = iflist;
++
++ if (a->argc < 5 || a->argc > 6)
++ return CLI_SHOWUSAGE;
++ if ((c = strchr(a->argv[4], ':'))) {
++ if (sscanf(a->argv[4], "%d:%d", &trunkgroup, &channel) != 2)
++ return CLI_SHOWUSAGE;
++ if ((trunkgroup < 1) || (channel < 1))
++ return CLI_SHOWUSAGE;
++ for (x=0;x<NUM_SPANS;x++) {
++ if (pris[x].trunkgroup == trunkgroup) {
++ pri = pris + x;
++ break;
++ }
++ }
++ if (pri) {
++ start = pri->crvs;
++ lock = &pri->lock;
++ } else {
++ ast_cli(fd, "No such trunk group %d\n", trunkgroup);
++ return CLI_FAILURE;
++ }
++ } else
++ channel = atoi(a->argv[4]);
++
++ if (a->argc == 6)
++ interfaceid = atoi(a->argv[5]);
++
++ /* either servicing a D-Channel */
++ for (x = 0; x < NUM_SPANS; x++) {
++ for (y = 0; y < NUM_DCHANS; y++) {
++ if (pris[x].dchannels[y] == channel) {
++ pri = pris + x;
++ pri_maintenance_service(pri->pri, interfaceid, -1, changestatus);
++ return CLI_SUCCESS;
++ }
++ }
++ }
++
++ /* or servicing a B-Channel */
++ ast_mutex_lock(lock);
++ tmp = start;
++ while (tmp) {
++ if (tmp->pri && tmp->channel == channel) {
++ if (!tmp->pri->enable_service_message_support) {
++ ast_cli(fd, "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n\tNote only 4ESS and 5ESS switch types are supported.\n\n");
++ return CLI_SUCCESS;
++ }
++ why = -1;
++ snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
++ if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
++ sscanf(db_answer, "%c:%d", &state, &why);
++ ast_db_del(db_chan_name, SRVST_DBKEY);
++ }
++ switch(changestatus) {
++ case 0: /* enable */
++ if (why > -1) {
++ if (why & SRVST_FAREND) {
++ why = SRVST_FAREND;
++ snprintf(db_answer, sizeof(db_answer), "%s:%d", SRVST_TYPE_OOS, why);
++ ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
++ ast_debug(2, "channel '%d' service state { near: in-service, far: out-of-service }\n", channel);
++ }
++ }
++ break;
++ /* case 1: -- loop */
++ case 2: /* disable */
++ if (why == -1) {
++ why = SRVST_NEAREND;
++ } else {
++ why |= SRVST_NEAREND;
++ }
++ snprintf(db_answer, sizeof(db_answer), "%s:%d", SRVST_TYPE_OOS, why);
++ ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
++ break;
++ /* case 3: -- continuity */
++ /* case 4: -- shutdown */
++ default:
++ ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
++ }
++ pri_maintenance_service(tmp->pri->pri, PRI_SPAN(PVT_TO_CHANNEL(tmp)), PVT_TO_CHANNEL(tmp), changestatus);
++ ast_mutex_unlock(lock);
++ return CLI_SUCCESS;
++ }
++ tmp = tmp->next;
++ }
++ ast_mutex_unlock(lock);
++
++ ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
++ return CLI_FAILURE;
++}
++
++static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
++{
++ switch (cmd) {
++ case CLI_INIT:
++ e->command = "pri service enable channel";
++ e->usage =
++ "Usage: pri service enable channel <channel> [<interface id>]\n"
++ " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
++ " to restore a channel to service, with optional interface id\n"
++ " as agreed upon with remote switch operator\n";
++ return NULL;
++ case CLI_GENERATE:
++ return NULL;
++ }
++ return handle_pri_service_generic(e, cmd, a, 0);
++}
++
++static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
++{
++ switch (cmd) {
++ case CLI_INIT:
++ e->command = "pri service disable channel";
++ e->usage =
++ "Usage: pri service disable channel <chan num> [<interface id>]\n"
++ " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
++ " to remove a channel from service, with optional interface id\n"
++ " as agreed upon with remote switch operator\n";
++ return NULL;
++ case CLI_GENERATE:
++ return NULL;
++ }
++ return handle_pri_service_generic(e, cmd, a, 2);
++}
++#endif
++
+ #if defined(HAVE_PRI)
+ static void build_status(char *s, size_t len, int status, int active)
+ {
+@@ -13814,6 +15450,10 @@
+ #if defined(HAVE_PRI)
+ static struct ast_cli_entry dahdi_pri_cli[] = {
+ AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
++#ifdef HAVE_PRI_SERVICE_MESSAGES
++ AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
++ AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
++#endif
+ AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI Information"),
+ AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI Information"),
+ AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
+@@ -14259,14 +15899,14 @@
+ ast_mutex_lock(&ss_thread_lock);
+ while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
+ int x = DAHDI_FLASH;
+- ast_debug(3, "Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
++ ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
+
+ for (p = iflist; p; p = p->next) {
+ if (p->owner)
+- ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); /* important to create an event for dahdi_wait_event to register so that all ss_threads terminate */
++ ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); /* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
+ }
+- ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
+- }
++ ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
++ }
+
+ /* ensure any created channels before monitor threads were stopped are hungup */
+ dahdi_softhangup_all();
+@@ -14619,6 +16259,9 @@
+ ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
+ ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
+ ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
++#if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
++ ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
++#endif
+ ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
+ ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
+ ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
+@@ -15054,14 +16697,14 @@
+ {
+ if (p) {
+ switch (mode) {
+- case TRANSFER:
+- p->fake_event = DAHDI_EVENT_WINKFLASH;
+- break;
+- case HANGUP:
+- p->fake_event = DAHDI_EVENT_ONHOOK;
+- break;
+- default:
+- ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
++ case TRANSFER:
++ p->fake_event = DAHDI_EVENT_WINKFLASH;
++ break;
++ case HANGUP:
++ p->fake_event = DAHDI_EVENT_ONHOOK;
++ break;
++ default:
++ ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
+ }
+ }
+ return 0;
+@@ -15746,11 +17389,11 @@
+ #endif
+
+ ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
+- ast_manager_unregister( "DAHDIDialOffhook" );
+- ast_manager_unregister( "DAHDIHangup" );
+- ast_manager_unregister( "DAHDITransfer" );
+- ast_manager_unregister( "DAHDIDNDoff" );
+- ast_manager_unregister( "DAHDIDNDon" );
++ ast_manager_unregister("DAHDIDialOffhook");
++ ast_manager_unregister("DAHDIHangup");
++ ast_manager_unregister("DAHDITransfer");
++ ast_manager_unregister("DAHDIDNDoff");
++ ast_manager_unregister("DAHDIDNDon");
+ ast_manager_unregister("DAHDIShowChannels");
+ ast_manager_unregister("DAHDIRestart");
+ ast_channel_unregister(&dahdi_tech);
+@@ -15993,49 +17636,15 @@
+ return -1;
+ ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
+ } else if (!strcasecmp(v->name, "buffers")) {
+- int res;
+- char policy[21] = "";
+-
+- res = sscanf(v->value, "%d,%20s", &confp->chan.buf_no, policy);
+- if (res != 2) {
+- ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
++ if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
++ ast_log(LOG_WARNING, "Using default buffer policy.\n");
+ confp->chan.buf_no = numbufs;
+- continue;
+- }
+- if (confp->chan.buf_no < 0)
+- confp->chan.buf_no = numbufs;
+- if (!strcasecmp(policy, "full")) {
+- confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
+- } else if (!strcasecmp(policy, "immediate")) {
+ confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
+-#ifdef HAVE_DAHDI_HALF_FULL
+- } else if (!strcasecmp(policy, "half_full")) {
+- confp->chan.buf_policy = DAHDI_POLICY_HALF_FULL;
+-#endif
+- } else {
+- ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
+ }
+ } else if (!strcasecmp(v->name, "faxbuffers")) {
+- int res;
+- char policy[21] = "";
+-
+- res = sscanf(v->value, "%d,%20s", &confp->chan.faxbuf_no, policy);
+- if (res != 2) {
+- ast_log(LOG_WARNING, "Parsing faxbuffers option data failed, using defaults.\n");
+- confp->chan.faxbuf_no = numbufs;
+- continue;
++ if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
++ confp->chan.usefaxbuffers = 1;
+ }
+- confp->chan.usefaxbuffers = 1;
+- if (confp->chan.faxbuf_no < 0)
+- confp->chan.faxbuf_no = numbufs;
+- if (!strcasecmp(policy, "full")) {
+- confp->chan.faxbuf_policy = DAHDI_POLICY_WHEN_FULL;
+- } else if (!strcasecmp(policy, "immediate")) {
+- confp->chan.faxbuf_policy = DAHDI_POLICY_IMMEDIATE;
+- } else {
+- ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
+- confp->chan.usefaxbuffers = 0;
+- }
+ } else if (!strcasecmp(v->name, "dahdichan")) {
+ ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
+ } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
+@@ -16597,6 +18206,14 @@
+ #endif
+ } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
+ confp->pri.discardremoteholdretrieval = ast_true(v->value);
++#ifdef HAVE_PRI_SERVICE_MESSAGES
++ } else if (!strcasecmp(v->name, "service_message_support")) {
++ /* assuming switchtype for this channel group has been configured already */
++ if ((confp->pri.switchtype == PRI_SWITCH_ATT4ESS || confp->pri.switchtype == PRI_SWITCH_LUCENT5E) && ast_true(v->value))
++ confp->pri.enable_service_message_support = 1;
++ else
++ confp->pri.enable_service_message_support = 0;
++#endif
+ #ifdef HAVE_PRI_INBANDDISCONNECT
+ } else if (!strcasecmp(v->name, "inbanddisconnect")) {
+ confp->pri.inbanddisconnect = ast_true(v->value);
+@@ -16619,10 +18236,9 @@
+ }
+ } else
+ ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer configuration string at line %d.\n", v->value, v->lineno);
+-
++#endif /* PRI_GETSET_TIMERS */
+ } else if (!strcasecmp(v->name, "facilityenable")) {
+ confp->pri.facilityenable = ast_true(v->value);
+-#endif /* PRI_GETSET_TIMERS */
+ #endif /* HAVE_PRI */
+ #ifdef HAVE_SS7
+ } else if (!strcasecmp(v->name, "ss7type")) {
+@@ -17220,13 +18836,13 @@
+ ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
+
+ memset(round_robin, 0, sizeof(round_robin));
+- ast_manager_register( "DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" );
+- ast_manager_register( "DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" );
+- ast_manager_register( "DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" );
+- ast_manager_register( "DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" );
+- ast_manager_register( "DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" );
+- ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels");
+- ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)");
++ ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
++ ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
++ ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
++ ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
++ ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
++ ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
++ ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
+
+ ast_cond_init(&ss_thread_complete, NULL);
+
+@@ -17345,6 +18961,7 @@
+ return 0;
+ }
+
++
+ /* This is a workaround so that menuselect displays a proper description
+ * AST_MODULE_INFO(, , "DAHDI Telephony"
+ */
+Index: channels/chan_phone.c
+===================================================================
+--- a/channels/chan_phone.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/channels/chan_phone.c (.../trunk) (revision 202568)
+@@ -303,13 +303,13 @@
+ snprintf(cid.min, sizeof(cid.min), "%02d", tm.tm_min);
+ }
+ /* the standard format of ast->callerid is: "name" <number>, but not always complete */
+- if (ast_strlen_zero(ast->cid.cid_name))
++ if (ast_strlen_zero(ast->connected.id.name))
+ strcpy(cid.name, DEFAULT_CALLER_ID);
+ else
+- ast_copy_string(cid.name, ast->cid.cid_name, sizeof(cid.name));
++ ast_copy_string(cid.name, ast->connected.id.name, sizeof(cid.name));
+
+- if (ast->cid.cid_num)
+- ast_copy_string(cid.number, ast->cid.cid_num, sizeof(cid.number));
++ if (ast->connected.id.number)
++ ast_copy_string(cid.number, ast->connected.id.number, sizeof(cid.number));
+
+ p = ast->tech_pvt;
+
+Index: channels/sig_analog.c
+===================================================================
+--- a/channels/sig_analog.c (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/channels/sig_analog.c (.../trunk) (revision 202568)
+@@ -0,0 +1,3262 @@
++/*
++ * Asterisk -- An open source telephony toolkit.
++ *
++ * Copyright (C) 1999 - 2009, Digium, Inc.
++ *
++ * Mark Spencer <markster@digium.com>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * 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.
++ */
++
++/*! \file
++ *
++ * \brief Analog signaling module
++ *
++ * \author Matthew Fredrickson <creslin@digium.com>
++ */
++
++#include "asterisk.h"
++
++#include <errno.h>
++#include <ctype.h>
++
++#include "asterisk/utils.h"
++#include "asterisk/options.h"
++#include "asterisk/pbx.h"
++#include "asterisk/file.h"
++#include "asterisk/callerid.h"
++#include "asterisk/say.h"
++#include "asterisk/manager.h"
++#include "asterisk/astdb.h"
++#include "asterisk/features.h"
++
++#include "sig_analog.h"
++
++#define POLARITY_IDLE 0
++#define POLARITY_REV 1
++#define MIN_MS_SINCE_FLASH ( (2000) ) /*!< 2000 ms */
++static int analog_matchdigittimeout = 3000;
++static int analog_gendigittimeout = 8000;
++static int analog_firstdigittimeout = 16000;
++static char analog_defaultcic[64] = "";
++static char analog_defaultozz[64] = "";
++
++static const struct {
++ enum analog_sigtype sigtype;
++ const char const *name;
++} sigtypes[] = {
++ { ANALOG_SIG_FXOLS, "fxo_ls" },
++ { ANALOG_SIG_FXOKS, "fxo_ks" },
++ { ANALOG_SIG_FXOGS, "fxo_gs" },
++ { ANALOG_SIG_FXSLS, "fxs_ls" },
++ { ANALOG_SIG_FXSKS, "fxs_ks" },
++ { ANALOG_SIG_FXSGS, "fxs_gs" },
++ { ANALOG_SIG_EMWINK, "em_w" },
++ { ANALOG_SIG_EM, "em" },
++ { ANALOG_SIG_EM_E1, "em_e1" },
++ { ANALOG_SIG_FEATD, "featd" },
++ { ANALOG_SIG_FEATDMF, "featdmf" },
++ { ANALOG_SIG_FEATDMF_TA, "featdmf_ta" },
++ { ANALOG_SIG_FEATB, "featb" },
++ { ANALOG_SIG_FGC_CAMA, "fgccama" },
++ { ANALOG_SIG_FGC_CAMAMF, "fgccamamf" },
++ { ANALOG_SIG_SF, "sf" },
++ { ANALOG_SIG_SFWINK, "sf_w" },
++ { ANALOG_SIG_SF_FEATD, "sf_featd" },
++ { ANALOG_SIG_SF_FEATDMF, "sf_featdmf" },
++ { ANALOG_SIG_SF_FEATB, "sf_featb" },
++ { ANALOG_SIG_E911, "e911" },
++};
++
++static const struct {
++ unsigned int cid_type;
++ const char const *name;
++} cidtypes[] = {
++ { CID_SIG_BELL, "bell" },
++ { CID_SIG_V23, "v23" },
++ { CID_SIG_V23_JP, "v23_jp" },
++ { CID_SIG_DTMF, "dtmf" },
++ /* "smdi" is intentionally not supported here, as there is a much better
++ * way to do this in the dialplan now. */
++};
++
++enum analog_sigtype analog_str_to_sigtype(const char *name)
++{
++ int i;
++
++ for (i = 0; i < ARRAY_LEN(sigtypes); i++) {
++ if (!strcasecmp(sigtypes[i].name, name)) {
++ return sigtypes[i].sigtype;
++ }
++ }
++
++ return 0;
++}
++
++const char *analog_sigtype_to_str(enum analog_sigtype sigtype)
++{
++ int i;
++
++ for (i = 0; i < ARRAY_LEN(sigtypes); i++) {
++ if (sigtype == sigtypes[i].sigtype) {
++ return sigtypes[i].name;
++ }
++ }
++
++ return "Unknown";
++}
++
++unsigned int analog_str_to_cidtype(const char *name)
++{
++ int i;
++
++ for (i = 0; i < ARRAY_LEN(cidtypes); i++) {
++ if (!strcasecmp(cidtypes[i].name, name)) {
++ return cidtypes[i].cid_type;
++ }
++ }
++
++ return 0;
++}
++
++const char *analog_cidtype_to_str(unsigned int cid_type)
++{
++ int i;
++
++ for (i = 0; i < ARRAY_LEN(cidtypes); i++) {
++ if (cid_type == cidtypes[i].cid_type) {
++ return cidtypes[i].name;
++ }
++ }
++
++ return "Unknown";
++}
++
++static int analog_start_cid_detect(struct analog_pvt *p, int cid_signalling)
++{
++ if (p->calls->start_cid_detect)
++ return p->calls->start_cid_detect(p->chan_pvt, cid_signalling);
++ else
++ return -1;
++}
++
++static int analog_stop_cid_detect(struct analog_pvt *p)
++{
++ if (p->calls->stop_cid_detect)
++ return p->calls->stop_cid_detect(p->chan_pvt);
++ else
++ return -1;
++}
++
++static int analog_get_callerid(struct analog_pvt *p, char *name, char *number, enum analog_event *ev, size_t timeout)
++{
++ if (p->calls->get_callerid)
++ return p->calls->get_callerid(p->chan_pvt, name, number, ev, timeout);
++ else
++ return -1;
++}
++
++static int analog_get_event(struct analog_pvt *p)
++{
++ if (p->calls->get_event)
++ return p->calls->get_event(p->chan_pvt);
++ else
++ return -1;
++}
++
++static int analog_wait_event(struct analog_pvt *p)
++{
++ if (p->calls->wait_event)
++ return p->calls->wait_event(p->chan_pvt);
++ else
++ return -1;
++}
++
++enum analog_cid_start analog_str_to_cidstart(const char *value)
++{
++ if (!strcasecmp(value, "ring")) {
++ return ANALOG_CID_START_RING;
++ } else if (!strcasecmp(value, "polarity")) {
++ return ANALOG_CID_START_POLARITY;
++ } else if (!strcasecmp(value, "polarity_in")) {
++ return ANALOG_CID_START_POLARITY_IN;
++ }
++
++ return 0;
++}
++
++const char *analog_cidstart_to_str(enum analog_cid_start cid_start)
++{
++ switch (cid_start) {
++ case ANALOG_CID_START_RING:
++ return "Ring";
++ case ANALOG_CID_START_POLARITY:
++ return "Polarity";
++ case ANALOG_CID_START_POLARITY_IN:
++ return "Polarity_In";
++ }
++
++ return "Unknown";
++}
++
++static char *analog_event2str(enum analog_event event)
++{
++ char *res;
++ switch (event) {
++ case ANALOG_EVENT_DIALCOMPLETE:
++ res = "ANALOG_EVENT_DIALCOMPLETE";
++ break;
++ case ANALOG_EVENT_WINKFLASH:
++ res = "ANALOG_EVENT_WINKFLASH";
++ break;
++ case ANALOG_EVENT_ONHOOK:
++ res = "ANALOG_EVENT_ONHOOK";
++ break;
++ case ANALOG_EVENT_RINGOFFHOOK:
++ res = "ANALOG_EVENT_RINGOFFHOOK";
++ break;
++ case ANALOG_EVENT_ALARM:
++ res = "ANALOG_EVENT_ALARM";
++ break;
++ case ANALOG_EVENT_NOALARM:
++ res = "ANALOG_EVENT_NOALARM";
++ break;
++ case ANALOG_EVENT_HOOKCOMPLETE:
++ res = "ANALOG_EVENT_HOOKCOMPLETE";
++ break;
++ case ANALOG_EVENT_POLARITY:
++ res = "ANALOG_EVENT_POLARITY";
++ break;
++ case ANALOG_EVENT_RINGERON:
++ res = "ANALOG_EVENT_RINGERON";
++ break;
++ case ANALOG_EVENT_RINGEROFF:
++ res = "ANALOG_EVENT_RINGEROFF";
++ break;
++ case ANALOG_EVENT_RINGBEGIN:
++ res = "ANALOG_EVENT_RINGBEGIN";
++ break;
++ case ANALOG_EVENT_PULSE_START:
++ res = "ANALOG_EVENT_PULSE_START";
++ break;
++ case ANALOG_EVENT_NEONMWI_ACTIVE:
++ res = "ANALOG_EVENT_NEONMWI_ACTIVE";
++ break;
++ case ANALOG_EVENT_NEONMWI_INACTIVE:
++ res = "ANALOG_EVENT_NEONMWI_INACTIVE";
++ break;
++ default:
++ res = "UNKNOWN/OTHER";
++ break;
++ }
++
++ return res;
++}
++
++static void analog_swap_subs(struct analog_pvt *p, enum analog_sub a, enum analog_sub b)
++{
++ int tinthreeway;
++ struct ast_channel *towner;
++
++ ast_debug(1, "Swapping %d and %d\n", a, b);
++
++ towner = p->subs[a].owner;
++ tinthreeway = p->subs[a].inthreeway;
++
++ p->subs[a].owner = p->subs[b].owner;
++ p->subs[a].inthreeway = p->subs[b].inthreeway;
++
++ p->subs[b].owner = towner;
++ p->subs[b].inthreeway = tinthreeway;
++
++ if (p->calls->swap_subs)
++ p->calls->swap_subs(p->chan_pvt, a, p->subs[a].owner, b, p->subs[b].owner);
++
++}
++
++static int analog_alloc_sub(struct analog_pvt *p, enum analog_sub x)
++{
++ p->subs[x].allocd = 1;
++ if (p->calls->allocate_sub)
++ return p->calls->allocate_sub(p->chan_pvt, x);
++
++ return 0;
++}
++
++static int analog_unalloc_sub(struct analog_pvt *p, enum analog_sub x)
++{
++ p->subs[x].allocd = 0;
++ p->subs[x].owner = NULL;
++ if (p->calls->unallocate_sub)
++ return p->calls->unallocate_sub(p->chan_pvt, x);
++
++ return 0;
++}
++
++static int analog_send_callerid(struct analog_pvt *p, int cwcid, struct ast_callerid *cid)
++{
++ ast_debug(1, "Sending callerid. CID_NAME: '%s' CID_NUM: '%s'\n", cid->cid_name, cid->cid_num);
++
++ if (cwcid) {
++ p->callwaitcas = 0;
++ }
++
++ if (p->calls->send_callerid)
++ return p->calls->send_callerid(p->chan_pvt, cwcid, cid);
++ else
++ return 0;
++}
++
++static int analog_get_index(struct ast_channel *ast, struct analog_pvt *p, int nullok)
++{
++ int res;
++ if (p->subs[ANALOG_SUB_REAL].owner == ast)
++ res = ANALOG_SUB_REAL;
++ else if (p->subs[ANALOG_SUB_CALLWAIT].owner == ast)
++ res = ANALOG_SUB_CALLWAIT;
++ else if (p->subs[ANALOG_SUB_THREEWAY].owner == ast)
++ res = ANALOG_SUB_THREEWAY;
++ else {
++ res = -1;
++ if (!nullok)
++ ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
++ }
++ return res;
++}
++
++static int analog_dsp_reset_and_flush_digits(struct analog_pvt *p)
++{
++ if (p->calls->dsp_reset_and_flush_digits)
++ return p->calls->dsp_reset_and_flush_digits(p->chan_pvt);
++ else
++ /* Return 0 since I think this is unnecessary to do in most cases it is used. Mostly only for ast_dsp */
++ return 0;
++}
++
++static int analog_play_tone(struct analog_pvt *p, enum analog_sub sub, enum analog_tone tone)
++{
++ if (p->calls->play_tone)
++ return p->calls->play_tone(p->chan_pvt, sub, tone);
++ else
++ return -1;
++}
++
++static struct ast_channel * analog_new_ast_channel(struct analog_pvt *p, int state, int startpbx, enum analog_sub sub)
++{
++ struct ast_channel *c;
++
++ if (p->calls->new_ast_channel)
++ c = p->calls->new_ast_channel(p->chan_pvt, state, startpbx, sub);
++ else
++ return NULL;
++
++ p->subs[sub].owner = c;
++ if (!p->owner)
++ p->owner = c;
++ return c;
++}
++
++static int analog_set_echocanceller(struct analog_pvt *p, int enable)
++{
++ if (p->calls->set_echocanceller)
++ return p->calls->set_echocanceller(p->chan_pvt, enable);
++ else
++ return -1;
++}
++
++static int analog_train_echocanceller(struct analog_pvt *p)
++{
++ if (p->calls->train_echocanceller)
++ return p->calls->train_echocanceller(p->chan_pvt);
++ else
++ return -1;
++}
++
++static int analog_is_off_hook(struct analog_pvt *p)
++{
++ if (p->calls->is_off_hook)
++ return p->calls->is_off_hook(p->chan_pvt);
++ else
++ return -1;
++}
++
++static int analog_ring(struct analog_pvt *p)
++{
++ if (p->calls->ring)
++ return p->calls->ring(p->chan_pvt);
++ else
++ return -1;
++}
++
++static int analog_start(struct analog_pvt *p)
++{
++ if (p->calls->start)
++ return p->calls->start(p->chan_pvt);
++ else
++ return -1;
++}
++
++static int analog_dial_digits(struct analog_pvt *p, enum analog_sub sub, struct analog_dialoperation *dop)
++{
++ if (p->calls->dial_digits)
++ return p->calls->dial_digits(p->chan_pvt, sub, dop);
++ else
++ return -1;
++}
++
++static int analog_on_hook(struct analog_pvt *p)
++{
++ if (p->calls->on_hook)
++ return p->calls->on_hook(p->chan_pvt);
++ else
++ return -1;
++}
++
++static int analog_check_for_conference(struct analog_pvt *p)
++{
++ if (p->calls->check_for_conference)
++ return p->calls->check_for_conference(p->chan_pvt);
++ else
++ return -1;
++}
++
++static void analog_all_subchannels_hungup(struct analog_pvt *p)
++{
++ if (p->calls->all_subchannels_hungup)
++ p->calls->all_subchannels_hungup(p->chan_pvt);
++}
++
++static void analog_unlock_private(struct analog_pvt *p)
++{
++ if (p->calls->unlock_private)
++ p->calls->unlock_private(p->chan_pvt);
++}
++
++static void analog_lock_private(struct analog_pvt *p)
++{
++ if (p->calls->lock_private)
++ p->calls->lock_private(p->chan_pvt);
++}
++
++static int analog_off_hook(struct analog_pvt *p)
++{
++ if (p->calls->off_hook)
++ return p->calls->off_hook(p->chan_pvt);
++ else
++ return -1;
++}
++
++static int analog_dsp_set_digitmode(struct analog_pvt *p, enum analog_dsp_digitmode mode)
++{
++ if (p->calls->dsp_set_digitmode)
++ return p->calls->dsp_set_digitmode(p->chan_pvt, mode);
++ else
++ return -1;
++}
++
++static void analog_cb_handle_dtmfup(struct analog_pvt *p, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
++{
++ if (p->calls->handle_dtmfup)
++ p->calls->handle_dtmfup(p->chan_pvt, ast, analog_index, dest);
++}
++
++static int analog_wink(struct analog_pvt *p, enum analog_sub index)
++{
++ if (p->calls->wink)
++ return p->calls->wink(p->chan_pvt, index);
++ else
++ return -1;
++}
++
++static int analog_has_voicemail(struct analog_pvt *p)
++{
++ if (p->calls->has_voicemail)
++ return p->calls->has_voicemail(p->chan_pvt);
++ else
++ return -1;
++}
++
++static int analog_is_dialing(struct analog_pvt *p, enum analog_sub index)
++{
++ if (p->calls->is_dialing)
++ return p->calls->is_dialing(p->chan_pvt, index);
++ else
++ return -1;
++}
++
++static int analog_attempt_transfer(struct analog_pvt *p)
++{
++ /* In order to transfer, we need at least one of the channels to
++ actually be in a call bridge. We can't conference two applications
++ together (but then, why would we want to?) */
++ if (ast_bridged_channel(p->subs[ANALOG_SUB_REAL].owner)) {
++ /* The three-way person we're about to transfer to could still be in MOH, so
++ stop if now if appropriate */
++ if (ast_bridged_channel(p->subs[ANALOG_SUB_THREEWAY].owner))
++ ast_queue_control(p->subs[ANALOG_SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
++ if (p->subs[ANALOG_SUB_REAL].owner->_state == AST_STATE_RINGING) {
++ ast_indicate(ast_bridged_channel(p->subs[ANALOG_SUB_REAL].owner), AST_CONTROL_RINGING);
++ }
++ if (p->subs[ANALOG_SUB_THREEWAY].owner->_state == AST_STATE_RING) {
++ analog_play_tone(p, ANALOG_SUB_THREEWAY, ANALOG_TONE_RINGTONE);
++ }
++ if (ast_channel_masquerade(p->subs[ANALOG_SUB_THREEWAY].owner, ast_bridged_channel(p->subs[ANALOG_SUB_REAL].owner))) {
++ ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
++ ast_bridged_channel(p->subs[ANALOG_SUB_REAL].owner)->name, p->subs[ANALOG_SUB_THREEWAY].owner->name);
++ return -1;
++ }
++ /* Orphan the channel after releasing the lock */
++ ast_channel_unlock(p->subs[ANALOG_SUB_THREEWAY].owner);
++ analog_unalloc_sub(p, ANALOG_SUB_THREEWAY);
++ } else if (ast_bridged_channel(p->subs[ANALOG_SUB_THREEWAY].owner)) {
++ ast_queue_control(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_UNHOLD);
++ if (p->subs[ANALOG_SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
++ ast_indicate(ast_bridged_channel(p->subs[ANALOG_SUB_THREEWAY].owner), AST_CONTROL_RINGING);
++ }
++ if (p->subs[ANALOG_SUB_REAL].owner->_state == AST_STATE_RING) {
++ analog_play_tone(p, ANALOG_SUB_REAL, ANALOG_TONE_RINGTONE);
++ }
++ if (ast_channel_masquerade(p->subs[ANALOG_SUB_REAL].owner, ast_bridged_channel(p->subs[ANALOG_SUB_THREEWAY].owner))) {
++ ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
++ ast_bridged_channel(p->subs[ANALOG_SUB_THREEWAY].owner)->name, p->subs[ANALOG_SUB_REAL].owner->name);
++ return -1;
++ }
++ /* Three-way is now the REAL */
++ analog_swap_subs(p, ANALOG_SUB_THREEWAY, ANALOG_SUB_REAL);
++ ast_channel_unlock(p->subs[ANALOG_SUB_THREEWAY].owner);
++ analog_unalloc_sub(p, ANALOG_SUB_THREEWAY);
++ /* Tell the caller not to hangup */
++ return 1;
++ } else {
++ ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
++ p->subs[ANALOG_SUB_REAL].owner->name, p->subs[ANALOG_SUB_THREEWAY].owner->name);
++ ast_softhangup_nolock(p->subs[ANALOG_SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
++ return -1;
++ }
++ return 0;
++}
++
++static int analog_update_conf(struct analog_pvt *p)
++{
++ int x;
++ int needconf = 0;
++
++ /* Start with the obvious, general stuff */
++ for (x = 0; x < 3; x++) {
++ /* Look for three way calls */
++ if ((p->subs[x].allocd) && p->subs[x].inthreeway) {
++ if (p->calls->conf_add)
++ p->calls->conf_add(p->chan_pvt, x);
++ needconf++;
++ } else {
++ if (p->calls->conf_del)
++ p->calls->conf_del(p->chan_pvt, x);
++ }
++ }
++ ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
++
++ if (p->calls->complete_conference_update)
++ p->calls->complete_conference_update(p->chan_pvt, needconf);
++ return 0;
++}
++
++struct ast_channel * analog_request(struct analog_pvt *p, int *callwait)
++{
++ ast_log(LOG_DEBUG, "%s %d\n", __FUNCTION__, p->channel);
++ *callwait = (p->owner != NULL);
++
++ if (p->owner) {
++ if (analog_alloc_sub(p, ANALOG_SUB_CALLWAIT)) {
++ ast_log(LOG_ERROR, "Unable to alloc subchannel\n");
++ return NULL;
++ }
++ }
++
++ return analog_new_ast_channel(p, AST_STATE_RESERVED, 0, p->owner ? ANALOG_SUB_CALLWAIT : ANALOG_SUB_REAL);
++}
++
++int analog_available(struct analog_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
++{
++ int offhook;
++
++ ast_log(LOG_DEBUG, "%s %d\n", __FUNCTION__, p->channel);
++ /* We're at least busy at this point */
++ if (busy) {
++ if ((p->sig == ANALOG_SIG_FXOKS) || (p->sig == ANALOG_SIG_FXOLS) || (p->sig == ANALOG_SIG_FXOGS))
++ *busy = 1;
++ }
++ /* If do not disturb, definitely not */
++ if (p->dnd)
++ return 0;
++ /* If guard time, definitely not */
++ if (p->guardtime && (time(NULL) < p->guardtime))
++ return 0;
++
++ /* If no owner definitely available */
++ if (!p->owner) {
++ if (p->sig == ANALOG_SIG_FXSLS)
++ return 1;
++
++ offhook = analog_is_off_hook(p);
++
++ if ((p->sig == ANALOG_SIG_FXSKS) || (p->sig == ANALOG_SIG_FXSGS)) {
++ /* When "onhook" that means no battery on the line, and thus
++ it is out of service..., if it's on a TDM card... If it's a channel
++ bank, there is no telling... */
++ if (offhook)
++ return 1;
++ else
++ return 0;
++ } else if (offhook) {
++ ast_debug(1, "Channel %d off hook, can't use\n", p->channel);
++ /* Not available when the other end is off hook */
++ return 0;
++ }
++ return 1;
++ }
++
++ /* If it's not an FXO, forget about call wait */
++ if ((p->sig != ANALOG_SIG_FXOKS) && (p->sig != ANALOG_SIG_FXOLS) && (p->sig != ANALOG_SIG_FXOGS))
++ return 0;
++
++ if (!p->callwaiting) {
++ /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
++ return 0;
++ }
++
++ if (p->subs[ANALOG_SUB_CALLWAIT].allocd) {
++ /* If there is already a call waiting call, then we can't take a second one */
++ return 0;
++ }
++
++ if ((p->owner->_state != AST_STATE_UP) &&
++ ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
++ /* If the current call is not up, then don't allow the call */
++ return 0;
++ }
++ if ((p->subs[ANALOG_SUB_THREEWAY].owner) && (!p->subs[ANALOG_SUB_THREEWAY].inthreeway)) {
++ /* Can't take a call wait when the three way calling hasn't been merged yet. */
++ return 0;
++ }
++ /* We're cool */
++ return 1;
++}
++
++static int analog_stop_callwait(struct analog_pvt *p)
++{
++ if (p->callwaitingcallerid)
++ p->callwaitcas = 0;
++
++ if (p->calls->stop_callwait)
++ return p->calls->stop_callwait(p->chan_pvt);
++ else
++ return 0;
++}
++
++static int analog_callwait(struct analog_pvt *p)
++{
++ if (p->callwaitingcallerid)
++ p->callwaitcas = 1;
++ if (p->calls->callwait)
++ return p->calls->callwait(p->chan_pvt);
++ else
++ return 0;
++}
++
++int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int timeout)
++{
++ int res, index,mysig;
++ char *c, *n, *l;
++ char dest[256]; /* must be same length as p->dialdest */
++
++ ast_log(LOG_DEBUG, "CALLING CID_NAME: %s CID_NUM:: %s\n", ast->connected.id.name, ast->connected.id.number);
++
++ ast_copy_string(dest, rdest, sizeof(dest));
++ ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
++
++ if ((ast->_state == AST_STATE_BUSY)) {
++ ast_queue_control(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_BUSY);
++ return 0;
++ }
++
++ if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
++ ast_log(LOG_WARNING, "analog_call called on %s, neither down nor reserved\n", ast->name);
++ return -1;
++ }
++
++ p->dialednone = 0;
++
++ mysig = p->sig;
++ if (p->outsigmod > -1)
++ mysig = p->outsigmod;
++
++ switch (mysig) {
++ case ANALOG_SIG_FXOLS:
++ case ANALOG_SIG_FXOGS:
++ case ANALOG_SIG_FXOKS:
++ if (p->owner == ast) {
++ /* Normal ring, on hook */
++
++ /* Don't send audio while on hook, until the call is answered */
++ p->dialing = 1;
++ /* XXX */
++#if 0
++ /* Choose proper cadence */
++ if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
++ if (ioctl(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
++ ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
++ p->cidrings = cidrings[p->distinctivering - 1];
++ } else {
++ if (ioctl(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
++ ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
++ p->cidrings = p->sendcalleridafter;
++ }
++#endif
++ p->cidrings = p->sendcalleridafter;
++
++ /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
++ c = strchr(dest, '/');
++ if (c)
++ c++;
++ if (c && (strlen(c) < p->stripmsd)) {
++ ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
++ c = NULL;
++ }
++ if (c) {
++ p->dop.op = ANALOG_DIAL_OP_REPLACE;
++ snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
++ ast_debug(1, "FXO: setup deferred dialstring: %s\n", c);
++ } else {
++ p->dop.dialstr[0] = '\0';
++ }
++
++ if (analog_ring(p)) {
++ ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
++ return -1;
++ }
++ p->dialing = 1;
++ } else {
++ if (ast->connected.id.number)
++ ast_copy_string(p->callwait_num, ast->connected.id.number, sizeof(p->callwait_num));
++ else
++ p->callwait_num[0] = '\0';
++ if (ast->connected.id.name)
++ ast_copy_string(p->callwait_name, ast->connected.id.name, sizeof(p->callwait_name));
++ else
++ p->callwait_name[0] = '\0';
++
++ /* Call waiting tone instead */
++ if (analog_callwait(p)) {
++ return -1;
++ }
++ /* Make ring-back */
++ if (analog_play_tone(p, ANALOG_SUB_CALLWAIT, ANALOG_TONE_RINGTONE))
++ ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
++
++ }
++ n = ast->connected.id.name;
++ l = ast->connected.id.number;
++ if (l)
++ ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
++ else
++ p->lastcid_num[0] = '\0';
++ if (n)
++ ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
++ else
++ p->lastcid_name[0] = '\0';
++
++ if (p->use_callerid) {
++ //p->callwaitcas = 0;
++ p->cid.cid_name = p->lastcid_name;
++ p->cid.cid_num = p->lastcid_num;
++ }
++
++
++ ast_setstate(ast, AST_STATE_RINGING);
++ index = analog_get_index(ast, p, 0);
++ if (index > -1) {
++ ast_queue_control(p->subs[index].owner, AST_CONTROL_RINGING);
++ }
++ break;
++ case ANALOG_SIG_FXSLS:
++ case ANALOG_SIG_FXSGS:
++ case ANALOG_SIG_FXSKS:
++ case ANALOG_SIG_EMWINK:
++ case ANALOG_SIG_EM:
++ case ANALOG_SIG_EM_E1:
++ case ANALOG_SIG_FEATD:
++ case ANALOG_SIG_FEATDMF:
++ case ANALOG_SIG_E911:
++ case ANALOG_SIG_FGC_CAMA:
++ case ANALOG_SIG_FGC_CAMAMF:
++ case ANALOG_SIG_FEATB:
++ case ANALOG_SIG_SFWINK:
++ case ANALOG_SIG_SF:
++ case ANALOG_SIG_SF_FEATD:
++ case ANALOG_SIG_SF_FEATDMF:
++ case ANALOG_SIG_FEATDMF_TA:
++ case ANALOG_SIG_SF_FEATB:
++ c = strchr(dest, '/');
++ if (c)
++ c++;
++ else
++ c = "";
++ if (strlen(c) < p->stripmsd) {
++ ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
++ return -1;
++ }
++ res = analog_start(p);
++ if (res < 0) {
++ if (errno != EINPROGRESS) {
++ return -1;
++ }
++ }
++ ast_log(LOG_DEBUG, "Dialing '%s'\n", c);
++ p->dop.op = ANALOG_DIAL_OP_REPLACE;
++
++ c += p->stripmsd;
++
++ switch (mysig) {
++ case ANALOG_SIG_FEATD:
++ l = ast->connected.id.number;
++ if (l)
++ snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
++ else
++ snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
++ break;
++ case ANALOG_SIG_FEATDMF:
++ l = ast->connected.id.number;
++ if (l)
++ snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
++ else
++ snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
++ break;
++ case ANALOG_SIG_FEATDMF_TA:
++ {
++ const char *cic = "", *ozz = "";
++
++ /* If you have to go through a Tandem Access point you need to use this */
++#ifndef STANDALONE
++ ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
++ if (!ozz)
++ ozz = analog_defaultozz;
++ cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
++ if (!cic)
++ cic = analog_defaultcic;
++#endif
++ if (!ozz || !cic) {
++ ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
++ return -1;
++ }
++ snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
++ snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
++ p->whichwink = 0;
++ }
++ break;
++ case ANALOG_SIG_E911:
++ ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
++ break;
++ case ANALOG_SIG_FGC_CAMA:
++ snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
++ break;
++ case ANALOG_SIG_FGC_CAMAMF:
++ case ANALOG_SIG_FEATB:
++ snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
++ break;
++ default:
++ if (p->pulse)
++ snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
++ else
++ snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
++ break;
++ }
++
++ if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
++ memset(p->echorest, 'w', sizeof(p->echorest) - 1);
++ strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
++ p->echorest[sizeof(p->echorest) - 1] = '\0';
++ p->echobreak = 1;
++ p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
++ } else
++ p->echobreak = 0;
++ if (!res) {
++ if (analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop)) {
++ int saveerr = errno;
++
++ analog_on_hook(p);
++ ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
++ return -1;
++ }
++ } else
++ ast_debug(1, "Deferring dialing...\n");
++ p->dialing = 1;
++ if (ast_strlen_zero(c))
++ p->dialednone = 1;
++ ast_setstate(ast, AST_STATE_DIALING);
++ break;
++ default:
++ ast_debug(1, "not yet implemented\n");
++ return -1;
++ }
++ return 0;
++}
++
++int analog_hangup(struct analog_pvt *p, struct ast_channel *ast)
++{
++ int res;
++ int index, x;
++
++ ast_log(LOG_DEBUG, "%s %d\n", __FUNCTION__, p->channel);
++ if (!ast->tech_pvt) {
++ ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
++ return 0;
++ }
++
++ index = analog_get_index(ast, p, 1);
++
++ x = 0;
++ if (p->origcid_num) {
++ ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
++ free(p->origcid_num);
++ p->origcid_num = NULL;
++ }
++ if (p->origcid_name) {
++ ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
++ free(p->origcid_name);
++ p->origcid_name = NULL;
++ }
++
++ analog_dsp_set_digitmode(p, ANALOG_DIGITMODE_DTMF);
++
++ ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
++ p->channel, index, p->subs[ANALOG_SUB_REAL].allocd, p->subs[ANALOG_SUB_CALLWAIT].allocd, p->subs[ANALOG_SUB_THREEWAY].allocd);
++ if (index > -1) {
++ /* Real channel, do some fixup */
++ p->subs[index].owner = NULL;
++ p->subs[index].needcallerid = 0;
++ p->polarity = POLARITY_IDLE;
++ if (index == ANALOG_SUB_REAL) {
++ if (p->subs[ANALOG_SUB_CALLWAIT].allocd && p->subs[ANALOG_SUB_THREEWAY].allocd) {
++ ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
++ if (p->subs[ANALOG_SUB_CALLWAIT].inthreeway) {
++ /* We had flipped over to answer a callwait and now it's gone */
++ ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
++ /* Move to the call-wait, but un-own us until they flip back. */
++ analog_swap_subs(p, ANALOG_SUB_CALLWAIT, ANALOG_SUB_REAL);
++ analog_unalloc_sub(p, ANALOG_SUB_CALLWAIT);
++ p->owner = NULL;
++ } else {
++ /* The three way hung up, but we still have a call wait */
++ ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
++ analog_swap_subs(p, ANALOG_SUB_THREEWAY, ANALOG_SUB_REAL);
++ analog_unalloc_sub(p, ANALOG_SUB_THREEWAY);
++ if (p->subs[ANALOG_SUB_REAL].inthreeway) {
++ /* This was part of a three way call. Immediately make way for
++ another call */
++ ast_debug(1, "Call was complete, setting owner to former third call\n");
++ p->owner = p->subs[ANALOG_SUB_REAL].owner;
++ } else {
++ /* This call hasn't been completed yet... Set owner to NULL */
++ ast_debug(1, "Call was incomplete, setting owner to NULL\n");
++ p->owner = NULL;
++ }
++ p->subs[ANALOG_SUB_REAL].inthreeway = 0;
++ }
++ } else if (p->subs[ANALOG_SUB_CALLWAIT].allocd) {
++ /* Move to the call-wait and switch back to them. */
++ analog_swap_subs(p, ANALOG_SUB_CALLWAIT, ANALOG_SUB_REAL);
++ analog_unalloc_sub(p, ANALOG_SUB_CALLWAIT);
++ p->owner = p->subs[ANALOG_SUB_REAL].owner;
++ if (p->owner->_state != AST_STATE_UP)
++ ast_queue_control(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_ANSWER);
++ if (ast_bridged_channel(p->subs[ANALOG_SUB_REAL].owner))
++ ast_queue_control(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_UNHOLD);
++ } else if (p->subs[ANALOG_SUB_THREEWAY].allocd) {
++ analog_swap_subs(p, ANALOG_SUB_THREEWAY, ANALOG_SUB_REAL);
++ analog_unalloc_sub(p, ANALOG_SUB_THREEWAY);
++ if (p->subs[ANALOG_SUB_REAL].inthreeway) {
++ /* This was part of a three way call. Immediately make way for
++ another call */
++ ast_debug(1, "Call was complete, setting owner to former third call\n");
++ p->owner = p->subs[ANALOG_SUB_REAL].owner;
++ } else {
++ /* This call hasn't been completed yet... Set owner to NULL */
++ ast_debug(1, "Call was incomplete, setting owner to NULL\n");
++ p->owner = NULL;
++ }
++ p->subs[ANALOG_SUB_REAL].inthreeway = 0;
++ }
++ } else if (index == ANALOG_SUB_CALLWAIT) {
++ /* Ditch the holding callwait call, and immediately make it availabe */
++ if (p->subs[ANALOG_SUB_CALLWAIT].inthreeway) {
++ /* This is actually part of a three way, placed on hold. Place the third part
++ on music on hold now */
++ if (p->subs[ANALOG_SUB_THREEWAY].owner && ast_bridged_channel(p->subs[ANALOG_SUB_THREEWAY].owner)) {
++ ast_queue_control_data(p->subs[ANALOG_SUB_THREEWAY].owner, AST_CONTROL_HOLD,
++ S_OR(p->mohsuggest, NULL),
++ !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
++ }
++ p->subs[ANALOG_SUB_THREEWAY].inthreeway = 0;
++ /* Make it the call wait now */
++ analog_swap_subs(p, ANALOG_SUB_CALLWAIT, ANALOG_SUB_THREEWAY);
++ analog_unalloc_sub(p, ANALOG_SUB_THREEWAY);
++ } else
++ analog_unalloc_sub(p, ANALOG_SUB_CALLWAIT);
++ } else if (index == ANALOG_SUB_THREEWAY) {
++ if (p->subs[ANALOG_SUB_CALLWAIT].inthreeway) {
++ /* The other party of the three way call is currently in a call-wait state.
++ Start music on hold for them, and take the main guy out of the third call */
++ if (p->subs[ANALOG_SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[ANALOG_SUB_CALLWAIT].owner)) {
++ ast_queue_control_data(p->subs[ANALOG_SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
++ S_OR(p->mohsuggest, NULL),
++ !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
++ }
++ p->subs[ANALOG_SUB_CALLWAIT].inthreeway = 0;
++ }
++ p->subs[ANALOG_SUB_REAL].inthreeway = 0;
++ /* If this was part of a three way call index, let us make
++ another three way call */
++ analog_unalloc_sub(p, ANALOG_SUB_THREEWAY);
++ } else {
++ /* This wasn't any sort of call, but how are we an index? */
++ ast_log(LOG_WARNING, "Index found but not any type of call?\n");
++ }
++ }
++
++ if (!p->subs[ANALOG_SUB_REAL].owner && !p->subs[ANALOG_SUB_CALLWAIT].owner && !p->subs[ANALOG_SUB_THREEWAY].owner) {
++ p->owner = NULL;
++#if 0
++ p->ringt = 0;
++#endif
++#if 0 /* Since we set it in _call */
++ p->cidrings = 1;
++#endif
++ p->outgoing = 0;
++
++ /* Perform low level hangup if no owner left */
++ res = analog_on_hook(p);
++ if (res < 0) {
++ ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
++ }
++ switch (p->sig) {
++ case ANALOG_SIG_FXOGS:
++ case ANALOG_SIG_FXOLS:
++ case ANALOG_SIG_FXOKS:
++ /* If they're off hook, try playing congestion */
++ if (analog_is_off_hook(p))
++ analog_play_tone(p, ANALOG_SUB_REAL, ANALOG_TONE_CONGESTION);
++ else
++ analog_play_tone(p, ANALOG_SUB_REAL, -1);
++ break;
++ case ANALOG_SIG_FXSGS:
++ case ANALOG_SIG_FXSLS:
++ case ANALOG_SIG_FXSKS:
++ /* Make sure we're not made available for at least two seconds assuming
++ we were actually used for an inbound or outbound call. */
++ if (ast->_state != AST_STATE_RESERVED) {
++ time(&p->guardtime);
++ p->guardtime += 2;
++ }
++ break;
++ default:
++ analog_play_tone(p, ANALOG_SUB_REAL, -1);
++ }
++
++
++ analog_set_echocanceller(p, 0);
++
++ x = 0;
++ ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
++ ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
++ p->callwaitcas = 0;
++ p->callwaiting = p->permcallwaiting;
++ p->hidecallerid = p->permhidecallerid;
++ p->dialing = 0;
++ analog_update_conf(p);
++ analog_all_subchannels_hungup(p);
++ }
++
++ analog_stop_callwait(p);
++ ast->tech_pvt = NULL;
++
++ if (option_verbose > 2) {
++ ast_verbose(VERBOSE_PREFIX_3 "Hanging up on '%s'\n", ast->name);
++ }
++
++ return 0;
++}
++
++int analog_answer(struct analog_pvt *p, struct ast_channel *ast)
++{
++ int res = 0;
++ int index;
++ int oldstate = ast->_state;
++ ast_log(LOG_DEBUG, "%s %d\n", __FUNCTION__, p->channel);
++ ast_setstate(ast, AST_STATE_UP);
++ index = analog_get_index(ast, p, 1);
++ if (index < 0)
++ index = ANALOG_SUB_REAL;
++ switch (p->sig) {
++ case ANALOG_SIG_FXSLS:
++ case ANALOG_SIG_FXSGS:
++ case ANALOG_SIG_FXSKS:
++#if 0
++ p->ringt = 0;
++#endif
++ /* Fall through */
++ case ANALOG_SIG_EM:
++ case ANALOG_SIG_EM_E1:
++ case ANALOG_SIG_EMWINK:
++ case ANALOG_SIG_FEATD:
++ case ANALOG_SIG_FEATDMF:
++ case ANALOG_SIG_FEATDMF_TA:
++ case ANALOG_SIG_E911:
++ case ANALOG_SIG_FGC_CAMA:
++ case ANALOG_SIG_FGC_CAMAMF:
++ case ANALOG_SIG_FEATB:
++ case ANALOG_SIG_SF:
++ case ANALOG_SIG_SFWINK:
++ case ANALOG_SIG_SF_FEATD:
++ case ANALOG_SIG_SF_FEATDMF:
++ case ANALOG_SIG_SF_FEATB:
++ case ANALOG_SIG_FXOLS:
++ case ANALOG_SIG_FXOGS:
++ case ANALOG_SIG_FXOKS:
++ /* Pick up the line */
++ ast_debug(1, "Took %s off hook\n", ast->name);
++ if (p->hanguponpolarityswitch) {
++ gettimeofday(&p->polaritydelaytv, NULL);
++ }
++ res = analog_off_hook(p);
++ analog_play_tone(p, index, -1);
++ p->dialing = 0;
++ if ((index == ANALOG_SUB_REAL) && p->subs[ANALOG_SUB_THREEWAY].inthreeway) {
++ if (oldstate == AST_STATE_RINGING) {
++ ast_debug(1, "Finally swapping real and threeway\n");
++ analog_play_tone(p, ANALOG_SUB_THREEWAY, -1);
++ analog_swap_subs(p, ANALOG_SUB_THREEWAY, ANALOG_SUB_REAL);
++ p->owner = p->subs[ANALOG_SUB_REAL].owner;
++ }
++ }
++ if ((p->sig == ANALOG_SIG_FXSLS) || (p->sig == ANALOG_SIG_FXSKS) || (p->sig == ANALOG_SIG_FXSGS)) {
++ analog_set_echocanceller(p, 1);
++ analog_train_echocanceller(p);
++ }
++ break;
++ default:
++ ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
++ res = -1;
++ }
++ ast_setstate(ast, AST_STATE_UP);
++ return res;
++}
++
++static int analog_handles_digit(struct ast_frame *f)
++{
++ char subclass = toupper(f->subclass);
++
++ switch (subclass) {
++ case '1':
++ case '2':
++ case '3':
++ case '4':
++ case '5':
++ case '6':
++ case '7':
++ case '9':
++ case 'A':
++ case 'B':
++ case 'C':
++ case 'D':
++ case 'E':
++ case 'F':
++ return 1;
++ default:
++ return 0;
++ }
++}
++
++void analog_handle_dtmfup(struct analog_pvt *p, struct ast_channel *ast, enum analog_sub index, struct ast_frame **dest)
++{
++ struct ast_frame *f = *dest;
++
++ if (p->callwaitcas) {
++ if ((f->subclass == 'A') || (f->subclass == 'D')) {
++ ast_log(LOG_ERROR, "Got some DTMF, but it's for the CAS\n");
++ p->cid.cid_name = p->callwait_name;
++ p->cid.cid_num = p->callwait_num;
++ analog_send_callerid(p, 1, &p->cid);
++ }
++ if (analog_handles_digit(f))
++ p->callwaitcas = 0;
++ p->subs[index].f.frametype = AST_FRAME_NULL;
++ p->subs[index].f.subclass = 0;
++ *dest = &p->subs[index].f;
++ } else {
++ analog_cb_handle_dtmfup(p, ast, index, dest);
++ }
++}
++
++static int analog_my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
++{
++ char c;
++
++ *str = 0; /* start with empty output buffer */
++ for (;;)
++ {
++ /* Wait for the first digit (up to specified ms). */
++ c = ast_waitfordigit(chan, ms);
++ /* if timeout, hangup or error, return as such */
++ if (c < 1)
++ return c;
++ *str++ = c;
++ *str = 0;
++ if (strchr(term, c))
++ return 1;
++ }
++}
++
++static int analog_handle_notify_message(struct ast_channel *chan, struct analog_pvt *p, int cid_flags, int neon_mwievent)
++{
++ if (p->calls->handle_notify_message) {
++ p->calls->handle_notify_message(chan, p->chan_pvt, cid_flags, neon_mwievent);
++ return 0;
++ }
++ else
++ return -1;
++}
++
++static int analog_increase_ss_count(struct analog_pvt *p)
++{
++ if (p->calls->increase_ss_count) {
++ p->calls->increase_ss_count();
++ return 0;
++ } else
++ return -1;
++}
++
++static int analog_decrease_ss_count(struct analog_pvt *p)
++{
++ if (p->calls->decrease_ss_count) {
++ p->calls->decrease_ss_count();
++ return 0;
++ } else
++ return -1;
++}
++
++#define ANALOG_NEED_MFDETECT(p) (((p)->sig == ANALOG_SIG_FEATDMF) || ((p)->sig == ANALOG_SIG_FEATDMF_TA) || ((p)->sig == ANALOG_SIG_E911) || ((p)->sig == ANALOG_SIG_FGC_CAMA) || ((p)->sig == ANALOG_SIG_FGC_CAMAMF) || ((p)->sig == ANALOG_SIG_FEATB))
++
++/* Note by jpeeler: This function has a rather large section of code ifdefed
++ * away. I'd like to leave the code there until more testing is done and I
++ * know for sure that nothing got left out. The plan is at the latest for this
++ * comment and code below to be removed shortly after the merging of sig_pri.
++ */
++static void *__analog_ss_thread(void *data)
++{
++ struct analog_pvt *p = data;
++ struct ast_channel *chan = p->ss_astchan;
++ char exten[AST_MAX_EXTENSION] = "";
++ char exten2[AST_MAX_EXTENSION] = "";
++ char dtmfcid[300];
++ char dtmfbuf[300];
++ char namebuf[ANALOG_MAX_CID];
++ char numbuf[ANALOG_MAX_CID];
++ struct callerid_state *cs = NULL;
++ char *name = NULL, *number = NULL;
++ int flags;
++#if 0
++ unsigned char buf[256];
++ int distMatches;
++ int curRingData[3];
++ int receivedRingT;
++ int samples = 0;
++ int counter1;
++ int counter;
++ int i;
++#endif
++ int timeout;
++ int getforward = 0;
++ char *s1, *s2;
++ int len = 0;
++ int res;
++ int index;
++
++ analog_increase_ss_count(p);
++
++ ast_log(LOG_DEBUG, "%s %d\n", __FUNCTION__, p->channel);
++
++ /* in the bizarre case where the channel has become a zombie before we
++ even get started here, abort safely
++ */
++ if (!p) {
++ ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
++ ast_hangup(chan);
++ goto quit;
++ }
++
++ ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
++ index = analog_get_index(chan, p, 1);
++ if (index < 0) {
++ ast_log(LOG_WARNING, "Huh?\n");
++ ast_hangup(chan);
++ goto quit;
++ }
++ analog_dsp_reset_and_flush_digits(p);
++ switch (p->sig) {
++ case ANALOG_SIG_FEATD:
++ case ANALOG_SIG_FEATDMF:
++ case ANALOG_SIG_FEATDMF_TA:
++ case ANALOG_SIG_E911:
++ case ANALOG_SIG_FGC_CAMAMF:
++ case ANALOG_SIG_FEATB:
++ case ANALOG_SIG_EMWINK:
++ case ANALOG_SIG_SF_FEATD:
++ case ANALOG_SIG_SF_FEATDMF:
++ case ANALOG_SIG_SF_FEATB:
++ case ANALOG_SIG_SFWINK:
++ if (analog_wink(p, index))
++ goto quit;
++ /* Fall through */
++ case ANALOG_SIG_EM:
++ case ANALOG_SIG_EM_E1:
++ case ANALOG_SIG_SF:
++ case ANALOG_SIG_FGC_CAMA:
++ res = analog_play_tone(p, index, -1);
++
++ analog_dsp_reset_and_flush_digits(p);
++
++ if (ANALOG_NEED_MFDETECT(p)) {
++ analog_dsp_set_digitmode(p, ANALOG_DIGITMODE_MF);
++ } else
++ analog_dsp_set_digitmode(p, ANALOG_DIGITMODE_DTMF);
++
++ memset(dtmfbuf, 0, sizeof(dtmfbuf));
++ /* Wait for the first digit only if immediate=no */
++ if (!p->immediate)
++ /* Wait for the first digit (up to 5 seconds). */
++ res = ast_waitfordigit(chan, 5000);
++ else
++ res = 0;
++ if (res > 0) {
++ /* save first char */
++ dtmfbuf[0] = res;
++ switch (p->sig) {
++ case ANALOG_SIG_FEATD:
++ case ANALOG_SIG_SF_FEATD:
++ res = analog_my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
++ if (res > 0)
++ res = analog_my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
++ if (res < 1)
++ analog_dsp_reset_and_flush_digits(p);
++ break;
++ case ANALOG_SIG_FEATDMF_TA:
++ res = analog_my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
++ if (res < 1)
++ analog_dsp_reset_and_flush_digits(p);
++ if (analog_wink(p, index)) goto quit;
++ dtmfbuf[0] = 0;
++ /* Wait for the first digit (up to 5 seconds). */
++ res = ast_waitfordigit(chan, 5000);
++ if (res <= 0) break;
++ dtmfbuf[0] = res;
++ /* fall through intentionally */
++ case ANALOG_SIG_FEATDMF:
++ case ANALOG_SIG_E911:
++ case ANALOG_SIG_FGC_CAMAMF:
++ case ANALOG_SIG_SF_FEATDMF:
++ res = analog_my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
++ /* if international caca, do it again to get real ANO */
++ if ((p->sig == ANALOG_SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
++ {
++ if (analog_wink(p, index)) goto quit;
++ dtmfbuf[0] = 0;
++ /* Wait for the first digit (up to 5 seconds). */
++ res = ast_waitfordigit(chan, 5000);
++ if (res <= 0) break;
++ dtmfbuf[0] = res;
++ res = analog_my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
++ }
++ if (res > 0) {
++ /* if E911, take off hook */
++ if (p->sig == ANALOG_SIG_E911)
++ analog_off_hook(p);
++ res = analog_my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
++ }
++ if (res < 1)
++ analog_dsp_reset_and_flush_digits(p);
++ break;
++ case ANALOG_SIG_FEATB:
++ case ANALOG_SIG_SF_FEATB:
++ res = analog_my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
++ if (res < 1)
++ analog_dsp_reset_and_flush_digits(p);
++ break;
++ case ANALOG_SIG_EMWINK:
++ /* if we received a '*', we are actually receiving Feature Group D
++ dial syntax, so use that mode; otherwise, fall through to normal
++ mode
++ */
++ if (res == '*') {
++ res = analog_my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
++ if (res > 0)
++ res = analog_my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
++ if (res < 1)
++ analog_dsp_reset_and_flush_digits(p);
++ break;
++ }
++ default:
++ /* If we got the first digit, get the rest */
++ len = 1;
++ dtmfbuf[len] = '\0';
++ while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
++ if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
++ timeout = analog_matchdigittimeout;
++ } else {
++ timeout = analog_gendigittimeout;
++ }
++ res = ast_waitfordigit(chan, timeout);
++ if (res < 0) {
++ ast_debug(1, "waitfordigit returned < 0...\n");
++ ast_hangup(chan);
++ goto quit;
++ } else if (res) {
++ dtmfbuf[len++] = res;
++ dtmfbuf[len] = '\0';
++ } else {
++ break;
++ }
++ }
++ break;
++ }
++ }
++ if (res == -1) {
++ ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
++ ast_hangup(chan);
++ goto quit;
++ } else if (res < 0) {
++ ast_debug(1, "Got hung up before digits finished\n");
++ ast_hangup(chan);
++ goto quit;
++ }
++
++ if (p->sig == ANALOG_SIG_FGC_CAMA) {
++ char anibuf[100];
++
++ if (ast_safe_sleep(chan,1000) == -1) {
++ ast_hangup(chan);
++ goto quit;
++ }
++ analog_off_hook(p);
++ analog_dsp_set_digitmode(p, ANALOG_DIGITMODE_MF);
++ res = analog_my_getsigstr(chan, anibuf, "#", 10000);
++ if ((res > 0) && (strlen(anibuf) > 2)) {
++ if (anibuf[strlen(anibuf) - 1] == '#')
++ anibuf[strlen(anibuf) - 1] = 0;
++ ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
++ }
++ analog_dsp_set_digitmode(p, ANALOG_DIGITMODE_DTMF);
++ }
++
++ ast_copy_string(exten, dtmfbuf, sizeof(exten));
++ if (ast_strlen_zero(exten))
++ ast_copy_string(exten, "s", sizeof(exten));
++ if (p->sig == ANALOG_SIG_FEATD || p->sig == ANALOG_SIG_EMWINK) {
++ /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
++ if (exten[0] == '*') {
++ char *stringp=NULL;
++ ast_copy_string(exten2, exten, sizeof(exten2));
++ /* Parse out extension and callerid */
++ stringp=exten2 +1;
++ s1 = strsep(&stringp, "*");
++ s2 = strsep(&stringp, "*");
++ if (s2) {
++ if (!ast_strlen_zero(p->cid_num))
++ ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
++ else
++ ast_set_callerid(chan, s1, NULL, s1);
++ ast_copy_string(exten, s2, sizeof(exten));
++ } else
++ ast_copy_string(exten, s1, sizeof(exten));
++ } else if (p->sig == ANALOG_SIG_FEATD)
++ ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
++ }
++ if ((p->sig == ANALOG_SIG_FEATDMF) || (p->sig == ANALOG_SIG_FEATDMF_TA)) {
++ if (exten[0] == '*') {
++ char *stringp=NULL;
++ ast_copy_string(exten2, exten, sizeof(exten2));
++ /* Parse out extension and callerid */
++ stringp=exten2 +1;
++ s1 = strsep(&stringp, "#");
++ s2 = strsep(&stringp, "#");
++ if (s2) {
++ if (!ast_strlen_zero(p->cid_num))
++ ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
++ else
++ if (*(s1 + 2))
++ ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
++ ast_copy_string(exten, s2 + 1, sizeof(exten));
++ } else
++ ast_copy_string(exten, s1 + 2, sizeof(exten));
++ } else
++ ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
++ }
++ if ((p->sig == ANALOG_SIG_E911) || (p->sig == ANALOG_SIG_FGC_CAMAMF)) {
++ if (exten[0] == '*') {
++ char *stringp=NULL;
++ ast_copy_string(exten2, exten, sizeof(exten2));
++ /* Parse out extension and callerid */
++ stringp=exten2 +1;
++ s1 = strsep(&stringp, "#");
++ s2 = strsep(&stringp, "#");
++ if (s2 && (*(s2 + 1) == '0')) {
++ if (*(s2 + 2))
++ ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
++ }
++ if (s1) ast_copy_string(exten, s1, sizeof(exten));
++ else ast_copy_string(exten, "911", sizeof(exten));
++ } else
++ ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
++ }
++ if (p->sig == ANALOG_SIG_FEATB) {
++ if (exten[0] == '*') {
++ char *stringp=NULL;
++ ast_copy_string(exten2, exten, sizeof(exten2));
++ /* Parse out extension and callerid */
++ stringp=exten2 +1;
++ s1 = strsep(&stringp, "#");
++ ast_copy_string(exten, exten2 + 1, sizeof(exten));
++ } else
++ ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
++ }
++ if ((p->sig == ANALOG_SIG_FEATDMF) || (p->sig == ANALOG_SIG_FEATDMF_TA)) {
++ analog_wink(p, index);
++ /* some switches require a minimum guard time between
++ the last FGD wink and something that answers
++ immediately. This ensures it */
++ if (ast_safe_sleep(chan,100)) goto quit;
++ }
++ analog_set_echocanceller(p, 1);
++
++ analog_dsp_set_digitmode(p, ANALOG_DIGITMODE_DTMF);
++
++ if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
++ ast_copy_string(chan->exten, exten, sizeof(chan->exten));
++ analog_dsp_reset_and_flush_digits(p);
++ res = ast_pbx_run(chan);
++ if (res) {
++ ast_log(LOG_WARNING, "PBX exited non-zero\n");
++ res = analog_play_tone(p, index, ANALOG_TONE_CONGESTION);
++ }
++ goto quit;
++ } else {
++ if (option_verbose > 2)
++ ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
++ sleep(2);
++ res = analog_play_tone(p, index, ANALOG_TONE_INFO);
++ if (res < 0)
++ ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
++ else
++ sleep(1);
++ res = ast_streamfile(chan, "ss-noservice", chan->language);
++ if (res >= 0)
++ ast_waitstream(chan, "");
++ res = analog_play_tone(p, index, ANALOG_TONE_CONGESTION);
++ ast_hangup(chan);
++ goto quit;
++ }
++ break;
++ case ANALOG_SIG_FXOLS:
++ case ANALOG_SIG_FXOGS:
++ case ANALOG_SIG_FXOKS:
++ /* Read the first digit */
++ timeout = analog_firstdigittimeout;
++ /* If starting a threeway call, never timeout on the first digit so someone
++ can use flash-hook as a "hold" feature */
++ if (p->subs[ANALOG_SUB_THREEWAY].owner)
++ timeout = 999999;
++ while (len < AST_MAX_EXTENSION-1) {
++ /* Read digit unless it's supposed to be immediate, in which case the
++ only answer is 's' */
++ if (p->immediate)
++ res = 's';
++ else
++ res = ast_waitfordigit(chan, timeout);
++ timeout = 0;
++ if (res < 0) {
++ ast_debug(1, "waitfordigit returned < 0...\n");
++ res = analog_play_tone(p, index, -1);
++ ast_hangup(chan);
++ goto quit;
++ } else if (res) {
++ exten[len++]=res;
++ exten[len] = '\0';
++ }
++ if (!ast_ignore_pattern(chan->context, exten))
++ analog_play_tone(p, index, -1);
++ else
++ analog_play_tone(p, index, ANALOG_TONE_DIALTONE);
++ if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
++ if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
++ if (getforward) {
++ /* Record this as the forwarding extension */
++ ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
++ if (option_verbose > 2)
++ ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
++ res = analog_play_tone(p, index, ANALOG_TONE_DIALRECALL);
++ if (res)
++ break;
++ usleep(500000);
++ res = analog_play_tone(p, index, -1);
++ sleep(1);
++ memset(exten, 0, sizeof(exten));
++ res = analog_play_tone(p, index, ANALOG_TONE_DIALTONE);
++ len = 0;
++ getforward = 0;
++ } else {
++ res = analog_play_tone(p, index, -1);
++ ast_copy_string(chan->exten, exten, sizeof(chan->exten));
++ if (!ast_strlen_zero(p->cid_num)) {
++ if (!p->hidecallerid)
++ ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
++ else
++ ast_set_callerid(chan, NULL, NULL, p->cid_num);
++ }
++ if (!ast_strlen_zero(p->cid_name)) {
++ if (!p->hidecallerid)
++ ast_set_callerid(chan, NULL, p->cid_name, NULL);
++ }
++ ast_setstate(chan, AST_STATE_RING);
++ analog_set_echocanceller(p, 1);
++ res = ast_pbx_run(chan);
++ if (res) {
++ ast_log(LOG_WARNING, "PBX exited non-zero\n");
++ res = analog_play_tone(p, index, ANALOG_TONE_CONGESTION);
++ }
++ goto quit;
++ }
++ } else {
++ /* It's a match, but they just typed a digit, and there is an ambiguous match,
++ so just set the timeout to analog_matchdigittimeout and wait some more */
++ timeout = analog_matchdigittimeout;
++ }
++ } else if (res == 0) {
++ ast_debug(1, "not enough digits (and no ambiguous match)...\n");
++ res = analog_play_tone(p, index, ANALOG_TONE_CONGESTION);
++ analog_wait_event(p);
++ ast_hangup(chan);
++ goto quit;
++ } else if (p->callwaiting && !strcmp(exten, "*70")) {
++ if (option_verbose > 2)
++ ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
++ /* Disable call waiting if enabled */
++ p->callwaiting = 0;
++ res = analog_play_tone(p, index, ANALOG_TONE_DIALRECALL);
++ if (res) {
++ ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
++ chan->name, strerror(errno));
++ }
++ len = 0;
++ memset(exten, 0, sizeof(exten));
++ timeout = analog_firstdigittimeout;
++
++ } else if (!strcmp(exten,ast_pickup_ext())) {
++ /* Scan all channels and see if there are any
++ * ringing channels that have call groups
++ * that equal this channels pickup group
++ */
++ if (index == ANALOG_SUB_REAL) {
++ /* Switch us from Third call to Call Wait */
++ if (p->subs[ANALOG_SUB_THREEWAY].owner) {
++ /* If you make a threeway call and the *8# a call, it should actually
++ look like a callwait */
++ analog_alloc_sub(p, ANALOG_SUB_CALLWAIT);
++ analog_swap_subs(p, ANALOG_SUB_CALLWAIT, ANALOG_SUB_THREEWAY);
++ analog_unalloc_sub(p, ANALOG_SUB_THREEWAY);
++ }
++ analog_set_echocanceller(p, 1);
++ if (ast_pickup_call(chan)) {
++ ast_debug(1, "No call pickup possible...\n");
++ res = analog_play_tone(p, index, ANALOG_TONE_CONGESTION);
++ analog_wait_event(p);
++ }
++ ast_hangup(chan);
++ goto quit;
++ } else {
++ ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
++ ast_hangup(chan);
++ goto quit;
++ }
++ } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
++ if (option_verbose > 2)
++ ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
++ /* Disable Caller*ID if enabled */
++ p->hidecallerid = 1;
++ if (chan->cid.cid_num)
++ free(chan->cid.cid_num);
++ chan->cid.cid_num = NULL;
++ if (chan->cid.cid_name)
++ free(chan->cid.cid_name);
++ chan->cid.cid_name = NULL;
++ res = analog_play_tone(p, index, ANALOG_TONE_DIALRECALL);
++ if (res) {
++ ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
++ chan->name, strerror(errno));
++ }
++ len = 0;
++ memset(exten, 0, sizeof(exten));
++ timeout = analog_firstdigittimeout;
++ } else if (p->callreturn && !strcmp(exten, "*69")) {
++ res = 0;
++ if (!ast_strlen_zero(p->lastcid_num)) {
++ res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
++ }
++ if (!res)
++ res = analog_play_tone(p, index, ANALOG_TONE_DIALRECALL);
++ break;
++ } else if (!strcmp(exten, "*78")) {
++ /* Do not disturb */
++ if (option_verbose > 2)
++ ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel);
++#if 0
++ manager_event(EVENT_FLAG_SYSTEM, "DNDState",
++ "Channel: %s/%d\r\n"
++ "Status: enabled\r\n", dahdi_chan_name, p->channel);
++#endif
++ res = analog_play_tone(p, index, ANALOG_TONE_DIALRECALL);
++ p->dnd = 1;
++ getforward = 0;
++ memset(exten, 0, sizeof(exten));
++ len = 0;
++ } else if (!strcmp(exten, "*79")) {
++ /* Do not disturb */
++ if (option_verbose > 2)
++ ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel);
++#if 0
++ manager_event(EVENT_FLAG_SYSTEM, "DNDState",
++ "Channel: %s/%d\r\n"
++ "Status: disabled\r\n", dahdi_chan_name, p->channel);
++#endif
++ res = analog_play_tone(p, index, ANALOG_TONE_DIALRECALL);
++ p->dnd = 0;
++ getforward = 0;
++ memset(exten, 0, sizeof(exten));
++ len = 0;
++ } else if (p->cancallforward && !strcmp(exten, "*72")) {
++ res = analog_play_tone(p, index, ANALOG_TONE_DIALRECALL);
++ getforward = 1;
++ memset(exten, 0, sizeof(exten));
++ len = 0;
++ } else if (p->cancallforward && !strcmp(exten, "*73")) {
++ if (option_verbose > 2)
++ ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel);
++ res = analog_play_tone(p, index, ANALOG_TONE_DIALRECALL);
++ memset(p->call_forward, 0, sizeof(p->call_forward));
++ getforward = 0;
++ memset(exten, 0, sizeof(exten));
++ len = 0;
++ } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
++ p->subs[ANALOG_SUB_THREEWAY].owner &&
++ ast_bridged_channel(p->subs[ANALOG_SUB_THREEWAY].owner)) {
++ /* This is a three way call, the main call being a real channel,
++ and we're parking the first call. */
++ ast_masq_park_call(ast_bridged_channel(p->subs[ANALOG_SUB_THREEWAY].owner), chan, 0, NULL);
++ if (option_verbose > 2)
++ ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
++ break;
++ } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
++ if (option_verbose > 2)
++ ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num);
++ res = ast_db_put("blacklist", p->lastcid_num, "1");
++ if (!res) {
++ res = analog_play_tone(p, index, ANALOG_TONE_DIALRECALL);
++ memset(exten, 0, sizeof(exten));
++ len = 0;
++ }
++ } else if (p->hidecallerid && !strcmp(exten, "*82")) {
++ if (option_verbose > 2)
++ ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
++ /* Enable Caller*ID if enabled */
++ p->hidecallerid = 0;
++ if (chan->cid.cid_num)
++ free(chan->cid.cid_num);
++ chan->cid.cid_num = NULL;
++ if (chan->cid.cid_name)
++ free(chan->cid.cid_name);
++ chan->cid.cid_name = NULL;
++ ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
++ res = analog_play_tone(p, index, ANALOG_TONE_DIALRECALL);
++ if (res) {
++ ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
++ chan->name, strerror(errno));
++ }
++ len = 0;
++ memset(exten, 0, sizeof(exten));
++ timeout = analog_firstdigittimeout;
++ } else if (!strcmp(exten, "*0")) {
++#ifdef XXX
++ struct ast_channel *nbridge = p->subs[ANALOG_SUB_THREEWAY].owner;
++ struct dahdi_pvt *pbridge = NULL;
++ /* set up the private struct of the bridged one, if any */
++ if (nbridge && ast_bridged_channel(nbridge))
++ pbridge = ast_bridged_channel(nbridge)->tech_pvt;
++ if (nbridge && pbridge &&
++ (nbridge->tech == chan_tech) &&
++ (ast_bridged_channel(nbridge)->tech == chan_tech) &&
++ ISTRUNK(pbridge)) {
++ int func = DAHDI_FLASH;
++ /* Clear out the dial buffer */
++ p->dop.dialstr[0] = '\0';
++ /* flash hookswitch */
++ if ((ioctl(pbridge->subs[ANALOG_SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
++ ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
++ nbridge->name, strerror(errno));
++ }
++ analog_swap_subs(p, ANALOG_SUB_REAL, ANALOG_SUB_THREEWAY);
++ analog_unalloc_sub(p, ANALOG_SUB_THREEWAY);
++ p->owner = p->subs[ANALOG_SUB_REAL].owner;
++ if (ast_bridged_channel(p->subs[ANALOG_SUB_REAL].owner))
++ ast_queue_control(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_UNHOLD);
++ ast_hangup(chan);
++ goto quit;
++ } else {
++ analog_play_tone(p, index, ANALOG_TONE_CONGESTION);
++ analog_wait_event(p);
++ analog_play_tone(p, index, -1);
++ analog_swap_subs(p, ANALOG_SUB_REAL, ANALOG_SUB_THREEWAY);
++ analog_unalloc_sub(p, ANALOG_SUB_THREEWAY);
++ p->owner = p->subs[ANALOG_SUB_REAL].owner;
++ ast_hangup(chan);
++ goto quit;
++ }
++#endif
++ } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
++ ((exten[0] != '*') || (strlen(exten) > 2))) {
++ ast_debug(1, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
++ break;
++ }
++ if (!timeout)
++ timeout = analog_gendigittimeout;
++ if (len && !ast_ignore_pattern(chan->context, exten))
++ analog_play_tone(p, index, -1);
++ }
++ break;
++ case ANALOG_SIG_FXSLS:
++ case ANALOG_SIG_FXSGS:
++ case ANALOG_SIG_FXSKS:
++
++ /* If we want caller id, we're in a prering state due to a polarity reversal
++ * and we're set to use a polarity reversal to trigger the start of caller id,
++ * grab the caller id and wait for ringing to start... */
++ if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == ANALOG_CID_START_POLARITY || p->cid_start == ANALOG_CID_START_POLARITY_IN))) {
++ /* If set to use DTMF CID signalling, listen for DTMF */
++ if (p->cid_signalling == CID_SIG_DTMF) {
++ int i = 0;
++ cs = NULL;
++ ast_debug(1, "Receiving DTMF cid on "
++ "channel %s\n", chan->name);
++#if 0
++ dahdi_setlinear(p->subs[index].dfd, 0);
++#endif
++ res = 2000;
++ for (;;) {
++ struct ast_frame *f;
++ res = ast_waitfor(chan, res);
++ if (res <= 0) {
++ ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
++ "Exiting simple switch\n");
++ ast_hangup(chan);
++ goto quit;
++ }
++ f = ast_read(chan);
++ if (!f)
++ break;
++ if (f->frametype == AST_FRAME_DTMF) {
++ dtmfbuf[i++] = f->subclass;
++ ast_debug(1, "CID got digit '%c'\n", f->subclass);
++ res = 2000;
++ }
++ ast_frfree(f);
++ if (chan->_state == AST_STATE_RING ||
++ chan->_state == AST_STATE_RINGING)
++ break; /* Got ring */
++ }
++ dtmfbuf[i] = '\0';
++#if 0
++ dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
++#endif
++ /* Got cid and ring. */
++ ast_debug(1, "CID got string '%s'\n", dtmfbuf);
++ callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
++ ast_debug(1, "CID is '%s', flags %d\n",
++ dtmfcid, flags);
++ /* If first byte is NULL, we have no cid */
++ if (!ast_strlen_zero(dtmfcid))
++ number = dtmfcid;
++ else
++ number = NULL;
++#if 0
++ /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
++ } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
++ cs = callerid_new(p->cid_signalling);
++ if (cs) {
++ samples = 0;
++#if 1
++ bump_gains(p);
++#endif
++ /* Take out of linear mode for Caller*ID processing */
++ dahdi_setlinear(p->subs[index].dfd, 0);
++
++ /* First we wait and listen for the Caller*ID */
++ for (;;) {
++ i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
++ if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
++ ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
++ callerid_free(cs);
++ ast_hangup(chan);
++ goto quit;
++ }
++ if (i & DAHDI_IOMUX_SIGEVENT) {
++ res = dahdi_get_event(p->subs[index].dfd);
++ ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
++
++ if (p->cid_signalling == CID_SIG_V23_JP) {
++#ifdef DAHDI_EVENT_RINGBEGIN
++ if (res == ANALOG_EVENT_RINGBEGIN) {
++ res = analog_off_hook(p);
++ usleep(1);
++ }
++#endif
++ } else {
++ res = 0;
++ break;
++ }
++ } else if (i & DAHDI_IOMUX_READ) {
++ res = read(p->subs[index].dfd, buf, sizeof(buf));
++ if (res < 0) {
++ if (errno != ELAST) {
++ ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
++ callerid_free(cs);
++ ast_hangup(chan);
++ goto quit;
++ }
++ break;
++ }
++ samples += res;
++
++ if (p->cid_signalling == CID_SIG_V23_JP) {
++ res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
++ } else {
++ res = callerid_feed(cs, buf, res, AST_LAW(p));
++ }
++
++ if (res < 0) {
++ ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
++ break;
++ } else if (res)
++ break;
++ else if (samples > (8000 * 10))
++ break;
++ }
++ }
++ if (res == 1) {
++ callerid_get(cs, &name, &number, &flags);
++ ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
++ }
++
++ if (p->cid_signalling == CID_SIG_V23_JP) {
++ res = analog_on_hook(p);
++ usleep(1);
++ res = 4000;
++ } else {
++
++ /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
++ res = 2000;
++ }
++
++ for (;;) {
++ struct ast_frame *f;
++ res = ast_waitfor(chan, res);
++ if (res <= 0) {
++ ast_log(LOG_WARNING, "CID timed out waiting for ring. "
++ "Exiting simple switch\n");
++ ast_hangup(chan);
++ goto quit;
++ }
++ if (!(f = ast_read(chan))) {
++ ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
++ ast_hangup(chan);
++ goto quit;
++ }
++ ast_frfree(f);
++ if (chan->_state == AST_STATE_RING ||
++ chan->_state == AST_STATE_RINGING)
++ break; /* Got ring */
++ }
++
++ /* Restore linear mode (if appropriate) for Caller*ID processing */
++ dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
++#if 1
++ restore_gains(p);
++#endif
++ } else
++ ast_log(LOG_WARNING, "Unable to get caller ID space\n");
++#endif
++ } else {
++ ast_log(LOG_WARNING, "Channel %s in prering "
++ "state, but I have nothing to do. "
++ "Terminating simple switch, should be "
++ "restarted by the actual ring.\n",
++ chan->name);
++ ast_hangup(chan);
++ goto quit;
++ }
++ } else if (p->use_callerid && p->cid_start == ANALOG_CID_START_RING) {
++ int timeout = 10000; /* Ten seconds */
++ struct timeval start = ast_tvnow();
++ enum analog_event ev;
++
++ namebuf[0] = 0;
++ numbuf[0] = 0;
++
++ if (!analog_start_cid_detect(p, p->cid_signalling)) {
++ while (1) {
++ res = analog_get_callerid(p, namebuf, numbuf, &ev, timeout - ast_tvdiff_ms(ast_tvnow(), start));
++
++ if (res == 0) {
++ break;
++ }
++
++ if (res == 1) {
++ if (ev == ANALOG_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
++ ast_debug(1, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
++ p->polarity = POLARITY_IDLE;
++ ast_hangup(chan);
++ goto quit;
++ } else if (ev != ANALOG_EVENT_NONE) {
++ break;
++ }
++ }
++
++ if (ast_tvdiff_ms(ast_tvnow(), start) > timeout)
++ break;
++
++ }
++ name = namebuf;
++ number = numbuf;
++
++ analog_stop_cid_detect(p);
++
++#if 0
++ /* XXX */
++ if (strcmp(p->context,p->defcontext) != 0) {
++ ast_copy_string(p->context, p->defcontext, sizeof(p->context));
++ ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
++ }
++
++ analog_get_callerid(p, name, number);
++ /* FSK Bell202 callerID */
++ cs = callerid_new(p->cid_signalling);
++ if (cs) {
++#if 1
++ bump_gains(p);
++#endif
++ samples = 0;
++ len = 0;
++ distMatches = 0;
++ /* Clear the current ring data array so we dont have old data in it. */
++ for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
++ curRingData[receivedRingT] = 0;
++ receivedRingT = 0;
++ counter = 0;
++ counter1 = 0;
++ /* Check to see if context is what it should be, if not set to be. */
++
++ /* Take out of linear mode for Caller*ID processing */
++ dahdi_setlinear(p->subs[index].dfd, 0);
++ for (;;) {
++ i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
++ if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
++ ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
++ callerid_free(cs);
++ ast_hangup(chan);
++ goto quit;
++ }
++ if (i & DAHDI_IOMUX_SIGEVENT) {
++ res = dahdi_get_event(p->subs[index].dfd);
++ ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
++ /* If we get a PR event, they hung up while processing calerid */
++ if ( res == ANALOG_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
++ ast_debug(1, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
++ p->polarity = POLARITY_IDLE;
++ callerid_free(cs);
++ ast_hangup(chan);
++ goto quit;
++ }
++ res = 0;
++ /* Let us detect callerid when the telco uses distinctive ring */
++
++ curRingData[receivedRingT] = p->ringt;
++
++ if (p->ringt < p->ringt_base/2)
++ break;
++ /* Increment the ringT counter so we can match it against
++ values in chan_dahdi.conf for distinctive ring */
++ if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
++ break;
++ } else if (i & DAHDI_IOMUX_READ) {
++ res = read(p->subs[index].dfd, buf, sizeof(buf));
++ if (res < 0) {
++ if (errno != ELAST) {
++ ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
++ callerid_free(cs);
++ ast_hangup(chan);
++ goto quit;
++ }
++ break;
++ }
++ if (p->ringt)
++ p->ringt--;
++ if (p->ringt == 1) {
++ res = -1;
++ break;
++ }
++ samples += res;
++ res = callerid_feed(cs, buf, res, AST_LAW(p));
++ if (res < 0) {
++ ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
++ break;
++ } else if (res)
++ break;
++ else if (samples > (8000 * 10))
++ break;
++ }
++ }
++ if (res == 1) {
++ callerid_get(cs, &name, &number, &flags);
++ ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
++ }
++ /* Restore linear mode (if appropriate) for Caller*ID processing */
++ dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
++#if 1
++ restore_gains(p);
++#endif
++ if (res < 0) {
++ ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
++ }
++ } else
++ ast_log(LOG_WARNING, "Unable to get caller ID space\n");
++#endif
++ } else
++ ast_log(LOG_WARNING, "Unable to get caller ID space\n");
++ }
++ else
++ cs = NULL;
++
++ if (number)
++ ast_shrink_phone_number(number);
++ ast_set_callerid(chan, number, name, number);
++
++ if (cs)
++ callerid_free(cs);
++
++ analog_handle_notify_message(chan, p, flags, -1);
++
++ ast_setstate(chan, AST_STATE_RING);
++ chan->rings = 1;
++#if 0
++ p->ringt = p->ringt_base;
++#endif
++ res = ast_pbx_run(chan);
++ if (res) {
++ ast_hangup(chan);
++ ast_log(LOG_WARNING, "PBX exited non-zero\n");
++ }
++ goto quit;
++ default:
++ ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", analog_sigtype_to_str(p->sig), p->channel);
++ res = analog_play_tone(p, index, ANALOG_TONE_CONGESTION);
++ if (res < 0)
++ ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
++ }
++ res = analog_play_tone(p, index, ANALOG_TONE_CONGESTION);
++ if (res < 0)
++ ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
++ ast_hangup(chan);
++quit:
++ analog_decrease_ss_count(p);
++ return NULL;
++}
++
++int analog_ss_thread_start(struct analog_pvt *p, struct ast_channel *chan)
++{
++ pthread_t threadid;
++ return ast_pthread_create_detached(&threadid, NULL, __analog_ss_thread, chan);
++}
++
++static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_channel *ast)
++{
++ int res, x;
++ int mysig;
++ enum analog_sub index;
++ char *c;
++ pthread_t threadid;
++ pthread_attr_t attr;
++ struct ast_channel *chan;
++ struct ast_frame *f;
++ ast_log(LOG_DEBUG, "%s %d\n", __FUNCTION__, p->channel);
++
++ index = analog_get_index(ast, p, 0);
++ mysig = p->sig;
++ if (p->outsigmod > -1)
++ mysig = p->outsigmod;
++ p->subs[index].f.frametype = AST_FRAME_NULL;
++ p->subs[index].f.subclass = 0;
++ p->subs[index].f.datalen = 0;
++ p->subs[index].f.samples = 0;
++ p->subs[index].f.mallocd = 0;
++ p->subs[index].f.offset = 0;
++ p->subs[index].f.src = "dahdi_handle_event";
++ p->subs[index].f.data.ptr = NULL;
++ f = &p->subs[index].f;
++
++ if (index < 0)
++ return &p->subs[index].f;
++
++ if (index != ANALOG_SUB_REAL) {
++ ast_log(LOG_ERROR, "We got an event on a non real sub. Fix it!\n");
++ }
++
++ res = analog_get_event(p);
++
++ ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", analog_event2str(res), res, p->channel, index);
++
++ switch (res) {
++#ifdef ANALOG_EVENT_EC_DISABLED
++ case ANALOG_EVENT_EC_DISABLED:
++ if (option_verbose > 2)
++ ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel);
++ p->echocanon = 0;
++ break;
++#endif
++ case ANALOG_EVENT_PULSE_START:
++ /* Stop tone if there's a pulse start and the PBX isn't started */
++ if (!ast->pbx)
++ analog_play_tone(p, ANALOG_SUB_REAL, -1);
++ break;
++ case ANALOG_EVENT_DIALCOMPLETE:
++ if (p->inalarm) break;
++ x = analog_is_dialing(p, index);
++ if (!x) { /* if not still dialing in driver */
++ analog_set_echocanceller(p, 1);
++ if (p->echobreak) {
++ analog_train_echocanceller(p);
++ ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
++ p->dop.op = ANALOG_DIAL_OP_REPLACE;
++ analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop);
++ p->echobreak = 0;
++ } else {
++ p->dialing = 0;
++ if ((mysig == ANALOG_SIG_E911) || (mysig == ANALOG_SIG_FGC_CAMA) || (mysig == ANALOG_SIG_FGC_CAMAMF)) {
++ /* if thru with dialing after offhook */
++ if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
++ ast_setstate(ast, AST_STATE_UP);
++ p->subs[index].f.frametype = AST_FRAME_CONTROL;
++ p->subs[index].f.subclass = AST_CONTROL_ANSWER;
++ break;
++ } else { /* if to state wait for offhook to dial rest */
++ /* we now wait for off hook */
++ ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
++ }
++ }
++ if (ast->_state == AST_STATE_DIALING) {
++ if ((!p->dialednone && ((mysig == ANALOG_SIG_EM) || (mysig == ANALOG_SIG_EM_E1) || (mysig == ANALOG_SIG_EMWINK) || (mysig == ANALOG_SIG_FEATD) || (mysig == ANALOG_SIG_FEATDMF_TA) || (mysig == ANALOG_SIG_FEATDMF) || (mysig == ANALOG_SIG_E911) || (mysig == ANALOG_SIG_FGC_CAMA) || (mysig == ANALOG_SIG_FGC_CAMAMF) || (mysig == ANALOG_SIG_FEATB) || (mysig == ANALOG_SIG_SF) || (mysig == ANALOG_SIG_SFWINK) || (mysig == ANALOG_SIG_SF_FEATD) || (mysig == ANALOG_SIG_SF_FEATDMF) || (mysig == ANALOG_SIG_SF_FEATB)))) {
++ ast_setstate(ast, AST_STATE_RINGING);
++ } else if (!p->answeronpolarityswitch) {
++ ast_setstate(ast, AST_STATE_UP);
++ p->subs[index].f.frametype = AST_FRAME_CONTROL;
++ p->subs[index].f.subclass = AST_CONTROL_ANSWER;
++ /* If aops=0 and hops=1, this is necessary */
++ p->polarity = POLARITY_REV;
++ } else {
++ /* Start clean, so we can catch the change to REV polarity when party answers */
++ p->polarity = POLARITY_IDLE;
++ }
++ }
++ }
++ }
++ break;
++ case ANALOG_EVENT_ALARM:
++ p->inalarm = 1;
++#if 0
++ res = get_alarms(p);
++ handle_alarms(p, res);
++#endif
++ case ANALOG_EVENT_ONHOOK:
++ switch (p->sig) {
++ case ANALOG_SIG_FXOLS:
++ case ANALOG_SIG_FXOGS:
++ case ANALOG_SIG_FXOKS:
++ /* Check for some special conditions regarding call waiting */
++ if (index == ANALOG_SUB_REAL) {
++ /* The normal line was hung up */
++ if (p->subs[ANALOG_SUB_CALLWAIT].owner) {
++ /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
++ analog_swap_subs(p, ANALOG_SUB_CALLWAIT, ANALOG_SUB_REAL);
++ if (option_verbose > 2)
++ ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel);
++ analog_unalloc_sub(p, ANALOG_SUB_CALLWAIT);
++ analog_stop_callwait(p);
++ p->owner = NULL;
++ /* Don't start streaming audio yet if the incoming call isn't up yet */
++ if (p->subs[ANALOG_SUB_REAL].owner->_state != AST_STATE_UP)
++ p->dialing = 1;
++ analog_ring(p);
++ } else if (p->subs[ANALOG_SUB_THREEWAY].owner) {
++ unsigned int mssinceflash;
++ /* Here we have to retain the lock on both the main channel, the 3-way channel, and
++ the private structure -- not especially easy or clean */
++ while (p->subs[ANALOG_SUB_THREEWAY].owner && ast_channel_trylock(p->subs[ANALOG_SUB_THREEWAY].owner)) {
++ /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
++ analog_unlock_private(p);
++ CHANNEL_DEADLOCK_AVOIDANCE(ast);
++ /* We can grab ast and p in that order, without worry. We should make sure
++ nothing seriously bad has happened though like some sort of bizarre double
++ masquerade! */
++ analog_lock_private(p);
++ if (p->owner != ast) {
++ ast_log(LOG_WARNING, "This isn't good...\n");
++ return NULL;
++ }
++ }
++ if (!p->subs[ANALOG_SUB_THREEWAY].owner) {
++ ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
++ return NULL;
++ }
++ mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
++ ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
++ if (mssinceflash < MIN_MS_SINCE_FLASH) {
++ /* It hasn't been long enough since the last flashook. This is probably a bounce on
++ hanging up. Hangup both channels now */
++ if (p->subs[ANALOG_SUB_THREEWAY].owner)
++ ast_queue_hangup(p->subs[ANALOG_SUB_THREEWAY].owner);
++ ast_softhangup_nolock(p->subs[ANALOG_SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
++ ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
++ ast_channel_unlock(p->subs[ANALOG_SUB_THREEWAY].owner);
++ } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
++ if (p->transfer) {
++ /* In any case this isn't a threeway call anymore */
++ p->subs[ANALOG_SUB_REAL].inthreeway = 0;
++ p->subs[ANALOG_SUB_THREEWAY].inthreeway = 0;
++ /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
++ if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
++ ast_channel_unlock(p->subs[ANALOG_SUB_THREEWAY].owner);
++ /* Swap subs and dis-own channel */
++ analog_swap_subs(p, ANALOG_SUB_THREEWAY, ANALOG_SUB_REAL);
++ p->owner = NULL;
++ /* Ring the phone */
++ analog_ring(p);
++ } else {
++ if ((res = analog_attempt_transfer(p)) < 0) {
++ ast_softhangup_nolock(p->subs[ANALOG_SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
++ if (p->subs[ANALOG_SUB_THREEWAY].owner)
++ ast_channel_unlock(p->subs[ANALOG_SUB_THREEWAY].owner);
++ } else if (res) {
++ /* Don't actually hang up at this point */
++ if (p->subs[ANALOG_SUB_THREEWAY].owner)
++ ast_channel_unlock(&p->subs[ANALOG_SUB_THREEWAY].owner);
++ break;
++ }
++ }
++ } else {
++ ast_softhangup_nolock(p->subs[ANALOG_SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
++ if (p->subs[ANALOG_SUB_THREEWAY].owner)
++ ast_channel_unlock(p->subs[ANALOG_SUB_THREEWAY].owner);
++ }
++ } else {
++ ast_channel_unlock(p->subs[ANALOG_SUB_THREEWAY].owner);
++ /* Swap subs and dis-own channel */
++ analog_swap_subs(p, ANALOG_SUB_THREEWAY, ANALOG_SUB_REAL);
++ p->owner = NULL;
++ /* Ring the phone */
++ analog_ring(p);
++ }
++ }
++ } else {
++ ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index);
++ }
++ /* Fall through */
++ default:
++ analog_set_echocanceller(p, 0);
++ return NULL;
++ }
++ break;
++ case ANALOG_EVENT_RINGOFFHOOK:
++ if (p->inalarm) break;
++ /* for E911, its supposed to wait for offhook then dial
++ the second half of the dial string */
++ if (((mysig == ANALOG_SIG_E911) || (mysig == ANALOG_SIG_FGC_CAMA) || (mysig == ANALOG_SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
++ c = strchr(p->dialdest, '/');
++ if (c)
++ c++;
++ else
++ c = p->dialdest;
++ if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
++ else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
++ if (strlen(p->dop.dialstr) > 4) {
++ memset(p->echorest, 'w', sizeof(p->echorest) - 1);
++ strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
++ p->echorest[sizeof(p->echorest) - 1] = '\0';
++ p->echobreak = 1;
++ p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
++ } else
++ p->echobreak = 0;
++ if (analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop)) {
++ int saveerr = errno;
++ analog_on_hook(p);
++ ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
++ return NULL;
++ }
++ p->dialing = 1;
++ return &p->subs[index].f;
++ }
++ switch (p->sig) {
++ case ANALOG_SIG_FXOLS:
++ case ANALOG_SIG_FXOGS:
++ case ANALOG_SIG_FXOKS:
++ switch (ast->_state) {
++ case AST_STATE_RINGING:
++ analog_set_echocanceller(p, 1);
++ analog_train_echocanceller(p);
++ p->subs[index].f.frametype = AST_FRAME_CONTROL;
++ p->subs[index].f.subclass = AST_CONTROL_ANSWER;
++ /* Make sure it stops ringing */
++ analog_off_hook(p);
++ ast_debug(1, "channel %d answered\n", p->channel);
++ p->dialing = 0;
++ p->callwaitcas = 0;
++ if (!ast_strlen_zero(p->dop.dialstr)) {
++ /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
++ res = analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop);
++ if (res < 0) {
++ ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
++ p->dop.dialstr[0] = '\0';
++ return NULL;
++ } else {
++ ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
++ p->subs[index].f.frametype = AST_FRAME_NULL;
++ p->subs[index].f.subclass = 0;
++ p->dialing = 1;
++ }
++ p->dop.dialstr[0] = '\0';
++ ast_setstate(ast, AST_STATE_DIALING);
++ } else
++ ast_setstate(ast, AST_STATE_UP);
++ return &p->subs[index].f;
++ case AST_STATE_DOWN:
++ ast_setstate(ast, AST_STATE_RING);
++ ast->rings = 1;
++ p->subs[index].f.frametype = AST_FRAME_CONTROL;
++ p->subs[index].f.subclass = AST_CONTROL_OFFHOOK;
++ ast_debug(1, "channel %d picked up\n", p->channel);
++ return &p->subs[index].f;
++ case AST_STATE_UP:
++ /* Make sure it stops ringing */
++ analog_off_hook(p);
++ /* Okay -- probably call waiting*/
++ if (ast_bridged_channel(p->owner))
++ ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
++ break;
++ case AST_STATE_RESERVED:
++ /* Start up dialtone */
++ if (analog_has_voicemail(p))
++ res = analog_play_tone(p, ANALOG_SUB_REAL, ANALOG_TONE_STUTTER);
++ else
++ res = analog_play_tone(p, ANALOG_SUB_REAL, ANALOG_TONE_DIALTONE);
++ break;
++ default:
++ ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
++ }
++ break;
++ case ANALOG_SIG_FXSLS:
++ case ANALOG_SIG_FXSGS:
++ case ANALOG_SIG_FXSKS:
++#if 0
++ if (ast->_state == AST_STATE_RING) {
++ p->ringt = p->ringt_base;
++ }
++#endif
++
++ /* Fall through */
++ case ANALOG_SIG_EM:
++ case ANALOG_SIG_EM_E1:
++ case ANALOG_SIG_EMWINK:
++ case ANALOG_SIG_FEATD:
++ case ANALOG_SIG_FEATDMF:
++ case ANALOG_SIG_FEATDMF_TA:
++ case ANALOG_SIG_E911:
++ case ANALOG_SIG_FGC_CAMA:
++ case ANALOG_SIG_FGC_CAMAMF:
++ case ANALOG_SIG_FEATB:
++ case ANALOG_SIG_SF:
++ case ANALOG_SIG_SFWINK:
++ case ANALOG_SIG_SF_FEATD:
++ case ANALOG_SIG_SF_FEATDMF:
++ case ANALOG_SIG_SF_FEATB:
++ if (ast->_state == AST_STATE_PRERING)
++ ast_setstate(ast, AST_STATE_RING);
++ if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
++ ast_debug(1, "Ring detected\n");
++ p->subs[index].f.frametype = AST_FRAME_CONTROL;
++ p->subs[index].f.subclass = AST_CONTROL_RING;
++ } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
++ ast_debug(1, "Line answered\n");
++ p->subs[index].f.frametype = AST_FRAME_CONTROL;
++ p->subs[index].f.subclass = AST_CONTROL_ANSWER;
++ ast_setstate(ast, AST_STATE_UP);
++ } else if (ast->_state != AST_STATE_RING)
++ ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
++ break;
++ default:
++ ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
++ }
++ break;
++#ifdef ANALOG_EVENT_RINGBEGIN
++ case ANALOG_EVENT_RINGBEGIN:
++ switch (p->sig) {
++ case ANALOG_SIG_FXSLS:
++ case ANALOG_SIG_FXSGS:
++ case ANALOG_SIG_FXSKS:
++#if 0
++ if (ast->_state == AST_STATE_RING) {
++ p->ringt = p->ringt_base;
++ }
++#endif
++ break;
++ }
++ break;
++#endif
++ case ANALOG_EVENT_RINGEROFF:
++ if (p->inalarm) break;
++ ast->rings++;
++ if (ast->rings == p->cidrings) {
++ analog_send_callerid(p, 0, &p->cid);
++ }
++
++ if (ast->rings > p->cidrings) {
++ p->callwaitcas = 0;
++ }
++ p->subs[index].f.frametype = AST_FRAME_CONTROL;
++ p->subs[index].f.subclass = AST_CONTROL_RINGING;
++ break;
++ case ANALOG_EVENT_RINGERON:
++ break;
++ case ANALOG_EVENT_NOALARM:
++ p->inalarm = 0;
++ if (!p->unknown_alarm) {
++ ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
++ manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
++ "Channel: %d\r\n", p->channel);
++ } else {
++ p->unknown_alarm = 0;
++ }
++ break;
++ case ANALOG_EVENT_WINKFLASH:
++ if (p->inalarm) break;
++ /* Remember last time we got a flash-hook */
++ gettimeofday(&p->flashtime, NULL);
++ switch (mysig) {
++ case ANALOG_SIG_FXOLS:
++ case ANALOG_SIG_FXOGS:
++ case ANALOG_SIG_FXOKS:
++#if 0
++ ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
++ index, p->subs[ANALOG_SUB_REAL].dfd, p->subs[ANALOG_SUB_CALLWAIT].dfd, p->subs[ANALOG_SUB_THREEWAY].dfd);
++#endif
++ p->callwaitcas = 0;
++
++ if (index != ANALOG_SUB_REAL) {
++ ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel);
++ goto winkflashdone;
++ }
++
++ if (p->subs[ANALOG_SUB_CALLWAIT].owner) {
++ /* Swap to call-wait */
++ int previous_state = p->subs[ANALOG_SUB_CALLWAIT].owner->_state;
++ if (p->subs[ANALOG_SUB_CALLWAIT].owner->_state == AST_STATE_RINGING) {
++ ast_setstate(p->subs[ANALOG_SUB_CALLWAIT].owner, AST_STATE_UP);
++ }
++ analog_swap_subs(p, ANALOG_SUB_REAL, ANALOG_SUB_CALLWAIT);
++ analog_play_tone(p, ANALOG_SUB_REAL, -1);
++ p->owner = p->subs[ANALOG_SUB_REAL].owner;
++ ast_debug(1, "Making %s the new owner\n", p->owner->name);
++ if (previous_state == AST_STATE_RINGING) {
++ ast_queue_control(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_ANSWER);
++ }
++ analog_stop_callwait(p);
++ /* Start music on hold if appropriate */
++ if (!p->subs[ANALOG_SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[ANALOG_SUB_CALLWAIT].owner)) {
++ ast_queue_control_data(p->subs[ANALOG_SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
++ S_OR(p->mohsuggest, NULL),
++ !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
++ }
++ ast_queue_control(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_ANSWER);
++ if (ast_bridged_channel(p->subs[ANALOG_SUB_REAL].owner)) {
++ ast_queue_control_data(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_HOLD,
++ S_OR(p->mohsuggest, NULL),
++ !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
++ }
++ ast_queue_control(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_UNHOLD);
++ } else if (!p->subs[ANALOG_SUB_THREEWAY].owner) {
++ char cid_num[256];
++ char cid_name[256];
++
++ if (!p->threewaycalling) {
++ /* Just send a flash if no 3-way calling */
++ ast_queue_control(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_FLASH);
++ goto winkflashdone;
++ } else if (!analog_check_for_conference(p)) {
++ if (p->dahditrcallerid && p->owner) {
++ if (p->owner->cid.cid_num)
++ ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
++ if (p->owner->cid.cid_name)
++ ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
++ }
++ /* XXX This section needs much more error checking!!! XXX */
++ /* Start a 3-way call if feasible */
++ if (!((ast->pbx) ||
++ (ast->_state == AST_STATE_UP) ||
++ (ast->_state == AST_STATE_RING))) {
++ ast_debug(1, "Flash when call not up or ringing\n");
++ goto winkflashdone;
++ }
++ if (analog_alloc_sub(p, ANALOG_SUB_THREEWAY)) {
++ ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
++ goto winkflashdone;
++ }
++ /* Make new channel */
++ chan = analog_new_ast_channel(p, AST_STATE_RESERVED, 0, ANALOG_SUB_THREEWAY);
++ if (p->dahditrcallerid) {
++ if (!p->origcid_num)
++ p->origcid_num = ast_strdup(p->cid_num);
++ if (!p->origcid_name)
++ p->origcid_name = ast_strdup(p->cid_name);
++ ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
++ ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
++ }
++ /* Swap things around between the three-way and real call */
++ analog_swap_subs(p, ANALOG_SUB_THREEWAY, ANALOG_SUB_REAL);
++ /* Disable echo canceller for better dialing */
++ analog_set_echocanceller(p, 0);
++ res = analog_play_tone(p, ANALOG_SUB_REAL, ANALOG_TONE_DIALRECALL);
++ if (res)
++ ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
++ p->ss_astchan = p->owner = chan;
++ pthread_attr_init(&attr);
++ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
++ if (!chan) {
++ ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
++ } else if (ast_pthread_create(&threadid, &attr, __analog_ss_thread, p)) {
++ ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
++ res = analog_play_tone(p, ANALOG_SUB_REAL, ANALOG_TONE_CONGESTION);
++ analog_set_echocanceller(p, 1);
++ ast_hangup(chan);
++ } else {
++ struct ast_channel *other = ast_bridged_channel(p->subs[ANALOG_SUB_THREEWAY].owner);
++ int way3bridge = 0, cdr3way = 0;
++
++ if (!other) {
++ other = ast_bridged_channel(p->subs[ANALOG_SUB_REAL].owner);
++ } else
++ way3bridge = 1;
++
++ if (p->subs[ANALOG_SUB_THREEWAY].owner->cdr)
++ cdr3way = 1;
++
++ if (option_verbose > 2)
++ ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel);
++ /* Start music on hold if appropriate */
++ if (ast_bridged_channel(p->subs[ANALOG_SUB_THREEWAY].owner)) {
++ ast_queue_control_data(p->subs[ANALOG_SUB_THREEWAY].owner, AST_CONTROL_HOLD,
++ S_OR(p->mohsuggest, NULL),
++ !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
++ }
++ }
++ pthread_attr_destroy(&attr);
++ }
++ } else {
++ /* Already have a 3 way call */
++ if (p->subs[ANALOG_SUB_THREEWAY].inthreeway) {
++ /* Call is already up, drop the last person */
++ ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
++ /* If the primary call isn't answered yet, use it */
++ if ((p->subs[ANALOG_SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[ANALOG_SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
++ /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
++ analog_swap_subs(p, ANALOG_SUB_THREEWAY, ANALOG_SUB_REAL);
++ p->owner = p->subs[ANALOG_SUB_REAL].owner;
++ }
++ /* Drop the last call and stop the conference */
++ if (option_verbose > 2)
++ ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[ANALOG_SUB_THREEWAY].owner->name);
++ ast_softhangup_nolock(p->subs[ANALOG_SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
++ p->subs[ANALOG_SUB_REAL].inthreeway = 0;
++ p->subs[ANALOG_SUB_THREEWAY].inthreeway = 0;
++ } else {
++ /* Lets see what we're up to */
++ if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
++ (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
++ int otherindex = ANALOG_SUB_THREEWAY;
++ struct ast_channel *other = ast_bridged_channel(p->subs[ANALOG_SUB_THREEWAY].owner);
++ int way3bridge = 0, cdr3way = 0;
++
++ if (!other) {
++ other = ast_bridged_channel(p->subs[ANALOG_SUB_REAL].owner);
++ } else
++ way3bridge = 1;
++
++ if (p->subs[ANALOG_SUB_THREEWAY].owner->cdr)
++ cdr3way = 1;
++
++ if (option_verbose > 2)
++ ast_verbose(VERBOSE_PREFIX_3 "Building conference on call on %s and %s\n", p->subs[ANALOG_SUB_THREEWAY].owner->name, p->subs[ANALOG_SUB_REAL].owner->name);
++ /* Put them in the threeway, and flip */
++ p->subs[ANALOG_SUB_THREEWAY].inthreeway = 1;
++ p->subs[ANALOG_SUB_REAL].inthreeway = 1;
++ if (ast->_state == AST_STATE_UP) {
++ analog_swap_subs(p, ANALOG_SUB_THREEWAY, ANALOG_SUB_REAL);
++ otherindex = ANALOG_SUB_REAL;
++ }
++ if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
++ ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
++ p->owner = p->subs[ANALOG_SUB_REAL].owner;
++ if (ast->_state == AST_STATE_RINGING) {
++ ast_debug(1, "Enabling ringtone on real and threeway\n");
++ analog_play_tone(p, ANALOG_SUB_REAL, ANALOG_TONE_RINGTONE);
++ analog_play_tone(p, ANALOG_SUB_THREEWAY, ANALOG_TONE_RINGTONE);
++ }
++ } else {
++ if (option_verbose > 2)
++ ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on on %s\n", p->subs[ANALOG_SUB_THREEWAY].owner->name);
++ analog_swap_subs(p, ANALOG_SUB_THREEWAY, ANALOG_SUB_REAL);
++ ast_softhangup_nolock(p->subs[ANALOG_SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
++ p->owner = p->subs[ANALOG_SUB_REAL].owner;
++ if (p->subs[ANALOG_SUB_REAL].owner && ast_bridged_channel(p->subs[ANALOG_SUB_REAL].owner))
++ ast_queue_control(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_UNHOLD);
++ analog_set_echocanceller(p, 1);
++ }
++ }
++ }
++ winkflashdone:
++ analog_update_conf(p);
++ break;
++ case ANALOG_SIG_EM:
++ case ANALOG_SIG_EM_E1:
++ case ANALOG_SIG_EMWINK:
++ case ANALOG_SIG_FEATD:
++ case ANALOG_SIG_SF:
++ case ANALOG_SIG_SFWINK:
++ case ANALOG_SIG_SF_FEATD:
++ case ANALOG_SIG_FXSLS:
++ case ANALOG_SIG_FXSGS:
++ if (p->dialing)
++ ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
++ else
++ ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
++ break;
++ case ANALOG_SIG_FEATDMF_TA:
++ switch (p->whichwink) {
++ case 0:
++ ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
++ snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
++ break;
++ case 1:
++ ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
++ break;
++ case 2:
++ ast_log(LOG_WARNING, "Received unexpected wink on channel of type ANALOG_SIG_FEATDMF_TA\n");
++ return NULL;
++ }
++ p->whichwink++;
++ /* Fall through */
++ case ANALOG_SIG_FEATDMF:
++ case ANALOG_SIG_E911:
++ case ANALOG_SIG_FGC_CAMAMF:
++ case ANALOG_SIG_FGC_CAMA:
++ case ANALOG_SIG_FEATB:
++ case ANALOG_SIG_SF_FEATDMF:
++ case ANALOG_SIG_SF_FEATB:
++ /* FGD MF *Must* wait for wink */
++ if (!ast_strlen_zero(p->dop.dialstr)) {
++ res = analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop);
++ if (res < 0) {
++ ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
++ p->dop.dialstr[0] = '\0';
++ return NULL;
++ } else
++ ast_debug(1, "Sent deferred digit string on channel %d: %s\n", p->channel, p->dop.dialstr);
++ }
++ p->dop.dialstr[0] = '\0';
++ break;
++ default:
++ ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
++ }
++ break;
++ case ANALOG_EVENT_HOOKCOMPLETE:
++ if (p->inalarm) break;
++ switch (mysig) {
++ case ANALOG_SIG_FXSLS: /* only interesting for FXS */
++ case ANALOG_SIG_FXSGS:
++ case ANALOG_SIG_FXSKS:
++ case ANALOG_SIG_EM:
++ case ANALOG_SIG_EM_E1:
++ case ANALOG_SIG_EMWINK:
++ case ANALOG_SIG_FEATD:
++ case ANALOG_SIG_SF:
++ case ANALOG_SIG_SFWINK:
++ case ANALOG_SIG_SF_FEATD:
++ if (!ast_strlen_zero(p->dop.dialstr)) {
++ res = analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop);
++ if (res < 0) {
++ ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
++ p->dop.dialstr[0] = '\0';
++ return NULL;
++ } else
++ ast_debug(1, "Sent deferred digit string on channel %d: %s\n", p->channel, p->dop.dialstr);
++ }
++ p->dop.dialstr[0] = '\0';
++ p->dop.op = ANALOG_DIAL_OP_REPLACE;
++ break;
++ case ANALOG_SIG_FEATDMF:
++ case ANALOG_SIG_FEATDMF_TA:
++ case ANALOG_SIG_E911:
++ case ANALOG_SIG_FGC_CAMA:
++ case ANALOG_SIG_FGC_CAMAMF:
++ case ANALOG_SIG_FEATB:
++ case ANALOG_SIG_SF_FEATDMF:
++ case ANALOG_SIG_SF_FEATB:
++ ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
++ break;
++ default:
++ break;
++ }
++ break;
++ case ANALOG_EVENT_POLARITY:
++ /*
++ * If we get a Polarity Switch event, check to see
++ * if we should change the polarity state and
++ * mark the channel as UP or if this is an indication
++ * of remote end disconnect.
++ */
++ if (p->polarity == POLARITY_IDLE) {
++ p->polarity = POLARITY_REV;
++ if (p->answeronpolarityswitch &&
++ ((ast->_state == AST_STATE_DIALING) ||
++ (ast->_state == AST_STATE_RINGING))) {
++ ast_debug(1, "Answering on polarity switch!\n");
++ ast_setstate(p->owner, AST_STATE_UP);
++ if (p->hanguponpolarityswitch) {
++ gettimeofday(&p->polaritydelaytv, NULL);
++ }
++ } else
++ ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
++ }
++ /* Removed else statement from here as it was preventing hangups from ever happening*/
++ /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
++ if (p->hanguponpolarityswitch &&
++ (p->polarityonanswerdelay > 0) &&
++ (p->polarity == POLARITY_REV) &&
++ ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
++ /* Added log_debug information below to provide a better indication of what is going on */
++ ast_debug(1, "Polarity Reversal event occured - DEBUG 1: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
++
++ if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
++ ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
++ ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
++ p->polarity = POLARITY_IDLE;
++ } else {
++ ast_debug(1, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast->_state);
++ }
++ } else {
++ p->polarity = POLARITY_IDLE;
++ ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
++ }
++ /* Added more log_debug information below to provide a better indication of what is going on */
++ ast_debug(1, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
++ break;
++ default:
++ ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
++ }
++ return &p->subs[index].f;
++}
++
++struct ast_frame *analog_exception(struct analog_pvt *p, struct ast_channel *ast)
++{
++ int res;
++ int usedindex=-1;
++ int index;
++ struct ast_frame *f;
++
++ ast_log(LOG_DEBUG, "%s %d\n", __FUNCTION__, p->channel);
++
++ index = analog_get_index(ast, p, 1);
++
++ p->subs[index].f.frametype = AST_FRAME_NULL;
++ p->subs[index].f.datalen = 0;
++ p->subs[index].f.samples = 0;
++ p->subs[index].f.mallocd = 0;
++ p->subs[index].f.offset = 0;
++ p->subs[index].f.subclass = 0;
++ p->subs[index].f.delivery = ast_tv(0,0);
++ p->subs[index].f.src = "dahdi_exception";
++ p->subs[index].f.data.ptr = NULL;
++
++
++ if (!p->owner) {
++ /* If nobody owns us, absorb the event appropriately, otherwise
++ we loop indefinitely. This occurs when, during call waiting, the
++ other end hangs up our channel so that it no longer exists, but we
++ have neither FLASH'd nor ONHOOK'd to signify our desire to
++ change to the other channel. */
++ res = analog_get_event(p);
++
++ /* Switch to real if there is one and this isn't something really silly... */
++ if ((res != ANALOG_EVENT_RINGEROFF) && (res != ANALOG_EVENT_RINGERON) &&
++ (res != ANALOG_EVENT_HOOKCOMPLETE)) {
++ ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
++ p->owner = p->subs[ANALOG_SUB_REAL].owner;
++ if (p->owner && ast_bridged_channel(p->owner))
++ ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
++ }
++ switch (res) {
++ case ANALOG_EVENT_ONHOOK:
++ analog_set_echocanceller(p, 0);
++ if (p->owner) {
++ if (option_verbose > 2)
++ ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name);
++ analog_ring(p);
++ analog_stop_callwait(p);
++ } else
++ ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
++ analog_update_conf(p);
++ break;
++ case ANALOG_EVENT_RINGOFFHOOK:
++ analog_set_echocanceller(p, 1);
++ analog_off_hook(p);
++ if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
++ ast_queue_control(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_ANSWER);
++ p->dialing = 0;
++ }
++ break;
++ case ANALOG_EVENT_HOOKCOMPLETE:
++ case ANALOG_EVENT_RINGERON:
++ case ANALOG_EVENT_RINGEROFF:
++ /* Do nothing */
++ break;
++ case ANALOG_EVENT_WINKFLASH:
++ gettimeofday(&p->flashtime, NULL);
++ if (p->owner) {
++ if (option_verbose > 2)
++ ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
++ if (p->owner->_state != AST_STATE_UP) {
++ /* Answer if necessary */
++ usedindex = analog_get_index(p->owner, p, 0);
++ if (usedindex > -1) {
++ ast_queue_control(p->subs[usedindex].owner, AST_CONTROL_ANSWER);
++ }
++ ast_setstate(p->owner, AST_STATE_UP);
++ }
++ analog_stop_callwait(p);
++ if (ast_bridged_channel(p->owner))
++ ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
++ } else
++ ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
++ analog_update_conf(p);
++ break;
++ default:
++ ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", analog_event2str(res));
++ }
++ f = &p->subs[index].f;
++ return f;
++ }
++ ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
++ /* If it's not us, return NULL immediately */
++ if (ast != p->owner) {
++ ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
++ f = &p->subs[index].f;
++ return f;
++ }
++ f = __analog_handle_event(p, ast);
++ return f;
++}
++
++int analog_handle_init_event(struct analog_pvt *i, int event)
++{
++ int res;
++ pthread_t threadid;
++ pthread_attr_t attr;
++ struct ast_channel *chan;
++
++ ast_debug(1, "channel (%d) - signaling (%d) - event (%s)\n",
++ i->channel, i->sig, analog_event2str(event));
++
++ pthread_attr_init(&attr);
++ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
++ /* Handle an event on a given channel for the monitor thread. */
++ switch (event) {
++ case ANALOG_EVENT_WINKFLASH:
++ case ANALOG_EVENT_RINGOFFHOOK:
++ if (i->inalarm) break;
++ /* Got a ring/answer. What kind of channel are we? */
++ switch (i->sig) {
++ case ANALOG_SIG_FXOLS:
++ case ANALOG_SIG_FXOGS:
++ case ANALOG_SIG_FXOKS:
++ res = analog_off_hook(i);
++ if (res && (errno == EBUSY))
++ break;
++ if (i->immediate) {
++ analog_set_echocanceller(i, 1);
++ /* The channel is immediately up. Start right away */
++ res = analog_play_tone(i, ANALOG_SUB_REAL, ANALOG_TONE_RINGTONE);
++ chan = analog_new_ast_channel(i, AST_STATE_RING, 1, ANALOG_SUB_REAL);
++ if (!chan) {
++ ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
++ res = analog_play_tone(i, ANALOG_SUB_REAL, ANALOG_TONE_CONGESTION);
++ if (res < 0)
++ ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
++ }
++ } else {
++ /* Check for callerid, digits, etc */
++ chan = analog_new_ast_channel(i, AST_STATE_RESERVED, 0, ANALOG_SUB_REAL);
++ i->ss_astchan = chan;
++ if (chan) {
++ if (analog_has_voicemail(i))
++ res = analog_play_tone(i, ANALOG_SUB_REAL, ANALOG_TONE_STUTTER);
++ else
++ res = analog_play_tone(i, ANALOG_SUB_REAL, ANALOG_TONE_DIALTONE);
++ if (res < 0)
++ ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
++ if (ast_pthread_create(&threadid, &attr, __analog_ss_thread, i)) {
++ ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
++ res = analog_play_tone(i, ANALOG_SUB_REAL, ANALOG_TONE_CONGESTION);
++ if (res < 0)
++ ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
++ ast_hangup(chan);
++ }
++ } else
++ ast_log(LOG_WARNING, "Unable to create channel\n");
++ }
++ break;
++ case ANALOG_SIG_FXSLS:
++ case ANALOG_SIG_FXSGS:
++ case ANALOG_SIG_FXSKS:
++#if 0
++ i->ringt = i->ringt_base;
++#endif
++ /* Fall through */
++ case ANALOG_SIG_EMWINK:
++ case ANALOG_SIG_FEATD:
++ case ANALOG_SIG_FEATDMF:
++ case ANALOG_SIG_FEATDMF_TA:
++ case ANALOG_SIG_E911:
++ case ANALOG_SIG_FGC_CAMA:
++ case ANALOG_SIG_FGC_CAMAMF:
++ case ANALOG_SIG_FEATB:
++ case ANALOG_SIG_EM:
++ case ANALOG_SIG_EM_E1:
++ case ANALOG_SIG_SFWINK:
++ case ANALOG_SIG_SF_FEATD:
++ case ANALOG_SIG_SF_FEATDMF:
++ case ANALOG_SIG_SF_FEATB:
++ case ANALOG_SIG_SF:
++ /* Check for callerid, digits, etc */
++ if (i->cid_start == ANALOG_CID_START_POLARITY_IN) {
++ chan = analog_new_ast_channel(i, AST_STATE_PRERING, 0, ANALOG_SUB_REAL);
++ } else {
++ chan = analog_new_ast_channel(i, AST_STATE_RING, 0, ANALOG_SUB_REAL);
++ }
++ i->ss_astchan = chan;
++ if (chan && ast_pthread_create(&threadid, &attr, __analog_ss_thread, i)) {
++ ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
++ res = analog_play_tone(i, ANALOG_SUB_REAL, ANALOG_TONE_CONGESTION);
++ if (res < 0)
++ ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
++ ast_hangup(chan);
++ } else if (!chan) {
++ ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
++ }
++ break;
++ default:
++ ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", analog_sigtype_to_str(i->sig), i->channel);
++ res = analog_play_tone(i, ANALOG_SUB_REAL, ANALOG_TONE_CONGESTION);
++ if (res < 0)
++ ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
++ return -1;
++ }
++ break;
++ case ANALOG_EVENT_NOALARM:
++ i->inalarm = 0;
++ if (!i->unknown_alarm) {
++ ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
++ manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
++ "Channel: %d\r\n", i->channel);
++ } else {
++ i->unknown_alarm = 0;
++ }
++ break;
++ case ANALOG_EVENT_ALARM:
++ i->inalarm = 1;
++#if 0
++ res = get_alarms(i);
++ handle_alarms(i, res);
++#endif
++ /* fall thru intentionally */
++ case ANALOG_EVENT_ONHOOK:
++ /* Back on hook. Hang up. */
++ switch (i->sig) {
++ case ANALOG_SIG_FXOLS:
++ case ANALOG_SIG_FXOGS:
++ case ANALOG_SIG_FEATD:
++ case ANALOG_SIG_FEATDMF:
++ case ANALOG_SIG_FEATDMF_TA:
++ case ANALOG_SIG_E911:
++ case ANALOG_SIG_FGC_CAMA:
++ case ANALOG_SIG_FGC_CAMAMF:
++ case ANALOG_SIG_FEATB:
++ case ANALOG_SIG_EM:
++ case ANALOG_SIG_EM_E1:
++ case ANALOG_SIG_EMWINK:
++ case ANALOG_SIG_SF_FEATD:
++ case ANALOG_SIG_SF_FEATDMF:
++ case ANALOG_SIG_SF_FEATB:
++ case ANALOG_SIG_SF:
++ case ANALOG_SIG_SFWINK:
++ case ANALOG_SIG_FXSLS:
++ case ANALOG_SIG_FXSGS:
++ case ANALOG_SIG_FXSKS:
++ analog_set_echocanceller(i, 0);
++ res = analog_play_tone(i, ANALOG_SUB_REAL, -1);
++ analog_on_hook(i);
++ break;
++ case ANALOG_SIG_FXOKS:
++ analog_set_echocanceller(i, 0);
++ /* Diddle the battery for the zhone */
++#ifdef ZHONE_HACK
++ analog_off_hook(i);
++ usleep(1);
++#endif
++ res = analog_play_tone(i, ANALOG_SUB_REAL, -1);
++ analog_on_hook(i);
++ break;
++ default:
++ ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", analog_sigtype_to_str(i->sig), i->channel);
++ res = analog_play_tone(i, ANALOG_SUB_REAL, -1);
++ return -1;
++ }
++ break;
++ case ANALOG_EVENT_POLARITY:
++ switch (i->sig) {
++ case ANALOG_SIG_FXSLS:
++ case ANALOG_SIG_FXSKS:
++ case ANALOG_SIG_FXSGS:
++ /* We have already got a PR before the channel was
++ created, but it wasn't handled. We need polarity
++ to be REV for remote hangup detection to work.
++ At least in Spain */
++ if (i->hanguponpolarityswitch)
++ i->polarity = POLARITY_REV;
++
++ if (i->cid_start == ANALOG_CID_START_POLARITY || i->cid_start == ANALOG_CID_START_POLARITY_IN) {
++ i->polarity = POLARITY_REV;
++ ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
++ "CID detection on channel %d\n",
++ i->channel);
++ chan = analog_new_ast_channel(i, AST_STATE_PRERING, 0, ANALOG_SUB_REAL);
++ i->ss_astchan = chan;
++ if (chan && ast_pthread_create(&threadid, &attr, __analog_ss_thread, i)) {
++ ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
++ }
++ }
++ break;
++ default:
++ ast_log(LOG_WARNING, "handle_init_event detected "
++ "polarity reversal on non-FXO (ANALOG_SIG_FXS) "
++ "interface %d\n", i->channel);
++ }
++ break;
++ case ANALOG_EVENT_NEONMWI_ACTIVE:
++ analog_handle_notify_message(NULL, i, -1, ANALOG_EVENT_NEONMWI_ACTIVE);
++ break;
++ case ANALOG_EVENT_NEONMWI_INACTIVE:
++ analog_handle_notify_message(NULL, i, -1, ANALOG_EVENT_NEONMWI_INACTIVE);
++ break;
++ }
++ pthread_attr_destroy(&attr);
++ return 0;
++}
++
++
++struct analog_pvt * analog_new(enum analog_sigtype signallingtype, struct analog_callback *c, void *private_data)
++{
++ struct analog_pvt *p;
++
++ p = ast_calloc(1, sizeof(*p));
++
++ if (!p)
++ return p;
++
++ p->calls = c;
++ p->outsigmod = ANALOG_SIG_NONE;
++ p->sig = signallingtype;
++ p->chan_pvt = private_data;
++
++ /* Some defaults for values */
++ p->sendcalleridafter = 1;
++ p->cid_start = ANALOG_CID_START_RING;
++ p->cid_signalling = CID_SIG_BELL;
++ /* Sub real is assumed to always be alloc'd */
++ p->subs[ANALOG_SUB_REAL].allocd = 1;
++
++ return p;
++}
++
++int analog_config_complete(struct analog_pvt *p)
++{
++ /* No call waiting on non FXS channels */
++ if ((p->sig != ANALOG_SIG_FXOKS) && (p->sig != ANALOG_SIG_FXOLS) && (p->sig != ANALOG_SIG_FXOGS))
++ p->permcallwaiting = 0;
++
++ p->callwaiting = p->permcallwaiting;
++
++ return 0;
++}
++
++void analog_free(struct analog_pvt *p)
++{
++ free(p);
++}
++
++/* called while dahdi_pvt is locked in dahdi_fixup */
++int analog_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, void *newp)
++{
++ struct analog_pvt *new_pvt = newp;
++ int x;
++ ast_debug(1, "New owner for channel %d is %s\n", new_pvt->channel, newchan->name);
++ if (new_pvt->owner == oldchan) {
++ new_pvt->owner = newchan;
++ }
++ for (x = 0; x < 3; x++)
++ if (new_pvt->subs[x].owner == oldchan) {
++ new_pvt->subs[x].owner = newchan;
++ }
++
++ analog_update_conf(new_pvt);
++ return 0;
++}
+
+Property changes on: channels/sig_analog.c
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+
+Index: channels/chan_h323.c
+===================================================================
+--- a/channels/chan_h323.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/channels/chan_h323.c (.../trunk) (revision 202568)
+@@ -76,7 +76,7 @@
+ #include "asterisk/utils.h"
+ #include "asterisk/sched.h"
+ #include "asterisk/io.h"
+-#include "asterisk/rtp.h"
++#include "asterisk/rtp_engine.h"
+ #include "asterisk/acl.h"
+ #include "asterisk/callerid.h"
+ #include "asterisk/cli.h"
+@@ -147,7 +147,7 @@
+ static call_options_t global_options;
+
+ /*! \brief Private structure of a OpenH323 channel */
+-struct oh323_pvt {
++static struct oh323_pvt {
+ ast_mutex_t lock; /*!< Channel private lock */
+ call_options_t options; /*!<!< Options to be used during call setup */
+ int alreadygone; /*!< Whether or not we've already been destroyed by our peer */
+@@ -163,7 +163,7 @@
+ char accountcode[256]; /*!< Account code */
+ char rdnis[80]; /*!< Referring DNIS, if available */
+ int amaflags; /*!< AMA Flags */
+- struct ast_rtp *rtp; /*!< RTP Session */
++ struct ast_rtp_instance *rtp; /*!< RTP Session */
+ struct ast_dsp *vad; /*!< Used for in-band DTMF detection */
+ int nativeformats; /*!< Codec formats supported by a channel */
+ int needhangup; /*!< Send hangup when Asterisk is ready */
+@@ -256,7 +256,7 @@
+ .write = oh323_write,
+ .indicate = oh323_indicate,
+ .fixup = oh323_fixup,
+- .bridge = ast_rtp_bridge,
++ .bridge = ast_rtp_instance_bridge,
+ };
+
+ static const char* redirectingreason2str(int redirectingreason)
+@@ -383,8 +383,8 @@
+ if (pvt->update_rtp_info > 0) {
+ if (pvt->rtp) {
+ ast_jb_configure(c, &global_jbconf);
+- ast_channel_set_fd(c, 0, ast_rtp_fd(pvt->rtp));
+- ast_channel_set_fd(c, 1, ast_rtcp_fd(pvt->rtp));
++ ast_channel_set_fd(c, 0, ast_rtp_instance_fd(pvt->rtp, 0));
++ ast_channel_set_fd(c, 1, ast_rtp_instance_fd(pvt->rtp, 1));
+ ast_queue_frame(pvt->owner, &ast_null_frame); /* Tell Asterisk to apply changes */
+ }
+ pvt->update_rtp_info = -1;
+@@ -446,7 +446,7 @@
+ AST_SCHED_DEL(sched, pvt->DTMFsched);
+
+ if (pvt->rtp) {
+- ast_rtp_destroy(pvt->rtp);
++ ast_rtp_instance_destroy(pvt->rtp);
+ }
+
+ /* Free dsp used for in-band DTMF detection */
+@@ -512,7 +512,7 @@
+ if (h323debug) {
+ ast_log(LOG_DTMF, "Begin sending out-of-band digit %c on %s\n", digit, c->name);
+ }
+- ast_rtp_senddigit_begin(pvt->rtp, digit);
++ ast_rtp_instance_dtmf_begin(pvt->rtp, digit);
+ ast_mutex_unlock(&pvt->lock);
+ } else if (pvt->txDtmfDigit != digit) {
+ /* in-band DTMF */
+@@ -551,7 +551,7 @@
+ if (h323debug) {
+ ast_log(LOG_DTMF, "End sending out-of-band digit %c on %s, duration %d\n", digit, c->name, duration);
+ }
+- ast_rtp_senddigit_end(pvt->rtp, digit);
++ ast_rtp_instance_dtmf_end(pvt->rtp, digit);
+ ast_mutex_unlock(&pvt->lock);
+ } else {
+ /* in-band DTMF */
+@@ -608,18 +608,18 @@
+ /* make sure null terminated */
+ called_addr[sizeof(called_addr) - 1] = '\0';
+
+- if (c->cid.cid_num)
+- ast_copy_string(pvt->options.cid_num, c->cid.cid_num, sizeof(pvt->options.cid_num));
++ if (c->connected.id.number)
++ ast_copy_string(pvt->options.cid_num, c->connected.id.number, sizeof(pvt->options.cid_num));
+
+- if (c->cid.cid_name)
+- ast_copy_string(pvt->options.cid_name, c->cid.cid_name, sizeof(pvt->options.cid_name));
++ if (c->connected.id.name)
++ ast_copy_string(pvt->options.cid_name, c->connected.id.name, sizeof(pvt->options.cid_name));
+
+ if (c->cid.cid_rdnis) {
+ ast_copy_string(pvt->options.cid_rdnis, c->cid.cid_rdnis, sizeof(pvt->options.cid_rdnis));
+ }
+
+- pvt->options.presentation = c->cid.cid_pres;
+- pvt->options.type_of_number = c->cid.cid_ton;
++ pvt->options.presentation = c->connected.id.number_presentation;
++ pvt->options.type_of_number = c->connected.id.number_type;
+
+ if ((addr = pbx_builtin_getvar_helper(c, "PRIREDIRECTREASON"))) {
+ if (!strcasecmp(addr, "UNKNOWN"))
+@@ -749,11 +749,11 @@
+
+ /* Only apply it for the first packet, we just need the correct ip/port */
+ if (pvt->options.nat) {
+- ast_rtp_setnat(pvt->rtp, pvt->options.nat);
++ ast_rtp_instance_set_prop(pvt->rtp, AST_RTP_PROPERTY_NAT, pvt->options.nat);
+ pvt->options.nat = 0;
+ }
+
+- f = ast_rtp_read(pvt->rtp);
++ f = ast_rtp_instance_read(pvt->rtp, 0);
+ /* Don't send RFC2833 if we're not supposed to */
+ if (f && (f->frametype == AST_FRAME_DTMF) && !(pvt->options.dtmfmode & (H323_DTMF_RFC2833 | H323_DTMF_CISCO))) {
+ return &ast_null_frame;
+@@ -810,7 +810,7 @@
+ break;
+ case 1:
+ if (pvt->rtp)
+- fr = ast_rtcp_read(pvt->rtp);
++ fr = ast_rtp_instance_read(pvt->rtp, 1);
+ else
+ fr = &ast_null_frame;
+ break;
+@@ -844,7 +844,7 @@
+ if (pvt) {
+ ast_mutex_lock(&pvt->lock);
+ if (pvt->rtp && !pvt->recvonly)
+- res = ast_rtp_write(pvt->rtp, frame);
++ res = ast_rtp_instance_write(pvt->rtp, frame);
+ __oh323_update_info(c, pvt);
+ ast_mutex_unlock(&pvt->lock);
+ }
+@@ -912,7 +912,7 @@
+ res = 0;
+ break;
+ case AST_CONTROL_SRCUPDATE:
+- ast_rtp_new_source(pvt->rtp);
++ ast_rtp_instance_new_source(pvt->rtp);
+ res = 0;
+ break;
+ case AST_CONTROL_PROCEEDING:
+@@ -948,17 +948,17 @@
+
+ static int __oh323_rtp_create(struct oh323_pvt *pvt)
+ {
+- struct in_addr our_addr;
++ struct sockaddr_in our_addr;
+
+ if (pvt->rtp)
+ return 0;
+
+- if (ast_find_ourip(&our_addr, bindaddr)) {
++ if (ast_find_ourip(&our_addr.sin_addr, bindaddr)) {
+ ast_mutex_unlock(&pvt->lock);
+ ast_log(LOG_ERROR, "Unable to locate local IP address for RTP stream\n");
+ return -1;
+ }
+- pvt->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, our_addr);
++ pvt->rtp = ast_rtp_instance_new(NULL, sched, &our_addr, NULL);
+ if (!pvt->rtp) {
+ ast_mutex_unlock(&pvt->lock);
+ ast_log(LOG_WARNING, "Unable to create RTP session: %s\n", strerror(errno));
+@@ -967,24 +967,24 @@
+ if (h323debug)
+ ast_debug(1, "Created RTP channel\n");
+
+- ast_rtp_setqos(pvt->rtp, tos, cos, "H323 RTP");
++ ast_rtp_instance_set_qos(pvt->rtp, tos, cos, "H323 RTP");
+
+ if (h323debug)
+ ast_debug(1, "Setting NAT on RTP to %d\n", pvt->options.nat);
+- ast_rtp_setnat(pvt->rtp, pvt->options.nat);
++ ast_rtp_instance_set_prop(pvt->rtp, AST_RTP_PROPERTY_NAT, pvt->options.nat);
+
+ if (pvt->dtmf_pt[0] > 0)
+- ast_rtp_set_rtpmap_type(pvt->rtp, pvt->dtmf_pt[0], "audio", "telephone-event", 0);
++ ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, pvt->dtmf_pt[0], "audio", "telephone-event", 0);
+ if (pvt->dtmf_pt[1] > 0)
+- ast_rtp_set_rtpmap_type(pvt->rtp, pvt->dtmf_pt[1], "audio", "cisco-telephone-event", 0);
++ ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, pvt->dtmf_pt[1], "audio", "cisco-telephone-event", 0);
+
+ if (pvt->peercapability)
+- ast_rtp_codec_setpref(pvt->rtp, &pvt->peer_prefs);
++ ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, &pvt->peer_prefs);
+
+ if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
+ ast_jb_configure(pvt->owner, &global_jbconf);
+- ast_channel_set_fd(pvt->owner, 0, ast_rtp_fd(pvt->rtp));
+- ast_channel_set_fd(pvt->owner, 1, ast_rtcp_fd(pvt->rtp));
++ ast_channel_set_fd(pvt->owner, 0, ast_rtp_instance_fd(pvt->rtp, 0));
++ ast_channel_set_fd(pvt->owner, 1, ast_rtp_instance_fd(pvt->rtp, 1));
+ ast_queue_frame(pvt->owner, &ast_null_frame); /* Tell Asterisk to apply changes */
+ ast_channel_unlock(pvt->owner);
+ } else
+@@ -1030,13 +1030,13 @@
+ if (!pvt->rtp)
+ __oh323_rtp_create(pvt);
+ #if 0
+- ast_channel_set_fd(ch, 0, ast_rtp_fd(pvt->rtp));
+- ast_channel_set_fd(ch, 1, ast_rtcp_fd(pvt->rtp));
++ ast_channel_set_fd(ch, 0, ast_rtp_instance_fd(pvt->rtp, 0));
++ ast_channel_set_fd(ch, 1, ast_rtp_instance_fd(pvt->rtp, 1));
+ #endif
+ #ifdef VIDEO_SUPPORT
+ if (pvt->vrtp) {
+- ast_channel_set_fd(ch, 2, ast_rtp_fd(pvt->vrtp));
+- ast_channel_set_fd(ch, 3, ast_rtcp_fd(pvt->vrtp));
++ ast_channel_set_fd(ch, 2, ast_rtp_instance_fd(pvt->vrtp, 0));
++ ast_channel_set_fd(ch, 3, ast_rtp_instance_fd(pvt->vrtp, 1));
+ }
+ #endif
+ #ifdef T38_SUPPORT
+@@ -1114,7 +1114,7 @@
+ }
+ if (!pvt->cd.call_token) {
+ ast_log(LOG_ERROR, "Not enough memory to alocate call token\n");
+- ast_rtp_destroy(pvt->rtp);
++ ast_rtp_instance_destroy(pvt->rtp);
+ ast_free(pvt);
+ return NULL;
+ }
+@@ -1916,7 +1916,7 @@
+ return NULL;
+ }
+ /* figure out our local RTP port and tell the H.323 stack about it */
+- ast_rtp_get_us(pvt->rtp, &us);
++ ast_rtp_instance_get_local_address(pvt->rtp, &us);
+ ast_mutex_unlock(&pvt->lock);
+
+ ast_copy_string(info->addr, ast_inet_ntoa(us.sin_addr), sizeof(info->addr));
+@@ -1935,7 +1935,6 @@
+ {
+ struct oh323_pvt *pvt;
+ struct sockaddr_in them;
+- struct rtpPayloadType rtptype;
+ int nativeformats_changed;
+ enum { NEED_NONE, NEED_HOLD, NEED_UNHOLD } rtp_change = NEED_NONE;
+
+@@ -1957,7 +1956,7 @@
+ __oh323_rtp_create(pvt);
+
+ if ((pt == 2) && (pvt->jointcapability & AST_FORMAT_G726_AAL2)) {
+- ast_rtp_set_rtpmap_type(pvt->rtp, pt, "audio", "G726-32", AST_RTP_OPT_G726_NONSTANDARD);
++ ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, pt, "audio", "G726-32", AST_RTP_OPT_G726_NONSTANDARD);
+ }
+
+ them.sin_family = AF_INET;
+@@ -1966,13 +1965,13 @@
+ them.sin_port = htons(remotePort);
+
+ if (them.sin_addr.s_addr) {
+- ast_rtp_set_peer(pvt->rtp, &them);
++ ast_rtp_instance_set_remote_address(pvt->rtp, &them);
+ if (pvt->recvonly) {
+ pvt->recvonly = 0;
+ rtp_change = NEED_UNHOLD;
+ }
+ } else {
+- ast_rtp_stop(pvt->rtp);
++ ast_rtp_instance_stop(pvt->rtp);
+ if (!pvt->recvonly) {
+ pvt->recvonly = 1;
+ rtp_change = NEED_HOLD;
+@@ -1982,7 +1981,7 @@
+ /* Change native format to reflect information taken from OLC/OLCAck */
+ nativeformats_changed = 0;
+ if (pt != 128 && pvt->rtp) { /* Payload type is invalid, so try to use previously decided */
+- rtptype = ast_rtp_lookup_pt(pvt->rtp, pt);
++ struct ast_rtp_payload_type rtptype = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(pvt->rtp), pt);
+ if (h323debug)
+ ast_debug(1, "Native format is set to %d from %d by RTP payload type %d\n", rtptype.code, pvt->nativeformats, pt);
+ if (pvt->nativeformats != rtptype.code) {
+@@ -2363,7 +2362,7 @@
+ }
+ if (pvt->rtp) {
+ /* Immediately stop RTP */
+- ast_rtp_destroy(pvt->rtp);
++ ast_rtp_instance_destroy(pvt->rtp);
+ pvt->rtp = NULL;
+ }
+ /* Free dsp used for in-band DTMF detection */
+@@ -2425,7 +2424,7 @@
+ return;
+ }
+ if (pvt->rtp) {
+- ast_rtp_set_rtpmap_type(pvt->rtp, payload, "audio", (is_cisco ? "cisco-telephone-event" : "telephone-event"), 0);
++ ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, payload, "audio", (is_cisco ? "cisco-telephone-event" : "telephone-event"), 0);
+ }
+ pvt->dtmf_pt[is_cisco ? 1 : 0] = payload;
+ ast_mutex_unlock(&pvt->lock);
+@@ -2458,10 +2457,10 @@
+ if (pvt->rtp) {
+ if (pvt->options.autoframing) {
+ ast_debug(2, "Autoframing option set, using peer's packetization settings\n");
+- ast_rtp_codec_setpref(pvt->rtp, &pvt->peer_prefs);
++ ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, &pvt->peer_prefs);
+ } else {
+ ast_debug(2, "Autoframing option not set, ignoring peer's packetization settings\n");
+- ast_rtp_codec_setpref(pvt->rtp, &pvt->options.prefs);
++ ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, &pvt->options.prefs);
+ }
+ }
+ }
+@@ -3132,19 +3131,19 @@
+ static struct ast_cli_entry cli_h323_reload =
+ AST_CLI_DEFINE(handle_cli_h323_reload, "Reload H.323 configuration");
+
+-static enum ast_rtp_get_result oh323_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
++static enum ast_rtp_glue_result oh323_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
+ {
+ struct oh323_pvt *pvt;
+- enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL;
++ enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_LOCAL;
+
+ if (!(pvt = (struct oh323_pvt *)chan->tech_pvt))
+- return AST_RTP_GET_FAILED;
++ return AST_RTP_GLUE_RESULT_FORBID;
+
+ ast_mutex_lock(&pvt->lock);
+- *rtp = pvt->rtp;
++ *instance = pvt->rtp ? ao2_ref(pvt->rtp, +1), pvt->rtp : NULL;
+ #if 0
+ if (pvt->options.bridge) {
+- res = AST_RTP_TRY_NATIVE;
++ res = AST_RTP_GLUE_RESULT_REMOTE;
+ }
+ #endif
+ ast_mutex_unlock(&pvt->lock);
+@@ -3152,11 +3151,6 @@
+ return res;
+ }
+
+-static enum ast_rtp_get_result oh323_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
+-{
+- return AST_RTP_GET_FAILED;
+-}
+-
+ static char *convertcap(int cap)
+ {
+ switch (cap) {
+@@ -3184,12 +3178,12 @@
+ }
+ }
+
+-static int oh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active)
++static int oh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, int codecs, int nat_active)
+ {
+ /* XXX Deal with Video */
+ struct oh323_pvt *pvt;
+- struct sockaddr_in them;
+- struct sockaddr_in us;
++ struct sockaddr_in them = { 0, };
++ struct sockaddr_in us = { 0, };
+ char *mode;
+
+ if (!rtp) {
+@@ -3202,19 +3196,18 @@
+ ast_log(LOG_ERROR, "No Private Structure, this is bad\n");
+ return -1;
+ }
+- ast_rtp_get_peer(rtp, &them);
+- ast_rtp_get_us(rtp, &us);
++ ast_rtp_instance_get_remote_address(rtp, &them);
++ ast_rtp_instance_get_local_address(rtp, &us);
+ #if 0 /* Native bridge still isn't ready */
+ h323_native_bridge(pvt->cd.call_token, ast_inet_ntoa(them.sin_addr), mode);
+ #endif
+ return 0;
+ }
+
+-static struct ast_rtp_protocol oh323_rtp = {
++static struct ast_rtp_glue oh323_rtp_glue = {
+ .type = "H323",
+ .get_rtp_info = oh323_get_rtp_peer,
+- .get_vrtp_info = oh323_get_vrtp_peer,
+- .set_rtp_peer = oh323_set_rtp_peer,
++ .update_peer = oh323_set_rtp_peer,
+ };
+
+ static enum ast_module_load_result load_module(void)
+@@ -3269,7 +3262,7 @@
+ }
+ ast_cli_register_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
+
+- ast_rtp_proto_register(&oh323_rtp);
++ ast_rtp_glue_register(&oh323_rtp_glue);
+
+ /* Register our callback functions */
+ h323_callback_register(setup_incoming_call,
+@@ -3290,7 +3283,7 @@
+ /* start the h.323 listener */
+ if (h323_start_listener(h323_signalling_port, bindaddr)) {
+ ast_log(LOG_ERROR, "Unable to create H323 listener.\n");
+- ast_rtp_proto_unregister(&oh323_rtp);
++ ast_rtp_glue_unregister(&oh323_rtp_glue);
+ ast_cli_unregister_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
+ ast_cli_unregister(&cli_h323_reload);
+ h323_end_process();
+@@ -3329,7 +3322,7 @@
+ ast_cli_unregister(&cli_h323_reload);
+
+ ast_channel_unregister(&oh323_tech);
+- ast_rtp_proto_unregister(&oh323_rtp);
++ ast_rtp_glue_unregister(&oh323_rtp_glue);
+
+ if (!ast_mutex_lock(&iflock)) {
+ /* hangup all interfaces if they have an owner */
+Index: channels/sig_analog.h
+===================================================================
+--- a/channels/sig_analog.h (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/channels/sig_analog.h (.../trunk) (revision 202568)
+@@ -0,0 +1,329 @@
++#ifndef _SIG_ANALOG_H
++#define _SIG_ANALOG_H
++/*
++ * Asterisk -- An open source telephony toolkit.
++ *
++ * Copyright (C) 1999 - 2009, Digium, Inc.
++ *
++ * Mark Spencer <markster@digium.com>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * 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.
++ */
++
++/*! \file
++ *
++ * \brief Interface header for analog signaling module
++ *
++ * \author Matthew Fredrickson <creslin@digium.com>
++ */
++
++#include "asterisk/channel.h"
++#include "asterisk/frame.h"
++
++/* Signalling types supported */
++enum analog_sigtype {
++ ANALOG_SIG_NONE = -1,
++ ANALOG_SIG_FXOLS = 1,
++ ANALOG_SIG_FXOKS,
++ ANALOG_SIG_FXOGS,
++ ANALOG_SIG_FXSLS,
++ ANALOG_SIG_FXSKS,
++ ANALOG_SIG_FXSGS,
++ ANALOG_SIG_EMWINK,
++ ANALOG_SIG_EM,
++ ANALOG_SIG_EM_E1,
++ ANALOG_SIG_FEATD,
++ ANALOG_SIG_FEATDMF,
++ ANALOG_SIG_E911,
++ ANALOG_SIG_FGC_CAMA,
++ ANALOG_SIG_FGC_CAMAMF,
++ ANALOG_SIG_FEATB,
++ ANALOG_SIG_SFWINK,
++ ANALOG_SIG_SF,
++ ANALOG_SIG_SF_FEATD,
++ ANALOG_SIG_SF_FEATDMF,
++ ANALOG_SIG_FEATDMF_TA,
++ ANALOG_SIG_SF_FEATB,
++};
++
++enum analog_tone {
++ ANALOG_TONE_RINGTONE = 0,
++ ANALOG_TONE_STUTTER,
++ ANALOG_TONE_CONGESTION,
++ ANALOG_TONE_DIALTONE,
++ ANALOG_TONE_DIALRECALL,
++ ANALOG_TONE_INFO,
++};
++
++enum analog_event {
++ ANALOG_EVENT_NONE = 0,
++ ANALOG_EVENT_DIALCOMPLETE,
++ ANALOG_EVENT_WINKFLASH,
++ ANALOG_EVENT_ONHOOK,
++ ANALOG_EVENT_RINGOFFHOOK,
++ ANALOG_EVENT_ALARM,
++ ANALOG_EVENT_NOALARM,
++ ANALOG_EVENT_HOOKCOMPLETE,
++ ANALOG_EVENT_POLARITY,
++ ANALOG_EVENT_RINGERON,
++ ANALOG_EVENT_RINGEROFF,
++ ANALOG_EVENT_RINGBEGIN,
++ ANALOG_EVENT_PULSE_START,
++ ANALOG_EVENT_ERROR,
++ ANALOG_EVENT_NEONMWI_ACTIVE,
++ ANALOG_EVENT_NEONMWI_INACTIVE,
++};
++
++enum analog_sub {
++ ANALOG_SUB_REAL = 0, /*!< Active call */
++ ANALOG_SUB_CALLWAIT, /*!< Call-Waiting call on hold */
++ ANALOG_SUB_THREEWAY, /*!< Three-way call */
++};
++
++enum analog_dsp_digitmode {
++ ANALOG_DIGITMODE_DTMF = 1,
++ ANALOG_DIGITMODE_MF,
++};
++
++enum analog_cid_start {
++ ANALOG_CID_START_POLARITY = 1,
++ ANALOG_CID_START_POLARITY_IN,
++ ANALOG_CID_START_RING,
++};
++
++#define ANALOG_MAX_CID 300
++
++enum dialop {
++ ANALOG_DIAL_OP_REPLACE = 2,
++};
++
++
++struct analog_dialoperation {
++ enum dialop op;
++ char dialstr[256];
++};
++
++struct analog_callback {
++ /* Unlock the private in the signalling private structure. This is used for three way calling madness. */
++ void (* const unlock_private)(void *pvt);
++ /* Lock the private in the signalling private structure. ... */
++ void (* const lock_private)(void *pvt);
++ /* Function which is called back to handle any other DTMF up events that are received. Called by analog_handle_event. Why is this
++ * important to use, instead of just directly using events received before they are passed into the library? Because sometimes,
++ * (CWCID) the library absorbs DTMF events received. */
++ void (* const handle_dtmfup)(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest);
++
++ int (* const get_event)(void *pvt);
++ int (* const wait_event)(void *pvt);
++ int (* const is_off_hook)(void *pvt);
++ int (* const is_dialing)(void *pvt, enum analog_sub sub);
++ /* Start a trunk type signalling protocol (everything except phone ports basically */
++ int (* const start)(void *pvt);
++ int (* const ring)(void *pvt);
++ int (* const flash)(void *pvt);
++ /*! \brief Set channel on hook */
++ int (* const on_hook)(void *pvt);
++ /*! \brief Set channel off hook */
++ int (* const off_hook)(void *pvt);
++ /* We're assuming that we're going to only wink on ANALOG_SUB_REAL - even though in the code there's an argument to the index
++ * function */
++ int (* const wink)(void *pvt, enum analog_sub sub);
++ int (* const dial_digits)(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop);
++ int (* const send_fsk)(void *pvt, struct ast_channel *ast, char *fsk);
++ int (* const play_tone)(void *pvt, enum analog_sub sub, enum analog_tone tone);
++
++ int (* const set_echocanceller)(void *pvt, int enable);
++ int (* const train_echocanceller)(void *pvt);
++ int (* const dsp_set_digitmode)(void *pvt, enum analog_dsp_digitmode mode);
++ int (* const dsp_reset_and_flush_digits)(void *pvt);
++ int (* const send_callerid)(void *pvt, int cwcid, struct ast_callerid *cid);
++ /* Returns 0 if CID received. Returns 1 if event received, and -1 if error. name and num are size ANALOG_MAX_CID */
++ int (* const get_callerid)(void *pvt, char *name, char *num, enum analog_event *ev, size_t timeout);
++ /* Start CID detection */
++ int (* const start_cid_detect)(void *pvt, int cid_signalling);
++ /* Stop CID detection */
++ int (* const stop_cid_detect)(void *pvt);
++
++ /* Play the CAS callwait tone on the REAL sub, then repeat after 10 seconds, and then stop */
++ int (* const callwait)(void *pvt);
++ /* Stop playing any CAS call waiting announcement tones that might be running on the REAL sub */
++ int (* const stop_callwait)(void *pvt);
++
++ /* Bearer control related (non signalling) callbacks */
++ int (* const allocate_sub)(void *pvt, enum analog_sub sub);
++ int (* const unallocate_sub)(void *pvt, enum analog_sub sub);
++ /*! This function is for swapping of the owners with the underlying subs. Typically it means you need to change the fds
++ * of the new owner to be the fds of the sub specified, for each of the two subs given */
++ void (* const swap_subs)(void *pvt, enum analog_sub a, struct ast_channel *new_a_owner, enum analog_sub b, struct ast_channel *new_b_owner);
++ struct ast_channel * (* const new_ast_channel)(void *pvt, int state, int startpbx, enum analog_sub sub);
++
++ /* Add the given sub to a conference */
++ int (* const conf_add)(void *pvt, enum analog_sub sub);
++ /* Delete the given sub from any conference that might be running on the channels */
++ int (* const conf_del)(void *pvt, enum analog_sub sub);
++
++ /* If you would like to do any optimizations after the conference members have been added and removed,
++ * you can do so here */
++ int (* const complete_conference_update)(void *pvt, int needconf);
++
++ /* This is called when there are no more subchannels on the given private that are left up,
++ * for any cleanup or whatever else you would like to do. Called from analog_hangup() */
++ void (* const all_subchannels_hungup)(void *pvt);
++
++ int (* const has_voicemail)(void *pvt);
++ int (* const check_for_conference)(void *pvt);
++ void (* const handle_notify_message)(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent);
++
++ /* callbacks for increasing and decreasing ss_thread_count, will handle locking and condition signal */
++ void (* const increase_ss_count)(void);
++ void (* const decrease_ss_count)(void);
++};
++
++
++
++#define READ_SIZE 160
++
++struct analog_subchannel {
++ struct ast_channel *owner;
++ struct ast_frame f; /*!< One frame for each channel. How did this ever work before? */
++ unsigned int needcallerid:1;
++ unsigned int inthreeway:1;
++ /* Have we allocated a subchannel yet or not */
++ unsigned int allocd:1;
++};
++
++struct analog_pvt {
++ /* Analog signalling type used in this private */
++ enum analog_sigtype sig;
++ /* To contain the private structure passed into the channel callbacks */
++ void *chan_pvt;
++ /* Callbacks for various functions needed by the analog API */
++ struct analog_callback *calls;
++ /* All members after this are giong to be transient, and most will probably change */
++ struct ast_channel *owner; /*!< Our current active owner (if applicable) */
++
++ struct analog_subchannel subs[3]; /*!< Sub-channels */
++ struct analog_dialoperation dop;
++
++ /* XXX: Option Variables - Set by allocator of private structure */
++ unsigned int answeronpolarityswitch:1;
++ unsigned int callreturn:1;
++ unsigned int cancallforward:1;
++ unsigned int canpark:1;
++ unsigned int dahditrcallerid:1; /*!< should we use the callerid from incoming call on dahdi transfer or not */
++ unsigned int hanguponpolarityswitch:1;
++ unsigned int immediate:1;
++ unsigned int permcallwaiting:1;
++ unsigned int permhidecallerid:1; /*!< Whether to hide our outgoing caller ID or not */
++ unsigned int pulse:1;
++ unsigned int threewaycalling:1;
++ unsigned int transfer:1;
++ unsigned int transfertobusy:1; /*!< allow flash-transfers to busy channels */
++ unsigned int use_callerid:1; /*!< Whether or not to use caller id on this channel */
++
++ /* Not used for anything but log messages. Could be just the TCID */
++ int channel; /*!< Channel Number or CRV */
++ enum analog_sigtype outsigmod;
++ int echotraining;
++ int cid_signalling; /*!< Asterisk callerid type we're using */
++ int polarityonanswerdelay;
++ int stripmsd;
++ enum analog_cid_start cid_start;
++ /* Number of rings to wait to send callerid on FXS. Set to 1 for US */
++ int sendcalleridafter;
++ int callwaitingcallerid;
++ char mohsuggest[MAX_MUSICCLASS];
++ char cid_num[AST_MAX_EXTENSION];
++ char cid_name[AST_MAX_EXTENSION];
++
++
++ /* XXX: All variables after this are internal */
++ unsigned int callwaiting:1;
++ unsigned int dialednone:1;
++ unsigned int dialing:1;
++ unsigned int dnd:1;
++ unsigned int echobreak:1;
++ unsigned int hidecallerid:1;
++ unsigned int outgoing:1;
++ unsigned int pulsedial:1; /*!< whether a pulse dial phone is detected */
++
++ char callwait_num[AST_MAX_EXTENSION];
++ char callwait_name[AST_MAX_EXTENSION];
++ char lastcid_num[AST_MAX_EXTENSION];
++ char lastcid_name[AST_MAX_EXTENSION];
++ struct ast_callerid cid;
++ int cidrings; /*!< Which ring to deliver CID on */
++ char echorest[20];
++ int polarity;
++ struct timeval polaritydelaytv;
++ char dialdest[256];
++ time_t guardtime; /*!< Must wait this much time before using for new call */
++ struct timeval flashtime; /*!< Last flash-hook time */
++ int whichwink; /*!< SIG_FEATDMF_TA Which wink are we on? */
++ char finaldial[64];
++ char *origcid_num; /*!< malloced original callerid */
++ char *origcid_name; /*!< malloced original callerid */
++ char call_forward[AST_MAX_EXTENSION];
++
++ /* Ast channel to pass to __ss_analog_thread */
++ void *ss_astchan;
++
++ /* All variables after this are definitely going to be audited */
++ unsigned int inalarm:1; //
++ unsigned int unknown_alarm:1;//
++
++ int callwaitcas;
++
++#if 0
++ int ringt; //
++ int ringt_base;
++#endif
++};
++
++struct analog_pvt * analog_new(enum analog_sigtype signallingtype, struct analog_callback *c, void *private_data);
++
++void analog_free(struct analog_pvt *p);
++
++int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int timeout);
++
++int analog_hangup(struct analog_pvt *p, struct ast_channel *ast);
++
++int analog_answer(struct analog_pvt *p, struct ast_channel *ast);
++
++struct ast_frame *analog_exception(struct analog_pvt *p, struct ast_channel *ast);
++
++struct ast_channel * analog_request(struct analog_pvt *p, int *callwait);
++
++int analog_available(struct analog_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched);
++
++int analog_handle_init_event(struct analog_pvt *i, int event);
++
++int analog_config_complete(struct analog_pvt *p);
++
++void analog_handle_dtmfup(struct analog_pvt *p, struct ast_channel *ast, enum analog_sub index, struct ast_frame **dest);
++
++enum analog_cid_start analog_str_to_cidstart(const char *value);
++
++const char *analog_cidstart_to_str(enum analog_cid_start cid_start);
++
++enum analog_sigtype analog_str_to_sigtype(const char *name);
++
++const char *analog_sigtype_to_str(enum analog_sigtype sigtype);
++
++unsigned int analog_str_to_cidtype(const char *name);
++
++const char *analog_cidtype_to_str(unsigned int cid_type);
++
++int analog_ss_thread_start(struct analog_pvt *p, struct ast_channel *ast);
++
++int analog_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, void *newp);
++
++#endif /* _SIG_ANSLOG_H */
+
+Property changes on: channels/sig_analog.h
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+
+Index: channels/chan_sip.c
+===================================================================
+--- a/channels/chan_sip.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/channels/chan_sip.c (.../trunk) (revision 202568)
+@@ -229,7 +229,7 @@
+ #include "asterisk/pbx.h"
+ #include "asterisk/sched.h"
+ #include "asterisk/io.h"
+-#include "asterisk/rtp.h"
++#include "asterisk/rtp_engine.h"
+ #include "asterisk/udptl.h"
+ #include "asterisk/acl.h"
+ #include "asterisk/manager.h"
+@@ -271,6 +271,7 @@
+ #include "asterisk/ast_version.h"
+ #include "asterisk/event.h"
+ #include "asterisk/tcptls.h"
++#include "asterisk/stun.h"
+
+ /*** DOCUMENTATION
+ <application name="SIPDtmfMode" language="en_US">
+@@ -472,6 +473,79 @@
+ Check the <literal>domain=</literal> configuration in <filename>sip.conf</filename>.</para>
+ </description>
+ </function>
++ <manager name="SIPpeers" language="en_US">
++ <synopsis>
++ List SIP peers (text format).
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ </syntax>
++ <description>
++ <para>Lists SIP peers in text format with details on current status.
++ Peerlist will follow as separate events, followed by a final event called
++ PeerlistComplete.</para>
++ </description>
++ </manager>
++ <manager name="SIPshowpeer" language="en_US">
++ <synopsis>
++ show SIP peer (text format).
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Peer" required="true">
++ <para>The peer name you want to check.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Show one SIP peer with details on current status.</para>
++ </description>
++ </manager>
++ <manager name="SIPqualifypeer" language="en_US">
++ <synopsis>
++ Qualify SIP peers.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Peer" required="true">
++ <para>The peer name you want to qualify.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Qualify a SIP peer.</para>
++ </description>
++ </manager>
++ <manager name="SIPshowregistry" language="en_US">
++ <synopsis>
++ Show SIP registrations (text format).
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ </syntax>
++ <description>
++ <para>Lists all registration requests and status. Registrations will follow as separate
++ events. followed by a final event called RegistrationsComplete.</para>
++ </description>
++ </manager>
++ <manager name="SIPnotify" language="en_US">
++ <synopsis>
++ Send a SIP notify.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Channel" required="true">
++ <para>Peer to receive the notify.</para>
++ </parameter>
++ <parameter name="Variable" required="true">
++ <para>At least one variable pair must be specified.
++ <replaceable>name</replaceable>=<replaceable>value</replaceable></para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Sends a SIP Notify event.</para>
++ <para>All parameters for this event must be specified in the body of this request
++ via multiple Variable: name=value sequences.</para>
++ </description>
++ </manager>
+ ***/
+
+ #ifndef FALSE
+@@ -691,6 +765,7 @@
+ AUTH_PEER_NOT_DYNAMIC = -6,
+ AUTH_ACL_FAILED = -7,
+ AUTH_BAD_TRANSPORT = -8,
++ AUTH_RTP_FAILED = 9,
+ };
+
+ /*! \brief States for outbound registrations (with register= lines in sip.conf */
+@@ -940,12 +1015,60 @@
+ { SIP_OPT_TARGET_DIALOG,NOT_SUPPORTED, "tdialog" },
+ };
+
++/*! \brief Diversion header reasons
++ *
++ * The core defines a bunch of constants used to define
++ * redirecting reasons. This provides a translation table
++ * between those and the strings which may be present in
++ * a SIP Diversion header
++ */
++static const struct sip_reasons {
++ enum AST_REDIRECTING_REASON code;
++ char * const text;
++} sip_reason_table[] = {
++ { AST_REDIRECTING_REASON_UNKNOWN, "unknown" },
++ { AST_REDIRECTING_REASON_USER_BUSY, "user-busy" },
++ { AST_REDIRECTING_REASON_NO_ANSWER, "no-answer" },
++ { AST_REDIRECTING_REASON_UNAVAILABLE, "unavailable" },
++ { AST_REDIRECTING_REASON_UNCONDITIONAL, "unconditional" },
++ { AST_REDIRECTING_REASON_TIME_OF_DAY, "time-of-day" },
++ { AST_REDIRECTING_REASON_DO_NOT_DISTURB, "do-not-disturb" },
++ { AST_REDIRECTING_REASON_DEFLECTION, "deflection" },
++ { AST_REDIRECTING_REASON_FOLLOW_ME, "follow-me" },
++ { AST_REDIRECTING_REASON_OUT_OF_ORDER, "out-of-service" },
++ { AST_REDIRECTING_REASON_AWAY, "away" },
++ { AST_REDIRECTING_REASON_CALL_FWD_DTE, "unknown"}
++};
+
++static enum AST_REDIRECTING_REASON sip_reason_str_to_code(const char *text)
++{
++ enum AST_REDIRECTING_REASON ast = AST_REDIRECTING_REASON_UNKNOWN;
++ int i;
++
++ for (i = 0; i < ARRAY_LEN(sip_reason_table); ++i) {
++ if (!strcasecmp(text, sip_reason_table[i].text)) {
++ ast = sip_reason_table[i].code;
++ break;
++ }
++ }
++
++ return ast;
++}
++
++static const char *sip_reason_code_to_str(enum AST_REDIRECTING_REASON code)
++{
++ if (code >= 0 && code < ARRAY_LEN(sip_reason_table)) {
++ return sip_reason_table[code].text;
++ }
++
++ return "unknown";
++}
++
+ /*! \brief SIP Methods we support
+ \todo This string should be set dynamically. We only support REFER and SUBSCRIBE if we have
+ allowsubscribe and allowrefer on in sip.conf.
+ */
+-#define ALLOWED_METHODS "INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY"
++#define ALLOWED_METHODS "INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO"
+
+ /*! \brief SIP Extensions we support
+ \note This should be generated based on the previous array
+@@ -980,6 +1103,7 @@
+ #define DEFAULT_MOHSUGGEST ""
+ #define DEFAULT_VMEXTEN "asterisk" /*!< Default voicemail extension */
+ #define DEFAULT_CALLERID "asterisk" /*!< Default caller ID */
++#define DEFAULT_MWI_FROM ""
+ #define DEFAULT_NOTIFYMIME "application/simple-message-summary"
+ #define DEFAULT_ALLOWGUEST TRUE
+ #define DEFAULT_RTPKEEPALIVE 0 /*!< Default RTPkeepalive setting */
+@@ -1011,6 +1135,7 @@
+ #define DEFAULT_USERAGENT "Asterisk PBX" /*!< Default Useragent: header unless re-defined in sip.conf */
+ #define DEFAULT_SDPSESSION "Asterisk PBX" /*!< Default SDP session name, (s=) header unless re-defined in sip.conf */
+ #define DEFAULT_SDPOWNER "root" /*!< Default SDP username field in (o=) header unless re-defined in sip.conf */
++#define DEFAULT_ENGINE "asterisk" /*!< Default RTP engine to use for sessions */
+ #endif
+ /*@}*/
+
+@@ -1021,6 +1146,7 @@
+ /*@{*/
+ static char default_language[MAX_LANGUAGE];
+ static char default_callerid[AST_MAX_EXTENSION];
++static char default_mwi_from[80];
+ static char default_fromdomain[AST_MAX_EXTENSION];
+ static char default_notifymime[AST_MAX_EXTENSION];
+ static int default_qualify; /*!< Default Qualify= setting */
+@@ -1029,6 +1155,7 @@
+ static char default_mohsuggest[MAX_MUSICCLASS]; /*!< Global setting for moh class to suggest when putting
+ * a bridged channel on hold */
+ static char default_parkinglot[AST_MAX_CONTEXT]; /*!< Parkinglot */
++static char default_engine[256]; /*!< Default RTP engine */
+ static int default_maxcallbitrate; /*!< Maximum bitrate for call */
+ static struct ast_codec_pref default_prefs; /*!< Default codec prefs */
+ static unsigned int default_transports; /*!< Default Transports (enum sip_transport) that are acceptable */
+@@ -1095,8 +1222,8 @@
+ static unsigned int global_cos_audio; /*!< 802.1p class of service for audio RTP packets */
+ static unsigned int global_cos_video; /*!< 802.1p class of service for video RTP packets */
+ static unsigned int global_cos_text; /*!< 802.1p class of service for text RTP packets */
+-static int recordhistory; /*!< Record SIP history. Off by default */
+-static int dumphistory; /*!< Dump history to verbose before destroying SIP dialog */
++static unsigned int recordhistory; /*!< Record SIP history. Off by default */
++static unsigned int dumphistory; /*!< Dump history to verbose before destroying SIP dialog */
+ static char global_regcontext[AST_MAX_CONTEXT]; /*!< Context for auto-extensions */
+ static char global_useragent[AST_MAX_EXTENSION]; /*!< Useragent for the SIP channel */
+ static char global_sdpsession[AST_MAX_EXTENSION]; /*!< SDP session name for the SIP channel */
+@@ -1105,7 +1232,7 @@
+ static int global_t1; /*!< T1 time */
+ static int global_t1min; /*!< T1 roundtrip time minimum */
+ static int global_timer_b; /*!< Timer B - RFC 3261 Section 17.1.1.2 */
+-static int global_autoframing; /*!< Turn autoframing on or off. */
++static unsigned int global_autoframing; /*!< Turn autoframing on or off. */
+ static int global_qualifyfreq; /*!< Qualify frequency */
+ static int global_qualify_gap; /*!< Time between our group of peer pokes */
+ static int global_qualify_peers; /*!< Number of peers to poke at a given time */
+@@ -1350,7 +1477,10 @@
+ #define SIP_PROG_INBAND_NO (1 << 25)
+ #define SIP_PROG_INBAND_YES (2 << 25)
+
+-#define SIP_SENDRPID (1 << 29) /*!< DP: Remote Party-ID Support */
++#define SIP_SENDRPID (3 << 29) /*!< DP: Remote Party-ID Support */
++#define SIP_SENDRPID_NO (0 << 29)
++#define SIP_SENDRPID_PAI (1 << 29) /*!< Use "P-Asserted-Identity" for rpid */
++#define SIP_SENDRPID_RPID (2 << 29) /*!< Use "Remote-Party-ID" for rpid */
+ #define SIP_G726_NONSTANDARD (1 << 31) /*!< DP: Use non-standard packing for G726-32 data */
+
+ /*! \brief Flags to copy from peer/user to dialog */
+@@ -1366,10 +1496,14 @@
+ /* realtime flags */
+ #define SIP_PAGE2_RTCACHEFRIENDS (1 << 0) /*!< GP: Should we keep RT objects in memory for extended time? */
+ #define SIP_PAGE2_RTAUTOCLEAR (1 << 2) /*!< GP: Should we clean memory from peers after expiry? */
++#define SIP_PAGE2_RPID_UPDATE (1 << 3)
+ /* Space for addition of other realtime flags in the future */
+ #define SIP_PAGE2_STATECHANGEQUEUE (1 << 9) /*!< D: Unsent state pending change exists */
+
+-#define SIP_PAGE2_RPORT_PRESENT (1 << 10) /*!< Was rport received in the Via header? */
++#define SIP_PAGE2_CONNECTLINEUPDATE_PEND (1 << 10)
++#define SIP_PAGE2_RPID_IMMEDIATE (1 << 11)
++#define SIP_PAGE2_RPORT_PRESENT (1 << 12) /*!< Was rport received in the Via header? */
++#define SIP_PAGE2_PREFERRED_CODEC (1 << 13) /*!< GDP: Only respond with single most preferred joint codec */
+ #define SIP_PAGE2_VIDEOSUPPORT (1 << 14) /*!< DP: Video supported if offered? */
+ #define SIP_PAGE2_TEXTSUPPORT (1 << 15) /*!< GDP: Global text enable */
+ #define SIP_PAGE2_ALLOWSUBSCRIBE (1 << 16) /*!< GP: Allow subscriptions from this peer? */
+@@ -1399,7 +1533,8 @@
+ (SIP_PAGE2_ALLOWSUBSCRIBE | SIP_PAGE2_ALLOWOVERLAP | SIP_PAGE2_IGNORESDPVERSION | \
+ SIP_PAGE2_VIDEOSUPPORT | SIP_PAGE2_T38SUPPORT | SIP_PAGE2_RFC2833_COMPENSATE | \
+ SIP_PAGE2_BUGGY_MWI | SIP_PAGE2_TEXTSUPPORT | SIP_PAGE2_FAX_DETECT | \
+- SIP_PAGE2_UDPTL_DESTINATION | SIP_PAGE2_VIDEOSUPPORT_ALWAYS)
++ SIP_PAGE2_UDPTL_DESTINATION | SIP_PAGE2_VIDEOSUPPORT_ALWAYS | SIP_PAGE2_PREFERRED_CODEC | \
++ SIP_PAGE2_RPID_IMMEDIATE | SIP_PAGE2_RPID_UPDATE)
+
+ /*@}*/
+
+@@ -1604,13 +1739,13 @@
+ AST_STRING_FIELD(peermd5secret);
+ AST_STRING_FIELD(cid_num); /*!< Caller*ID number */
+ AST_STRING_FIELD(cid_name); /*!< Caller*ID name */
++ AST_STRING_FIELD(mwi_from); /*!< Name to place in the From header in outgoing NOTIFY requests */
+ AST_STRING_FIELD(fullcontact); /*!< The Contact: that the UA registers with us */
+ /* we only store the part in <brackets> in this field. */
+ AST_STRING_FIELD(our_contact); /*!< Our contact header */
+- AST_STRING_FIELD(rpid); /*!< Our RPID header */
+- AST_STRING_FIELD(rpid_from); /*!< Our RPID From header */
+ AST_STRING_FIELD(url); /*!< URL to be sent with next message to peer */
+ AST_STRING_FIELD(parkinglot); /*!< Parkinglot */
++ AST_STRING_FIELD(engine); /*!< RTP engine to use */
+ );
+ char via[128]; /*!< Via: header */
+ struct sip_socket socket; /*!< The socket used for this dialog */
+@@ -1622,15 +1757,21 @@
+ int lastnoninvite; /*!< Last Cseq of non-invite */
+ struct ast_flags flags[2]; /*!< SIP_ flags */
+
+- /* boolean or small integers that don't belong in flags */
+- char do_history; /*!< Set if we want to record history */
+- char alreadygone; /*!< already destroyed by our peer */
+- char needdestroy; /*!< need to be destroyed by the monitor thread */
+- char outgoing_call; /*!< this is an outgoing call */
+- char answered_elsewhere; /*!< This call is cancelled due to answer on another channel */
+- char novideo; /*!< Didn't get video in invite, don't offer */
+- char notext; /*!< Text not supported (?) */
+-
++ /* boolean flags that don't belong in flags */
++ unsigned short do_history:1; /*!< Set if we want to record history */
++ unsigned short alreadygone:1; /*!< already destroyed by our peer */
++ unsigned short needdestroy:1; /*!< need to be destroyed by the monitor thread */
++ unsigned short outgoing_call:1; /*!< this is an outgoing call */
++ unsigned short answered_elsewhere:1; /*!< This call is cancelled due to answer on another channel */
++ unsigned short novideo:1; /*!< Didn't get video in invite, don't offer */
++ unsigned short notext:1; /*!< Text not supported (?) */
++ unsigned short session_modify:1; /*!< Session modification request true/false */
++ unsigned short route_persistent:1; /*!< Is this the "real" route? */
++ unsigned short autoframing:1; /*!< Whether to use our local configuration for frame sizes (off)
++ * or respect the other endpoint's request for frame sizes (on)
++ * for incoming calls
++ */
++ char tag[11]; /*!< Our tag for this session */
+ int timer_t1; /*!< SIP timer T1, ms rtt */
+ int timer_b; /*!< SIP timer B, ms */
+ unsigned int sipoptions; /*!< Supported SIP options on the other end */
+@@ -1644,20 +1785,19 @@
+ int jointnoncodeccapability; /*!< Joint Non codec capability */
+ int redircodecs; /*!< Redirect codecs */
+ int maxcallbitrate; /*!< Maximum Call Bitrate for Video Calls */
++ int request_queue_sched_id; /*!< Scheduler ID of any scheduled action to process queued requests */
++ int authtries; /*!< Times we've tried to authenticate */
+ struct sip_proxy *outboundproxy; /*!< Outbound proxy for this dialog. Use ref_proxy to set this instead of setting it directly*/
+ struct t38properties t38; /*!< T38 settings */
+ struct sockaddr_in udptlredirip; /*!< Where our T.38 UDPTL should be going if not to us */
+ struct ast_udptl *udptl; /*!< T.38 UDPTL session */
+ int callingpres; /*!< Calling presentation */
+- int authtries; /*!< Times we've tried to authenticate */
+ int expiry; /*!< How long we take to expire */
++ int sessionversion; /*!< SDP Session Version */
++ int sessionid; /*!< SDP Session ID */
+ long branch; /*!< The branch identifier of this session */
+ long invite_branch; /*!< The branch used when we sent the initial INVITE */
+- char tag[11]; /*!< Our tag for this session */
+- int sessionid; /*!< SDP Session ID */
+- int sessionversion; /*!< SDP Session Version */
+- uint64_t sessionversion_remote; /*!< Remote UA's SDP Session Version */
+- int session_modify; /*!< Session modification request true/false */
++ int64_t sessionversion_remote; /*!< Remote UA's SDP Session Version */
+ struct sockaddr_in sa; /*!< Our peer */
+ struct sockaddr_in redirip; /*!< Where our RTP should be going if not to us */
+ struct sockaddr_in vredirip; /*!< Where our Video RTP should be going if not to us */
+@@ -1667,9 +1807,9 @@
+ int rtptimeout; /*!< RTP timeout time */
+ struct sockaddr_in recv; /*!< Received as */
+ struct sockaddr_in ourip; /*!< Our IP (as seen from the outside) */
++ enum transfermodes allowtransfer; /*!< REFER: restriction scheme */
+ struct ast_channel *owner; /*!< Who owns us (if we have an owner) */
+ struct sip_route *route; /*!< Head of linked list of routing steps (fm Record-Route) */
+- int route_persistant; /*!< Is this the "real" route? */
+ struct ast_variable *notify_headers; /*!< Custom notify type */
+ struct sip_auth *peerauth; /*!< Realm authentication */
+ int noncecount; /*!< Nonce-count */
+@@ -1687,38 +1827,37 @@
+ int waitid; /*!< Wait ID for scheduler after 491 or other delays */
+ int autokillid; /*!< Auto-kill ID (scheduler) */
+ int t38id; /*!< T.38 Response ID */
+- enum transfermodes allowtransfer; /*!< REFER: restriction scheme */
+ struct sip_refer *refer; /*!< REFER: SIP transfer data structure */
+ enum subscriptiontype subscribed; /*!< SUBSCRIBE: Is this dialog a subscription? */
+ int stateid; /*!< SUBSCRIBE: ID for devicestate subscriptions */
+ int laststate; /*!< SUBSCRIBE: Last known extension state */
+ int dialogver; /*!< SUBSCRIBE: Version for subscription dialog-info */
+
+- struct ast_dsp *vad; /*!< Inband DTMF Detection dsp */
++ struct ast_dsp *dsp; /*!< Inband DTMF Detection dsp */
+
+ struct sip_peer *relatedpeer; /*!< If this dialog is related to a peer, which one
+ Used in peerpoke, mwi subscriptions */
+ struct sip_registry *registry; /*!< If this is a REGISTER dialog, to which registry */
+- struct ast_rtp *rtp; /*!< RTP Session */
+- struct ast_rtp *vrtp; /*!< Video RTP session */
+- struct ast_rtp *trtp; /*!< Text RTP session */
++ struct ast_rtp_instance *rtp; /*!< RTP Session */
++ struct ast_rtp_instance *vrtp; /*!< Video RTP session */
++ struct ast_rtp_instance *trtp; /*!< Text RTP session */
+ struct sip_pkt *packets; /*!< Packets scheduled for re-transmission */
+ struct sip_history_head *history; /*!< History of this SIP dialog */
+ size_t history_entries; /*!< Number of entires in the history */
+ struct ast_variable *chanvars; /*!< Channel variables to set for inbound call */
+ AST_LIST_HEAD_NOLOCK(request_queue, sip_request) request_queue; /*!< Requests that arrived but could not be processed immediately */
+- int request_queue_sched_id; /*!< Scheduler ID of any scheduled action to process queued requests */
+ struct sip_invite_param *options; /*!< Options for INVITE */
+- int autoframing; /*!< The number of Asters we group in a Pyroflax
+- before strolling to the Grokyzpå
+- (A bit unsure of this, please correct if
+- you know more) */
+ struct sip_st_dlg *stimer; /*!< SIP Session-Timers */
+
+ int red; /*!< T.140 RTP Redundancy */
+ int hangupcause; /*!< Storage of hangupcause copied from our owner before we disconnect from the AST channel (only used at hangup) */
+
+ struct sip_subscription_mwi *mwi; /*!< If this is a subscription MWI dialog, to which subscription */
++ /*! The SIP methods allowed on this dialog. We get this information from the Allow header present in
++ * the peer's REGISTER. If peer does not register with us, then we will use the first transaction we
++ * have with this peer to determine its allowed methods.
++ */
++ unsigned int allowed_methods;
+ };
+
+
+@@ -1730,7 +1869,7 @@
+ * the container and individual items, and functions to add/remove
+ * references to the individual items.
+ */
+-struct ao2_container *dialogs;
++static struct ao2_container *dialogs;
+
+ #define sip_pvt_lock(x) ao2_lock(x)
+ #define sip_pvt_trylock(x) ao2_trylock(x)
+@@ -1791,6 +1930,7 @@
+ int seqno; /*!< Sequence number */
+ char is_resp; /*!< 1 if this is a response packet (e.g. 200 OK), 0 if it is a request */
+ char is_fatal; /*!< non-zero if there is a fatal error */
++ int response_code; /*!< If this is a response, the response code */
+ struct sip_pvt *owner; /*!< Owner AST call */
+ int retransid; /*!< Retransmission ID */
+ int timer_a; /*!< SIP timer A, retransmission timer */
+@@ -1844,11 +1984,23 @@
+ AST_STRING_FIELD(mohsuggest); /*!< Music on Hold class */
+ AST_STRING_FIELD(parkinglot); /*!< Parkinglot */
+ AST_STRING_FIELD(useragent); /*!< User agent in SIP request (saved from registration) */
++ AST_STRING_FIELD(mwi_from); /*!< Name to place in From header for outgoing NOTIFY requests */
++ AST_STRING_FIELD(engine); /*!< RTP Engine to use */
+ );
+ struct sip_socket socket; /*!< Socket used for this peer */
+ enum sip_transport default_outbound_transport; /*!< Peer Registration may change the default outbound transport.
+- If register expires, default should be reset. to this value */
+- unsigned int transports:3; /*!< Transports (enum sip_transport) that are acceptable for this peer */
++ If register expires, default should be reset. to this value */
++ /* things that don't belong in flags */
++ unsigned short transports:3; /*!< Transports (enum sip_transport) that are acceptable for this peer */
++ unsigned short is_realtime:1; /*!< this is a 'realtime' peer */
++ unsigned short rt_fromcontact:1;/*!< copy fromcontact from realtime */
++ unsigned short host_dynamic:1; /*!< Dynamic Peers register with Asterisk */
++ unsigned short selfdestruct:1; /*!< Automatic peers need to destruct themselves */
++ unsigned short the_mark:1; /*!< moved out of ASTOBJ into struct proper; That which bears the_mark should be deleted! */
++ unsigned short autoframing:1; /*!< Whether to use our local configuration for frame sizes (off)
++ * or respect the other endpoint's request for frame sizes (on)
++ * for incoming calls
++ */
+ struct sip_auth *auth; /*!< Realm authentication list */
+ int amaflags; /*!< AMA Flags (for billing) */
+ int callingpres; /*!< Calling id presentation */
+@@ -1866,13 +2018,7 @@
+ /*! Mailboxes that this peer cares about */
+ AST_LIST_HEAD_NOLOCK(, sip_mailbox) mailboxes;
+
+- /* things that don't belong in flags */
+- char is_realtime; /*!< this is a 'realtime' peer */
+- char rt_fromcontact; /*!< copy fromcontact from realtime */
+- char host_dynamic; /*!< Dynamic Peers register with Asterisk */
+- char selfdestruct; /*!< Automatic peers need to destruct themselves */
+- char the_mark; /*!< moved out of ASTOBJ into struct proper; That which bears the_mark should be deleted! */
+-
++ int maxcallbitrate; /*!< Maximum Bitrate for a video call */
+ int expire; /*!< When to expire this peer registration */
+ int capability; /*!< Codec capability */
+ int rtptimeout; /*!< RTP timeout */
+@@ -1883,8 +2029,6 @@
+ struct sip_proxy *outboundproxy; /*!< Outbound proxy for this peer */
+ struct ast_dnsmgr_entry *dnsmgr;/*!< DNS refresh manager for peer */
+ struct sockaddr_in addr; /*!< IP address of peer */
+- int maxcallbitrate; /*!< Maximum Bitrate for a video call */
+-
+ /* Qualification */
+ struct sip_pvt *call; /*!< Call pointer */
+ int pokeexpire; /*!< When to expire poke (qualify= checking) */
+@@ -1897,7 +2041,6 @@
+ struct ast_ha *contactha; /*!< Restrict what IPs are allowed in the Contact header (for registration) */
+ struct ast_variable *chanvars; /*!< Variables to set for channel created by user */
+ struct sip_pvt *mwipvt; /*!< Subscription for MWI */
+- int autoframing;
+ struct sip_st_cfg stimer; /*!< SIP Session-Timers */
+ int timer_t1; /*!< The maximum T1 value for the peer */
+ int timer_b; /*!< The maximum timer B (transaction timeouts) */
+@@ -1905,6 +2048,7 @@
+
+ /*XXX Seems like we suddenly have two flags with the same content. Why? To be continued... */
+ enum sip_peer_type type; /*!< Distinguish between "user" and "peer" types. This is used solely for CLI and manager commands */
++ unsigned int allowed_methods;
+ };
+
+
+@@ -1919,12 +2063,6 @@
+ * or once the previously completed registration one expires).
+ * The registration can be in one of many states, though at the moment
+ * the handling is a bit mixed.
+- *
+- * XXX \todo Reference count handling for this object has some problems with
+- * respect to scheduler entries. The ref count is handled in some places,
+- * but not all of them. There are some places where references get leaked
+- * when this scheduler entry gets cancelled. At worst, this would cause
+- * memory leaks on reloads if registrations get removed from configuration.
+ */
+ struct sip_registry {
+ ASTOBJ_COMPONENTS_FULL(struct sip_registry,1,1);
+@@ -2005,8 +2143,8 @@
+ static AST_LIST_HEAD_STATIC(threadl, sip_threadinfo);
+
+ /*! \brief The peer list: Users, Peers and Friends */
+-struct ao2_container *peers;
+-struct ao2_container *peers_by_ip;
++static struct ao2_container *peers;
++static struct ao2_container *peers_by_ip;
+
+ /*! \brief The register list: Other SIP proxies we register with and place calls to */
+ static struct ast_register_list {
+@@ -2215,6 +2353,7 @@
+ static int sip_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
+ static int sip_senddigit_begin(struct ast_channel *ast, char digit);
+ static int sip_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration);
++static int sip_setoption(struct ast_channel *chan, int option, void *data, int datalen);
+ static int sip_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
+ static const char *sip_get_callid(struct ast_channel *chan);
+
+@@ -2233,7 +2372,7 @@
+ static int transmit_response(struct sip_pvt *p, const char *msg, const struct sip_request *req);
+ static int transmit_response_reliable(struct sip_pvt *p, const char *msg, const struct sip_request *req);
+ static int transmit_response_with_date(struct sip_pvt *p, const char *msg, const struct sip_request *req);
+-static int transmit_response_with_sdp(struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable, int oldsdp);
++static int transmit_response_with_sdp(struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable, int oldsdp, int rpid);
+ static int transmit_response_with_unsupported(struct sip_pvt *p, const char *msg, const struct sip_request *req, const char *unsupported);
+ static int transmit_response_with_auth(struct sip_pvt *p, const char *msg, const struct sip_request *req, const char *rand, enum xmittype reliable, const char *header, int stale);
+ static int transmit_response_with_allow(struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable);
+@@ -2254,12 +2393,12 @@
+ static int send_request(struct sip_pvt *p, struct sip_request *req, enum xmittype reliable, int seqno);
+ static void copy_request(struct sip_request *dst, const struct sip_request *src);
+ static void receive_message(struct sip_pvt *p, struct sip_request *req);
+-static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req);
++static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req, char **name, char **number, int set_call_forward);
+ static int sip_send_mwi_to_peer(struct sip_peer *peer, const struct ast_event *event, int cache_only);
+
+ /*--- Dialog management */
+ static struct sip_pvt *sip_alloc(ast_string_field callid, struct sockaddr_in *sin,
+- int useglobal_nat, const int intended_method);
++ int useglobal_nat, const int intended_method, struct sip_request *req);
+ static int __sip_autodestruct(const void *data);
+ static void sip_scheddestroy(struct sip_pvt *p, int ms);
+ static int sip_cancel_destroy(struct sip_pvt *p);
+@@ -2279,7 +2418,7 @@
+ static void list_route(struct sip_route *route);
+ static void build_route(struct sip_pvt *p, struct sip_request *req, int backwards);
+ static enum check_auth_result register_verify(struct sip_pvt *p, struct sockaddr_in *sin,
+- struct sip_request *req, char *uri);
++ struct sip_request *req, const char *uri);
+ static struct sip_pvt *get_sip_pvt_byid_locked(const char *callid, const char *totag, const char *fromtag);
+ static void check_pendings(struct sip_pvt *p);
+ static void *sip_park_thread(void *stuff);
+@@ -2307,11 +2446,11 @@
+ static int build_reply_digest(struct sip_pvt *p, int method, char *digest, int digest_len);
+ static enum check_auth_result check_auth(struct sip_pvt *p, struct sip_request *req, const char *username,
+ const char *secret, const char *md5secret, int sipmethod,
+- char *uri, enum xmittype reliable, int ignore);
++ const char *uri, enum xmittype reliable, int ignore);
+ static enum check_auth_result check_user_full(struct sip_pvt *p, struct sip_request *req,
+- int sipmethod, char *uri, enum xmittype reliable,
++ int sipmethod, const char *uri, enum xmittype reliable,
+ struct sockaddr_in *sin, struct sip_peer **authpeer);
+-static int check_user(struct sip_pvt *p, struct sip_request *req, int sipmethod, char *uri, enum xmittype reliable, struct sockaddr_in *sin);
++static int check_user(struct sip_pvt *p, struct sip_request *req, int sipmethod, const char *uri, enum xmittype reliable, struct sockaddr_in *sin);
+
+ /*--- Domain handling */
+ static int check_sip_domain(const char *domain, char *context, size_t len); /* Check if domain is one of our local domains */
+@@ -2416,13 +2555,13 @@
+ static char *sip_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
+ static char *sip_show_channelstats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
+ static char *sip_show_history(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
+-static char *sip_do_debug_ip(int fd, char *arg);
+-static char *sip_do_debug_peer(int fd, char *arg);
++static char *sip_do_debug_ip(int fd, const char *arg);
++static char *sip_do_debug_peer(int fd, const char *arg);
+ static char *sip_do_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
+ static char *sip_cli_notify(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
+ static char *sip_set_history(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
+-static int sip_dtmfmode(struct ast_channel *chan, void *data);
+-static int sip_addheader(struct ast_channel *chan, void *data);
++static int sip_dtmfmode(struct ast_channel *chan, const char *data);
++static int sip_addheader(struct ast_channel *chan, const char *data);
+ static int sip_do_reload(enum channelreloadreason reason);
+ static char *sip_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
+ static int acf_channel_read(struct ast_channel *chan, const char *funcname, char *preparse, char *buf, size_t buflen);
+@@ -2443,7 +2582,6 @@
+ static void sip_dump_history(struct sip_pvt *dialog);
+
+ /*--- Device object handling */
+-static struct sip_peer *temp_peer(const char *name);
+ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime);
+ static int update_call_counter(struct sip_pvt *fup, int event);
+ static void sip_destroy_peer(struct sip_peer *peer);
+@@ -2458,6 +2596,7 @@
+ static void destroy_association(struct sip_peer *peer);
+ static void set_insecure_flags(struct ast_flags *flags, const char *value, int lineno);
+ static int handle_common_options(struct ast_flags *flags, struct ast_flags *mask, struct ast_variable *v);
++static void set_socket_transport(struct sip_socket *socket, int transport);
+
+ /* Realtime device support */
+ static void realtime_update_peer(const char *peername, struct sockaddr_in *sin, const char *username, const char *fullcontact, const char *useragent, int expirey, int deprecated_username, int lastms);
+@@ -2468,7 +2607,7 @@
+ static char *sip_prune_realtime(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
+
+ /*--- Internal UA client handling (outbound registrations) */
+-static void ast_sip_ouraddrfor(struct in_addr *them, struct sockaddr_in *us);
++static void ast_sip_ouraddrfor(struct in_addr *them, struct sockaddr_in *us, struct sip_pvt *p);
+ static void sip_registry_destroy(struct sip_registry *reg);
+ static int sip_register(const char *value, int lineno);
+ static const char *regstate2str(enum sipregistrystate regstate) attribute_const;
+@@ -2485,6 +2624,8 @@
+ static const char *gettag(const struct sip_request *req, const char *header, char *tagbuf, int tagbufsize);
+ static int find_sip_method(const char *msg);
+ static unsigned int parse_sip_options(struct sip_pvt *pvt, const char *supported);
++static unsigned int parse_allowed_methods(struct sip_request *req);
++static unsigned int set_pvt_allowed_methods(struct sip_pvt *pvt, struct sip_request *req);
+ static int parse_request(struct sip_request *req);
+ static const char *get_header(const struct sip_request *req, const char *name);
+ static const char *referstatus2str(enum referstatus rstatus) attribute_pure;
+@@ -2502,11 +2643,14 @@
+ static int set_address_from_contact(struct sip_pvt *pvt);
+ static void check_via(struct sip_pvt *p, struct sip_request *req);
+ static char *get_calleridname(const char *input, char *output, size_t outputsize);
+-static int get_rpid_num(const char *input, char *output, int maxlen);
+-static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq);
++static int get_rpid(struct sip_pvt *p, struct sip_request *oreq);
++static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq, char **name, char **number, int *reason);
+ static int get_destination(struct sip_pvt *p, struct sip_request *oreq);
+ static int get_msg_text(char *buf, int len, struct sip_request *req, int addnewline);
+ static int transmit_state_notify(struct sip_pvt *p, int state, int full, int timeout);
++static void update_connectedline(struct sip_pvt *p, const void *data, size_t datalen);
++static void update_redirecting(struct sip_pvt *p, const void *data, size_t datalen);
++static void change_redirecting_information(struct sip_pvt *p, struct sip_request *req, struct ast_party_redirecting *redirecting, int set_call_forward);
+
+ /*-- TCP connection handling ---*/
+ static void *_sip_tcp_helper_thread(struct sip_pvt *pvt, struct ast_tcptls_session_instance *tcptls_session);
+@@ -2533,6 +2677,7 @@
+ static int add_line(struct sip_request *req, const char *line);
+ static int add_text(struct sip_request *req, const char *text);
+ static int add_digit(struct sip_request *req, char digit, unsigned int duration, int mode);
++static int add_rpid(struct sip_request *req, struct sip_pvt *p);
+ static int add_vidupdate(struct sip_request *req);
+ static void add_route(struct sip_request *req, struct sip_route *route);
+ static int copy_header(struct sip_request *req, const struct sip_request *orig, const char *field);
+@@ -2541,39 +2686,31 @@
+ static void set_destination(struct sip_pvt *p, char *uri);
+ static void append_date(struct sip_request *req);
+ static void build_contact(struct sip_pvt *p);
+-static void build_rpid(struct sip_pvt *p);
+
+ /*------Request handling functions */
+ static int handle_incoming(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, int *recount, int *nounlock);
+-static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int debug, int seqno, struct sockaddr_in *sin, int *recount, char *e, int *nounlock);
++static int handle_request_update(struct sip_pvt *p, struct sip_request *req);
++static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int debug, int seqno, struct sockaddr_in *sin, int *recount, const char *e, int *nounlock);
+ static int handle_request_refer(struct sip_pvt *p, struct sip_request *req, int debug, int seqno, int *nounlock);
+ static int handle_request_bye(struct sip_pvt *p, struct sip_request *req);
+-static int handle_request_register(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, char *e);
++static int handle_request_register(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, const char *e);
+ static int handle_request_cancel(struct sip_pvt *p, struct sip_request *req);
+ static int handle_request_message(struct sip_pvt *p, struct sip_request *req);
+-static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, int seqno, char *e);
++static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, int seqno, const char *e);
+ static void handle_request_info(struct sip_pvt *p, struct sip_request *req);
+ static int handle_request_options(struct sip_pvt *p, struct sip_request *req);
+ static int handle_invite_replaces(struct sip_pvt *p, struct sip_request *req, int debug, int seqno, struct sockaddr_in *sin);
+-static int handle_request_notify(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, int seqno, char *e);
++static int handle_request_notify(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, int seqno, const char *e);
+ static int local_attended_transfer(struct sip_pvt *transferer, struct sip_dual *current, struct sip_request *req, int seqno);
+
+ /*------Response handling functions */
+-static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno);
+-static void handle_response_notify(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno);
+-static void handle_response_refer(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno);
+-static void handle_response_subscribe(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno);
+-static int handle_response_register(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno);
+-static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno);
++static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno);
++static void handle_response_notify(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno);
++static void handle_response_refer(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno);
++static void handle_response_subscribe(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno);
++static int handle_response_register(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno);
++static void handle_response(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno);
+
+-/*----- RTP interface functions */
+-static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active);
+-static enum ast_rtp_get_result sip_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp);
+-static enum ast_rtp_get_result sip_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp **rtp);
+-static enum ast_rtp_get_result sip_get_trtp_peer(struct ast_channel *chan, struct ast_rtp **rtp);
+-static int sip_get_codec(struct ast_channel *chan);
+-static struct ast_frame *sip_rtp_read(struct ast_channel *ast, struct sip_pvt *p, int *faxdetect);
+-
+ /*------ T38 Support --------- */
+ static int transmit_response_with_t38_sdp(struct sip_pvt *p, char *msg, struct sip_request *req, int retrans);
+ static struct ast_udptl *sip_get_udptl_peer(struct ast_channel *chan);
+@@ -2594,6 +2731,9 @@
+ static enum st_mode st_get_mode(struct sip_pvt *);
+ static struct sip_st_dlg* sip_st_alloc(struct sip_pvt *const p);
+
++/*------- RTP Glue functions -------- */
++static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *instance, struct ast_rtp_instance *vinstance, struct ast_rtp_instance *tinstance, int codecs, int nat_active);
++
+ /*!--- SIP MWI Subscription support */
+ static int sip_subscribe_mwi(const char *value, int lineno);
+ static void sip_subscribe_mwi_destroy(struct sip_subscription_mwi *mwi);
+@@ -2622,10 +2762,11 @@
+ .fixup = sip_fixup, /* called with chan locked */
+ .send_digit_begin = sip_senddigit_begin, /* called with chan unlocked */
+ .send_digit_end = sip_senddigit_end,
+- .bridge = ast_rtp_bridge, /* XXX chan unlocked ? */
+- .early_bridge = ast_rtp_early_bridge,
++ .bridge = ast_rtp_instance_bridge, /* XXX chan unlocked ? */
++ .early_bridge = ast_rtp_instance_early_bridge,
+ .send_text = sip_sendtext, /* called with chan locked */
+ .func_channel_read = acf_channel_read,
++ .setoption = sip_setoption,
+ .queryoption = sip_queryoption,
+ .get_pvt_uniqueid = sip_get_callid,
+ };
+@@ -2696,17 +2837,6 @@
+ return errorvalue;
+ }
+
+-
+-/*! \brief Interface structure with callbacks used to connect to RTP module */
+-static struct ast_rtp_protocol sip_rtp = {
+- .type = "SIP",
+- .get_rtp_info = sip_get_rtp_peer,
+- .get_vrtp_info = sip_get_vrtp_peer,
+- .get_trtp_info = sip_get_trtp_peer,
+- .set_rtp_peer = sip_set_rtp_peer,
+- .get_codec = sip_get_codec,
+-};
+-
+ /*!
+ * duplicate a list of channel variables, \return the copy.
+ */
+@@ -2777,14 +2907,14 @@
+ reqcpy.data = str_save;
+ ast_str_reset(reqcpy.data);
+
+- req.socket.fd = tcptls_session->fd;
+ if (tcptls_session->ssl) {
+- req.socket.type = SIP_TRANSPORT_TLS;
++ set_socket_transport(&req.socket, SIP_TRANSPORT_TLS);
+ req.socket.port = htons(ourport_tls);
+ } else {
+- req.socket.type = SIP_TRANSPORT_TCP;
++ set_socket_transport(&req.socket, SIP_TRANSPORT_TCP);
+ req.socket.port = htons(ourport_tcp);
+ }
++ req.socket.fd = tcptls_session->fd;
+ res = ast_wait_for_input(tcptls_session->fd, -1);
+ if (res < 0) {
+ ast_debug(2, "SIP %s server :: ast_wait_for_input returned %d\n", tcptls_session->ssl ? "SSL": "TCP", res);
+@@ -3270,8 +3400,9 @@
+ */
+ static inline const char *get_transport_pvt(struct sip_pvt *p)
+ {
+- if (p->outboundproxy && p->outboundproxy->transport)
+- p->socket.type = p->outboundproxy->transport;
++ if (p->outboundproxy && p->outboundproxy->transport) {
++ set_socket_transport(&p->socket, p->outboundproxy->transport);
++ }
+
+ return get_transport(p->socket.type);
+ }
+@@ -3346,7 +3477,7 @@
+ * externip or can get away with our internal bindaddr
+ * 'us' is always overwritten.
+ */
+-static void ast_sip_ouraddrfor(struct in_addr *them, struct sockaddr_in *us)
++static void ast_sip_ouraddrfor(struct in_addr *them, struct sockaddr_in *us, struct sip_pvt *p)
+ {
+ struct sockaddr_in theirs;
+ /* Set want_remap to non-zero if we want to remap 'us' to an externally
+@@ -3390,10 +3521,34 @@
+ ast_log(LOG_WARNING, "stun failed\n");
+ ast_debug(1, "Target address %s is not local, substituting externip\n",
+ ast_inet_ntoa(*(struct in_addr *)&them->s_addr));
++ } else if (p) {
++ /* no remapping, but we bind to a specific address, so use it. */
++ switch (p->socket.type) {
++ case SIP_TRANSPORT_TCP:
++ if (sip_tcp_desc.local_address.sin_addr.s_addr) {
++ *us = sip_tcp_desc.local_address;
++ } else {
++ us->sin_port = sip_tcp_desc.local_address.sin_port;
++ }
++ break;
++ case SIP_TRANSPORT_TLS:
++ if (sip_tls_desc.local_address.sin_addr.s_addr) {
++ *us = sip_tls_desc.local_address;
++ } else {
++ us->sin_port = sip_tls_desc.local_address.sin_port;
++ }
++ break;
++ case SIP_TRANSPORT_UDP:
++ /* fall through on purpose */
++ default:
++ if (bindaddr.sin_addr.s_addr) {
++ *us = bindaddr;
++ }
++ }
+ } else if (bindaddr.sin_addr.s_addr) {
+- /* no remapping, but we bind to a specific address, so use it. */
+ *us = bindaddr;
+ }
++ ast_debug(3, "Setting SIP_TRANSPORT_%s with address %s:%d\n", get_transport(p->socket.type), ast_inet_ntoa(us->sin_addr), ntohs(us->sin_port));
+ }
+
+ /*! \brief Append to SIP dialog history with arg list */
+@@ -3573,6 +3728,7 @@
+ struct sip_pkt *pkt = NULL;
+ int siptimer_a = DEFAULT_RETRANS;
+ int xmitres = 0;
++ int respid;
+
+ if (sipmethod == SIP_INVITE) {
+ /* Note this is a pending invite */
+@@ -3609,6 +3765,12 @@
+ pkt->owner = dialog_ref(p, "__sip_reliable_xmit: setting pkt->owner");
+ pkt->next = p->packets;
+ p->packets = pkt; /* Add it to the queue */
++ if (resp) {
++ /* Parse out the response code */
++ if (sscanf(ast_str_buffer(pkt->data), "SIP/2.0 %d", &respid) == 1) {
++ pkt->response_code = respid;
++ }
++ }
+ pkt->timer_t1 = p->timer_t1; /* Set SIP timer T1 */
+ pkt->retransid = -1;
+ if (pkt->timer_t1)
+@@ -3916,12 +4078,74 @@
+ return res;
+ }
+
++static void enable_digit_detect(struct sip_pvt *p)
++{
++ if (p->dsp) {
++ return;
++ }
++
++ if (!(p->dsp = ast_dsp_new())) {
++ return;
++ }
++
++ ast_dsp_set_features(p->dsp, DSP_FEATURE_DIGIT_DETECT);
++ if (global_relaxdtmf) {
++ ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | DSP_DIGITMODE_RELAXDTMF);
++ }
++}
++
++static void disable_digit_detect(struct sip_pvt *p)
++{
++ if (p->dsp) {
++ ast_dsp_free(p->dsp);
++ p->dsp = NULL;
++ }
++}
++
++/*! \brief Set an option on a SIP dialog */
++static int sip_setoption(struct ast_channel *chan, int option, void *data, int datalen)
++{
++ int res = -1;
++ struct sip_pvt *p = chan->tech_pvt;
++
++ switch (option) {
++ case AST_OPTION_FORMAT_READ:
++ res = ast_rtp_instance_set_read_format(p->rtp, *(int *) data);
++ break;
++ case AST_OPTION_FORMAT_WRITE:
++ res = ast_rtp_instance_set_write_format(p->rtp, *(int *) data);
++ break;
++ case AST_OPTION_MAKE_COMPATIBLE:
++ res = ast_rtp_instance_make_compatible(chan, p->rtp, (struct ast_channel *) data);
++ break;
++ case AST_OPTION_DIGIT_DETECT:
++ if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) ||
++ (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) {
++ char *cp = (char *) data;
++
++ ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
++ if (*cp) {
++ enable_digit_detect(p);
++ } else {
++ disable_digit_detect(p);
++ }
++ res = 0;
++ }
++ break;
++ default:
++ break;
++ }
++
++ return res;
++}
++
+ /*! \brief Query an option on a SIP dialog */
+ static int sip_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
+ {
+ int res = -1;
+ enum ast_t38_state state = T38_STATE_UNAVAILABLE;
+ struct sip_pvt *p = (struct sip_pvt *) chan->tech_pvt;
++ char *cp;
+
+ switch (option) {
+ case AST_OPTION_T38_STATE:
+@@ -3955,6 +4179,11 @@
+ res = 0;
+
+ break;
++ case AST_OPTION_DIGIT_DETECT:
++ cp = (char *) data;
++ *cp = p->dsp ? 1 : 0;
++ ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
++ break;
+ default:
+ break;
+ }
+@@ -4642,11 +4871,11 @@
+
+ if (p->rtp) {
+ ast_debug(1, "Setting NAT on RTP to %s\n", mode);
+- ast_rtp_setnat(p->rtp, natflags);
++ ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_NAT, natflags);
+ }
+ if (p->vrtp) {
+ ast_debug(1, "Setting NAT on VRTP to %s\n", mode);
+- ast_rtp_setnat(p->vrtp, natflags);
++ ast_rtp_instance_set_prop(p->vrtp, AST_RTP_PROPERTY_NAT, natflags);
+ }
+ if (p->udptl) {
+ ast_debug(1, "Setting NAT on UDPTL to %s\n", mode);
+@@ -4654,7 +4883,7 @@
+ }
+ if (p->trtp) {
+ ast_debug(1, "Setting NAT on TRTP to %s\n", mode);
+- ast_rtp_setnat(p->trtp, natflags);
++ ast_rtp_instance_set_prop(p->trtp, AST_RTP_PROPERTY_NAT, natflags);
+ }
+ }
+
+@@ -4746,6 +4975,53 @@
+ *to_sock = *from_sock;
+ }
+
++/*! \brief Initialize RTP portion of a dialog
++ * \returns -1 on failure, 0 on success
++ */
++static int dialog_initialize_rtp(struct sip_pvt *dialog)
++{
++ if (!sip_methods[dialog->method].need_rtp) {
++ return 0;
++ }
++
++ if (!(dialog->rtp = ast_rtp_instance_new(dialog->engine, sched, &bindaddr, NULL))) {
++ return -1;
++ }
++
++ if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT) && (dialog->capability & AST_FORMAT_VIDEO_MASK)) {
++ if (!(dialog->vrtp = ast_rtp_instance_new(dialog->engine, sched, &bindaddr, NULL))) {
++ return -1;
++ }
++ ast_rtp_instance_set_timeout(dialog->vrtp, global_rtptimeout);
++ ast_rtp_instance_set_hold_timeout(dialog->vrtp, global_rtpholdtimeout);
++
++ ast_rtp_instance_set_prop(dialog->vrtp, AST_RTP_PROPERTY_RTCP, 1);
++ }
++
++ if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_TEXTSUPPORT)) {
++ if (!(dialog->trtp = ast_rtp_instance_new(dialog->engine, sched, &bindaddr, NULL))) {
++ return -1;
++ }
++ ast_rtp_instance_set_timeout(dialog->trtp, global_rtptimeout);
++ ast_rtp_instance_set_hold_timeout(dialog->trtp, global_rtpholdtimeout);
++
++ ast_rtp_instance_set_prop(dialog->trtp, AST_RTP_PROPERTY_RTCP, 1);
++ }
++
++ ast_rtp_instance_set_timeout(dialog->rtp, global_rtptimeout);
++ ast_rtp_instance_set_hold_timeout(dialog->rtp, global_rtpholdtimeout);
++
++ ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_RTCP, 1);
++ ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF, ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
++ ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_test_flag(&dialog->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
++
++ ast_rtp_instance_set_qos(dialog->rtp, global_tos_audio, 0, "SIP RTP");
++
++ do_setnat(dialog, ast_test_flag(&dialog->flags[0], SIP_NAT) & SIP_NAT_ROUTE);
++
++ return 0;
++}
++
+ /*! \brief Create address structure from peer reference.
+ * This function copies data from peer to the dialog, so we don't have to look up the peer
+ * again from memory or database during the life time of the dialog.
+@@ -4773,17 +5049,6 @@
+ ast_copy_flags(&dialog->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY);
+ ast_copy_flags(&dialog->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY);
+ dialog->capability = peer->capability;
+- if (!ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT_ALWAYS) &&
+- (!ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT) ||
+- !(dialog->capability & AST_FORMAT_VIDEO_MASK)) &&
+- dialog->vrtp) {
+- ast_rtp_destroy(dialog->vrtp);
+- dialog->vrtp = NULL;
+- }
+- if (!ast_test_flag(&dialog->flags[1], SIP_PAGE2_TEXTSUPPORT) && dialog->trtp) {
+- ast_rtp_destroy(dialog->trtp);
+- dialog->trtp = NULL;
+- }
+ dialog->prefs = peer->prefs;
+ if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_T38SUPPORT)) {
+ if (!dialog->udptl) {
+@@ -4797,31 +5062,29 @@
+ ast_udptl_destroy(dialog->udptl);
+ dialog->udptl = NULL;
+ }
+- do_setnat(dialog, ast_test_flag(&dialog->flags[0], SIP_NAT) & SIP_NAT_ROUTE);
+
++ ast_string_field_set(dialog, engine, peer->engine);
++
++ if (dialog_initialize_rtp(dialog)) {
++ return -1;
++ }
++
+ if (dialog->rtp) { /* Audio */
+- ast_rtp_setdtmf(dialog->rtp, ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
+- ast_rtp_setdtmfcompensate(dialog->rtp, ast_test_flag(&dialog->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
+- ast_rtp_set_rtptimeout(dialog->rtp, peer->rtptimeout);
+- ast_rtp_set_rtpholdtimeout(dialog->rtp, peer->rtpholdtimeout);
+- ast_rtp_set_rtpkeepalive(dialog->rtp, peer->rtpkeepalive);
++ ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF, ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
++ ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_test_flag(&dialog->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
++ ast_rtp_instance_set_timeout(dialog->rtp, peer->rtptimeout);
++ ast_rtp_instance_set_hold_timeout(dialog->rtp, peer->rtpholdtimeout);
+ /* Set Frame packetization */
+- ast_rtp_codec_setpref(dialog->rtp, &dialog->prefs);
++ ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(dialog->rtp), dialog->rtp, &dialog->prefs);
+ dialog->autoframing = peer->autoframing;
+ }
+ if (dialog->vrtp) { /* Video */
+- ast_rtp_setdtmf(dialog->vrtp, 0);
+- ast_rtp_setdtmfcompensate(dialog->vrtp, 0);
+- ast_rtp_set_rtptimeout(dialog->vrtp, peer->rtptimeout);
+- ast_rtp_set_rtpholdtimeout(dialog->vrtp, peer->rtpholdtimeout);
+- ast_rtp_set_rtpkeepalive(dialog->vrtp, peer->rtpkeepalive);
++ ast_rtp_instance_set_timeout(dialog->vrtp, peer->rtptimeout);
++ ast_rtp_instance_set_hold_timeout(dialog->vrtp, peer->rtpholdtimeout);
+ }
+ if (dialog->trtp) { /* Realtime text */
+- ast_rtp_setdtmf(dialog->trtp, 0);
+- ast_rtp_setdtmfcompensate(dialog->trtp, 0);
+- ast_rtp_set_rtptimeout(dialog->trtp, peer->rtptimeout);
+- ast_rtp_set_rtpholdtimeout(dialog->trtp, peer->rtpholdtimeout);
+- ast_rtp_set_rtpkeepalive(dialog->trtp, peer->rtpkeepalive);
++ ast_rtp_instance_set_timeout(dialog->trtp, peer->rtptimeout);
++ ast_rtp_instance_set_hold_timeout(dialog->trtp, peer->rtpholdtimeout);
+ }
+
+ ast_string_field_set(dialog, peername, peer->name);
+@@ -4834,7 +5097,11 @@
+ ast_string_field_set(dialog, tohost, peer->tohost);
+ ast_string_field_set(dialog, fullcontact, peer->fullcontact);
+ ast_string_field_set(dialog, context, peer->context);
++ ast_string_field_set(dialog, cid_num, peer->cid_num);
++ ast_string_field_set(dialog, cid_name, peer->cid_name);
++ ast_string_field_set(dialog, mwi_from, peer->mwi_from);
+ ast_string_field_set(dialog, parkinglot, peer->parkinglot);
++ ast_string_field_set(dialog, engine, peer->engine);
+ ref_proxy(dialog, obproxy_get(dialog, peer));
+ dialog->callgroup = peer->callgroup;
+ dialog->pickupgroup = peer->pickupgroup;
+@@ -4843,6 +5110,7 @@
+ dialog->rtptimeout = peer->rtptimeout;
+ dialog->peerauth = peer->auth;
+ dialog->maxcallbitrate = peer->maxcallbitrate;
++ dialog->allowed_methods = peer->allowed_methods;
+ if (ast_strlen_zero(dialog->tohost))
+ ast_string_field_set(dialog, tohost, ast_inet_ntoa(dialog->sa.sin_addr));
+ if (!ast_strlen_zero(peer->fromdomain)) {
+@@ -4918,8 +5186,9 @@
+
+ if (peer) {
+ int res;
+- if (newdialog)
+- dialog->socket.type = 0;
++ if (newdialog) {
++ set_socket_transport(&dialog->socket, 0);
++ }
+ res = create_addr_from_peer(dialog, peer);
+ if (!ast_strlen_zero(port)) {
+ if ((portno = atoi(port))) {
+@@ -4930,7 +5199,9 @@
+ return res;
+ }
+
+- do_setnat(dialog, ast_test_flag(&dialog->flags[0], SIP_NAT) & SIP_NAT_ROUTE);
++ if (dialog_initialize_rtp(dialog)) {
++ return -1;
++ }
+
+ ast_string_field_set(dialog, tohost, peername);
+
+@@ -4981,7 +5252,7 @@
+ }
+
+ if (!dialog->socket.type)
+- dialog->socket.type = SIP_TRANSPORT_UDP;
++ set_socket_transport(&dialog->socket, SIP_TRANSPORT_UDP);
+ if (!dialog->socket.port)
+ dialog->socket.port = bindaddr.sin_port;
+ dialog->sa.sin_port = htons(portno);
+@@ -5075,7 +5346,7 @@
+ return res;
+ }
+ p->callingpres = ast->cid.cid_pres;
+- p->jointcapability = ast_translate_available_formats(p->capability, p->prefcodec);
++ p->jointcapability = ast_rtp_instance_available_formats(p->rtp, p->capability, p->prefcodec);
+ p->jointnoncodeccapability = p->noncodeccapability;
+
+ /* If there are no audio formats left to offer, punt */
+@@ -5088,11 +5359,13 @@
+ p->t38.jointcapability = p->t38.capability;
+ ast_debug(2, "Our T38 capability (%d), joint T38 capability (%d)\n", p->t38.capability, p->t38.jointcapability);
+
++ sip_pvt_lock(p);
+ xmitres = transmit_invite(p, SIP_INVITE, 1, 2);
++ sip_pvt_unlock(p);
+ if (xmitres == XMIT_ERROR)
+ return -1;
+ p->invitestate = INV_CALLING;
+-
++
+ /* Initialize auto-congest time */
+ AST_SCHED_REPLACE_UNREF(p->initid, sched, p->timer_b, auto_congest, p,
+ dialog_unref(_data, "dialog ptr dec when SCHED_REPLACE del op succeeded"),
+@@ -5199,15 +5472,13 @@
+ p->notify_headers = NULL;
+ }
+ if (p->rtp) {
+- ast_rtp_destroy(p->rtp);
++ ast_rtp_instance_destroy(p->rtp);
+ }
+ if (p->vrtp) {
+- ast_rtp_destroy(p->vrtp);
++ ast_rtp_instance_destroy(p->vrtp);
+ }
+ if (p->trtp) {
+- while (ast_rtp_get_bridged(p->trtp))
+- usleep(1);
+- ast_rtp_destroy(p->trtp);
++ ast_rtp_instance_destroy(p->trtp);
+ }
+ if (p->udptl)
+ ast_udptl_destroy(p->udptl);
+@@ -5506,6 +5777,16 @@
+ case 606: /* Not acceptable */
+ return AST_CAUSE_BEARERCAPABILITY_NOTAVAIL;
+ default:
++ if (cause < 500 && cause >= 400) {
++ /* 4xx class error that is unknown - someting wrong with our request */
++ return AST_CAUSE_INTERWORKING;
++ } else if (cause < 600 && cause >= 500) {
++ /* 5xx class error - problem in the remote end */
++ return AST_CAUSE_CONGESTION;
++ } else if (cause < 700 && cause >= 600) {
++ /* 6xx - global errors in the 4xx class */
++ return AST_CAUSE_INTERWORKING;
++ }
+ return AST_CAUSE_NORMAL;
+ }
+ /* Never reached */
+@@ -5591,7 +5872,6 @@
+ return 0;
+ }
+
+-
+ /*! \brief sip_hangup: Hangup SIP call
+ * Part of PBX interface, called from ast_hangup */
+ static int sip_hangup(struct ast_channel *ast)
+@@ -5670,8 +5950,7 @@
+ append_history(p, needcancel ? "Cancel" : "Hangup", "Cause %s", p->owner ? ast_cause2str(p->hangupcause) : "Unknown");
+
+ /* Disconnect */
+- if (p->vad)
+- ast_dsp_free(p->vad);
++ disable_digit_detect(p);
+
+ p->owner = NULL;
+ ast->tech_pvt = dialog_unref(ast->tech_pvt, "unref ast->tech_pvt");
+@@ -5726,58 +6005,62 @@
+
+ if (!p->pendinginvite) {
+ struct ast_channel *bridge = ast_bridged_channel(oldowner);
+- char *audioqos = "";
+- char *videoqos = "";
+- char *textqos = "";
++ char quality_buf[AST_MAX_USER_FIELD], *quality;
+
+- /* We need to get the lock on bridge because ast_rtp_set_vars will attempt
++ /* We need to get the lock on bridge because ast_rtp_instance_set_stats_vars will attempt
+ * to lock the bridge. This may get hairy...
+ */
+ while (bridge && ast_channel_trylock(bridge)) {
+- struct ast_channel *chan = p->owner;
+ sip_pvt_unlock(p);
+ do {
+- /* Use chan since p->owner could go NULL on us
+- * while p is unlocked
+- */
+- CHANNEL_DEADLOCK_AVOIDANCE(chan);
++ CHANNEL_DEADLOCK_AVOIDANCE(oldowner);
+ } while (sip_pvt_trylock(p));
+- bridge = p->owner ? ast_bridged_channel(p->owner) : NULL;
++ bridge = ast_bridged_channel(oldowner);
+ }
+
+- if (p->rtp)
+- ast_rtp_set_vars(oldowner, p->rtp);
++ if (p->rtp) {
++ ast_rtp_instance_set_stats_vars(oldowner, p->rtp);
++ }
+
+ if (bridge) {
+ struct sip_pvt *q = bridge->tech_pvt;
+
+- if (IS_SIP_TECH(bridge->tech) && q && q->rtp)
+- ast_rtp_set_vars(bridge, q->rtp);
++ if (IS_SIP_TECH(bridge->tech) && q && q->rtp) {
++ ast_rtp_instance_set_stats_vars(bridge, q->rtp);
++ }
+ ast_channel_unlock(bridge);
+ }
+
+- if (p->vrtp)
+- videoqos = ast_rtp_get_quality(p->vrtp, NULL, RTPQOS_SUMMARY);
+- if (p->trtp)
+- textqos = ast_rtp_get_quality(p->trtp, NULL, RTPQOS_SUMMARY);
++ if (p->do_history || oldowner) {
++ if (p->rtp && (quality = ast_rtp_instance_get_quality(p->rtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, quality_buf, sizeof(quality_buf)))) {
++ if (p->do_history) {
++ append_history(p, "RTCPaudio", "Quality:%s", quality);
++ }
++ if (oldowner) {
++ pbx_builtin_setvar_helper(oldowner, "RTPAUDIOQOS", quality);
++ }
++ }
++ if (p->vrtp && (quality = ast_rtp_instance_get_quality(p->vrtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, quality_buf, sizeof(quality_buf)))) {
++ if (p->do_history) {
++ append_history(p, "RTCPvideo", "Quality:%s", quality);
++ }
++ if (oldowner) {
++ pbx_builtin_setvar_helper(oldowner, "RTPVIDEOQOS", quality);
++ }
++ }
++ if (p->trtp && (quality = ast_rtp_instance_get_quality(p->trtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, quality_buf, sizeof(quality_buf)))) {
++ if (p->do_history) {
++ append_history(p, "RTCPtext", "Quality:%s", quality);
++ }
++ if (oldowner) {
++ pbx_builtin_setvar_helper(oldowner, "RTPTEXTQOS", quality);
++ }
++ }
++ }
++
+ /* Send a hangup */
+ transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, 1);
+
+- /* Get RTCP quality before end of call */
+- if (p->do_history) {
+- if (p->rtp)
+- append_history(p, "RTCPaudio", "Quality:%s", audioqos);
+- if (p->vrtp)
+- append_history(p, "RTCPvideo", "Quality:%s", videoqos);
+- if (p->trtp)
+- append_history(p, "RTCPtext", "Quality:%s", textqos);
+- }
+- if (p->rtp && oldowner)
+- pbx_builtin_setvar_helper(oldowner, "RTPAUDIOQOS", audioqos);
+- if (p->vrtp && oldowner)
+- pbx_builtin_setvar_helper(oldowner, "RTPVIDEOQOS", videoqos);
+- if (p->trtp && oldowner)
+- pbx_builtin_setvar_helper(oldowner, "RTPTEXTQOS", textqos);
+ } else {
+ /* Note we will need a BYE when this all settles out
+ but we can't send one while we have "INVITE" outstanding. */
+@@ -5801,9 +6084,27 @@
+ {
+ int fmt;
+ const char *codec;
++ struct ast_channel* chan;
+
+- codec = pbx_builtin_getvar_helper(p->owner, "SIP_CODEC");
+- if (!codec)
++ chan = ast_channel_ref(p->owner);
++ while (ast_channel_trylock(chan)) {
++ sip_pvt_unlock(p);
++ sched_yield();
++ sip_pvt_lock(p);
++ }
++
++ if (p->outgoing_call) {
++ codec = pbx_builtin_getvar_helper(p->owner, "SIP_CODEC_OUTBOUND");
++ } else if (!(codec = pbx_builtin_getvar_helper(p->owner, "SIP_CODEC_INBOUND"))) {
++ codec = pbx_builtin_getvar_helper(p->owner, "SIP_CODEC");
++ }
++
++ codec = ast_strdupa(S_OR(codec, ""));
++
++ ast_channel_unlock(chan);
++ chan = ast_channel_unref(chan);
++
++ if (ast_strlen_zero(codec))
+ return;
+
+ fmt = ast_getformatbyname(codec);
+@@ -5832,8 +6133,11 @@
+
+ ast_setstate(ast, AST_STATE_UP);
+ ast_debug(1, "SIP answering channel: %s\n", ast->name);
+- ast_rtp_new_source(p->rtp);
+- res = transmit_response_with_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL, FALSE);
++ if (p->t38.state == T38_PEER_DIRECT) {
++ change_t38_state(p, T38_ENABLED);
++ }
++ ast_rtp_instance_new_source(p->rtp);
++ res = transmit_response_with_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL, FALSE, TRUE);
+ ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
+ }
+ sip_pvt_unlock(p);
+@@ -5867,16 +6171,16 @@
+ if ((ast->_state != AST_STATE_UP) &&
+ !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) &&
+ !ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
+- ast_rtp_new_source(p->rtp);
++ ast_rtp_instance_new_source(p->rtp);
+ p->invitestate = INV_EARLY_MEDIA;
+- transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE, FALSE);
+- ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
++ transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE, FALSE, FALSE);
++ ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
+ } else if (p->t38.state == T38_ENABLED && !p->t38.direct) {
+ change_t38_state(p, T38_DISABLED);
+ transmit_reinvite_with_sdp(p, FALSE, FALSE);
+ } else {
+ p->lastrtptx = time(NULL);
+- res = ast_rtp_write(p->rtp, frame);
++ res = ast_rtp_instance_write(p->rtp, frame);
+ }
+ }
+ sip_pvt_unlock(p);
+@@ -5891,11 +6195,11 @@
+ !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) &&
+ !ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
+ p->invitestate = INV_EARLY_MEDIA;
+- transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE, FALSE);
+- ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
++ transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE, FALSE, FALSE);
++ ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
+ }
+ p->lastrtptx = time(NULL);
+- res = ast_rtp_write(p->vrtp, frame);
++ res = ast_rtp_instance_write(p->vrtp, frame);
+ }
+ sip_pvt_unlock(p);
+ }
+@@ -5904,7 +6208,7 @@
+ if (p) {
+ sip_pvt_lock(p);
+ if (p->red) {
+- red_buffer_t140(p->trtp, frame);
++ ast_rtp_red_buffer(p->trtp, frame);
+ } else {
+ if (p->trtp) {
+ /* Activate text early media */
+@@ -5912,11 +6216,11 @@
+ !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) &&
+ !ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
+ p->invitestate = INV_EARLY_MEDIA;
+- transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE, FALSE);
+- ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
++ transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE, FALSE, FALSE);
++ ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
+ }
+ p->lastrtptx = time(NULL);
+- res = ast_rtp_write(p->trtp, frame);
++ res = ast_rtp_instance_write(p->trtp, frame);
+ }
+ }
+ sip_pvt_unlock(p);
+@@ -6004,11 +6308,15 @@
+ sip_pvt_lock(p);
+ switch (ast_test_flag(&p->flags[0], SIP_DTMF)) {
+ case SIP_DTMF_INBAND:
+- res = -1; /* Tell Asterisk to generate inband indications */
++ if (p->rtp && ast_rtp_instance_dtmf_mode_get(p->rtp) == AST_RTP_DTMF_MODE_INBAND) {
++ ast_rtp_instance_dtmf_begin(p->rtp, digit);
++ } else {
++ res = -1; /* Tell Asterisk to generate inband indications */
++ }
+ break;
+ case SIP_DTMF_RFC2833:
+ if (p->rtp)
+- ast_rtp_senddigit_begin(p->rtp, digit);
++ ast_rtp_instance_dtmf_begin(p->rtp, digit);
+ break;
+ default:
+ break;
+@@ -6033,10 +6341,14 @@
+ break;
+ case SIP_DTMF_RFC2833:
+ if (p->rtp)
+- ast_rtp_senddigit_end(p->rtp, digit);
++ ast_rtp_instance_dtmf_end(p->rtp, digit);
+ break;
+ case SIP_DTMF_INBAND:
+- res = -1; /* Tell Asterisk to stop inband indications */
++ if (p->rtp && ast_rtp_instance_dtmf_mode_get(p->rtp) == AST_RTP_DTMF_MODE_INBAND) {
++ ast_rtp_instance_dtmf_end(p->rtp, digit);
++ } else {
++ res = -1; /* Tell Asterisk to stop inband indications */
++ }
+ break;
+ }
+ sip_pvt_unlock(p);
+@@ -6124,18 +6436,18 @@
+ !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) &&
+ !ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
+ p->invitestate = INV_EARLY_MEDIA;
+- transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE, FALSE);
+- ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
++ transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE, FALSE, FALSE);
++ ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
+ break;
+ }
+ res = -1;
+ break;
+ case AST_CONTROL_HOLD:
+- ast_rtp_new_source(p->rtp);
++ ast_rtp_instance_new_source(p->rtp);
+ ast_moh_start(ast, data, p->mohinterpret);
+ break;
+ case AST_CONTROL_UNHOLD:
+- ast_rtp_new_source(p->rtp);
++ ast_rtp_instance_new_source(p->rtp);
+ ast_moh_stop(ast);
+ break;
+ case AST_CONTROL_VIDUPDATE: /* Request a video frame update */
+@@ -6181,8 +6493,14 @@
+ }
+ break;
+ case AST_CONTROL_SRCUPDATE:
+- ast_rtp_new_source(p->rtp);
++ ast_rtp_instance_new_source(p->rtp);
+ break;
++ case AST_CONTROL_CONNECTED_LINE:
++ update_connectedline(p, data, datalen);
++ break;
++ case AST_CONTROL_REDIRECTING:
++ update_redirecting(p, data, datalen);
++ break;
+ case -1:
+ res = -1;
+ break;
+@@ -6195,7 +6513,6 @@
+ return res;
+ }
+
+-
+ /*! \brief Initiate a call in the SIP channel
+ called from sip_request_call (calls from the pbx ) for outbound channels
+ and from handle_request_invite for inbound channels
+@@ -6294,24 +6611,28 @@
+ else
+ ast_debug(3, "This channel will not be able to handle video.\n");
+
+- if ((ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) || (ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) {
+- i->vad = ast_dsp_new();
+- ast_dsp_set_features(i->vad, DSP_FEATURE_DIGIT_DETECT);
+- if (global_relaxdtmf)
+- ast_dsp_set_digitmode(i->vad, DSP_DIGITMODE_DTMF | DSP_DIGITMODE_RELAXDTMF);
++ if ((ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) ||
++ (ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) {
++ if (!i->rtp || ast_rtp_instance_dtmf_mode_set(i->rtp, AST_RTP_DTMF_MODE_INBAND)) {
++ enable_digit_detect(i);
++ }
++ } else if (ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) {
++ if (i->rtp) {
++ ast_rtp_instance_dtmf_mode_set(i->rtp, AST_RTP_DTMF_MODE_RFC2833);
++ }
+ }
+
+ /* Set file descriptors for audio, video, realtime text and UDPTL as needed */
+ if (i->rtp) {
+- ast_channel_set_fd(tmp, 0, ast_rtp_fd(i->rtp));
+- ast_channel_set_fd(tmp, 1, ast_rtcp_fd(i->rtp));
++ ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(i->rtp, 0));
++ ast_channel_set_fd(tmp, 1, ast_rtp_instance_fd(i->rtp, 1));
+ }
+ if (needvideo && i->vrtp) {
+- ast_channel_set_fd(tmp, 2, ast_rtp_fd(i->vrtp));
+- ast_channel_set_fd(tmp, 3, ast_rtcp_fd(i->vrtp));
++ ast_channel_set_fd(tmp, 2, ast_rtp_instance_fd(i->vrtp, 0));
++ ast_channel_set_fd(tmp, 3, ast_rtp_instance_fd(i->vrtp, 1));
+ }
+ if (needtext && i->trtp)
+- ast_channel_set_fd(tmp, 4, ast_rtp_fd(i->trtp));
++ ast_channel_set_fd(tmp, 4, ast_rtp_instance_fd(i->trtp, 0));
+ if (i->udptl)
+ ast_channel_set_fd(tmp, 5, ast_udptl_fd(i->udptl));
+
+@@ -6493,9 +6814,9 @@
+ for (pass = 0; name && pass < 2;pass++) {
+ int x, len = strlen(name);
+ for (x = *start; x < req->headers; x++) {
+- char *header = REQ_OFFSET_TO_STR(req, header[x]);
++ const char *header = REQ_OFFSET_TO_STR(req, header[x]);
+ if (!strncasecmp(header, name, len)) {
+- char *r = header + len; /* skip name */
++ const char *r = header + len; /* skip name */
+ if (sip_cfg.pedanticsipchecking)
+ r = ast_skip_blanks(r);
+
+@@ -6535,19 +6856,19 @@
+
+ switch(ast->fdno) {
+ case 0:
+- f = ast_rtp_read(p->rtp); /* RTP Audio */
++ f = ast_rtp_instance_read(p->rtp, 0); /* RTP Audio */
+ break;
+ case 1:
+- f = ast_rtcp_read(p->rtp); /* RTCP Control Channel */
++ f = ast_rtp_instance_read(p->rtp, 1); /* RTCP Control Channel */
+ break;
+ case 2:
+- f = ast_rtp_read(p->vrtp); /* RTP Video */
++ f = ast_rtp_instance_read(p->vrtp, 0); /* RTP Video */
+ break;
+ case 3:
+- f = ast_rtcp_read(p->vrtp); /* RTCP Control Channel for video */
++ f = ast_rtp_instance_read(p->vrtp, 1); /* RTCP Control Channel for video */
+ break;
+ case 4:
+- f = ast_rtp_read(p->trtp); /* RTP Text */
++ f = ast_rtp_instance_read(p->trtp, 0); /* RTP Text */
+ if (sipdebug_text) {
+ int i;
+ unsigned char* arr = f->data.ptr;
+@@ -6589,8 +6910,8 @@
+ ast_set_write_format(p->owner, p->owner->writeformat);
+ }
+
+- if (f && (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) && p->vad) {
+- f = ast_dsp_process(p->owner, p->vad, f);
++ if (f && p->dsp) {
++ f = ast_dsp_process(p->owner, p->dsp, f);
+ if (f && f->frametype == AST_FRAME_DTMF) {
+ if (ast_test_flag(&p->t38.t38support, SIP_PAGE2_T38SUPPORT_UDPTL) && f->subclass == 'f') {
+ ast_debug(1, "Fax CNG detected on %s\n", ast->name);
+@@ -6706,7 +7027,7 @@
+ * remember to release the reference.
+ */
+ static struct sip_pvt *sip_alloc(ast_string_field callid, struct sockaddr_in *sin,
+- int useglobal_nat, const int intended_method)
++ int useglobal_nat, const int intended_method, struct sip_request *req)
+ {
+ struct sip_pvt *p;
+
+@@ -6718,8 +7039,13 @@
+ return NULL;
+ }
+
++ if (req) {
++ set_socket_transport(&p->socket, req->socket.type); /* Later in ast_sip_ouraddrfor we need this to choose the right ip and port for the specific transport */
++ } else {
++ set_socket_transport(&p->socket, SIP_TRANSPORT_UDP);
++ }
++
+ p->socket.fd = -1;
+- p->socket.type = SIP_TRANSPORT_UDP;
+ p->method = intended_method;
+ p->initid = -1;
+ p->waitid = -1;
+@@ -6742,7 +7068,7 @@
+ p->ourip = internip;
+ else {
+ p->sa = *sin;
+- ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip);
++ ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip, p);
+ }
+
+ /* Copy global flags to this PVT at setup. */
+@@ -6756,50 +7082,11 @@
+ p->ocseq = INITIAL_CSEQ;
+
+ if (sip_methods[intended_method].need_rtp) {
+- p->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
+- /* If the global videosupport flag is on, we always create a RTP interface for video */
+- if (ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT))
+- p->vrtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
+- if (ast_test_flag(&p->flags[1], SIP_PAGE2_TEXTSUPPORT))
+- p->trtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
+- if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT))
+- p->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, bindaddr.sin_addr);
+- if (!p->rtp|| (ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT) && !p->vrtp)
+- || (ast_test_flag(&p->flags[1], SIP_PAGE2_TEXTSUPPORT) && !p->trtp)) {
+- ast_log(LOG_WARNING, "Unable to create RTP audio %s%ssession: %s\n",
+- ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT) ? "and video " : "",
+- ast_test_flag(&p->flags[1], SIP_PAGE2_TEXTSUPPORT) ? "and text " : "", strerror(errno));
+- if (p->chanvars) {
+- ast_variables_destroy(p->chanvars);
+- p->chanvars = NULL;
+- }
+- ao2_t_ref(p, -1, "failed to create RTP audio session, drop p");
+- return NULL;
++ if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) && (p->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, bindaddr.sin_addr))) {
++ ast_udptl_setqos(p->udptl, global_tos_audio, global_cos_audio);
+ }
+- ast_rtp_setqos(p->rtp, global_tos_audio, global_cos_audio, "SIP RTP");
+- ast_rtp_setdtmf(p->rtp, ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
+- ast_rtp_setdtmfcompensate(p->rtp, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
+- ast_rtp_set_rtptimeout(p->rtp, global_rtptimeout);
+- ast_rtp_set_rtpholdtimeout(p->rtp, global_rtpholdtimeout);
+- ast_rtp_set_rtpkeepalive(p->rtp, global_rtpkeepalive);
+- if (p->vrtp) {
+- ast_rtp_setqos(p->vrtp, global_tos_video, global_cos_video, "SIP VRTP");
+- ast_rtp_setdtmf(p->vrtp, 0);
+- ast_rtp_setdtmfcompensate(p->vrtp, 0);
+- ast_rtp_set_rtptimeout(p->vrtp, global_rtptimeout);
+- ast_rtp_set_rtpholdtimeout(p->vrtp, global_rtpholdtimeout);
+- ast_rtp_set_rtpkeepalive(p->vrtp, global_rtpkeepalive);
+- }
+- if (p->trtp) {
+- ast_rtp_setqos(p->trtp, global_tos_text, global_cos_text, "SIP TRTP");
+- ast_rtp_setdtmf(p->trtp, 0);
+- ast_rtp_setdtmfcompensate(p->trtp, 0);
+- }
+- if (p->udptl)
+- ast_udptl_setqos(p->udptl, global_tos_audio, global_cos_audio);
+ p->maxcallbitrate = default_maxcallbitrate;
+ p->autoframing = global_autoframing;
+- ast_rtp_codec_setpref(p->rtp, &p->prefs);
+ }
+
+ if (useglobal_nat && sin) {
+@@ -6831,6 +7118,7 @@
+ }
+ ast_string_field_set(p, context, sip_cfg.default_context);
+ ast_string_field_set(p, parkinglot, default_parkinglot);
++ ast_string_field_set(p, engine, default_engine);
+
+ AST_LIST_HEAD_INIT_NOLOCK(&p->request_queue);
+
+@@ -6985,7 +7273,7 @@
+ transmit_response_using_temp(callid, sin, 1, intended_method, req, "489 Bad event");
+ } else {
+ /* Ok, time to create a new SIP dialog object, a pvt */
+- if ((p = sip_alloc(callid, sin, 1, intended_method))) {
++ if ((p = sip_alloc(callid, sin, 1, intended_method, req))) {
+ /* Ok, we've created a dialog, let's go and process it */
+ sip_pvt_lock(p);
+ } else {
+@@ -7027,19 +7315,20 @@
+ enum sip_transport transport = SIP_TRANSPORT_UDP;
+ char buf[256] = "";
+ char *username = NULL;
+- char *hostname=NULL, *secret=NULL, *authuser=NULL, *expire=NULL;
++ char *hostname=NULL, *secret=NULL, *authuser=NULL, *expire=NULL, *buf2=NULL;
+ char *callback=NULL;
+
+ if (!value)
+ return -1;
+
+ ast_copy_string(buf, value, sizeof(buf));
++ buf2 = strrchr(buf, '@');
+
+- /* split [/contact][~expiry] */
+- expire = strchr(buf, '~');
++ /* split [/extension][~expiry] */
++ expire = strchr(buf2, '~');
+ if (expire)
+ *expire++ = '\0';
+- callback = strrchr(buf, '/');
++ callback = strrchr(buf2, '/');
+ if (callback)
+ *callback++ = '\0';
+ if (ast_strlen_zero(callback))
+@@ -7182,6 +7471,97 @@
+ return 0;
+ }
+
++static void mark_method_allowed(unsigned int *allowed_methods, enum sipmethod method)
++{
++ (*allowed_methods) |= (1 << method);
++}
++
++static void mark_method_unallowed(unsigned int *allowed_methods, enum sipmethod method)
++{
++ (*allowed_methods) &= ~(1 << method);
++}
++
++static int is_method_allowed(unsigned int *allowed_methods, enum sipmethod method)
++{
++ return ((*allowed_methods) >> method) & 1;
++}
++
++/*!
++ * \brief parse the Allow header to see what methods the endpoint we
++ * are communicating with allows.
++ *
++ * We parse the allow header on incoming Registrations and save the
++ * result to the SIP peer that is registering. When the registration
++ * expires, we clear what we know about the peer's allowed methods.
++ * When the peer re-registers, we once again parse to see if the
++ * list of allowed methods has changed.
++ *
++ * For peers that do not register, we parse the first message we receive
++ * during a call to see what is allowed, and save the information
++ * for the duration of the call.
++ * \param req The SIP request we are parsing
++ * \retval The methods allowed
++ */
++static unsigned int parse_allowed_methods(struct sip_request *req)
++{
++ char *allow = ast_strdupa(get_header(req, "Allow"));
++ char *method;
++ unsigned int allowed_methods = SIP_UNKNOWN;
++
++ if (ast_strlen_zero(allow)) {
++ /* I have witnessed that REGISTER requests from Polycom phones do not
++ * place the phone's allowed methods in an Allow header. Instead, they place the
++ * allowed methods in a methods= parameter in the Contact header.
++ */
++ char *contact = ast_strdupa(get_header(req, "Contact"));
++ char *methods = strstr(contact, ";methods=");
++
++ if (ast_strlen_zero(methods)) {
++ /* RFC 3261 states:
++ *
++ * "The absence of an Allow header field MUST NOT be
++ * interpreted to mean that the UA sending the message supports no
++ * methods. Rather, it implies that the UA is not providing any
++ * information on what methods it supports."
++ *
++ * For simplicity, we'll assume that the peer allows all known
++ * SIP methods if they have no Allow header. We can then clear out the necessary
++ * bits if the peer lets us know that we have sent an unsupported method.
++ */
++ return UINT_MAX;
++ }
++ allow = ast_strip_quoted(methods + 9, "\"", "\"");
++ }
++ for (method = strsep(&allow, ","); !ast_strlen_zero(method); method = strsep(&allow, ",")) {
++ int id = find_sip_method(ast_skip_blanks(method));
++ if (id == SIP_UNKNOWN) {
++ continue;
++ }
++ mark_method_allowed(&allowed_methods, id);
++ }
++ return allowed_methods;
++}
++
++/*! A wrapper for parse_allowed_methods geared toward sip_pvts
++ *
++ * This function, in addition to setting the allowed methods for a sip_pvt
++ * also will take into account the setting of the SIP_PAGE2_RPID_UPDATE flag.
++ *
++ * \param pvt The sip_pvt we are setting the allowed_methods for
++ * \param req The request which we are parsing
++ * \retval The methods alloweded by the sip_pvt
++ */
++static unsigned int set_pvt_allowed_methods(struct sip_pvt *pvt, struct sip_request *req)
++{
++ pvt->allowed_methods = parse_allowed_methods(req);
++
++ if (ast_test_flag(&pvt->flags[1], SIP_PAGE2_RPID_UPDATE)) {
++ mark_method_allowed(&pvt->allowed_methods, SIP_UPDATE);
++ }
++
++ return pvt->allowed_methods;
++}
++
+ /*! \brief Parse multiline SIP headers into one header
+ This is enabled if pedanticsipchecking is enabled */
+ static int lws2sws(char *msgbuf, int len)
+@@ -7397,7 +7777,7 @@
+ sdp part and the end boundry if it exists */
+
+ for (x = 0; x < (req->lines); x++) {
+- char *line = REQ_OFFSET_TO_STR(req, line[x]);
++ const char *line = REQ_OFFSET_TO_STR(req, line[x]);
+ if (!strncasecmp(line, boundary, strlen(boundary))){
+ if (found_application_sdp && found_end_of_headers) {
+ req->sdp_end = x-1;
+@@ -7446,7 +7826,7 @@
+ /* Continue since there may be a valid host in a c= line specific to the audio stream */
+ }
+ /* We only want the m and c lines for audio */
+- while ((m = get_sdp_iterate(&miterator, req, "m"))) {
++ for (m = get_sdp_iterate(&miterator, req, "m"); !ast_strlen_zero(m); m = get_sdp_iterate(&miterator, req, "m")) {
+ if ((media == SDP_AUDIO && ((sscanf(m, "audio %d/%d RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
+ (sscanf(m, "audio %d RTP/AVP %n", &x, &len) == 1 && len > 0))) ||
+ (media == SDP_VIDEO && ((sscanf(m, "video %d/%d RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
+@@ -7522,7 +7902,7 @@
+ int iterator;
+ int sendonly = -1;
+ int numberofports;
+- struct ast_rtp *newaudiortp, *newvideortp, *newtextrtp; /* Buffers for codec handling */
++ struct ast_rtp_codecs newaudiortp, newvideortp, newtextrtp;
+ int newjointcapability; /* Negotiated capability */
+ int newpeercapability;
+ int newnoncodeccapability;
+@@ -7533,7 +7913,7 @@
+ int last_rtpmap_codec=0;
+
+ char buf[SIPBUFSIZE];
+- uint64_t rua_version;
++ int64_t rua_version;
+
+ int red_data_pt[10];
+ int red_num_gen = 0;
+@@ -7547,34 +7927,11 @@
+ return -1;
+ }
+
+- /* Initialize the temporary RTP structures we use to evaluate the offer from the peer */
+-#ifdef LOW_MEMORY
+- newaudiortp = ast_threadstorage_get(&ts_audio_rtp, ast_rtp_alloc_size());
+-#else
+- newaudiortp = alloca(ast_rtp_alloc_size());
+-#endif
+- memset(newaudiortp, 0, ast_rtp_alloc_size());
+- ast_rtp_new_init(newaudiortp);
+- ast_rtp_pt_clear(newaudiortp);
++ /* Make sure that the codec structures are all cleared out */
++ ast_rtp_codecs_payloads_clear(&newaudiortp, NULL);
++ ast_rtp_codecs_payloads_clear(&newvideortp, NULL);
++ ast_rtp_codecs_payloads_clear(&newtextrtp, NULL);
+
+-#ifdef LOW_MEMORY
+- newvideortp = ast_threadstorage_get(&ts_video_rtp, ast_rtp_alloc_size());
+-#else
+- newvideortp = alloca(ast_rtp_alloc_size());
+-#endif
+- memset(newvideortp, 0, ast_rtp_alloc_size());
+- ast_rtp_new_init(newvideortp);
+- ast_rtp_pt_clear(newvideortp);
+-
+-#ifdef LOW_MEMORY
+- newtextrtp = ast_threadstorage_get(&ts_text_rtp, ast_rtp_alloc_size());
+-#else
+- newtextrtp = alloca(ast_rtp_alloc_size());
+-#endif
+- memset(newtextrtp, 0, ast_rtp_alloc_size());
+- ast_rtp_new_init(newtextrtp);
+- ast_rtp_pt_clear(newtextrtp);
+-
+ /* Update our last rtprx when we receive an SDP, too */
+ p->lastrtprx = p->lastrtptx = time(NULL); /* XXX why both ? */
+
+@@ -7609,21 +7966,44 @@
+ ast_log(LOG_WARNING, "SDP syntax error in o= line\n");
+ return -1;
+ }
+- if (!sscanf(token, "%" SCNu64, &rua_version)) {
++ if (!sscanf(token, "%" SCNd64, &rua_version)) {
+ ast_log(LOG_WARNING, "SDP syntax error in o= line version\n");
+ return -1;
+ }
+
+- if (ast_test_flag(&p->flags[1], SIP_PAGE2_IGNORESDPVERSION)
+- || p->sessionversion_remote < 0
+- || p->sessionversion_remote != rua_version) {
+-
++ /* we need to check the SDP version number the other end sent us;
++ * our rules for deciding what to accept are a bit complex.
++ *
++ * 1) if 'ignoresdpversion' has been set for this dialog, then
++ * we will just accept whatever they sent and assume it is
++ * a modification of the session, even if it is not
++ * 2) otherwise, if this is the first SDP we've seen from them
++ * we accept it
++ * 3) otherwise, if the new SDP version number is higher than the
++ * old one, we accept it
++ * 4) otherwise, if this SDP is in response to us requesting a switch
++ * to T.38, we accept the SDP, but also generate a warning message
++ * that this peer should have the 'ignoresdpversion' option set,
++ * because it is not following the SDP offer/answer RFC; if we did
++ * not request a switch to T.38, then we stop parsing the SDP, as it
++ * has not changed from the previous version
++ */
++
++ if (ast_test_flag(&p->flags[1], SIP_PAGE2_IGNORESDPVERSION) ||
++ (p->sessionversion_remote < 0) ||
++ (p->sessionversion_remote < rua_version)) {
+ p->sessionversion_remote = rua_version;
+ p->session_modify = TRUE;
+- } else if (p->sessionversion_remote == rua_version) {
+- p->session_modify = FALSE;
+- ast_debug(2, "SDP version number same as previous SDP. Not parsing this SDP.\n");
+- return 0;
++ } else {
++ if (p->t38.state == T38_LOCAL_REINVITE) {
++ p->sessionversion_remote = rua_version;
++ p->session_modify = TRUE;
++ ast_log(LOG_WARNING, "Call %s responded to our T.38 reinvite without changing SDP version; 'ignoresdpversion' should be set for this peer.\n", p->callid);
++ } else {
++ p->session_modify = FALSE;
++ ast_debug(2, "Call %s responded to our reinvite without changing SDP version; ignoring SDP.\n", p->callid);
++ return 0;
++ }
+ }
+
+ /* Try to find first media stream */
+@@ -7655,12 +8035,14 @@
+ p->novideo = TRUE;
+ p->notext = TRUE;
+
+- if (p->vrtp)
+- ast_rtp_pt_clear(newvideortp); /* Must be cleared in case no m=video line exists */
+-
+- if (p->trtp)
+- ast_rtp_pt_clear(newtextrtp); /* Must be cleared in case no m=text line exists */
++ if (p->vrtp) {
++ ast_rtp_codecs_payloads_clear(&newvideortp, NULL);
++ }
+
++ if (p->trtp) {
++ ast_rtp_codecs_payloads_clear(&newtextrtp, NULL);
++ }
++
+ /* Find media streams in this SDP offer */
+ while ((m = get_sdp_iterate(&iterator, req, "m"))[0] != '\0') {
+ int x;
+@@ -7684,7 +8066,8 @@
+ }
+ if (debug)
+ ast_verbose("Found RTP audio format %d\n", codec);
+- ast_rtp_set_m_type(newaudiortp, codec);
++
++ ast_rtp_codecs_payloads_set_m_type(&newaudiortp, NULL, codec);
+ }
+ } else if ((sscanf(m, "video %d/%d RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
+ (sscanf(m, "video %d RTP/AVP %n", &x, &len) == 1 && len >= 0)) {
+@@ -7700,7 +8083,7 @@
+ }
+ if (debug)
+ ast_verbose("Found RTP video format %d\n", codec);
+- ast_rtp_set_m_type(newvideortp, codec);
++ ast_rtp_codecs_payloads_set_m_type(&newvideortp, NULL, codec);
+ }
+ } else if ((sscanf(m, "text %d/%d RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
+ (sscanf(m, "text %d RTP/AVP %n", &x, &len) == 1 && len > 0)) {
+@@ -7716,7 +8099,7 @@
+ }
+ if (debug)
+ ast_verbose("Found RTP text format %d\n", codec);
+- ast_rtp_set_m_type(newtextrtp, codec);
++ ast_rtp_codecs_payloads_set_m_type(&newtextrtp, NULL, codec);
+ }
+ } else if (p->udptl && ( (sscanf(m, "image %d udptl t38%n", &x, &len) == 1 && len > 0) ||
+ (sscanf(m, "image %d UDPTL t38%n", &x, &len) == 1 && len > 0) )) {
+@@ -7781,10 +8164,10 @@
+ if (udptlportno > 0) {
+ sin.sin_port = htons(udptlportno);
+ if (ast_test_flag(&p->flags[0], SIP_NAT) && ast_test_flag(&p->flags[1], SIP_PAGE2_UDPTL_DESTINATION)) {
+- struct sockaddr_in peer;
+- ast_rtp_get_peer(p->rtp, &peer);
+- if (peer.sin_addr.s_addr) {
+- memcpy(&sin.sin_addr, &peer.sin_addr, sizeof(sin.sin_addr));
++ struct sockaddr_in remote_address = { 0, };
++ ast_rtp_instance_get_remote_address(p->rtp, &remote_address);
++ if (remote_address.sin_addr.s_addr) {
++ memcpy(&sin, &remote_address, sizeof(sin));
+ if (debug) {
+ ast_log(LOG_DEBUG, "Peer T.38 UDPTL is set behind NAT and with destination, destination address now %s\n", ast_inet_ntoa(sin.sin_addr));
+ }
+@@ -7804,7 +8187,7 @@
+ if (p->rtp) {
+ if (portno > 0) {
+ sin.sin_port = htons(portno);
+- ast_rtp_set_peer(p->rtp, &sin);
++ ast_rtp_instance_set_remote_address(p->rtp, &sin);
+ if (debug)
+ ast_verbose("Peer audio RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
+ } else {
+@@ -7812,7 +8195,7 @@
+ if (debug)
+ ast_verbose("Got T.38 Re-invite without audio. Keeping RTP active during T.38 session. Callid %s\n", p->callid);
+ } else {
+- ast_rtp_stop(p->rtp);
++ ast_rtp_instance_stop(p->rtp);
+ if (debug)
+ ast_verbose("Peer doesn't provide audio. Callid %s\n", p->callid);
+ }
+@@ -7895,18 +8278,17 @@
+ }
+ }
+ if (framing && p->autoframing) {
+- struct ast_codec_pref *pref = ast_rtp_codec_getpref(p->rtp);
++ struct ast_codec_pref *pref = &ast_rtp_instance_get_codecs(p->rtp)->pref;
+ int codec_n;
+- int format = 0;
+- for (codec_n = 0; codec_n < MAX_RTP_PT; codec_n++) {
+- format = ast_rtp_codec_getformat(codec_n);
+- if (!format) /* non-codec or not found */
++ for (codec_n = 0; codec_n < AST_RTP_MAX_PT; codec_n++) {
++ struct ast_rtp_payload_type format = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(p->rtp), codec_n);
++ if (!format.asterisk_format || !format.code) /* non-codec or not found */
+ continue;
+ if (option_debug)
+- ast_log(LOG_DEBUG, "Setting framing for %d to %ld\n", format, framing);
+- ast_codec_pref_setsize(pref, format, framing);
++ ast_log(LOG_DEBUG, "Setting framing for %d to %ld\n", format.code, framing);
++ ast_codec_pref_setsize(pref, format.code, framing);
+ }
+- ast_rtp_codec_setpref(p->rtp, pref);
++ ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, pref);
+ }
+ continue;
+ }
+@@ -7918,7 +8300,7 @@
+
+ sscanf(red_cp, "%u", &red_data_pt[red_num_gen]);
+ red_cp = strtok(red_cp, "/");
+- while (red_cp && red_num_gen++ < RED_MAX_GENERATION) {
++ while (red_cp && red_num_gen++ < AST_RED_MAX_GENERATION) {
+ sscanf(red_cp, "%u", &red_data_pt[red_num_gen]);
+ red_cp = strtok(NULL, "/");
+ }
+@@ -7927,15 +8309,15 @@
+ }
+
+ if (sscanf(a, "fmtp: %u %63s", &codec, fmtp_string) == 2) {
+- struct rtpPayloadType payload;
++ struct ast_rtp_payload_type payload;
+ unsigned int handled = 0;
+
+- payload = ast_rtp_lookup_pt(newaudiortp, codec);
++ payload = ast_rtp_codecs_payload_lookup(&newaudiortp, codec);
+ if (!payload.code) {
+ /* it wasn't found, try the video rtp */
+- payload = ast_rtp_lookup_pt(newvideortp, codec);
++ payload = ast_rtp_codecs_payload_lookup(&newvideortp, codec);
+ }
+- if (payload.code && payload.isAstFormat) {
++ if (payload.code && payload.asterisk_format) {
+ unsigned int bit_rate;
+
+ switch (payload.code) {
+@@ -7943,7 +8325,7 @@
+ if (sscanf(fmtp_string, "bitrate=%u", &bit_rate) == 1) {
+ if (bit_rate != 32000) {
+ ast_log(LOG_WARNING, "Got Siren7 offer at %d bps, but only 32000 bps supported; ignoring.\n", bit_rate);
+- ast_rtp_unset_m_type(newaudiortp, codec);
++ ast_rtp_codecs_payloads_unset(&newaudiortp, NULL, codec);
+ } else {
+ handled = 1;
+ }
+@@ -7953,7 +8335,7 @@
+ if (sscanf(fmtp_string, "bitrate=%u", &bit_rate) == 1) {
+ if (bit_rate != 48000) {
+ ast_log(LOG_WARNING, "Got Siren14 offer at %d bps, but only 48000 bps supported; ignoring.\n", bit_rate);
+- ast_rtp_unset_m_type(newaudiortp, codec);
++ ast_rtp_codecs_payloads_unset(&newaudiortp, NULL, codec);
+ } else {
+ handled = 1;
+ }
+@@ -7975,24 +8357,24 @@
+ /* Note: should really look at the '#chans' params too */
+ /* Note: This should all be done in the context of the m= above */
+ if (!strncasecmp(mimeSubtype, "H26", 3) || !strncasecmp(mimeSubtype, "MP4", 3)) { /* Video */
+- if (ast_rtp_set_rtpmap_type_rate(newvideortp, codec, "video", mimeSubtype, 0, sample_rate) != -1) {
++ if (ast_rtp_codecs_payloads_set_rtpmap_type_rate(&newvideortp, NULL, codec, "video", mimeSubtype, 0, sample_rate) != -1) {
+ if (debug)
+ ast_verbose("Found video description format %s for ID %d\n", mimeSubtype, codec);
+ found_rtpmap_codecs[last_rtpmap_codec] = codec;
+ last_rtpmap_codec++;
+ } else {
+- ast_rtp_unset_m_type(newvideortp, codec);
++ ast_rtp_codecs_payloads_unset(&newvideortp, NULL, codec);
+ if (debug)
+ ast_verbose("Found unknown media description format %s for ID %d\n", mimeSubtype, codec);
+ }
+ } else if (!strncasecmp(mimeSubtype, "T140", 4)) { /* Text */
+ if (p->trtp) {
+ /* ast_verbose("Adding t140 mimeSubtype to textrtp struct\n"); */
+- ast_rtp_set_rtpmap_type(newtextrtp, codec, "text", mimeSubtype, 0);
++ ast_rtp_codecs_payloads_set_rtpmap_type_rate(&newtextrtp, NULL, codec, "text", mimeSubtype, 0, sample_rate);
+ }
+ } else if (!strncasecmp(mimeSubtype, "RED", 3)) { /* Text with Redudancy */
+ if (p->trtp) {
+- ast_rtp_set_rtpmap_type(newtextrtp, codec, "text", mimeSubtype, 0);
++ ast_rtp_codecs_payloads_set_rtpmap_type_rate(&newtextrtp, NULL, codec, "text", mimeSubtype, 0, sample_rate);
+ red_pt = codec;
+ sprintf(red_fmtp, "fmtp:%d ", red_pt);
+
+@@ -8000,15 +8382,14 @@
+ ast_verbose("RED submimetype has payload type: %d\n", red_pt);
+ }
+ } else { /* Must be audio?? */
+- if (ast_rtp_set_rtpmap_type_rate(newaudiortp, codec, "audio", mimeSubtype,
+- ast_test_flag(&p->flags[0], SIP_G726_NONSTANDARD) ? AST_RTP_OPT_G726_NONSTANDARD : 0,
+- sample_rate) != -1) {
++ if (ast_rtp_codecs_payloads_set_rtpmap_type_rate(&newaudiortp, NULL, codec, "audio", mimeSubtype,
++ ast_test_flag(&p->flags[0], SIP_G726_NONSTANDARD) ? AST_RTP_OPT_G726_NONSTANDARD : 0, sample_rate) != -1) {
+ if (debug)
+ ast_verbose("Found audio description format %s for ID %d\n", mimeSubtype, codec);
+ found_rtpmap_codecs[last_rtpmap_codec] = codec;
+ last_rtpmap_codec++;
+ } else {
+- ast_rtp_unset_m_type(newaudiortp, codec);
++ ast_rtp_codecs_payloads_unset(&newaudiortp, NULL, codec);
+ if (debug)
+ ast_verbose("Found unknown media description format %s for ID %d\n", mimeSubtype, codec);
+ }
+@@ -8147,15 +8528,14 @@
+ }
+
+ /* Now gather all of the codecs that we are asked for: */
+- ast_rtp_get_current_formats(newaudiortp, &peercapability, &peernoncodeccapability);
+- ast_rtp_get_current_formats(newvideortp, &vpeercapability, &vpeernoncodeccapability);
+- ast_rtp_get_current_formats(newtextrtp, &tpeercapability, &tpeernoncodeccapability);
++ ast_rtp_codecs_payload_formats(&newaudiortp, &peercapability, &peernoncodeccapability);
++ ast_rtp_codecs_payload_formats(&newvideortp, &vpeercapability, &vpeernoncodeccapability);
++ ast_rtp_codecs_payload_formats(&newtextrtp, &tpeercapability, &tpeernoncodeccapability);
+
+ newjointcapability = p->capability & (peercapability | vpeercapability | tpeercapability);
+ newpeercapability = (peercapability | vpeercapability | tpeercapability);
+ newnoncodeccapability = p->noncodeccapability & peernoncodeccapability;
+-
+-
++
+ if (debug) {
+ /* shame on whoever coded this.... */
+ char s1[SIPBUFSIZE], s2[SIPBUFSIZE], s3[SIPBUFSIZE], s4[SIPBUFSIZE], s5[SIPBUFSIZE];
+@@ -8166,11 +8546,17 @@
+ ast_getformatname_multiple(s3, SIPBUFSIZE, vpeercapability),
+ ast_getformatname_multiple(s4, SIPBUFSIZE, tpeercapability),
+ ast_getformatname_multiple(s5, SIPBUFSIZE, newjointcapability));
++ }
+
++ if (debug) {
++ struct ast_str *s1 = ast_str_alloca(SIPBUFSIZE);
++ struct ast_str *s2 = ast_str_alloca(SIPBUFSIZE);
++ struct ast_str *s3 = ast_str_alloca(SIPBUFSIZE);
++
+ ast_verbose("Non-codec capabilities (dtmf): us - %s, peer - %s, combined - %s\n",
+- ast_rtp_lookup_mime_multiple(s1, SIPBUFSIZE, p->noncodeccapability, 0, 0),
+- ast_rtp_lookup_mime_multiple(s2, SIPBUFSIZE, peernoncodeccapability, 0, 0),
+- ast_rtp_lookup_mime_multiple(s3, SIPBUFSIZE, newnoncodeccapability, 0, 0));
++ ast_rtp_lookup_mime_multiple2(s1, p->noncodeccapability, 0, 0),
++ ast_rtp_lookup_mime_multiple2(s2, peernoncodeccapability, 0, 0),
++ ast_rtp_lookup_mime_multiple2(s3, newnoncodeccapability, 0, 0));
+ }
+ if (!newjointcapability) {
+ /* If T.38 was not negotiated either, totally bail out... */
+@@ -8190,18 +8576,24 @@
+ p->peercapability = newpeercapability; /* The other sides capability in latest offer */
+ p->jointnoncodeccapability = newnoncodeccapability; /* DTMF capabilities */
+
++ if (ast_test_flag(&p->flags[1], SIP_PAGE2_PREFERRED_CODEC)) { /* respond with single most preferred joint codec, limiting the other side's choice */
++ p->jointcapability = ast_codec_choose(&p->prefs, p->jointcapability, 1);
++ }
++
+ if (p->jointcapability & AST_FORMAT_T140RED) {
+- p->red = 1;
+- rtp_red_init(p->trtp, 300, red_data_pt, 2);
++ p->red = 1;
++ ast_rtp_red_init(p->trtp, 300, red_data_pt, 2);
+ } else {
+- p->red = 0;
++ p->red = 0;
+ }
+
+- ast_rtp_pt_copy(p->rtp, newaudiortp);
+- if (p->vrtp)
+- ast_rtp_pt_copy(p->vrtp, newvideortp);
+- if (p->trtp)
+- ast_rtp_pt_copy(p->trtp, newtextrtp);
++ ast_rtp_codecs_payloads_copy(&newaudiortp, ast_rtp_instance_get_codecs(p->rtp), p->rtp);
++ if (p->vrtp) {
++ ast_rtp_codecs_payloads_copy(&newvideortp, ast_rtp_instance_get_codecs(p->vrtp), p->vrtp);
++ }
++ if (p->trtp) {
++ ast_rtp_codecs_payloads_copy(&newtextrtp, ast_rtp_instance_get_codecs(p->trtp), p->trtp);
++ }
+
+ if (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO) {
+ ast_clear_flag(&p->flags[0], SIP_DTMF);
+@@ -8209,8 +8601,8 @@
+ /* XXX Would it be reasonable to drop the DSP at this point? XXX */
+ ast_set_flag(&p->flags[0], SIP_DTMF_RFC2833);
+ /* Since RFC2833 is now negotiated we need to change some properties of the RTP stream */
+- ast_rtp_setdtmf(p->rtp, 1);
+- ast_rtp_setdtmfcompensate(p->rtp, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
++ ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_DTMF, 1);
++ ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
+ } else {
+ ast_set_flag(&p->flags[0], SIP_DTMF_INBAND);
+ }
+@@ -8218,21 +8610,21 @@
+
+ /* Setup audio port number */
+ if (p->rtp && sin.sin_port) {
+- ast_rtp_set_peer(p->rtp, &sin);
++ ast_rtp_instance_set_remote_address(p->rtp, &sin);
+ if (debug)
+ ast_verbose("Peer audio RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
+ }
+
+ /* Setup video port number */
+ if (p->vrtp && vsin.sin_port) {
+- ast_rtp_set_peer(p->vrtp, &vsin);
++ ast_rtp_instance_set_remote_address(p->vrtp, &vsin);
+ if (debug)
+ ast_verbose("Peer video RTP is at port %s:%d\n", ast_inet_ntoa(vsin.sin_addr), ntohs(vsin.sin_port));
+ }
+
+ /* Setup text port number */
+ if (p->trtp && tsin.sin_port) {
+- ast_rtp_set_peer(p->trtp, &tsin);
++ ast_rtp_instance_set_remote_address(p->trtp, &tsin);
+ if (debug)
+ ast_verbose("Peer text RTP is at port %s:%d\n", ast_inet_ntoa(tsin.sin_addr), ntohs(tsin.sin_port));
+ }
+@@ -8279,7 +8671,7 @@
+ S_OR(p->mohsuggest, NULL),
+ !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
+ if (sendonly)
+- ast_rtp_stop(p->rtp);
++ ast_rtp_instance_stop(p->rtp);
+ /* RTCP needs to go ahead, even if we're on hold!!! */
+ /* Activate a re-invite */
+ ast_queue_frame(p->owner, &ast_null_frame);
+@@ -8749,7 +9141,7 @@
+ * Similarly, if we need to re-send an INVITE with auth credentials, then we
+ * need to use the same branch as we did the first time we sent the INVITE.
+ */
+- if (sipmethod == SIP_CANCEL || (sipmethod == SIP_INVITE && !ast_strlen_zero(p->options->auth))) {
++ if (sipmethod == SIP_CANCEL || (sipmethod == SIP_INVITE && p->options && !ast_strlen_zero(p->options->auth))) {
+ p->branch = p->invite_branch;
+ build_via(p);
+ } else if (newbranch) {
+@@ -8830,9 +9222,6 @@
+ if (!ast_strlen_zero(global_useragent))
+ add_header(req, "User-Agent", global_useragent);
+
+- if (!ast_strlen_zero(p->rpid))
+- add_header(req, "Remote-Party-ID", p->rpid);
+-
+ if (!ast_strlen_zero(p->url)) {
+ add_header(req, "Access-URL", p->url);
+ ast_string_field_set(p, url, NULL);
+@@ -8870,6 +9259,14 @@
+ return -1;
+ }
+ respprep(&resp, p, msg, req);
++
++ if (ast_test_flag(&p->flags[0], SIP_SENDRPID)
++ && ast_test_flag(&p->flags[1], SIP_PAGE2_CONNECTLINEUPDATE_PEND)
++ && (!strncmp(msg, "180", 3) || !strncmp(msg, "183", 3))) {
++ ast_clear_flag(&p->flags[1], SIP_PAGE2_CONNECTLINEUPDATE_PEND);
++ add_rpid(&resp, p);
++ }
++
+ add_header_contentLength(&resp, 0);
+ /* If we are cancelling an incoming invite for some reason, add information
+ about the reason why we are doing this in clear text */
+@@ -8924,7 +9321,7 @@
+ p->ourip = internip;
+ else {
+ p->sa = *sin;
+- ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip);
++ ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip, p);
+ }
+
+ p->branch = ast_random();
+@@ -9089,6 +9486,89 @@
+ return 0;
+ }
+
++/*!
++ * \pre if p->owner exists, it must be locked
++ * \brief Add Remote-Party-ID header to SIP message
++ */
++static int add_rpid(struct sip_request *req, struct sip_pvt *p)
++{
++ struct ast_str *tmp = ast_str_alloca(256);
++ char *lid_num = NULL;
++ char *lid_name = NULL;
++ int lid_pres;
++ const char *fromdomain;
++ const char *privacy = NULL;
++ const char *screen = NULL;
++ const char *anonymous_string = "\"Anonymous\" <anonymous@anonymous.invalid>";
++
++ if (!ast_test_flag(&p->flags[0], SIP_SENDRPID)) {
++ return 0;
++ }
++
++ if (p->owner && p->owner->connected.id.number)
++ lid_num = p->owner->connected.id.number;
++ if (p->owner && p->owner->connected.id.name)
++ lid_name = p->owner->connected.id.name;
++ lid_pres = (p->owner) ? p->owner->connected.id.number_presentation : AST_PRES_NUMBER_NOT_AVAILABLE;
++
++ if (ast_strlen_zero(lid_num))
++ return 0;
++ if (ast_strlen_zero(lid_name))
++ lid_name = lid_num;
++ fromdomain = S_OR(p->fromdomain, ast_inet_ntoa(p->ourip.sin_addr));
++
++ if (ast_test_flag(&p->flags[0], SIP_SENDRPID_PAI)) {
++ if ((lid_pres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED) {
++ ast_str_set(&tmp, -1, "%s", anonymous_string);
++ } else {
++ ast_str_set(&tmp, -1, "\"%s\" <sip:%s@%s>", lid_name, lid_num, fromdomain);
++ }
++ add_header(req, "P-Asserted-Identity", ast_str_buffer(tmp));
++ } else {
++ ast_str_set(&tmp, -1, "\"%s\" <sip:%s@%s>;party=%s", lid_name, lid_num, fromdomain, ast_test_flag(&p->flags[0], SIP_OUTGOING) ? "calling" : "called");
++
++ switch (lid_pres) {
++ case AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
++ case AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
++ privacy = "off";
++ screen = "no";
++ break;
++ case AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
++ case AST_PRES_ALLOWED_NETWORK_NUMBER:
++ privacy = "off";
++ screen = "yes";
++ break;
++ case AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
++ case AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
++ privacy = "full";
++ screen = "no";
++ break;
++ case AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
++ case AST_PRES_PROHIB_NETWORK_NUMBER:
++ privacy = "full";
++ screen = "yes";
++ break;
++ case AST_PRES_NUMBER_NOT_AVAILABLE:
++ break;
++ default:
++ if ((lid_pres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED) {
++ privacy = "full";
++ }
++ else
++ privacy = "off";
++ screen = "no";
++ break;
++ }
++
++ if (!ast_strlen_zero(privacy) && !ast_strlen_zero(screen)) {
++ ast_str_append(&tmp, -1, ";privacy=%s;screen=%s", privacy, screen);
++ }
++
++ add_header(req, "Remote-Party-ID", ast_str_buffer(tmp));
++ }
++ return 0;
++}
++
+ /*! \brief add XML encoded media control with update
+ \note XML: The only way to turn 0 bits of information into a few hundred. (markster) */
+ static int add_vidupdate(struct sip_request *req)
+@@ -9120,19 +9600,19 @@
+
+ if (debug)
+ ast_verbose("Adding codec 0x%x (%s) to SDP\n", codec, ast_getformatname(codec));
+- if ((rtp_code = ast_rtp_lookup_code(p->rtp, 1, codec)) == -1)
++ if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->rtp), 1, codec)) == -1)
+ return;
+
+ if (p->rtp) {
+- struct ast_codec_pref *pref = ast_rtp_codec_getpref(p->rtp);
++ struct ast_codec_pref *pref = &ast_rtp_instance_get_codecs(p->rtp)->pref;
+ fmt = ast_codec_pref_getsize(pref, codec);
+ } else /* I dont see how you couldn't have p->rtp, but good to check for and error out if not there like earlier code */
+ return;
+ ast_str_append(m_buf, 0, " %d", rtp_code);
+ ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code,
+- ast_rtp_lookup_mime_subtype(1, codec,
++ ast_rtp_lookup_mime_subtype2(1, codec,
+ ast_test_flag(&p->flags[0], SIP_G726_NONSTANDARD) ? AST_RTP_OPT_G726_NONSTANDARD : 0),
+- ast_rtp_lookup_sample_rate(1, codec));
++ ast_rtp_lookup_sample_rate2(1, codec));
+
+ switch (codec) {
+ case AST_FORMAT_G729A:
+@@ -9179,13 +9659,13 @@
+ if (debug)
+ ast_verbose("Adding video codec 0x%x (%s) to SDP\n", codec, ast_getformatname(codec));
+
+- if ((rtp_code = ast_rtp_lookup_code(p->vrtp, 1, codec)) == -1)
++ if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->vrtp), 1, codec)) == -1)
+ return;
+
+ ast_str_append(m_buf, 0, " %d", rtp_code);
+ ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code,
+- ast_rtp_lookup_mime_subtype(1, codec, 0),
+- ast_rtp_lookup_sample_rate(1, codec));
++ ast_rtp_lookup_mime_subtype2(1, codec, 0),
++ ast_rtp_lookup_sample_rate2(1, codec));
+ /* Add fmtp code here */
+ }
+
+@@ -9202,20 +9682,21 @@
+ if (debug)
+ ast_verbose("Adding text codec 0x%x (%s) to SDP\n", codec, ast_getformatname(codec));
+
+- if ((rtp_code = ast_rtp_lookup_code(p->trtp, 1, codec)) == -1)
++ if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->trtp), 1, codec)) == -1)
+ return;
+
+ ast_str_append(m_buf, 0, " %d", rtp_code);
+ ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code,
+- ast_rtp_lookup_mime_subtype(1, codec, 0),
+- ast_rtp_lookup_sample_rate(1, codec));
++ ast_rtp_lookup_mime_subtype2(1, codec, 0),
++ ast_rtp_lookup_sample_rate2(1, codec));
+ /* Add fmtp code here */
+
+ if (codec == AST_FORMAT_T140RED) {
+- ast_str_append(a_buf, 0, "a=fmtp:%d %d/%d/%d\r\n", rtp_code,
+- ast_rtp_lookup_code(p->trtp, 1, AST_FORMAT_T140),
+- ast_rtp_lookup_code(p->trtp, 1, AST_FORMAT_T140),
+- ast_rtp_lookup_code(p->trtp, 1, AST_FORMAT_T140));
++ int t140code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->trtp), 1, AST_FORMAT_T140);
++ ast_str_append(a_buf, 0, "a=fmtp:%d %d/%d/%d\r\n", rtp_code,
++ t140code,
++ t140code,
++ t140code);
+
+ }
+ }
+@@ -9258,14 +9739,14 @@
+ int rtp_code;
+
+ if (debug)
+- ast_verbose("Adding non-codec 0x%x (%s) to SDP\n", format, ast_rtp_lookup_mime_subtype(0, format, 0));
+- if ((rtp_code = ast_rtp_lookup_code(p->rtp, 0, format)) == -1)
++ ast_verbose("Adding non-codec 0x%x (%s) to SDP\n", format, ast_rtp_lookup_mime_subtype2(0, format, 0));
++ if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->rtp), 0, format)) == -1)
+ return;
+
+ ast_str_append(m_buf, 0, " %d", rtp_code);
+ ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code,
+- ast_rtp_lookup_mime_subtype(0, format, 0),
+- ast_rtp_lookup_sample_rate(0, format));
++ ast_rtp_lookup_mime_subtype2(0, format, 0),
++ ast_rtp_lookup_sample_rate2(0, format));
+ if (format == AST_RTP_DTMF) /* Indicate we support DTMF and FLASH... */
+ ast_str_append(a_buf, 0, "a=fmtp:%d 0-16\r\n", rtp_code);
+ }
+@@ -9278,11 +9759,11 @@
+ struct sockaddr_in *dest, struct sockaddr_in *vdest)
+ {
+ /* First, get our address */
+- ast_rtp_get_us(p->rtp, sin);
++ ast_rtp_instance_get_local_address(p->rtp, sin);
+ if (p->vrtp)
+- ast_rtp_get_us(p->vrtp, vsin);
++ ast_rtp_instance_get_local_address(p->vrtp, vsin);
+ if (p->trtp)
+- ast_rtp_get_us(p->trtp, tsin);
++ ast_rtp_instance_get_local_address(p->trtp, tsin);
+
+ /* Now, try to figure out where we want them to send data */
+ /* Is this a re-invite to move the media out, then use the original offer from caller */
+@@ -9317,11 +9798,11 @@
+ int len = 0;
+ int alreadysent = 0;
+
+- struct sockaddr_in sin;
+- struct sockaddr_in vsin;
+- struct sockaddr_in tsin;
+- struct sockaddr_in dest;
+- struct sockaddr_in udptlsin;
++ struct sockaddr_in sin = { 0, };
++ struct sockaddr_in vsin = { 0, };
++ struct sockaddr_in tsin = { 0, };
++ struct sockaddr_in dest = { 0, };
++ struct sockaddr_in udptlsin = { 0, };
+ struct sockaddr_in vdest = { 0, };
+ struct sockaddr_in tdest = { 0, };
+ struct sockaddr_in udptldest = { 0, };
+@@ -9701,7 +10182,7 @@
+ /*! \brief Used for 200 OK and 183 early media
+ \return Will return XMIT_ERROR for network errors.
+ */
+-static int transmit_response_with_sdp(struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable, int oldsdp)
++static int transmit_response_with_sdp(struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable, int oldsdp, int rpid)
+ {
+ struct sip_request resp;
+ int seqno;
+@@ -9710,10 +10191,13 @@
+ return -1;
+ }
+ respprep(&resp, p, msg, req);
++ if (rpid == TRUE) {
++ add_rpid(&resp, p);
++ }
+ if (p->rtp) {
+ if (!p->autoframing && !ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
+ ast_debug(1, "Setting framing from config on incoming call\n");
+- ast_rtp_codec_setpref(p->rtp, &p->prefs);
++ ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, &p->prefs);
+ }
+ try_suggested_sip_codec(p);
+ if (p->t38.state == T38_PEER_DIRECT || p->t38.state == T38_ENABLED) {
+@@ -9799,8 +10283,13 @@
+ add_header(&req, "X-asterisk-Info", "SIP re-invite (External RTP bridge)");
+ }
+
++ if (ast_test_flag(&p->flags[1], SIP_SENDRPID))
++ add_rpid(&req, p);
++
+ if (p->do_history)
+ append_history(p, "ReInv", "Re-invite sent");
++
++ try_suggested_sip_codec(p);
+ if (t38version)
+ add_sdp(&req, p, oldsdp, FALSE, TRUE);
+ else
+@@ -9847,95 +10336,18 @@
+ {
+
+ int ourport = ntohs(p->ourip.sin_port);
+-
+- if (p->socket.type & SIP_TRANSPORT_UDP) {
+- if (!sip_standard_port(p->socket.type, ourport))
++ /* only add port if it's non-standard for the transport type */
++ if (!sip_standard_port(p->socket.type, ourport)) {
++ if (p->socket.type == SIP_TRANSPORT_UDP)
+ ast_string_field_build(p, our_contact, "<sip:%s%s%s:%d>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip.sin_addr), ourport);
+ else
++ ast_string_field_build(p, our_contact, "<sip:%s%s%s:%d;transport=%s>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip.sin_addr), ourport, get_transport(p->socket.type));
++ } else {
++ if (p->socket.type == SIP_TRANSPORT_UDP)
+ ast_string_field_build(p, our_contact, "<sip:%s%s%s>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip.sin_addr));
+- } else {
+- /*! \todo We should not always add port here. Port is only added if it's non-standard (see code above) */
+- ast_string_field_build(p, our_contact, "<sip:%s%s%s:%d;transport=%s>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip.sin_addr), ourport, get_transport(p->socket.type));
+- }
+-}
+-
+-/*! \brief Build the Remote Party-ID & From using callingpres options */
+-static void build_rpid(struct sip_pvt *p)
+-{
+- int send_pres_tags = TRUE;
+- const char *privacy=NULL;
+- const char *screen=NULL;
+- char buf[256];
+- const char *clid = default_callerid;
+- const char *clin = NULL;
+- const char *fromdomain;
+-
+- if (!ast_strlen_zero(p->rpid) || !ast_strlen_zero(p->rpid_from))
+- return;
+-
+- if (p->owner && p->owner->cid.cid_num)
+- clid = p->owner->cid.cid_num;
+- if (p->owner && p->owner->cid.cid_name)
+- clin = p->owner->cid.cid_name;
+- if (ast_strlen_zero(clin))
+- clin = clid;
+-
+- switch (p->callingpres) {
+- case AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
+- privacy = "off";
+- screen = "no";
+- break;
+- case AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
+- privacy = "off";
+- screen = "yes";
+- break;
+- case AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
+- privacy = "off";
+- screen = "no";
+- break;
+- case AST_PRES_ALLOWED_NETWORK_NUMBER:
+- privacy = "off";
+- screen = "yes";
+- break;
+- case AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
+- privacy = "full";
+- screen = "no";
+- break;
+- case AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
+- privacy = "full";
+- screen = "yes";
+- break;
+- case AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
+- privacy = "full";
+- screen = "no";
+- break;
+- case AST_PRES_PROHIB_NETWORK_NUMBER:
+- privacy = "full";
+- screen = "yes";
+- break;
+- case AST_PRES_NUMBER_NOT_AVAILABLE:
+- send_pres_tags = FALSE;
+- break;
+- default:
+- ast_log(LOG_WARNING, "Unsupported callingpres (%d)\n", p->callingpres);
+- if ((p->callingpres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED)
+- privacy = "full";
+ else
+- privacy = "off";
+- screen = "no";
+- break;
++ ast_string_field_build(p, our_contact, "<sip:%s%s%s;transport=%s>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip.sin_addr), get_transport(p->socket.type));
+ }
+-
+- fromdomain = S_OR(p->fromdomain, ast_inet_ntoa(p->ourip.sin_addr));
+-
+- snprintf(buf, sizeof(buf), "\"%s\" <sip:%s@%s>", clin, clid, fromdomain);
+- if (send_pres_tags)
+- snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ";privacy=%s;screen=%s", privacy, screen);
+- ast_string_field_set(p, rpid, buf);
+-
+- ast_string_field_build(p, rpid_from, "\"%s\" <sip:%s@%s>;tag=%s", clin,
+- S_OR(p->fromuser, clid),
+- fromdomain, p->tag);
+ }
+
+ /*! \brief Initiate new SIP request to peer/user */
+@@ -9973,16 +10385,21 @@
+
+ snprintf(p->lastmsg, sizeof(p->lastmsg), "Init: %s", sip_methods[sipmethod].text);
+
+- if (p->owner) {
+- l = p->owner->cid.cid_num;
+- n = p->owner->cid.cid_name;
++ if (p->owner && (p->owner->connected.id.number_presentation & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED) {
++ l = p->owner->connected.id.number;
++ n = p->owner->connected.id.name;
+ }
+- /* if we are not sending RPID and user wants his callerid restricted */
+- if (!ast_test_flag(&p->flags[0], SIP_SENDRPID) &&
+- ((p->callingpres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED)) {
+- l = CALLERID_UNKNOWN;
+- n = l;
++
++ /* Hey, it's a NOTIFY! See if they've configured a mwi_from.
++ * XXX Right now, this logic works because the only place that mwi_from
++ * is set on the sip_pvt is in sip_send_mwi_to_peer. If things changed, then
++ * we might end up putting the mwi_from setting into other types of NOTIFY
++ * messages as well.
++ */
++ if (sipmethod == SIP_NOTIFY && !ast_strlen_zero(p->mwi_from)) {
++ l = p->mwi_from;
+ }
++
+ if (ast_strlen_zero(l))
+ l = default_callerid;
+ if (ast_strlen_zero(n))
+@@ -10070,12 +10487,7 @@
+ /* SLD: FIXME?: do Route: here too? I think not cos this is the first request.
+ * OTOH, then we won't have anything in p->route anyway */
+
+- /* Build Remote Party-ID and From */
+- if (ast_test_flag(&p->flags[0], SIP_SENDRPID) && (sipmethod == SIP_INVITE)) {
+- build_rpid(p);
+- add_header(req, "From", p->rpid_from);
+- } else
+- add_header(req, "From", from);
++ add_header(req, "From", from);
+ add_header(req, "To", to);
+ ast_string_field_set(p, exten, l);
+ build_contact(p);
+@@ -10084,10 +10496,46 @@
+ add_header(req, "CSeq", tmp_n);
+ if (!ast_strlen_zero(global_useragent))
+ add_header(req, "User-Agent", global_useragent);
+- if (!ast_strlen_zero(p->rpid))
+- add_header(req, "Remote-Party-ID", p->rpid);
+ }
+
++/*! \brief Add "Diversion" header to outgoing message
++ *
++ * We need to add a Diversion header if the owner channel of
++ * this dialog has redirecting information associated with it.
++ *
++ * \param req The request/response to which we will add the header
++ * \param pvt The sip_pvt which represents the call-leg
++ * \param apr Redirecting data used to make the diversion header
++ */
++static void add_diversion_header(struct sip_request *req, struct sip_pvt *pvt)
++{
++ const char *diverting_number;
++ const char *diverting_name;
++ const char *reason;
++ char header_text[256];
++
++ if (!pvt->owner) {
++ return;
++ }
++
++ diverting_number = pvt->owner->cid.cid_rdnis;
++ diverting_name = pvt->owner->redirecting.from.name;
++ reason = sip_reason_code_to_str(pvt->owner->redirecting.reason);
++
++ if (ast_strlen_zero(diverting_number)) {
++ return;
++ }
++
++ /* We at least have a number to place in the Diversion header, which is enough */
++ if (ast_strlen_zero(diverting_name)) {
++ snprintf(header_text, sizeof(header_text), "<sip:%s@%s>;reason=%s", diverting_number, ast_inet_ntoa(pvt->ourip.sin_addr), reason);
++ } else {
++ snprintf(header_text, sizeof(header_text), "\"%s\" <sip:%s@%s>;reason=%s", diverting_name, diverting_number, ast_inet_ntoa(pvt->ourip.sin_addr), reason);
++ }
++
++ add_header(req, "Diversion", header_text);
++}
++
+ /*! \brief Build REFER/INVITE/OPTIONS/SUBSCRIBE message and transmit it
+ \param init 0 = Prepare request within dialog, 1= prepare request, new branch, 2= prepare new request and new dialog. do_proxy_auth calls this with init!=2
+ \param p sip_pvt structure
+@@ -10206,13 +10654,20 @@
+
+ ast_channel_unlock(chan);
+ }
++ if ((sipmethod == SIP_INVITE || sipmethod == SIP_UPDATE) && ast_test_flag(&p->flags[0], SIP_SENDRPID))
++ add_rpid(&req, p);
++ if (sipmethod == SIP_INVITE) {
++ add_diversion_header(&req, p);
++ }
+ if (sdp) {
+ if (p->udptl && p->t38.state == T38_LOCAL_REINVITE) {
+ ast_udptl_offered_from_local(p->udptl, 1);
+ ast_debug(1, "T38 is in state %d on channel %s\n", p->t38.state, p->owner ? p->owner->name : "<none>");
+ add_sdp(&req, p, FALSE, FALSE, TRUE);
+- } else if (p->rtp)
++ } else if (p->rtp) {
++ try_suggested_sip_codec(p);
+ add_sdp(&req, p, FALSE, TRUE, FALSE);
++ }
+ } else {
+ if (!p->notify_headers) {
+ add_header_contentLength(&req, 0);
+@@ -10221,7 +10676,9 @@
+
+ if (!p->initreq.headers || init > 2)
+ initialize_initreq(p, &req);
+- p->lastinvite = p->ocseq;
++ if (sipmethod == SIP_INVITE) {
++ p->lastinvite = p->ocseq;
++ }
+ return send_request(p, &req, init ? XMIT_CRITICAL : XMIT_RELIABLE, p->ocseq);
+ }
+
+@@ -10258,7 +10715,7 @@
+ }
+
+ /* Create a dialog that we will use for the subscription */
+- if (!(mwi->call = sip_alloc(NULL, NULL, 0, SIP_SUBSCRIBE))) {
++ if (!(mwi->call = sip_alloc(NULL, NULL, 0, SIP_SUBSCRIBE, NULL))) {
+ return -1;
+ }
+
+@@ -10296,9 +10753,9 @@
+ if (!ast_strlen_zero(mwi->secret)) {
+ ast_string_field_set(mwi->call, peersecret, mwi->secret);
+ }
+- mwi->call->socket.type = mwi->transport;
++ set_socket_transport(&mwi->call->socket, mwi->transport);
+ mwi->call->socket.port = htons(mwi->portno);
+- ast_sip_ouraddrfor(&mwi->call->sa.sin_addr, &mwi->call->ourip);
++ ast_sip_ouraddrfor(&mwi->call->sa.sin_addr, &mwi->call->ourip, mwi->call);
+ build_contact(mwi->call);
+ build_via(mwi->call);
+ build_callid_pvt(mwi->call);
+@@ -10313,30 +10770,31 @@
+ return 0;
+ }
+
+-static int find_calling_channel(struct ast_channel *c, void *data) {
++static int find_calling_channel(void *obj, void *arg, void *data, int flags)
++{
++ struct ast_channel *c = obj;
+ struct sip_pvt *p = data;
++ int res;
+
+- return (c->pbx &&
++ ast_channel_lock(c);
++
++ res = (c->pbx &&
+ (!strcasecmp(c->macroexten, p->exten) || !strcasecmp(c->exten, p->exten)) &&
+ (sip_cfg.notifycid == IGNORE_CONTEXT || !strcasecmp(c->context, p->context)));
++
++ ast_channel_unlock(c);
++
++ return res ? CMP_MATCH | CMP_STOP : 0;
+ }
+
+-/*! \brief Used in the SUBSCRIBE notification subsystem (RFC3265) */
+-static int transmit_state_notify(struct sip_pvt *p, int state, int full, int timeout)
++/*! \brief Builds XML portion of state NOTIFY messages */
++static void state_notify_build_xml(int state, int full, const char *exten, const char *context, struct ast_str **tmp, struct sip_pvt *p, int subscribed, const char *mfrom, const char *mto)
+ {
+- struct ast_str *tmp = ast_str_alloca(4000);
+- char from[256], to[256];
+- char *c, *mfrom, *mto;
+- struct sip_request req;
++ enum state { NOTIFY_OPEN, NOTIFY_INUSE, NOTIFY_CLOSED } local_state = NOTIFY_OPEN;
++ const char *statestring = "terminated";
++ const char *pidfstate = "--";
++ const char *pidfnote= "Ready";
+ char hint[AST_MAX_EXTENSION];
+- char *statestring = "terminated";
+- const struct cfsubscription_types *subscriptiontype;
+- enum state { NOTIFY_OPEN, NOTIFY_INUSE, NOTIFY_CLOSED } local_state = NOTIFY_OPEN;
+- char *pidfstate = "--";
+- char *pidfnote= "Ready";
+-
+- memset(from, 0, sizeof(from));
+- memset(to, 0, sizeof(to));
+
+ switch (state) {
+ case (AST_EXTENSION_RINGING | AST_EXTENSION_INUSE):
+@@ -10381,10 +10839,8 @@
+ break;
+ }
+
+- subscriptiontype = find_subscription_type(p->subscribed);
+-
+ /* Check which device/devices we are watching and if they are registered */
+- if (ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, p->context, p->exten)) {
++ if (ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, context, exten)) {
+ char *hint2 = hint, *individual_hint = NULL;
+ int hint_count = 0, unavailable_count = 0;
+
+@@ -10405,103 +10861,64 @@
+ }
+ }
+
+- ast_copy_string(from, get_header(&p->initreq, "From"), sizeof(from));
+- c = get_in_brackets(from);
+- if (strncasecmp(c, "sip:", 4) && strncasecmp(c, "sips:", 5)) {
+- ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", c);
+- return -1;
+- }
+-
+- mfrom = remove_uri_parameters(c);
+-
+- ast_copy_string(to, get_header(&p->initreq, "To"), sizeof(to));
+- c = get_in_brackets(to);
+- if (strncasecmp(c, "sip:", 4) && strncasecmp(c, "sips:", 5)) {
+- ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", c);
+- return -1;
+- }
+- mto = remove_uri_parameters(c);
+-
+- reqprep(&req, p, SIP_NOTIFY, 0, 1);
+-
+-
+- add_header(&req, "Event", subscriptiontype->event);
+- add_header(&req, "Content-Type", subscriptiontype->mediatype);
+- switch(state) {
+- case AST_EXTENSION_DEACTIVATED:
+- if (timeout)
+- add_header(&req, "Subscription-State", "terminated;reason=timeout");
+- else {
+- add_header(&req, "Subscription-State", "terminated;reason=probation");
+- add_header(&req, "Retry-After", "60");
+- }
+- break;
+- case AST_EXTENSION_REMOVED:
+- add_header(&req, "Subscription-State", "terminated;reason=noresource");
+- break;
+- default:
+- if (p->expiry)
+- add_header(&req, "Subscription-State", "active");
+- else /* Expired */
+- add_header(&req, "Subscription-State", "terminated;reason=timeout");
+- }
+- switch (p->subscribed) {
++ switch (subscribed) {
+ case XPIDF_XML:
+ case CPIM_PIDF_XML:
+- ast_str_append(&tmp, 0,
++ ast_str_append(tmp, 0,
+ "<?xml version=\"1.0\"?>\n"
+ "<!DOCTYPE presence PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n"
+ "<presence>\n");
+- ast_str_append(&tmp, 0, "<presentity uri=\"%s;method=SUBSCRIBE\" />\n", mfrom);
+- ast_str_append(&tmp, 0, "<atom id=\"%s\">\n", p->exten);
+- ast_str_append(&tmp, 0, "<address uri=\"%s;user=ip\" priority=\"0.800000\">\n", mto);
+- ast_str_append(&tmp, 0, "<status status=\"%s\" />\n", (local_state == NOTIFY_OPEN) ? "open" : (local_state == NOTIFY_INUSE) ? "inuse" : "closed");
+- ast_str_append(&tmp, 0, "<msnsubstatus substatus=\"%s\" />\n", (local_state == NOTIFY_OPEN) ? "online" : (local_state == NOTIFY_INUSE) ? "onthephone" : "offline");
+- ast_str_append(&tmp, 0, "</address>\n</atom>\n</presence>\n");
++ ast_str_append(tmp, 0, "<presentity uri=\"%s;method=SUBSCRIBE\" />\n", mfrom);
++ ast_str_append(tmp, 0, "<atom id=\"%s\">\n", exten);
++ ast_str_append(tmp, 0, "<address uri=\"%s;user=ip\" priority=\"0.800000\">\n", mto);
++ ast_str_append(tmp, 0, "<status status=\"%s\" />\n", (local_state == NOTIFY_OPEN) ? "open" : (local_state == NOTIFY_INUSE) ? "inuse" : "closed");
++ ast_str_append(tmp, 0, "<msnsubstatus substatus=\"%s\" />\n", (local_state == NOTIFY_OPEN) ? "online" : (local_state == NOTIFY_INUSE) ? "onthephone" : "offline");
++ ast_str_append(tmp, 0, "</address>\n</atom>\n</presence>\n");
+ break;
+ case PIDF_XML: /* Eyebeam supports this format */
+- ast_str_append(&tmp, 0,
++ ast_str_append(tmp, 0,
+ "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n"
+ "<presence xmlns=\"urn:ietf:params:xml:ns:pidf\" \nxmlns:pp=\"urn:ietf:params:xml:ns:pidf:person\"\nxmlns:es=\"urn:ietf:params:xml:ns:pidf:rpid:status:rpid-status\"\nxmlns:ep=\"urn:ietf:params:xml:ns:pidf:rpid:rpid-person\"\nentity=\"%s\">\n", mfrom);
+- ast_str_append(&tmp, 0, "<pp:person><status>\n");
++ ast_str_append(tmp, 0, "<pp:person><status>\n");
+ if (pidfstate[0] != '-')
+- ast_str_append(&tmp, 0, "<ep:activities><ep:%s/></ep:activities>\n", pidfstate);
+- ast_str_append(&tmp, 0, "</status></pp:person>\n");
+- ast_str_append(&tmp, 0, "<note>%s</note>\n", pidfnote); /* Note */
+- ast_str_append(&tmp, 0, "<tuple id=\"%s\">\n", p->exten); /* Tuple start */
+- ast_str_append(&tmp, 0, "<contact priority=\"1\">%s</contact>\n", mto);
++ ast_str_append(tmp, 0, "<ep:activities><ep:%s/></ep:activities>\n", pidfstate);
++ ast_str_append(tmp, 0, "</status></pp:person>\n");
++ ast_str_append(tmp, 0, "<note>%s</note>\n", pidfnote); /* Note */
++ ast_str_append(tmp, 0, "<tuple id=\"%s\">\n", exten); /* Tuple start */
++ ast_str_append(tmp, 0, "<contact priority=\"1\">%s</contact>\n", mto);
+ if (pidfstate[0] == 'b') /* Busy? Still open ... */
+- ast_str_append(&tmp, 0, "<status><basic>open</basic></status>\n");
++ ast_str_append(tmp, 0, "<status><basic>open</basic></status>\n");
+ else
+- ast_str_append(&tmp, 0, "<status><basic>%s</basic></status>\n", (local_state != NOTIFY_CLOSED) ? "open" : "closed");
+- ast_str_append(&tmp, 0, "</tuple>\n</presence>\n");
++ ast_str_append(tmp, 0, "<status><basic>%s</basic></status>\n", (local_state != NOTIFY_CLOSED) ? "open" : "closed");
++ ast_str_append(tmp, 0, "</tuple>\n</presence>\n");
+ break;
+ case DIALOG_INFO_XML: /* SNOM subscribes in this format */
+- ast_str_append(&tmp, 0, "<?xml version=\"1.0\"?>\n");
+- ast_str_append(&tmp, 0, "<dialog-info xmlns=\"urn:ietf:params:xml:ns:dialog-info\" version=\"%d\" state=\"%s\" entity=\"%s\">\n", p->dialogver++, full ? "full" : "partial", mto);
++ ast_str_append(tmp, 0, "<?xml version=\"1.0\"?>");
++ ast_str_append(tmp, 0, "<dialog-info xmlns=\"urn:ietf:params:xml:ns:dialog-info\" version=\"%d\" state=\"%s\" entity=\"%s\">", p->dialogver, full ? "full" : "partial", mto);
+ if ((state & AST_EXTENSION_RINGING) && sip_cfg.notifyringing) {
+- const char *local_display = p->exten;
+- char *local_target = mto;
++ const char *local_display = exten;
++ char *local_target = ast_strdupa(mto);
+
+ /* There are some limitations to how this works. The primary one is that the
+ callee must be dialing the same extension that is being monitored. Simply dialing
+ the hint'd device is not sufficient. */
+ if (sip_cfg.notifycid) {
+- struct ast_channel *caller = ast_channel_search_locked(find_calling_channel, p);
++ struct ast_channel *caller;
+
+- if (caller) {
++ if ((caller = ast_channel_callback(find_calling_channel, NULL, p, 0))) {
+ int need = strlen(caller->cid.cid_num) + strlen(p->fromdomain) + sizeof("sip:@");
+ local_target = alloca(need);
++ ast_channel_lock(caller);
+ snprintf(local_target, need, "sip:%s@%s", caller->cid.cid_num, p->fromdomain);
+ local_display = ast_strdupa(caller->cid.cid_name);
+ ast_channel_unlock(caller);
+- caller = NULL;
++ caller = ast_channel_unref(caller);
+ }
+ }
+
+ /* We create a fake call-id which the phone will send back in an INVITE
+ Replaces header which we can grab and do some magic with. */
+- ast_str_append(&tmp, 0,
++ ast_str_append(tmp, 0,
+ "<dialog id=\"%s\" call-id=\"pickup-%s\" direction=\"recipient\">\n"
+ "<remote>\n"
+ /* See the limitations of this above. Luckily the phone seems to still be
+@@ -10513,23 +10930,102 @@
+ "<identity>%s</identity>\n"
+ "<target uri=\"%s\"/>\n"
+ "</local>\n",
+- p->exten, p->callid, local_display, local_target, local_target, mto, mto);
++ exten, p->callid, local_display, local_target, local_target, mto, mto);
+ } else {
+- ast_str_append(&tmp, 0, "<dialog id=\"%s\">\n", p->exten);
++ ast_str_append(tmp, 0, "<dialog id=\"%s\">", exten);
+ }
+- ast_str_append(&tmp, 0, "<state>%s</state>\n", statestring);
++ ast_str_append(tmp, 0, "<state>%s</state>\n", statestring);
+ if (state == AST_EXTENSION_ONHOLD) {
+- ast_str_append(&tmp, 0, "<local>\n<target uri=\"%s\">\n"
+- "<param pname=\"+sip.rendering\" pvalue=\"no\"/>\n"
+- "</target>\n</local>\n", mto);
++ ast_str_append(tmp, 0, "<local>\n<target uri=\"%s\">\n"
++ "<param pname=\"+sip.rendering\" pvalue=\"no\"/>\n"
++ "</target>\n</local>\n", mto);
+ }
+- ast_str_append(&tmp, 0, "</dialog>\n</dialog-info>\n");
++ ast_str_append(tmp, 0, "</dialog>\n</dialog-info>\n");
+ break;
+ case NONE:
+ default:
+ break;
+ }
++}
+
++
++/*! \brief Used in the SUBSCRIBE notification subsystem (RFC3265) */
++static int transmit_state_notify(struct sip_pvt *p, int state, int full, int timeout)
++{
++ struct ast_str *tmp = ast_str_alloca(4000);
++ char from[256], to[256];
++ char *c, *mfrom, *mto;
++ struct sip_request req;
++ const struct cfsubscription_types *subscriptiontype;
++
++ memset(from, 0, sizeof(from));
++ memset(to, 0, sizeof(to));
++
++ subscriptiontype = find_subscription_type(p->subscribed);
++
++ ast_copy_string(from, get_header(&p->initreq, "From"), sizeof(from));
++ c = get_in_brackets(from);
++ if (strncasecmp(c, "sip:", 4) && strncasecmp(c, "sips:", 5)) {
++ ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", c);
++ return -1;
++ }
++
++ mfrom = remove_uri_parameters(c);
++
++ ast_copy_string(to, get_header(&p->initreq, "To"), sizeof(to));
++ c = get_in_brackets(to);
++ if (strncasecmp(c, "sip:", 4) && strncasecmp(c, "sips:", 5)) {
++ ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", c);
++ return -1;
++ }
++ mto = remove_uri_parameters(c);
++
++ reqprep(&req, p, SIP_NOTIFY, 0, 1);
++
++ switch(state) {
++ case AST_EXTENSION_DEACTIVATED:
++ if (timeout)
++ add_header(&req, "Subscription-State", "terminated;reason=timeout");
++ else {
++ add_header(&req, "Subscription-State", "terminated;reason=probation");
++ add_header(&req, "Retry-After", "60");
++ }
++ break;
++ case AST_EXTENSION_REMOVED:
++ add_header(&req, "Subscription-State", "terminated;reason=noresource");
++ break;
++ default:
++ if (p->expiry)
++ add_header(&req, "Subscription-State", "active");
++ else /* Expired */
++ add_header(&req, "Subscription-State", "terminated;reason=timeout");
++ }
++
++ switch (p->subscribed) {
++ case XPIDF_XML:
++ case CPIM_PIDF_XML:
++ add_header(&req, "Event", subscriptiontype->event);
++ state_notify_build_xml(state, full, p->exten, p->context, &tmp, p, p->subscribed, mfrom, mto);
++ add_header(&req, "Content-Type", subscriptiontype->mediatype);
++ p->dialogver++;
++ break;
++ case PIDF_XML: /* Eyebeam supports this format */
++ add_header(&req, "Event", subscriptiontype->event);
++ state_notify_build_xml(state, full, p->exten, p->context, &tmp, p, p->subscribed, mfrom, mto);
++ add_header(&req, "Content-Type", subscriptiontype->mediatype);
++ p->dialogver++;
++ break;
++ case DIALOG_INFO_XML: /* SNOM subscribes in this format */
++ add_header(&req, "Event", subscriptiontype->event);
++ state_notify_build_xml(state, full, p->exten, p->context, &tmp, p, p->subscribed, mfrom, mto);
++ add_header(&req, "Content-Type", subscriptiontype->mediatype);
++ p->dialogver++;
++ break;
++ case NONE:
++ default:
++ break;
++ }
++
+ add_header_contentLength(&req, tmp->used);
+ add_line(&req, tmp->str);
+
+@@ -10644,7 +11140,7 @@
+ channame += 4;
+ }
+
+- if (!(p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY))) {
++ if (!(p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY, NULL))) {
+ astman_send_error(s, m, "Unable to build sip pvt data for notify (memory/socket error)");
+ return 0;
+ }
+@@ -10662,7 +11158,7 @@
+ ast_set_flag(&p->flags[0], SIP_OUTGOING);
+
+ /* Recalculate our side, and recalculate Call ID */
+- ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip);
++ ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip, p);
+ build_via(p);
+ ao2_t_unlink(dialogs, p, "About to change the callid -- remove the old name");
+ build_callid_pvt(p);
+@@ -10679,15 +11175,85 @@
+ return 0;
+ }
+
+-static char mandescr_sipnotify[] =
+-"Description: Sends a SIP Notify event\n"
+-"All parameters for this event must be specified in the body of this request\n"
+-"via multiple Variable: name=value sequences.\n"
+-"Variables: \n"
+-" *Channel: <peername> Peer to receive the notify. Required.\n"
+-" *Variable: <name>=<value> At least one variable pair must be specified.\n"
+-" ActionID: <id> Action ID for this transaction. Will be returned.\n";
++/*! \brief Send a provisional response indicating that a call was redirected
++ */
++static void update_redirecting(struct sip_pvt *p, const void *data, size_t datalen)
++{
++ struct sip_request resp;
+
++ if (p->owner->_state == AST_STATE_UP || ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
++ return;
++ }
++
++ if (!ast_strlen_zero(p->owner->redirecting.to.number)) {
++ ast_string_field_set(p, exten, p->owner->redirecting.to.number);
++ build_contact(p);
++ }
++ respprep(&resp, p, "181 Call is being forwarded", &p->initreq);
++ add_diversion_header(&resp, p);
++ send_response(p, &resp, XMIT_UNRELIABLE, 0);
++}
++
++/*! \brief Notify peer that the connected line has changed */
++static void update_connectedline(struct sip_pvt *p, const void *data, size_t datalen)
++{
++
++ if (!ast_test_flag(&p->flags[0], SIP_SENDRPID))
++ return;
++ if (ast_strlen_zero(p->owner->connected.id.number))
++ return;
++
++ append_history(p, "ConnectedLine", "%s party is now %s <%s>", ast_test_flag(&p->flags[0], SIP_OUTGOING) ? "Calling" : "Called", p->owner->connected.id.name, p->owner->connected.id.number);
++
++ if (p->owner->_state == AST_STATE_UP || ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
++ struct sip_request req;
++
++ if (p->invitestate == INV_CONFIRMED || p->invitestate == INV_TERMINATED) {
++ reqprep(&req, p, ast_test_flag(&p->flags[0], SIP_REINVITE_UPDATE) ? SIP_UPDATE : SIP_INVITE, 0, 1);
++
++ add_header(&req, "Allow", ALLOWED_METHODS);
++ add_header(&req, "Supported", SUPPORTED_EXTENSIONS);
++ add_rpid(&req, p);
++ add_sdp(&req, p, FALSE, TRUE, FALSE);
++
++ initialize_initreq(p, &req);
++ p->lastinvite = p->ocseq;
++ ast_set_flag(&p->flags[0], SIP_OUTGOING);
++ p->invitestate = INV_CALLING;
++ send_request(p, &req, XMIT_CRITICAL, p->ocseq);
++ } else if (is_method_allowed(&p->allowed_methods, SIP_UPDATE)) {
++ reqprep(&req, p, SIP_UPDATE, 0, 1);
++ add_rpid(&req, p);
++ add_header(&req, "X-Asterisk-rpid-update", "Yes");
++ add_header_contentLength(&req, 0);
++ send_request(p, &req, XMIT_CRITICAL, p->ocseq);
++ } else {
++ /* We cannot send the update yet, so we have to wait until we can */
++ ast_set_flag(&p->flags[0], SIP_NEEDREINVITE);
++ }
++ } else {
++ if (ast_test_flag(&p->flags[1], SIP_PAGE2_RPID_IMMEDIATE)) {
++ struct sip_request resp;
++
++ if ((p->owner->_state == AST_STATE_RING) && !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT)) {
++ respprep(&resp, p, "180 Ringing", &p->initreq);
++ add_rpid(&resp, p);
++ send_response(p, &resp, XMIT_UNRELIABLE, 0);
++ ast_set_flag(&p->flags[0], SIP_RINGING);
++ } else if (p->owner->_state == AST_STATE_RINGING) {
++ respprep(&resp, p, "183 Session Progress", &p->initreq);
++ add_rpid(&resp, p);
++ send_response(p, &resp, XMIT_UNRELIABLE, 0);
++ ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
++ } else {
++ ast_log(LOG_DEBUG, "Unable able to send update to '%s' in state '%s'\n", p->owner->name, ast_state2str(p->owner->_state));
++ }
++ } else {
++ ast_set_flag(&p->flags[1], SIP_PAGE2_CONNECTLINEUPDATE_PEND);
++ }
++ }
++}
++
+ static const struct _map_x_s regstatestrings[] = {
+ { REG_STATE_FAILED, "Failed" },
+ { REG_STATE_UNREGISTERED, "Unregistered"},
+@@ -10715,7 +11281,7 @@
+ static int sip_reregister(const void *data)
+ {
+ /* if we are here, we know that we need to reregister. */
+- struct sip_registry *r= (struct sip_registry *) data;
++ struct sip_registry *r = (struct sip_registry *) data;
+
+ /* if we couldn't get a reference to the registry object, punt */
+ if (!r)
+@@ -10730,7 +11296,7 @@
+
+ r->expire = -1;
+ __sip_do_register(r);
+- registry_unref(r, "unreg the re-registered");
++ registry_unref(r, "unref the re-register scheduled event");
+ return 0;
+ }
+
+@@ -10849,7 +11415,7 @@
+ r->callid_valid = TRUE;
+ }
+ /* Allocate SIP dialog for registration */
+- if (!(p = sip_alloc( r->callid, NULL, 0, SIP_REGISTER))) {
++ if (!(p = sip_alloc( r->callid, NULL, 0, SIP_REGISTER, NULL))) {
+ ast_log(LOG_WARNING, "Unable to allocate registration transaction (memory or socket error)\n");
+ return 0;
+ }
+@@ -10916,7 +11482,7 @@
+ ast_string_field_set(p, exten, r->callback);
+
+ /* Set transport and port so the correct contact is built */
+- p->socket.type = r->transport;
++ set_socket_transport(&p->socket, r->transport);
+ if (r->transport == SIP_TRANSPORT_TLS || r->transport == SIP_TRANSPORT_TCP) {
+ p->socket.port = sip_tcp_desc.local_address.sin_port;
+ }
+@@ -10926,7 +11492,7 @@
+ based on whether the remote host is on the external or
+ internal network so we can register through nat
+ */
+- ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip);
++ ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip, p);
+ build_contact(p);
+ }
+
+@@ -11248,19 +11814,20 @@
+ ast_update_realtime(tablename, "name", peer->name, "fullcontact", "", "ipaddr", "", "port", "", "regseconds", "0", peer->deprecated_username ? "username" : "defaultuser", "", "regserver", "", "useragent", "", "lastms", "", SENTINEL);
+ } else {
+ ast_db_del("SIP/Registry", peer->name);
++ ast_db_del("SIP/PeerMethods", peer->name);
+ }
+ }
+ }
+
+-static void set_peer_transport(struct sip_peer *peer, int transport)
++static void set_socket_transport(struct sip_socket *socket, int transport)
+ {
+ /* if the transport type changes, clear all socket data */
+- if (peer->socket.type != transport) {
+- peer->socket.type = transport;
+- peer->socket.fd = -1;
+- if (peer->socket.tcptls_session) {
+- ao2_ref(peer->socket.tcptls_session, -1);
+- peer->socket.tcptls_session = NULL;
++ if (socket->type != transport) {
++ socket->fd = -1;
++ socket->type = transport;
++ if (socket->tcptls_session) {
++ ao2_ref(socket->tcptls_session, -1);
++ socket->tcptls_session = NULL;
+ }
+ }
+ }
+@@ -11277,11 +11844,12 @@
+ memset(&peer->addr, 0, sizeof(peer->addr));
+
+ destroy_association(peer); /* remove registration data from storage */
+- set_peer_transport(peer, peer->default_outbound_transport);
++ set_socket_transport(&peer->socket, peer->default_outbound_transport);
+
+ manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", peer->name);
+ register_peer_exten(peer, FALSE); /* Remove regexten */
+ ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", peer->name);
++ peer->allowed_methods = SIP_UNKNOWN;
+
+ /* Do we need to release this peer from memory?
+ Only for realtime peers and autocreated peers
+@@ -11324,11 +11892,13 @@
+ int expire;
+ int port;
+ char *scan, *addr, *port_str, *expiry_str, *username, *contact;
++ char allowed_methods_str[256] = "";
+
+ if (peer->rt_fromcontact)
+ return;
+ if (ast_db_get("SIP/Registry", peer->name, data, sizeof(data)))
+ return;
++ ast_db_get("SIP/PeerMethods", peer->name, allowed_methods_str, sizeof(allowed_methods_str));
+
+ scan = data;
+ addr = strsep(&scan, ":");
+@@ -11355,6 +11925,10 @@
+ if (contact)
+ ast_string_field_set(peer, fullcontact, contact);
+
++ if (!ast_strlen_zero(allowed_methods_str)) {
++ peer->allowed_methods = atoi(allowed_methods_str);
++ }
++
+ ast_debug(2, "SIP Seeding peer from astdb: '%s' at %s@%s:%d for %d\n",
+ peer->name, peer->username, ast_inet_ntoa(in), port, expire);
+
+@@ -11524,7 +12098,7 @@
+ } else if (!strcasecmp(curi, "*") || !expire) { /* Unregister this peer */
+ /* This means remove all registrations and return OK */
+ memset(&peer->addr, 0, sizeof(peer->addr));
+- set_peer_transport(peer, peer->default_outbound_transport);
++ set_socket_transport(&peer->socket, peer->default_outbound_transport);
+
+ AST_SCHED_DEL_UNREF(sched, peer->expire,
+ unref_peer(peer, "remove register expire ref"));
+@@ -11579,7 +12153,7 @@
+ * transport type, change it. If it got this far, it is a
+ * supported type, but check just in case */
+ if ((peer->socket.type != transport_type) && (peer->transports & transport_type)) {
+- set_peer_transport(peer, transport_type);
++ set_socket_transport(&peer->socket, transport_type);
+ }
+
+ oldsin = peer->addr;
+@@ -11712,8 +12286,8 @@
+ int len;
+ const char *rr, *contact, *c;
+
+- /* Once a persistant route is set, don't fool with it */
+- if (p->route && p->route_persistant) {
++ /* Once a persistent route is set, don't fool with it */
++ if (p->route && p->route_persistent) {
+ ast_debug(1, "build_route: Retaining previous route: <%s>\n", p->route->hop);
+ return;
+ }
+@@ -11724,7 +12298,7 @@
+ }
+
+ /* We only want to create the route set the first time this is called */
+- p->route_persistant = 1;
++ p->route_persistent = 1;
+
+ /* Build a tailq, then assign it to p->route when done.
+ * If backwards, we add entries from the head so they end up
+@@ -11817,7 +12391,7 @@
+ */
+ static enum check_auth_result check_auth(struct sip_pvt *p, struct sip_request *req, const char *username,
+ const char *secret, const char *md5secret, int sipmethod,
+- char *uri, enum xmittype reliable, int ignore)
++ const char *uri, enum xmittype reliable, int ignore)
+ {
+ const char *response;
+ char *reqheader, *respheader;
+@@ -12182,15 +12756,16 @@
+ - Registration requests are only matched with peers that are marked as "dynamic"
+ */
+ static enum check_auth_result register_verify(struct sip_pvt *p, struct sockaddr_in *sin,
+- struct sip_request *req, char *uri)
++ struct sip_request *req, const char *uri)
+ {
+ enum check_auth_result res = AUTH_NOT_FOUND;
+ struct sip_peer *peer;
+ char tmp[256];
+ char *name, *c;
+ char *domain;
++ char *uri2 = ast_strdupa(uri);
+
+- terminate_uri(uri); /* warning, overwrite the string */
++ terminate_uri(uri2);
+
+ ast_copy_string(tmp, get_header(req, "To"), sizeof(tmp));
+ if (sip_cfg.pedanticsipchecking)
+@@ -12242,12 +12817,7 @@
+ }
+
+ if (peer) {
+- /*! \todo OEJ Remove this - there's never RTP in a REGISTER dialog... */
+- /* Set Frame packetization */
+- if (p->rtp) {
+- ast_rtp_codec_setpref(p->rtp, &peer->prefs);
+- p->autoframing = peer->autoframing;
+- }
++ ao2_lock(peer);
+ if (!peer->host_dynamic) {
+ ast_log(LOG_ERROR, "Peer '%s' is trying to register, but not configured as host=dynamic\n", peer->name);
+ res = AUTH_PEER_NOT_DYNAMIC;
+@@ -12255,7 +12825,7 @@
+ ast_copy_flags(&p->flags[0], &peer->flags[0], SIP_NAT);
+ if (ast_test_flag(&p->flags[1], SIP_PAGE2_REGISTERTRYING))
+ transmit_response(p, "100 Trying", req);
+- if (!(res = check_auth(p, req, peer->name, peer->secret, peer->md5secret, SIP_REGISTER, uri, XMIT_UNRELIABLE, req->ignore))) {
++ if (!(res = check_auth(p, req, peer->name, peer->secret, peer->md5secret, SIP_REGISTER, uri2, XMIT_UNRELIABLE, req->ignore))) {
+ if (sip_cancel_destroy(p))
+ ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n");
+
+@@ -12292,6 +12862,7 @@
+
+ }
+ }
++ ao2_unlock(peer);
+ }
+ if (!peer && sip_cfg.autocreatepeer) {
+ /* Create peer if we have autocreate mode enabled */
+@@ -12301,7 +12872,7 @@
+ if (peer->addr.sin_addr.s_addr) {
+ ao2_t_link(peers_by_ip, peer, "link peer into peers-by-ip table");
+ }
+-
++ ao2_lock(peer);
+ if (sip_cancel_destroy(p))
+ ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n");
+ switch (parse_register_contact(p, peer, req)) {
+@@ -12324,6 +12895,7 @@
+ res = 0;
+ break;
+ }
++ ao2_unlock(peer);
+ }
+ }
+ if (!peer && sip_cfg.alwaysauthreject) {
+@@ -12386,8 +12958,19 @@
+ break;
+ }
+ }
+- if (peer)
++ if (peer) {
++ ao2_lock(peer);
++ if (peer->allowed_methods == SIP_UNKNOWN) {
++ peer->allowed_methods = set_pvt_allowed_methods(p, req);
++ }
++ if (!peer->rt_fromcontact) {
++ char allowed_methods_str[256];
++ snprintf(allowed_methods_str, sizeof(allowed_methods_str), "%u", peer->allowed_methods);
++ ast_db_put("SIP/PeerMethods", peer->name, allowed_methods_str);
++ }
++ ao2_unlock(peer);
+ unref_peer(peer, "register_verify: unref_peer: tossing stack peer pointer at end of func");
++ }
+
+ return res;
+ }
+@@ -12422,23 +13005,199 @@
+ }
+ }
+
++/*! \brief Parse the parts of the P-Asserted-Identity header
++ * on an incoming packet. Returns 1 if a valid header is found
++ * and it is different from the current caller id.
++ */
++static int get_pai(struct sip_pvt *p, struct sip_request *req)
++{
++ char pai[256];
++ char privacy[64];
++ char *cid_num = "";
++ char *cid_name = "";
++ int callingpres = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
++ char *start = NULL, *end = NULL;
++
++ ast_copy_string(pai, get_header(req, "P-Asserted-Identity"), sizeof(pai));
++
++ if (ast_strlen_zero(pai)) {
++ return 0;
++ }
++
++ start = pai;
++ if (*start == '"') {
++ *start++ = '\0';
++ end = strchr(start, '"');
++ if (!end)
++ return 0;
++ *end++ = '\0';
++ cid_name = start;
++ start = ast_skip_blanks(end);
++ }
++
++ if (*start != '<')
++ return 0;
++ *start++ = '\0';
++ end = strchr(start, '@');
++ if (!end)
++ return 0;
++ *end++ = '\0';
++ if (!strncasecmp(start, "anonymous@anonymous.invalid", 27)) {
++ callingpres = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
++ /*XXX Assume no change in cid_num. Perhaps it should be
++ * blanked?
++ */
++ cid_num = (char *)p->cid_num;
++ } else if (!strncasecmp(start, "sip:", 4)) {
++ cid_num = start + 4;
++ if (ast_is_shrinkable_phonenumber(cid_num))
++ ast_shrink_phone_number(cid_num);
++ start = end;
++
++ end = strchr(start, '>');
++ if (!end)
++ return 0;
++ *end = '\0';
++ } else {
++ return 0;
++ }
++
++ ast_copy_string(privacy, get_header(req, "Privacy"), sizeof(privacy));
++ if (!ast_strlen_zero(privacy) && strncmp(privacy, "id", 2)) {
++ callingpres = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
++ }
++
++ /* Only return true if the supplied caller id is different */
++ if (!strcasecmp(p->cid_num, cid_num) && !strcasecmp(p->cid_name, cid_name) && p->callingpres == callingpres)
++ return 0;
++
++ ast_string_field_set(p, cid_num, cid_num);
++ ast_string_field_set(p, cid_name, cid_name);
++ p->callingpres = callingpres;
++
++ if (p->owner) {
++ ast_set_callerid(p->owner, cid_num, cid_name, NULL);
++ p->owner->cid.cid_pres = callingpres;
++ }
++
++ return 1;
++}
++
++/*! \brief Get name, number and presentation from remote party id header,
++ * returns true if a valid header was found and it was different from the
++ * current caller id.
++ */
++static int get_rpid(struct sip_pvt *p, struct sip_request *oreq)
++{
++ char tmp[256];
++ struct sip_request *req;
++ char *cid_num = "";
++ char *cid_name = "";
++ int callingpres = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
++ char *privacy = "";
++ char *screen = "";
++ char *start, *end;
++
++ if (!ast_test_flag(&p->flags[0], SIP_TRUSTRPID))
++ return 0;
++ req = oreq;
++ if (!req)
++ req = &p->initreq;
++ ast_copy_string(tmp, get_header(req, "Remote-Party-ID"), sizeof(tmp));
++ if (ast_strlen_zero(tmp)) {
++ return get_pai(p, req);
++ }
++
++ start = tmp;
++ if (*start == '"') {
++ *start++ = '\0';
++ end = strchr(start, '"');
++ if (!end)
++ return 0;
++ *end++ = '\0';
++ cid_name = start;
++ start = ast_skip_blanks(end);
++ }
++
++ if (*start != '<')
++ return 0;
++ *start++ = '\0';
++ end = strchr(start, '@');
++ if (!end)
++ return 0;
++ *end++ = '\0';
++ if (strncasecmp(start, "sip:", 4))
++ return 0;
++ cid_num = start + 4;
++ if (ast_is_shrinkable_phonenumber(cid_num))
++ ast_shrink_phone_number(cid_num);
++ start = end;
++
++ end = strchr(start, '>');
++ if (!end)
++ return 0;
++ *end++ = '\0';
++ if (*end) {
++ start = end;
++ if (*start != ';')
++ return 0;
++ *start++ = '\0';
++ while (!ast_strlen_zero(start)) {
++ end = strchr(start, ';');
++ if (end)
++ *end++ = '\0';
++ if (!strncasecmp(start, "privacy=", 8))
++ privacy = start + 8;
++ else if (!strncasecmp(start, "screen=", 7))
++ screen = start + 7;
++ start = end;
++ }
++
++ if (!strcasecmp(privacy, "full")) {
++ if (!strcasecmp(screen, "yes"))
++ callingpres = AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN;
++ else if (!strcasecmp(screen, "no"))
++ callingpres = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
++ } else {
++ if (!strcasecmp(screen, "yes"))
++ callingpres = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
++ else if (!strcasecmp(screen, "no"))
++ callingpres = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
++ }
++ }
++
++ /* Only return true if the supplied caller id is different */
++ if (!strcasecmp(p->cid_num, cid_num) && !strcasecmp(p->cid_name, cid_name) && p->callingpres == callingpres)
++ return 0;
++
++ ast_string_field_set(p, cid_num, cid_num);
++ ast_string_field_set(p, cid_name, cid_name);
++ p->callingpres = callingpres;
++
++ if (p->owner) {
++ ast_set_callerid(p->owner, cid_num, cid_name, NULL);
++ p->owner->cid.cid_pres = callingpres;
++ }
++
++ return 1;
++}
++
+ /*! \brief Get referring dnis */
+-static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq)
++static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq, char **name, char **number, int *reason)
+ {
+- char tmp[256], *exten, *rexten, *rdomain;
+- char *params, *reason = NULL;
++ char tmp[256], *exten, *rexten, *rdomain, *rname = NULL;
++ char *params, *reason_param = NULL;
+ struct sip_request *req;
+-
++
+ req = oreq ? oreq : &p->initreq;
+
+ ast_copy_string(tmp, get_header(req, "Diversion"), sizeof(tmp));
+ if (ast_strlen_zero(tmp))
+- return 0;
++ return -1;
+
+- /*! \todo This function does not take user-parameters into consideration.
+- First look for @, then start looking for ; to find uri-parameters.
+- */
+- params = strchr(tmp, ';');
++ if ((params = strchr(tmp, '>'))) {
++ params = strchr(params, ';');
++ }
+
+ exten = get_in_brackets(tmp);
+ if (!strncasecmp(exten, "sip:", 4)) {
+@@ -12457,16 +13216,16 @@
+ while (*params == ';' || *params == ' ')
+ params++;
+ /* Check if we have a reason parameter */
+- if ((reason = strcasestr(params, "reason="))) {
+- reason+=7;
++ if ((reason_param = strcasestr(params, "reason="))) {
++ reason_param+=7;
+ /* Remove enclosing double-quotes */
+- if (*reason == '"')
+- ast_strip_quoted(reason, "\"", "\"");
+- if (!ast_strlen_zero(reason)) {
+- sip_set_redirstr(p, reason);
++ if (*reason_param == '"')
++ ast_strip_quoted(reason_param, "\"", "\"");
++ if (!ast_strlen_zero(reason_param)) {
++ sip_set_redirstr(p, reason_param);
+ if (p->owner) {
+ pbx_builtin_setvar_helper(p->owner, "__PRIREDIRECTREASON", p->redircause);
+- pbx_builtin_setvar_helper(p->owner, "__SIPREDIRECTREASON", reason);
++ pbx_builtin_setvar_helper(p->owner, "__SIPREDIRECTREASON", reason_param);
+ }
+ }
+ }
+@@ -12474,14 +13233,33 @@
+
+ rdomain = exten;
+ rexten = strsep(&rdomain, "@"); /* trim anything after @ */
+- if (p->owner)
++ if (p->owner)
+ pbx_builtin_setvar_helper(p->owner, "__SIPRDNISDOMAIN", rdomain);
+
+ if (sip_debug_test_pvt(p))
+- ast_verbose("RDNIS for this call is is %s (reason %s)\n", exten, reason ? reason : "");
++ ast_verbose("RDNIS for this call is %s (reason %s)\n", exten, reason ? reason_param : "");
+
+- ast_string_field_set(p, rdnis, rexten);
++ /*ast_string_field_set(p, rdnis, rexten);*/
+
++ if (*tmp == '\"') {
++ char *end_quote;
++ rname = tmp + 1;
++ end_quote = strchr(rname, '\"');
++ *end_quote = '\0';
++ }
++
++ if (number) {
++ *number = ast_strdup(rexten);
++ }
++
++ if (name && rname) {
++ *name = ast_strdup(rname);
++ }
++
++ if (reason && !ast_strlen_zero(reason_param)) {
++ *reason = sip_reason_str_to_code(reason_param);
++ }
++
+ return 0;
+ }
+
+@@ -13093,58 +13871,12 @@
+ return output;
+ }
+
+-/*! \brief Get caller id number from Remote-Party-ID header field
+- * Returns true if number should be restricted (privacy setting found)
+- * output is set to NULL if no number found
+- */
+-static int get_rpid_num(const char *input, char *output, int maxlen)
+-{
+- char *start;
+- char *end;
+
+- start = strchr(input, ':');
+- if (!start) {
+- output[0] = '\0';
+- return 0;
+- }
+- start++;
+-
+- /* we found "number" */
+- ast_copy_string(output, start, maxlen);
+- output[maxlen-1] = '\0';
+-
+- end = strchr(output, '@');
+- if (end)
+- *end = '\0';
+- else
+- output[0] = '\0';
+- if (strstr(input, "privacy=full") || strstr(input, "privacy=uri"))
+- return AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
+-
+- return 0;
+-}
+-
+-
+-/*! \brief helper function for check_{user|peer}_ok() */
+-static void replace_cid(struct sip_pvt *p, const char *rpid_num, const char *calleridname)
+-{
+- /* replace callerid if rpid found, and not restricted */
+- if (!ast_strlen_zero(rpid_num) && ast_test_flag(&p->flags[0], SIP_TRUSTRPID)) {
+- char *tmp = ast_strdupa(rpid_num); /* XXX the copy can be done later */
+- if (!ast_strlen_zero(calleridname))
+- ast_string_field_set(p, cid_name, calleridname);
+- if (ast_is_shrinkable_phonenumber(tmp))
+- ast_shrink_phone_number(tmp);
+- ast_string_field_set(p, cid_num, tmp);
+- }
+-}
+-
+ /*! \brief Validate device authentication */
+ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
+ struct sip_request *req, int sipmethod, struct sockaddr_in *sin,
+ struct sip_peer **authpeer,
+- enum xmittype reliable,
+- char *rpid_num, char *calleridname, char *uri2)
++ enum xmittype reliable, char *calleridname, char *uri2)
+ {
+ enum check_auth_result res;
+ int debug=sip_debug_test_addr(sin);
+@@ -13195,7 +13927,7 @@
+ /* XXX what about p->prefs = peer->prefs; ? */
+ /* Set Frame packetization */
+ if (p->rtp) {
+- ast_rtp_codec_setpref(p->rtp, &peer->prefs);
++ ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, &peer->prefs);
+ p->autoframing = peer->autoframing;
+ }
+
+@@ -13208,7 +13940,6 @@
+ if (p->sipoptions)
+ peer->sipoptions = p->sipoptions;
+
+- replace_cid(p, rpid_num, calleridname);
+ do_setnat(p, ast_test_flag(&p->flags[0], SIP_NAT_ROUTE));
+
+ ast_string_field_set(p, peersecret, peer->secret);
+@@ -13217,6 +13948,12 @@
+ ast_string_field_set(p, mohinterpret, peer->mohinterpret);
+ ast_string_field_set(p, mohsuggest, peer->mohsuggest);
+ ast_string_field_set(p, parkinglot, peer->parkinglot);
++ ast_string_field_set(p, engine, peer->engine);
++ if (peer->allowed_methods == SIP_UNKNOWN) {
++ set_pvt_allowed_methods(p, req);
++ } else {
++ p->allowed_methods = peer->allowed_methods;
++ }
+ if (peer->callingpres) /* Peer calling pres setting will override RPID */
+ p->callingpres = peer->callingpres;
+ if (peer->maxms && peer->lastms)
+@@ -13260,14 +13997,18 @@
+ /* XXX this takes the name from the caller... can we override ? */
+ ast_string_field_set(p, authname, peer->username);
+ }
+- if (!ast_strlen_zero(peer->cid_num)) {
+- char *tmp = ast_strdupa(peer->cid_num);
+- if (ast_is_shrinkable_phonenumber(tmp))
+- ast_shrink_phone_number(tmp);
+- ast_string_field_set(p, cid_num, tmp);
++ if (!get_rpid(p, req)) {
++ if (!ast_strlen_zero(peer->cid_num)) {
++ char *tmp = ast_strdupa(peer->cid_num);
++ if (ast_is_shrinkable_phonenumber(tmp))
++ ast_shrink_phone_number(tmp);
++ ast_string_field_set(p, cid_num, tmp);
++ }
++ if (!ast_strlen_zero(peer->cid_name))
++ ast_string_field_set(p, cid_name, peer->cid_name);
++ if (peer->callingpres)
++ p->callingpres = peer->callingpres;
+ }
+- if (!ast_strlen_zero(peer->cid_name))
+- ast_string_field_set(p, cid_name, peer->cid_name);
+ ast_string_field_set(p, fullcontact, peer->fullcontact);
+ if (!ast_strlen_zero(peer->context))
+ ast_string_field_set(p, context, peer->context);
+@@ -13284,17 +14025,6 @@
+ if (p->peercapability)
+ p->jointcapability &= p->peercapability;
+ p->maxcallbitrate = peer->maxcallbitrate;
+- if (!ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT_ALWAYS) &&
+- (!ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT) ||
+- !(p->capability & AST_FORMAT_VIDEO_MASK)) &&
+- p->vrtp) {
+- ast_rtp_destroy(p->vrtp);
+- p->vrtp = NULL;
+- }
+- if ((!ast_test_flag(&p->flags[1], SIP_PAGE2_TEXTSUPPORT) || !(p->capability & AST_FORMAT_TEXT_MASK)) && p->trtp) {
+- ast_rtp_destroy(p->trtp);
+- p->trtp = NULL;
+- }
+ if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) ||
+ (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO))
+ p->noncodeccapability |= AST_RTP_DTMF;
+@@ -13303,6 +14033,14 @@
+ p->jointnoncodeccapability = p->noncodeccapability;
+ if (p->t38.peercapability)
+ p->t38.jointcapability &= p->t38.peercapability;
++ if (!dialog_initialize_rtp(p)) {
++ if (p->rtp) {
++ ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, &peer->prefs);
++ p->autoframing = peer->autoframing;
++ }
++ } else {
++ res = AUTH_RTP_FAILED;
++ }
+ }
+ unref_peer(peer, "check_peer_ok: unref_peer: tossing temp ptr to peer from find_peer");
+ return res;
+@@ -13315,15 +14053,13 @@
+ \return 0 on success, non-zero on failure
+ */
+ static enum check_auth_result check_user_full(struct sip_pvt *p, struct sip_request *req,
+- int sipmethod, char *uri, enum xmittype reliable,
++ int sipmethod, const char *uri, enum xmittype reliable,
+ struct sockaddr_in *sin, struct sip_peer **authpeer)
+ {
+ char from[256];
+ char *dummy; /* dummy return value for parse_uri */
+ char *domain; /* dummy return value for parse_uri */
+ char *of, *of2;
+- char rpid_num[50];
+- const char *rpid;
+ enum check_auth_result res;
+ char calleridname[50];
+ char *uri2 = ast_strdupa(uri);
+@@ -13339,11 +14075,6 @@
+ if (calleridname[0])
+ ast_string_field_set(p, cid_name, calleridname);
+
+- rpid = get_header(req, "Remote-Party-ID");
+- memset(rpid_num, 0, sizeof(rpid_num));
+- if (!ast_strlen_zero(rpid))
+- p->callingpres = get_rpid_num(rpid, rpid_num, sizeof(rpid_num));
+-
+ of = get_in_brackets(from);
+ if (ast_strlen_zero(p->exten)) {
+ char *t = uri2;
+@@ -13417,14 +14148,18 @@
+ }
+
+ res = check_peer_ok(p, of, req, sipmethod, sin,
+- authpeer, reliable, rpid_num, calleridname, uri2);
++ authpeer, reliable, calleridname, uri2);
+ if (res != AUTH_DONT_KNOW)
+ return res;
+
+ /* Finally, apply the guest policy */
+ if (sip_cfg.allowguest) {
+- replace_cid(p, rpid_num, calleridname);
+- res = AUTH_SUCCESSFUL;
++ get_rpid(p, req);
++ if (!dialog_initialize_rtp(p)) {
++ res = AUTH_SUCCESSFUL;
++ } else {
++ res = AUTH_RTP_FAILED;
++ }
+ } else if (sip_cfg.alwaysauthreject)
+ res = AUTH_FAKE_AUTH; /* reject with fake authorization request */
+ else
+@@ -13441,7 +14176,7 @@
+ /*! \brief Find user
+ If we get a match, this will add a reference pointer to the user object in ASTOBJ, that needs to be unreferenced
+ */
+-static int check_user(struct sip_pvt *p, struct sip_request *req, int sipmethod, char *uri, enum xmittype reliable, struct sockaddr_in *sin)
++static int check_user(struct sip_pvt *p, struct sip_request *req, int sipmethod, const char *uri, enum xmittype reliable, struct sockaddr_in *sin)
+ {
+ return check_user_full(p, req, sipmethod, uri, reliable, sin, NULL);
+ }
+@@ -13458,7 +14193,7 @@
+ if (y < 0)
+ y = 0;
+ for (x = 0; x < req->lines; x++) {
+- char *line = REQ_OFFSET_TO_STR(req, line[x]);
++ const char *line = REQ_OFFSET_TO_STR(req, line[x]);
+ strncat(buf, line, y); /* safe */
+ y -= strlen(line) + 1;
+ if (y < 0)
+@@ -13577,7 +14312,7 @@
+ return "strict";
+ }
+
+-static struct _map_x_s natmodes[] = {
++static const struct _map_x_s natmodes[] = {
+ { SIP_NAT_NEVER, "No"},
+ { SIP_NAT_ROUTE, "Route"},
+ { SIP_NAT_ALWAYS, "Always"},
+@@ -13596,7 +14331,7 @@
+ delete it. Keeping it enabled generates compiler warnings.
+ */
+
+-static struct _map_x_s natcfgmodes[] = {
++static const struct _map_x_s natcfgmodes[] = {
+ { SIP_NAT_NEVER, "never"},
+ { SIP_NAT_ROUTE, "route"},
+ { SIP_NAT_ALWAYS, "yes"},
+@@ -13617,7 +14352,7 @@
+
+
+ /* Session-Timer Modes */
+-static struct _map_x_s stmodes[] = {
++static const struct _map_x_s stmodes[] = {
+ { SESSION_TIMER_MODE_ACCEPT, "Accept"},
+ { SESSION_TIMER_MODE_ORIGINATE, "Originate"},
+ { SESSION_TIMER_MODE_REFUSE, "Refuse"},
+@@ -13635,7 +14370,7 @@
+ }
+
+ /* Session-Timer Refreshers */
+-static struct _map_x_s strefreshers[] = {
++static const struct _map_x_s strefreshers[] = {
+ { SESSION_TIMER_REFRESHER_AUTO, "auto"},
+ { SESSION_TIMER_REFRESHER_UAC, "uac"},
+ { SESSION_TIMER_REFRESHER_UAS, "uas"},
+@@ -13793,14 +14528,6 @@
+ #undef FORMAT
+ }
+
+-/*! \brief Manager Action SIPShowRegistry description */
+-static char mandescr_show_registry[] =
+-"Description: Lists all registration requests and status\n"
+-"Registrations will follow as separate events. followed by a final event called\n"
+-"RegistrationsComplete.\n"
+-"Variables: \n"
+-" ActionID: <id> Action ID for this transaction. Will be returned.\n";
+-
+ /*! \brief Show SIP registrations in the manager API */
+ static int manager_show_registry(struct mansession *s, const struct message *m)
+ {
+@@ -13839,13 +14566,6 @@
+ return 0;
+ }
+
+-static char mandescr_show_peers[] =
+-"Description: Lists SIP peers in text format with details on current status.\n"
+-"Peerlist will follow as separate events, followed by a final event called\n"
+-"PeerlistComplete.\n"
+-"Variables: \n"
+-" ActionID: <id> Action ID for this transaction. Will be returned.\n";
+-
+ /*! \brief Show SIP peers in the manager API */
+ /* Inspired from chan_iax2 */
+ static int manager_sip_show_peers(struct mansession *s, const struct message *m)
+@@ -14075,10 +14795,10 @@
+ {
+ struct sip_peer *peer = userobj;
+ int refc = ao2_t_ref(userobj, 0, "");
+- int *fd = arg;
++ struct ast_cli_args *a = (struct ast_cli_args *) arg;
+
+- ast_cli(*fd, "name: %s\ntype: peer\nobjflags: %d\nrefcount: %d\n\n",
+- peer->name, 0, refc);
++ ast_cli(a->fd, "name: %s\ntype: peer\nobjflags: %d\nrefcount: %d\n\n",
++ peer->name, 0, refc);
+ return 0;
+ }
+
+@@ -14086,10 +14806,10 @@
+ {
+ struct sip_pvt *pvt = userobj;
+ int refc = ao2_t_ref(userobj, 0, "");
+- int *fd = arg;
++ struct ast_cli_args *a = (struct ast_cli_args *) arg;
+
+- ast_cli(*fd, "name: %s\ntype: dialog\nobjflags: %d\nrefcount: %d\n\n",
+- pvt->callid, 0, refc);
++ ast_cli(a->fd, "name: %s\ntype: dialog\nobjflags: %d\nrefcount: %d\n\n",
++ pvt->callid, 0, refc);
+ return 0;
+ }
+
+@@ -14113,22 +14833,22 @@
+ if (a->argc != 3)
+ return CLI_SHOWUSAGE;
+ ast_cli(a->fd, "-= Peer objects: %d static, %d realtime, %d autocreate =-\n\n", speerobjs, rpeerobjs, apeerobjs);
+- ao2_t_callback(peers, OBJ_NODATA, peer_dump_func, &a->fd, "initiate ao2_callback to dump peers");
++ ao2_t_callback(peers, OBJ_NODATA, peer_dump_func, a, "initiate ao2_callback to dump peers");
+ ast_cli(a->fd, "-= Registry objects: %d =-\n\n", regobjs);
+ ASTOBJ_CONTAINER_DUMP(a->fd, tmp, sizeof(tmp), &regl);
+ ast_cli(a->fd, "-= Dialog objects:\n\n");
+- ao2_t_callback(dialogs, OBJ_NODATA, dialog_dump_func, &a->fd, "initiate ao2_callback to dump dialogs");
++ ao2_t_callback(dialogs, OBJ_NODATA, dialog_dump_func, a, "initiate ao2_callback to dump dialogs");
+ return CLI_SUCCESS;
+ }
+ /*! \brief Print call group and pickup group */
+-static void print_group(int fd, ast_group_t group, int crlf)
++static void print_group(int fd, ast_group_t group, int crlf)
+ {
+ char buf[256];
+ ast_cli(fd, crlf ? "%s\r\n" : "%s\n", ast_print_group(buf, sizeof(buf), group) );
+ }
+
+ /*! \brief mapping between dtmf flags and strings */
+-static struct _map_x_s dtmfstr[] = {
++static const struct _map_x_s dtmfstr[] = {
+ { SIP_DTMF_RFC2833, "rfc2833" },
+ { SIP_DTMF_INFO, "info" },
+ { SIP_DTMF_SHORTINFO, "shortinfo" },
+@@ -14149,7 +14869,7 @@
+ return map_s_x(dtmfstr, str, -1);
+ }
+
+-static struct _map_x_s insecurestr[] = {
++static const struct _map_x_s insecurestr[] = {
+ { SIP_INSECURE_PORT, "port" },
+ { SIP_INSECURE_INVITE, "invite" },
+ { SIP_INSECURE_PORT | SIP_INSECURE_INVITE, "port,invite" },
+@@ -14211,7 +14931,20 @@
+ * that we can wait for the next time around. */
+ return 0;
+ }
+-
++
++ /* We absolutely cannot destroy the rtp struct while a bridge is active or we WILL crash */
++ if (dialog->rtp && ast_rtp_instance_get_bridged(dialog->rtp)) {
++ ast_debug(2, "Bridge still active. Delaying destroy of SIP dialog '%s' Method: %s\n", dialog->callid, sip_methods[dialog->method].text);
++ sip_pvt_unlock(dialog);
++ return 0;
++ }
++
++ if (dialog->vrtp && ast_rtp_instance_get_bridged(dialog->vrtp)) {
++ ast_debug(2, "Bridge still active. Delaying destroy of SIP dialog '%s' Method: %s\n", dialog->callid, sip_methods[dialog->method].text);
++ sip_pvt_unlock(dialog);
++ return 0;
++ }
++
+ /* Check RTP timeouts and kill calls if we have a timeout set and do not get RTP */
+ check_rtp_timeout(dialog, *t);
+
+@@ -14220,13 +14953,13 @@
+ - if that's the case, wait with destruction */
+ if (dialog->needdestroy && !dialog->packets && !dialog->owner) {
+ /* We absolutely cannot destroy the rtp struct while a bridge is active or we WILL crash */
+- if (dialog->rtp && ast_rtp_get_bridged(dialog->rtp)) {
++ if (dialog->rtp && ast_rtp_instance_get_bridged(dialog->rtp)) {
+ ast_debug(2, "Bridge still active. Delaying destruction of SIP dialog '%s' Method: %s\n", dialog->callid, sip_methods[dialog->method].text);
+ sip_pvt_unlock(dialog);
+ return 0;
+ }
+
+- if (dialog->vrtp && ast_rtp_get_bridged(dialog->vrtp)) {
++ if (dialog->vrtp && ast_rtp_instance_get_bridged(dialog->vrtp)) {
+ ast_debug(2, "Bridge still active. Delaying destroy of SIP dialog '%s' Method: %s\n", dialog->callid, sip_methods[dialog->method].text);
+ sip_pvt_unlock(dialog);
+ return 0;
+@@ -14259,10 +14992,10 @@
+ struct sip_peer *peer, *pi;
+ int prunepeer = FALSE;
+ int multi = FALSE;
+- char *name = NULL;
++ const char *name = NULL;
+ regex_t regexbuf;
+ struct ao2_iterator i;
+- static char *choices[] = { "all", "like", NULL };
++ static const char * const choices[] = { "all", "like", NULL };
+ char *cmplt;
+
+ if (cmd == CLI_INIT) {
+@@ -14451,12 +15184,6 @@
+ }
+ #undef FORMAT
+
+-static char mandescr_show_peer[] =
+-"Description: Show one SIP peer with details on current status.\n"
+-"Variables: \n"
+-" Peer: <name> The peer name you want to check.\n"
+-" ActionID: <id> Optional action ID for this AMI transaction.\n";
+-
+ /*! \brief Show SIP peers in the manager API */
+ static int manager_sip_show_peer(struct mansession *s, const struct message *m)
+ {
+@@ -14716,6 +15443,7 @@
+ ast_cli(fd, " Sess-Refresh : %s\n", strefresher2str(peer->stimer.st_ref));
+ ast_cli(fd, " Sess-Expires : %d secs\n", peer->stimer.st_max_se);
+ ast_cli(fd, " Min-Sess : %d secs\n", peer->stimer.st_min_se);
++ ast_cli(fd, " RTP Engine : %s\n", peer->engine);
+ ast_cli(fd, "\n");
+ peer = unref_peer(peer, "sip_show_peer: unref_peer: done with peer ptr");
+ } else if (peer && type == 1) { /* manager listing */
+@@ -14763,6 +15491,7 @@
+ astman_append(s, "SIP-Sess-Refresh: %s\r\n", strefresher2str(peer->stimer.st_ref));
+ astman_append(s, "SIP-Sess-Expires: %d\r\n", peer->stimer.st_max_se);
+ astman_append(s, "SIP-Sess-Min: %d\r\n", peer->stimer.st_min_se);
++ astman_append(s, "SIP-RTP-Engine: %s\r\n", peer->engine);
+
+ /* - is enumerated */
+ astman_append(s, "SIP-DTMFmode: %s\r\n", dtmfmode2str(ast_test_flag(&peer->flags[0], SIP_DTMF)));
+@@ -14895,6 +15624,7 @@
+ ast_cli(a->fd, " Sess-Refresh : %s\n", strefresher2str(user->stimer.st_ref));
+ ast_cli(a->fd, " Sess-Expires : %d secs\n", user->stimer.st_max_se);
+ ast_cli(a->fd, " Sess-Min-SE : %d secs\n", user->stimer.st_min_se);
++ ast_cli(a->fd, " RTP Engine : %s\n", user->engine);
+
+ ast_cli(a->fd, " Codec Order : (");
+ print_codec_to_cli(a->fd, &user->prefs);
+@@ -15051,11 +15781,10 @@
+ #define FORMAT2 "%-15.15s %-11.11s %-8.8s %-10.10s %-10.10s (%-2.2s) %-6.6s %-10.10s %-10.10s ( %%) %-6.6s\n"
+ #define FORMAT "%-15.15s %-11.11s %-8.8s %-10.10u%-1.1s %-10.10u (%-2.2u%%) %-6.6u %-10.10u%-1.1s %-10.10u (%-2.2u%%) %-6.6u\n"
+ struct sip_pvt *cur = __cur;
+- unsigned int rxcount;
+- unsigned int txcount;
++ struct ast_rtp_instance_stats stats;
+ char durbuf[10];
+- int duration;
+- int durh, durm, durs;
++ int duration;
++ int durh, durm, durs;
+ struct ast_channel *c = cur->owner;
+ struct __show_chan_arg *arg = __arg;
+ int fd = arg->fd;
+@@ -15069,10 +15798,9 @@
+ ast_cli(fd, "%-15.15s %-11.11s (inv state: %s) -- %s\n", ast_inet_ntoa(cur->sa.sin_addr), cur->callid, invitestate2string[cur->invitestate].desc, "-- No RTP active");
+ return 0; /* don't care, we scan all channels */
+ }
+- rxcount = ast_rtp_get_qosvalue(cur->rtp, AST_RTP_RXCOUNT);
+- txcount = ast_rtp_get_qosvalue(cur->rtp, AST_RTP_TXCOUNT);
+
+- /* Find the duration of this channel */
++ ast_rtp_instance_get_stats(cur->rtp, &stats, AST_RTP_INSTANCE_STAT_ALL);
++
+ if (c && c->cdr && !ast_tvzero(c->cdr->start)) {
+ duration = (int)(ast_tvdiff_ms(ast_tvnow(), c->cdr->start) / 1000);
+ durh = duration / 3600;
+@@ -15082,21 +15810,21 @@
+ } else {
+ durbuf[0] = '\0';
+ }
+- /* Print stats for every call with RTP */
++
+ ast_cli(fd, FORMAT,
+ ast_inet_ntoa(cur->sa.sin_addr),
+ cur->callid,
+ durbuf,
+- rxcount > (unsigned int) 100000 ? (unsigned int) (rxcount)/(unsigned int) 1000 : rxcount,
+- rxcount > (unsigned int) 100000 ? "K":" ",
+- ast_rtp_get_qosvalue(cur->rtp, AST_RTP_RXPLOSS),
+- rxcount > ast_rtp_get_qosvalue(cur->rtp, AST_RTP_RXPLOSS) ? (unsigned int) (ast_rtp_get_qosvalue(cur->rtp, AST_RTP_RXPLOSS) / rxcount * 100) : 0,
+- ast_rtp_get_qosvalue(cur->rtp, AST_RTP_RXJITTER),
+- txcount > (unsigned int) 100000 ? (unsigned int) (txcount)/(unsigned int) 1000 : txcount,
+- txcount > (unsigned int) 100000 ? "K":" ",
+- ast_rtp_get_qosvalue(cur->rtp, AST_RTP_TXPLOSS),
+- txcount > ast_rtp_get_qosvalue(cur->rtp, AST_RTP_TXPLOSS) ? (unsigned int) (ast_rtp_get_qosvalue(cur->rtp, AST_RTP_TXPLOSS)/ txcount * 100) : 0,
+- ast_rtp_get_qosvalue(cur->rtp, AST_RTP_TXJITTER)
++ stats.rxcount > (unsigned int) 100000 ? (unsigned int) (stats.rxcount)/(unsigned int) 1000 : stats.rxcount,
++ stats.rxcount > (unsigned int) 100000 ? "K":" ",
++ stats.rxploss,
++ stats.rxcount > stats.rxploss ? (stats.rxploss / stats.rxcount * 100) : 0,
++ stats.rxjitter,
++ stats.txcount > (unsigned int) 100000 ? (unsigned int) (stats.txcount)/(unsigned int) 1000 : stats.txcount,
++ stats.txcount > (unsigned int) 100000 ? "K":" ",
++ stats.txploss,
++ stats.txcount > stats.txploss ? (stats.txploss / stats.txcount * 100) : 0,
++ stats.txjitter
+ );
+ arg->numchans++;
+
+@@ -16009,14 +16737,14 @@
+ }
+
+ /*! \brief Enable SIP Debugging for a single IP */
+-static char *sip_do_debug_ip(int fd, char *arg)
++static char *sip_do_debug_ip(int fd, const char *arg)
+ {
+ struct hostent *hp;
+ struct ast_hostent ahp;
+ int port = 0;
+ char *p;
+
+- p = arg;
++ p = ast_strdupa(arg);
+ strsep(&p, ":");
+ if (p)
+ port = atoi(p);
+@@ -16038,7 +16766,7 @@
+ }
+
+ /*! \brief Turn on SIP debugging for a given peer */
+-static char *sip_do_debug_peer(int fd, char *arg)
++static char *sip_do_debug_peer(int fd, const char *arg)
+ {
+ struct sip_peer *peer = find_peer(arg, NULL, TRUE, FINDPEERS, FALSE);
+ if (!peer)
+@@ -16062,7 +16790,7 @@
+ static char *sip_do_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+ {
+ int oldsipdebug = sipdebug & sip_debug_console;
+- char *what;
++ const char *what;
+
+ if (cmd == CLI_INIT) {
+ e->command = "sip set debug {on|off|ip|peer}";
+@@ -16137,7 +16865,7 @@
+ for (i = 3; i < a->argc; i++) {
+ struct sip_pvt *p;
+
+- if (!(p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY))) {
++ if (!(p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY, NULL))) {
+ ast_log(LOG_WARNING, "Unable to build sip pvt data for notify (memory/socket error)\n");
+ return CLI_FAILURE;
+ }
+@@ -16155,7 +16883,7 @@
+ ast_set_flag(&p->flags[0], SIP_OUTGOING);
+
+ /* Recalculate our side, and recalculate Call ID */
+- ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip);
++ ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip, p);
+ build_via(p);
+ ao2_t_unlink(dialogs, p, "About to change the callid -- remove the old name");
+ build_callid_pvt(p);
+@@ -16639,29 +17367,150 @@
+ .read = function_sipchaninfo_read,
+ };
+
++static int read_to_parts(struct sip_pvt *p, struct sip_request *req, char **name, char **number)
++{
++
++ char to_header[256];
++ char *to_name = NULL;
++ char *to_number = NULL;
++ char *separator;
++
++ ast_copy_string(to_header, get_header(req, "To"), sizeof(to_header));
++
++ /* Let's get that number first! */
++ to_number = get_in_brackets(to_header);
++
++ if (!strncasecmp(to_number, "sip:", 4)) {
++ to_number += 4;
++ } else if (!strncasecmp(to_number, "sips:", 5)) {
++ to_number += 5;
++ } else {
++ ast_log(LOG_WARNING, "Not a SIP URI? (%s)!\n", to_number);
++ return -1;
++ }
++
++ /* Remove the host and such since we just want the number */
++ if ((separator = strchr(to_number, '@'))) {
++ *separator = '\0';
++ }
++
++ /* We have the number. Let's get the name now. */
++
++ if (*to_header == '\"') {
++ to_name = to_header + 1;
++ if (!(separator = (char *)find_closing_quote(to_name, NULL))) {
++ ast_log(LOG_NOTICE, "No closing quote in name section of To: header (%s)\n", to_header);
++ return -1;
++ }
++ *separator = '\0';
++ }
++
++ if (number) {
++ *number = ast_strdup(to_number);
++ }
++ if (name && !ast_strlen_zero(to_name)) {
++ *name = ast_strdup(to_name);
++ }
++
++ return 0;
++}
++
++/*! \brief update redirecting information for a channel based on headers
++ *
++ */
++static void change_redirecting_information(struct sip_pvt *p, struct sip_request *req, struct ast_party_redirecting *redirecting, int set_call_forward)
++{
++ char *redirecting_from_name = NULL;
++ char *redirecting_from_number = NULL;
++ char *redirecting_to_name = NULL;
++ char *redirecting_to_number = NULL;
++ int reason = AST_REDIRECTING_REASON_UNCONDITIONAL;
++ int is_response = req->method == SIP_RESPONSE;
++ int res = 0;
++
++ res = get_rdnis(p, req, &redirecting_from_name, &redirecting_from_number, &reason);
++ if (res == -1) {
++ if (is_response) {
++ read_to_parts(p, req, &redirecting_from_name, &redirecting_from_number);
++ } else {
++ return;
++ }
++ }
++
++ /* At this point, all redirecting "from" info should be filled in appropriately
++ * on to the "to" info
++ */
++
++ if (is_response) {
++ parse_moved_contact(p, req, &redirecting_to_name, &redirecting_to_number, set_call_forward);
++ } else {
++ read_to_parts(p, req, &redirecting_to_name, &redirecting_to_number);
++ }
++
++ if (!ast_strlen_zero(redirecting_from_number)) {
++ if (redirecting->from.number) {
++ ast_free(redirecting->from.number);
++ }
++ ast_debug(3, "Got redirecting from number %s\n", redirecting_from_number);
++ redirecting->from.number = redirecting_from_number;
++ }
++ if (!ast_strlen_zero(redirecting_from_name)) {
++ if (redirecting->from.name) {
++ ast_free(redirecting->from.name);
++ }
++ ast_debug(3, "Got redirecting from name %s\n", redirecting_from_name);
++ redirecting->from.name = redirecting_from_name;
++ }
++ if (!ast_strlen_zero(redirecting_to_number)) {
++ if (redirecting->to.number) {
++ ast_free(redirecting->to.number);
++ }
++ ast_debug(3, "Got redirecting to number %s\n", redirecting_to_number);
++ redirecting->to.number = redirecting_to_number;
++ }
++ if (!ast_strlen_zero(redirecting_to_name)) {
++ if (redirecting->to.name) {
++ ast_free(redirecting->to.name);
++ }
++ ast_debug(3, "Got redirecting to name %s\n", redirecting_from_number);
++ redirecting->to.name = redirecting_to_name;
++ }
++ redirecting->reason = reason;
++}
++
+ /*! \brief Parse 302 Moved temporalily response
+ \todo XXX Doesn't redirect over TLS on sips: uri's.
+ If we get a redirect to a SIPS: uri, this needs to be going back to the
+ dialplan (this is a request for a secure signalling path).
+ Note that transport=tls is deprecated, but we need to support it on incoming requests.
+ */
+-static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req)
++static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req, char **name, char **number, int set_call_forward)
+ {
+- char tmp[SIPBUFSIZE];
+- char *s, *e, *t, *trans;
++ char contact[SIPBUFSIZE];
++ char *contact_name = NULL;
++ char *contact_number = NULL;
++ char *separator, *trans;
+ char *domain;
+ enum sip_transport transport = SIP_TRANSPORT_UDP;
+
+- ast_copy_string(tmp, get_header(req, "Contact"), sizeof(tmp));
+- if ((t = strchr(tmp, ',')))
+- *t = '\0';
++ ast_copy_string(contact, get_header(req, "Contact"), sizeof(contact));
++ if ((separator = strchr(contact, ',')))
++ *separator = '\0';
+
+- s = get_in_brackets(tmp);
+- if ((trans = strcasestr(s, ";transport="))) do {
++ /* ooh, a name */
++ if (*contact == '"') {
++ contact_name = contact + 1;
++ if ((separator = strchr(contact_name, '"'))) {
++ *separator++ = '\0';
++ }
++ }
++
++ contact_number = get_in_brackets(contact);
++ if ((trans = strcasestr(contact_number, ";transport="))) {
+ trans += 11;
+
+- if ((e = strchr(trans, ';')))
+- *e = '\0';
++ if ((separator = strchr(trans, ';')))
++ *separator = '\0';
+
+ if (!strncasecmp(trans, "tcp", 3))
+ transport = SIP_TRANSPORT_TCP;
+@@ -16669,66 +17518,84 @@
+ transport = SIP_TRANSPORT_TLS;
+ else {
+ if (strncasecmp(trans, "udp", 3))
+- ast_debug(1, "received contact with an invalid transport, '%s'\n", s);
++ ast_debug(1, "received contact with an invalid transport, '%s'\n", contact_number);
+ /* This will assume UDP for all unknown transports */
+ transport = SIP_TRANSPORT_UDP;
+ }
+- } while(0);
+- s = remove_uri_parameters(s);
++ }
++ contact_number = remove_uri_parameters(contact_number);
+
+ if (p->socket.tcptls_session) {
+ ao2_ref(p->socket.tcptls_session, -1);
+ p->socket.tcptls_session = NULL;
+ }
+
+- p->socket.fd = -1;
+- p->socket.type = transport;
++ set_socket_transport(&p->socket, transport);
+
+- if (ast_test_flag(&p->flags[0], SIP_PROMISCREDIR)) {
++ if (set_call_forward && ast_test_flag(&p->flags[0], SIP_PROMISCREDIR)) {
+ char *host = NULL;
+- if (!strncasecmp(s, "sip:", 4))
+- s += 4;
+- else if (!strncasecmp(s, "sips:", 5))
+- s += 5;
+- e = strchr(s, '/');
+- if (e)
+- *e = '\0';
+- if ((host = strchr(s, '@'))) {
++ if (!strncasecmp(contact_number, "sip:", 4))
++ contact_number += 4;
++ else if (!strncasecmp(contact_number, "sips:", 5))
++ contact_number += 5;
++ separator = strchr(contact_number, '/');
++ if (separator)
++ *separator = '\0';
++ if ((host = strchr(contact_number, '@'))) {
+ *host++ = '\0';
+- ast_debug(2, "Found promiscuous redirection to 'SIP/%s::::%s@%s'\n", s, get_transport(transport), host);
++ ast_debug(2, "Found promiscuous redirection to 'SIP/%s::::%s@%s'\n", contact_number, get_transport(transport), host);
+ if (p->owner)
+- ast_string_field_build(p->owner, call_forward, "SIP/%s::::%s@%s", s, get_transport(transport), host);
++ ast_string_field_build(p->owner, call_forward, "SIP/%s::::%s@%s", contact_number, get_transport(transport), host);
+ } else {
+- ast_debug(2, "Found promiscuous redirection to 'SIP/::::%s@%s'\n", get_transport(transport), s);
++ ast_debug(2, "Found promiscuous redirection to 'SIP/::::%s@%s'\n", get_transport(transport), contact_number);
+ if (p->owner)
+- ast_string_field_build(p->owner, call_forward, "SIP/::::%s@%s", get_transport(transport), s);
++ ast_string_field_build(p->owner, call_forward, "SIP/::::%s@%s", get_transport(transport), contact_number);
+ }
+ } else {
+- e = strchr(tmp, '@');
+- if (e) {
+- *e++ = '\0';
+- domain = e;
++ separator = strchr(contact, '@');
++ if (separator) {
++ *separator++ = '\0';
++ domain = separator;
+ } else {
+ /* No username part */
+- domain = tmp;
++ domain = contact;
+ }
+- e = strchr(tmp, '/'); /* WHEN do we hae a forward slash in the URI? */
+- if (e)
+- *e = '\0';
++ separator = strchr(contact, '/'); /* WHEN do we hae a forward slash in the URI? */
++ if (separator)
++ *separator = '\0';
+
+- if (!strncasecmp(s, "sip:", 4))
+- s += 4;
+- else if (!strncasecmp(s, "sips:", 5))
+- s += 5;
+- e = strchr(s, ';'); /* And username ; parameters? */
+- if (e)
+- *e = '\0';
+- ast_debug(2, "Received 302 Redirect to extension '%s' (domain %s)\n", s, domain);
+- if (p->owner) {
+- pbx_builtin_setvar_helper(p->owner, "SIPDOMAIN", domain);
+- ast_string_field_set(p->owner, call_forward, s);
++ if (!strncasecmp(contact_number, "sip:", 4))
++ contact_number += 4;
++ else if (!strncasecmp(contact_number, "sips:", 5))
++ contact_number += 5;
++ separator = strchr(contact_number, ';'); /* And username ; parameters? */
++ if (separator)
++ *separator = '\0';
++ if (set_call_forward) {
++ ast_debug(2, "Received 302 Redirect to extension '%s' (domain %s)\n", contact_number, domain);
++ if (p->owner) {
++ pbx_builtin_setvar_helper(p->owner, "SIPDOMAIN", domain);
++ ast_string_field_set(p->owner, call_forward, contact_number);
++ }
+ }
+ }
++
++ /* We've gotten the number for the contact, now get the name */
++
++ if (*contact == '\"') {
++ contact_name = contact + 1;
++ if (!(separator = (char *)find_closing_quote(contact_name, NULL))) {
++ ast_log(LOG_NOTICE, "No closing quote on name in Contact header? %s\n", contact);
++ }
++ *separator = '\0';
++ }
++
++ if (name && !ast_strlen_zero(contact_name)) {
++ *name = ast_strdup(contact_name);
++ }
++ if (number) {
++ *number = ast_strdup(contact_number);
++ }
+ }
+
+ /*! \brief Check pending actions on SIP call */
+@@ -16781,9 +17648,23 @@
+ return 0;
+ }
+
++/*!
++ * \brief Handle authentication challenge for SIP UPDATE
++ *
++ * This function is only called upon the receipt of a 401/407 response to an UPDATE.
++ */
++static void handle_response_update(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno)
++{
++ if (p->options) {
++ p->options->auth_type = (resp == 401 ? WWW_AUTH : PROXY_AUTH);
++ }
++ if ((p->authtries == MAX_AUTHTRIES) || do_proxy_auth(p, req, resp, SIP_UPDATE, 1)) {
++ ast_log(LOG_NOTICE, "Failed to authenticate on UPDATE to '%s'\n", get_header(&p->initreq, "From"));
++ }
++}
+
+ /*! \brief Handle SIP response to INVITE dialogue */
+-static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno)
++static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno)
+ {
+ int outgoing = ast_test_flag(&p->flags[0], SIP_OUTGOING);
+ int res = 0;
+@@ -16791,12 +17672,28 @@
+ int reinvite = (p->owner && p->owner->_state == AST_STATE_UP);
+ char *p_hdrval;
+ int rtn;
++ struct ast_party_connected_line connected;
+
+ if (reinvite)
+ ast_debug(4, "SIP response %d to RE-invite on %s call %s\n", resp, outgoing ? "outgoing" : "incoming", p->callid);
+ else
+ ast_debug(4, "SIP response %d to standard invite\n", resp);
+
++ /* If this is a response to our initial INVITE, we need to set what we can use
++ * for this peer.
++ */
++ if (!reinvite && p->allowed_methods == SIP_UNKNOWN) {
++ struct sip_peer *peer = find_peer(p->peername, NULL, 1, FINDPEERS, FALSE);
++ if (!peer || peer->allowed_methods == SIP_UNKNOWN) {
++ set_pvt_allowed_methods(p, req);
++ } else {
++ p->allowed_methods = peer->allowed_methods;
++ }
++ if (peer) {
++ unref_peer(peer, "handle_response_invite: Getting supported methods from peer");
++ }
++ }
++
+ if (p->alreadygone) { /* This call is already gone */
+ ast_debug(1, "Got response on call that is already terminated: %s (ignoring)\n", p->callid);
+ return;
+@@ -16809,7 +17706,7 @@
+ /* RFC3261 says we must treat every 1xx response (but not 100)
+ that we don't recognize as if it was 183.
+ */
+- if (resp > 100 && resp < 200 && resp!=101 && resp != 180 && resp != 182 && resp != 183)
++ if (resp > 100 && resp < 200 && resp!=101 && resp != 180 && resp != 181 && resp != 182 && resp != 183)
+ resp = 183;
+
+ /* Any response between 100 and 199 is PROCEEDING */
+@@ -16837,6 +17734,14 @@
+ if (!req->ignore && p->invitestate != INV_CANCELLED && sip_cancel_destroy(p))
+ ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n");
+ if (!req->ignore && p->owner) {
++ if (get_rpid(p, req)) {
++ ast_party_connected_line_init(&connected);
++ connected.id.number = (char *) p->cid_num;
++ connected.id.name = (char *) p->cid_name;
++ connected.id.number_presentation = p->callingpres;
++ connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
++ ast_channel_queue_connected_line_update(p->owner, &connected);
++ }
+ ast_queue_control(p->owner, AST_CONTROL_RINGING);
+ if (p->owner->_state != AST_STATE_UP) {
+ ast_setstate(p->owner, AST_STATE_RINGING);
+@@ -16854,10 +17759,32 @@
+ check_pendings(p);
+ break;
+
++ case 181: /* Call Is Being Forwarded */
++ if (!req->ignore && (p->invitestate != INV_CANCELLED) && sip_cancel_destroy(p))
++ ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n");
++ if (!req->ignore && p->owner) {
++ struct ast_party_redirecting redirecting = {{0,},};
++ change_redirecting_information(p, req, &redirecting, FALSE);
++ ast_channel_queue_redirecting_update(p->owner, &redirecting);
++ }
++ check_pendings(p);
++ break;
++
+ case 183: /* Session progress */
+ if (!req->ignore && (p->invitestate != INV_CANCELLED) && sip_cancel_destroy(p))
+ ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n");
+ /* Ignore 183 Session progress without SDP */
++ if (!req->ignore && p->owner) {
++ if (get_rpid(p, req)) {
++ /* Queue a connected line update */
++ ast_party_connected_line_init(&connected);
++ connected.id.number = (char *) p->cid_num;
++ connected.id.name = (char *) p->cid_name;
++ connected.id.number_presentation = p->callingpres;
++ connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
++ ast_channel_queue_connected_line_update(p->owner, &connected);
++ }
++ }
+ if (find_sdp(req)) {
+ if (p->invitestate != INV_CANCELLED)
+ p->invitestate = INV_EARLY_MEDIA;
+@@ -16879,9 +17806,19 @@
+ if (!reinvite)
+ /* This 200 OK's SDP is not acceptable, so we need to ack, then hangup */
+ /* For re-invites, we try to recover */
+- ast_set_flag(&p->flags[0], SIP_PENDINGBYE);
++ ast_set_flag(&p->flags[0], SIP_PENDINGBYE);
+ }
+
++ if (!req->ignore && p->owner && (get_rpid(p, req) || !reinvite)) {
++ /* Queue a connected line update */
++ ast_party_connected_line_init(&connected);
++ connected.id.number = (char *) p->cid_num;
++ connected.id.name = (char *) p->cid_name;
++ connected.id.number_presentation = p->callingpres;
++ connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
++ ast_channel_queue_connected_line_update(p->owner, &connected);
++ }
++
+ /* Parse contact header for continued conversation */
+ /* When we get 200 OK, we know which device (and IP) to contact for this call */
+ /* This is important when we have a SIP proxy between us and the phone */
+@@ -17043,7 +17980,7 @@
+ if (p->udptl && p->t38.state == T38_LOCAL_REINVITE) {
+ change_t38_state(p, T38_DISABLED);
+ /* Try to reset RTP timers */
+- ast_rtp_set_rtptimers_onhold(p->rtp);
++ //ast_rtp_set_rtptimers_onhold(p->rtp);
+
+ /* Trigger a reinvite back to audio */
+ transmit_reinvite_with_sdp(p, FALSE, FALSE);
+@@ -17082,6 +18019,7 @@
+ }
+ break;
+
++ case 405: /* Not allowed */
+ case 501: /* Not implemented */
+ xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE);
+ if (p->owner)
+@@ -17095,7 +18033,7 @@
+ /* \brief Handle SIP response in NOTIFY transaction
+ We've sent a NOTIFY, now handle responses to it
+ */
+-static void handle_response_notify(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno)
++static void handle_response_notify(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno)
+ {
+ switch (resp) {
+ case 200: /* Notify accepted */
+@@ -17138,8 +18076,9 @@
+ }
+
+ /* \brief Handle SIP response in SUBSCRIBE transaction */
+-static void handle_response_subscribe(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno)
++static void handle_response_subscribe(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno)
+ {
++ struct sip_peer *peer;
+ if (!p->mwi) {
+ return;
+ }
+@@ -17147,6 +18086,15 @@
+ switch (resp) {
+ case 200: /* Subscription accepted */
+ ast_debug(3, "Got 200 OK on subscription for MWI\n");
++ peer = find_peer(p->peername, NULL, 1, FINDPEERS, FALSE);
++ if (!peer || peer->allowed_methods == SIP_UNKNOWN) {
++ set_pvt_allowed_methods(p, req);
++ } else {
++ p->allowed_methods = peer->allowed_methods;
++ }
++ if (peer) {
++ unref_peer(peer, "handle_response_subscribe: Getting supported methods");
++ }
+ if (p->options) {
+ ast_free(p->options);
+ p->options = NULL;
+@@ -17199,8 +18147,10 @@
+ /* \brief Handle SIP response in REFER transaction
+ We've sent a REFER, now handle responses to it
+ */
+-static void handle_response_refer(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno)
++static void handle_response_refer(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno)
+ {
++ enum ast_control_transfer message = AST_TRANSFER_FAILED;
++
+ /* If no refer structure exists, then do nothing */
+ if (!p->refer)
+ return;
+@@ -17220,14 +18170,32 @@
+ if (ast_strlen_zero(p->authname)) {
+ ast_log(LOG_WARNING, "Asked to authenticate REFER to %s:%d but we have no matching peer or realm auth!\n",
+ ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port));
++ if (p->owner) {
++ ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message));
++ }
+ pvt_set_needdestroy(p, "unable to authenticate REFER");
+ }
+ if (p->authtries > 1 || do_proxy_auth(p, req, resp, SIP_REFER, 0)) {
+ ast_log(LOG_NOTICE, "Failed to authenticate on REFER to '%s'\n", get_header(&p->initreq, "From"));
+ p->refer->status = REFER_NOAUTH;
+- pvt_set_needdestroy(p, "failed to authenticat REFER");
++ if (p->owner) {
++ ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message));
++ }
++ pvt_set_needdestroy(p, "failed to authenticate REFER");
+ }
+ break;
++
++ case 405: /* Method not allowed */
++ /* Return to the current call onhold */
++ /* Status flag needed to be reset */
++ ast_log(LOG_NOTICE, "SIP transfer to %s failed, REFER not allowed. \n", p->refer->refer_to);
++ pvt_set_needdestroy(p, "received 405 response");
++ p->refer->status = REFER_FAILED;
++ if (p->owner) {
++ ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message));
++ }
++ break;
++
+ case 481: /* Call leg does not exist */
+
+ /* A transfer with Replaces did not work */
+@@ -17246,17 +18214,23 @@
+ ast_log(LOG_NOTICE, "SIP transfer to %s failed, call miserably fails. \n", p->refer->refer_to);
+ pvt_set_needdestroy(p, "received 500/501 response");
+ p->refer->status = REFER_FAILED;
++ if (p->owner) {
++ ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message));
++ }
+ break;
+ case 603: /* Transfer declined */
+ ast_log(LOG_NOTICE, "SIP transfer to %s declined, call miserably fails. \n", p->refer->refer_to);
+ p->refer->status = REFER_FAILED;
+ pvt_set_needdestroy(p, "received 603 response");
++ if (p->owner) {
++ ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message));
++ }
+ break;
+ }
+ }
+
+ /*! \brief Handle responses on REGISTER to services */
+-static int handle_response_register(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno)
++static int handle_response_register(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno)
+ {
+ int expires, expires_ms;
+ struct sip_registry *r;
+@@ -17271,7 +18245,7 @@
+ break;
+ case 403: /* Forbidden */
+ ast_log(LOG_WARNING, "Forbidden - wrong password on authentication for REGISTER for '%s' to '%s'\n", p->registry->username, p->registry->hostname);
+- AST_SCHED_DEL(sched, r->timeout);
++ AST_SCHED_DEL_UNREF(sched, r->timeout, registry_unref(r, "reg ptr unref from handle_response_register 403"));
+ r->regstate = REG_STATE_NOAUTH;
+ pvt_set_needdestroy(p, "received 403 response");
+ break;
+@@ -17281,7 +18255,7 @@
+ if (r->call)
+ r->call = dialog_unref(r->call, "unsetting registry->call pointer-- case 404");
+ r->regstate = REG_STATE_REJECTED;
+- AST_SCHED_DEL(sched, r->timeout);
++ AST_SCHED_DEL_UNREF(sched, r->timeout, registry_unref(r, "reg ptr unref from handle_response_register 404"));
+ break;
+ case 407: /* Proxy auth */
+ if (p->authtries == MAX_AUTHTRIES || do_register_auth(p, req, resp)) {
+@@ -17300,8 +18274,7 @@
+ case 423: /* Interval too brief */
+ r->expiry = atoi(get_header(req, "Min-Expires"));
+ ast_log(LOG_WARNING, "Got 423 Interval too brief for service %s@%s, minimum is %d seconds\n", p->registry->username, p->registry->hostname, r->expiry);
+- AST_SCHED_DEL(sched, r->timeout);
+- r->timeout = -1;
++ AST_SCHED_DEL_UNREF(sched, r->timeout, registry_unref(r, "reg ptr unref from handle_response_register 423"));
+ if (r->call) {
+ r->call = dialog_unref(r->call, "unsetting registry->call pointer-- case 423");
+ pvt_set_needdestroy(p, "received 423 response");
+@@ -17322,7 +18295,7 @@
+ if (r->call)
+ r->call = dialog_unref(r->call, "unsetting registry->call pointer-- case 479");
+ r->regstate = REG_STATE_REJECTED;
+- AST_SCHED_DEL(sched, r->timeout);
++ AST_SCHED_DEL_UNREF(sched, r->timeout, registry_unref(r, "reg ptr unref from handle_response_register 479"));
+ break;
+ case 200: /* 200 OK */
+ if (!r) {
+@@ -17339,7 +18312,7 @@
+ if (r->timeout > -1) {
+ ast_debug(1, "Cancelling timeout %d\n", r->timeout);
+ }
+- AST_SCHED_DEL(sched, r->timeout);
++ AST_SCHED_DEL_UNREF(sched, r->timeout, registry_unref(r, "reg ptr unref from handle_response_register 200"));
+ if (r->call)
+ r->call = dialog_unref(r->call, "unsetting registry->call pointer-- case 200");
+ p->registry = registry_unref(p->registry, "unref registry entry p->registry");
+@@ -17347,14 +18320,12 @@
+ sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
+ /* p->needdestroy = 1; */
+
+- /* set us up for re-registering */
+- /* figure out how long we got registered for */
+- AST_SCHED_DEL(sched, r->expire);
+-
+- /* according to section 6.13 of RFC, contact headers override
+- expires headers, so check those first */
++ /* set us up for re-registering
++ * figure out how long we got registered for
++ * according to section 6.13 of RFC, contact headers override
++ * expires headers, so check those first */
+ expires = 0;
+-
++
+ /* XXX todo: try to save the extra call */
+ if (!ast_strlen_zero(get_header(req, "Contact"))) {
+ const char *contact = NULL;
+@@ -17398,9 +18369,6 @@
+ registry_unref(_data,"unref in REPLACE del fail"),
+ registry_unref(r,"unref in REPLACE add fail"),
+ registry_addref(r,"The Addition side of REPLACE"));
+- /* it is clear that we would not want to destroy the registry entry if we just
+- scheduled a callback and recorded it in there! */
+- /* since we never bumped the count, we shouldn't decrement it! registry_unref(r, "unref registry ptr r"); if this gets deleted, p->registry will be a bad pointer! */
+ }
+ return 1;
+ }
+@@ -17445,6 +18413,12 @@
+ manager_event(EVENT_FLAG_SYSTEM, "PeerStatus",
+ "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: %s\r\nTime: %d\r\n",
+ peer->name, s, pingtime);
++ if (!is_reachable) {
++ peer->allowed_methods = SIP_UNKNOWN;
++ } else {
++ set_pvt_allowed_methods(p, req);
++ peer->allowed_methods = p->allowed_methods;
++ }
+ if (is_reachable && sip_cfg.regextenonqualify)
+ register_peer_exten(peer, TRUE);
+ }
+@@ -17465,18 +18439,18 @@
+ {
+ /* Immediately stop RTP, VRTP and UDPTL as applicable */
+ if (p->rtp)
+- ast_rtp_stop(p->rtp);
++ ast_rtp_instance_stop(p->rtp);
+ if (p->vrtp)
+- ast_rtp_stop(p->vrtp);
++ ast_rtp_instance_stop(p->vrtp);
+ if (p->trtp)
+- ast_rtp_stop(p->trtp);
++ ast_rtp_instance_stop(p->trtp);
+ if (p->udptl)
+ ast_udptl_stop(p->udptl);
+ }
+
+ /*! \brief Handle SIP response in dialogue
+ \note only called by handle_incoming */
+-static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno)
++static void handle_response(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno)
+ {
+ struct ast_channel *owner;
+ int sipmethod;
+@@ -17486,6 +18460,7 @@
+ char *c_copy = ast_strdupa(c);
+ /* Skip the Cseq and its subsequent spaces */
+ const char *msg = ast_skip_blanks(ast_skip_nonblanks(c_copy));
++ struct sip_peer *peer;
+
+ if (!msg)
+ msg = "";
+@@ -17546,6 +18521,7 @@
+ case 183: /* 183 Session Progress */
+ case 180: /* 180 Ringing */
+ case 182: /* 182 Queued */
++ case 181: /* 181 Call Is Being Forwarded */
+ if (sipmethod == SIP_INVITE)
+ handle_response_invite(p, resp, rest, req, seqno);
+ break;
+@@ -17585,7 +18561,9 @@
+ handle_response_subscribe(p, resp, rest, req, seqno);
+ else if (p->registry && sipmethod == SIP_REGISTER)
+ res = handle_response_register(p, resp, rest, req, seqno);
+- else if (sipmethod == SIP_BYE) {
++ else if (sipmethod == SIP_UPDATE) {
++ handle_response_update(p, resp, rest, req, seqno);
++ } else if (sipmethod == SIP_BYE) {
+ if (p->options)
+ p->options->auth_type = resp;
+ if (ast_strlen_zero(p->authname)) {
+@@ -17684,7 +18662,13 @@
+ pvt_set_needdestroy(p, "received 491 response");
+ }
+ break;
++ case 405:
+ case 501: /* Not Implemented */
++ mark_method_unallowed(&p->allowed_methods, sipmethod);
++ if ((peer = find_peer(p->peername, 0, 1, FINDPEERS, FALSE))) {
++ peer->allowed_methods = p->allowed_methods;
++ unref_peer(peer, "handle_response: marking a specific method as unallowed");
++ }
+ if (sipmethod == SIP_INVITE)
+ handle_response_invite(p, resp, rest, req, seqno);
+ else if (sipmethod == SIP_REFER)
+@@ -17713,7 +18697,11 @@
+ case 301: /* Moved permanently */
+ case 302: /* Moved temporarily */
+ case 305: /* Use Proxy */
+- parse_moved_contact(p, req);
++ {
++ struct ast_party_redirecting redirecting = {{0,},};
++ change_redirecting_information(p, req, &redirecting, TRUE);
++ ast_channel_set_redirecting(p->owner, &redirecting);
++ }
+ /* Fall through */
+ case 486: /* Busy here */
+ case 600: /* Busy everywhere */
+@@ -18173,7 +19161,7 @@
+ }
+
+ /*! \brief Handle incoming notifications */
+-static int handle_request_notify(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, int seqno, char *e)
++static int handle_request_notify(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, int seqno, const char *e)
+ {
+ /* This is mostly a skeleton for future improvements */
+ /* Mostly created to return proper answers on notifications on outbound REFER's */
+@@ -18287,7 +19275,11 @@
+ if (!success) {
+ ast_log(LOG_NOTICE, "Transfer failed. Sorry. Nothing further to do with this call\n");
+ }
+-
++
++ if (p->owner) {
++ enum ast_control_transfer message = success ? AST_TRANSFER_SUCCESS : AST_TRANSFER_FAILED;
++ ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message));
++ }
+ /* Confirm that we received this packet */
+ transmit_response(p, "200 OK", req);
+ } else if (p->mwi && !strcmp(event, "message-summary")) {
+@@ -18405,7 +19397,7 @@
+ /* We should answer something here. If we are here, the
+ call we are replacing exists, so an accepted
+ can't harm */
+- transmit_response_with_sdp(p, "200 OK", req, XMIT_RELIABLE, FALSE);
++ transmit_response_with_sdp(p, "200 OK", req, XMIT_RELIABLE, FALSE, FALSE);
+ /* Do something more clever here */
+ ast_channel_unlock(c);
+ sip_pvt_unlock(p->refer->refer_call);
+@@ -18439,7 +19431,7 @@
+ Targetcall is not touched by the masq */
+
+ /* Answer the incoming call and set channel to UP state */
+- transmit_response_with_sdp(p, "200 OK", req, XMIT_RELIABLE, FALSE);
++ transmit_response_with_sdp(p, "200 OK", req, XMIT_RELIABLE, FALSE, FALSE);
+
+ ast_setstate(c, AST_STATE_UP);
+
+@@ -18839,13 +19831,44 @@
+ return 0;
+ }
+
+-/*! \brief Handle incoming INVITE request
+-\note If the INVITE has a Replaces header, it is part of an
++/*!
++ * \brief bare-bones support for SIP UPDATE
++ *
++ * XXX This is not even close to being RFC 3311-compliant. We don't advertise
++ * that we support the UPDATE method, so no one should ever try sending us
++ * an UPDATE anyway. However, Asterisk can send an UPDATE to change connected
++ * line information, so we need to be prepared to handle this. The way we distinguish
++ * such an UPDATE is through the X-Asterisk-rpid-update header.
++ *
++ * Actually updating the media session may be some future work.
++ */
++static int handle_request_update(struct sip_pvt *p, struct sip_request *req)
++{
++ if (ast_strlen_zero(get_header(req, "X-Asterisk-rpid-update"))) {
++ transmit_response(p, "501 Method Not Implemented", req);
++ return 0;
++ }
++ if (get_rpid(p, req)) {
++ struct ast_party_connected_line connected;
++ ast_party_connected_line_init(&connected);
++ connected.id.number = (char *) p->cid_num;
++ connected.id.name = (char *) p->cid_name;
++ connected.id.number_presentation = p->callingpres;
++ connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
++ ast_channel_queue_connected_line_update(p->owner, &connected);
++ }
++ transmit_response(p, "200 OK", req);
++ return 0;
++}
++
++/*!
++ * \brief Handle incoming INVITE request
++ * \note If the INVITE has a Replaces header, it is part of an
+ * attended transfer. If so, we do not go through the dial
+- * plan but tries to find the active call and masquerade
++ * plan but try to find the active call and masquerade
+ * into it
+ */
+-static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int debug, int seqno, struct sockaddr_in *sin, int *recount, char *e, int *nounlock)
++static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int debug, int seqno, struct sockaddr_in *sin, int *recount, const char *e, int *nounlock)
+ {
+ int res = 1;
+ int gotdest;
+@@ -18908,8 +19931,8 @@
+ /* If pedantic is on, we need to check the tags. If they're different, this is
+ in fact a forked call through a SIP proxy somewhere. */
+ int different;
+- char *initial_rlPart2 = REQ_OFFSET_TO_STR(&p->initreq, rlPart2);
+- char *this_rlPart2 = REQ_OFFSET_TO_STR(req, rlPart2);
++ const char *initial_rlPart2 = REQ_OFFSET_TO_STR(&p->initreq, rlPart2);
++ const char *this_rlPart2 = REQ_OFFSET_TO_STR(req, rlPart2);
+ if (sip_cfg.pedanticsipchecking)
+ different = sip_uri_cmp(initial_rlPart2, this_rlPart2);
+ else
+@@ -18961,19 +19984,19 @@
+ __sip_ack(p, p->lastinvite, 1, 0);
+ } else {
+ /* We already have a pending invite. Sorry. You are on hold. */
+- p->glareinvite = seqno; /* must hold on to this seqno to process ack and retransmit correctly */
++ p->glareinvite = seqno;
+ if (p->rtp && find_sdp(req)) {
+ struct sockaddr_in sin;
+ if (get_ip_and_port_from_sdp(req, SDP_AUDIO, &sin)) {
+ ast_log(LOG_WARNING, "Failed to set an alternate media source on glared reinvite. Audio may not work properly on this call.\n");
+ } else {
+- ast_rtp_set_alt_peer(p->rtp, &sin);
++ ast_rtp_instance_set_alt_remote_address(p->rtp, &sin);
+ }
+ if (p->vrtp) {
+ if (get_ip_and_port_from_sdp(req, SDP_VIDEO, &sin)) {
+ ast_log(LOG_WARNING, "Failed to set an alternate media source on glared reinvite. Video may not work properly on this call.\n");
+ } else {
+- ast_rtp_set_alt_peer(p->vrtp, &sin);
++ ast_rtp_instance_set_alt_remote_address(p->vrtp, &sin);
+ }
+ }
+ }
+@@ -19136,6 +20159,16 @@
+ parse_ok_contact(p, req);
+ } else { /* Re-invite on existing call */
+ ast_clear_flag(&p->flags[0], SIP_OUTGOING); /* This is now an inbound dialog */
++ if (get_rpid(p, req)) {
++ struct ast_party_connected_line connected;
++
++ ast_party_connected_line_init(&connected);
++ connected.id.number = (char *) p->cid_num;
++ connected.id.name = (char *) p->cid_name;
++ connected.id.number_presentation = p->callingpres;
++ connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
++ ast_channel_queue_connected_line_update(p->owner, &connected);
++ }
+ /* Handle SDP here if we already have an owner */
+ if (find_sdp(req)) {
+ if (process_sdp(p, req, SDP_T38_INITIATE)) {
+@@ -19158,6 +20191,7 @@
+ if (!p->lastinvite && !req->ignore && !p->owner) {
+ /* This is a new invite */
+ /* Handle authentication if this is our first invite */
++ struct ast_party_redirecting redirecting = {{0,},};
+ res = check_user(p, req, SIP_INVITE, e, XMIT_RELIABLE, sin);
+ if (res == AUTH_CHALLENGE_SENT) {
+ p->invitestate = INV_COMPLETED; /* Needs to restart in another INVITE transaction */
+@@ -19220,13 +20254,13 @@
+ return 0;
+ }
+ gotdest = get_destination(p, NULL); /* Get destination right away */
+- get_rdnis(p, NULL); /* Get redirect information */
++ change_redirecting_information(p, req, &redirecting, FALSE); /*Will return immediately if no Diversion header is present */
+ extract_uri(p, req); /* Get the Contact URI */
+ build_contact(p); /* Build our contact header */
+
+ if (p->rtp) {
+- ast_rtp_setdtmf(p->rtp, ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
+- ast_rtp_setdtmfcompensate(p->rtp, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
++ ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_DTMF, ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
++ ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
+ }
+
+ if (!replace_id && gotdest) { /* No matching extension found */
+@@ -19264,9 +20298,11 @@
+ if (c) {
+ /* Pre-lock the call */
+ ast_channel_lock(c);
++ ast_channel_set_redirecting(c, &redirecting);
+ }
+ }
+ } else {
++ struct ast_party_redirecting redirecting = {{0,},};
+ if (sipdebug) {
+ if (!req->ignore)
+ ast_debug(2, "Got a SIP re-invite for call %s\n", p->callid);
+@@ -19276,6 +20312,10 @@
+ if (!req->ignore)
+ reinvite = 1;
+ c = p->owner;
++ change_redirecting_information(p, req, &redirecting, FALSE); /*Will return immediately if no Diversion header is present */
++ if (c) {
++ ast_channel_set_redirecting(c, &redirecting);
++ }
+ }
+
+ /* Session-Timers */
+@@ -19486,7 +20526,6 @@
+ c->hangupcause = AST_CAUSE_CALL_REJECTED;
+ } else {
+ sip_pvt_unlock(p);
+- ast_setstate(c, AST_STATE_DOWN);
+ c->hangupcause = AST_CAUSE_NORMAL_CLEARING;
+ }
+ p->invitestate = INV_COMPLETED;
+@@ -19528,7 +20567,7 @@
+ } else if (p->t38.state == T38_DISABLED) {
+ /* If this is not a re-invite or something to ignore - it's critical */
+ ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
+- transmit_response_with_sdp(p, "200 OK", req, (reinvite ? XMIT_RELIABLE : (req->ignore ? XMIT_UNRELIABLE : XMIT_CRITICAL)), p->session_modify == TRUE ? FALSE:TRUE);
++ transmit_response_with_sdp(p, "200 OK", req, (reinvite ? XMIT_RELIABLE : (req->ignore ? XMIT_UNRELIABLE : XMIT_CRITICAL)), p->session_modify == TRUE ? FALSE : TRUE, FALSE);
+ }
+
+ p->invitestate = INV_TERMINATED;
+@@ -19564,6 +20603,8 @@
+ /* Chan 2: Call from Asterisk to target */
+ int res = 0;
+ struct sip_pvt *targetcall_pvt;
++ struct ast_party_connected_line connected_to_transferee;
++ struct ast_party_connected_line connected_to_target;
+
+ /* Check if the call ID of the replaces header does exist locally */
+ if (!(targetcall_pvt = get_sip_pvt_byid_locked(transferer->refer->replaces_callid, transferer->refer->replaces_callid_totag,
+@@ -19631,6 +20672,13 @@
+ transferer->callid,
+ target.chan1->name,
+ target.chan1->uniqueid);
++ ast_party_connected_line_init(&connected_to_transferee);
++ ast_party_connected_line_init(&connected_to_target);
++ /* No need to lock current->chan1 here since it was locked in sipsock_read */
++ ast_party_connected_line_copy(&connected_to_transferee, &current->chan1->connected);
++ /* No need to lock target.chan1 here since it was locked in get_sip_pvt_byid_locked */
++ ast_party_connected_line_copy(&connected_to_target, &target.chan1->connected);
++ connected_to_target.source = connected_to_transferee.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
+ res = attempt_transfer(current, &target);
+ sip_pvt_unlock(targetcall_pvt);
+ if (res) {
+@@ -19655,7 +20703,30 @@
+ ast_debug(1, "SIP attended transfer: Unlocking channel %s\n", targetcall_pvt->owner->name);
+ ast_channel_unlock(targetcall_pvt->owner);
+ }
++
++ /* By forcing the masquerade, we know that target.chan1 and target.chan2 are bridged. We then
++ * can queue connected line updates where they need to go.
++ *
++ * No need to lock target.chan1 here since it was previously locked in get_sip_pvt_byid_locked
++ */
++ if (target.chan1->masq) {
++ /* If the channel thread already did the masquerade, then we don't need to do anything */
++ ast_do_masquerade(target.chan1);
++ }
++ if (target.chan2) {
++ ast_channel_queue_connected_line_update(target.chan1, &connected_to_transferee);
++ ast_channel_queue_connected_line_update(target.chan2, &connected_to_target);
++ } else {
++ /* Since target.chan1 isn't actually connected to another channel, there is no way for us
++ * to queue a frame so that its connected line status will be updated. Instead, we have to
++ * change it directly. Since we are not the channel thread, we cannot run a connected line
++ * interception macro on target.chan1
++ */
++ ast_channel_update_connected_line(target.chan1, &connected_to_target);
++ }
+ }
++ ast_party_connected_line_free(&connected_to_target);
++ ast_party_connected_line_free(&connected_to_transferee);
+ if (targetcall_pvt)
+ ao2_t_ref(targetcall_pvt, -1, "drop targetcall_pvt");
+ return 1;
+@@ -20040,6 +21111,30 @@
+ else
+ sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
+ if (p->initreq.len > 0) {
++ struct sip_pkt *pkt, *prev_pkt;
++ /* If the CANCEL we are receiving is a retransmission, and we already have scheduled
++ * a reliable 487, then we don't want to schedule another one on top of the previous
++ * one.
++ *
++ * As odd as this may sound, we can't rely on the previously-transmitted "reliable"
++ * response in this situation. What if we've sent all of our reliable responses
++ * already and now all of a sudden, we get this second CANCEL?
++ *
++ * The only way to do this correctly is to cancel our previously-scheduled reliably-
++ * transmitted response and send a new one in its place.
++ */
++ for (pkt = p->packets, prev_pkt = NULL; pkt; prev_pkt = pkt, pkt = pkt->next) {
++ if (pkt->seqno == p->lastinvite && pkt->response_code == 487) {
++ AST_SCHED_DEL(sched, pkt->retransid);
++ if (prev_pkt) {
++ prev_pkt->next = pkt->next;
++ } else {
++ p->packets = pkt->next;
++ }
++ ast_free(pkt);
++ break;
++ }
++ }
+ transmit_response_reliable(p, "487 Request Terminated", &p->initreq);
+ transmit_response(p, "200 OK", req);
+ return 1;
+@@ -20052,7 +21147,7 @@
+ static int acf_channel_read(struct ast_channel *chan, const char *funcname, char *preparse, char *buf, size_t buflen)
+ {
+ struct sip_pvt *p = chan->tech_pvt;
+- char *all = "", *parse = ast_strdupa(preparse);
++ char *parse = ast_strdupa(preparse);
+ int res = 0;
+ AST_DECLARE_APP_ARGS(args,
+ AST_APP_ARG(param);
+@@ -20069,6 +21164,10 @@
+
+ memset(buf, 0, buflen);
+
++ if (p == NULL) {
++ return -1;
++ }
++
+ if (!strcasecmp(args.param, "peerip")) {
+ ast_copy_string(buf, p->sa.sin_addr.s_addr ? ast_inet_ntoa(p->sa.sin_addr) : "", buflen);
+ } else if (!strcasecmp(args.param, "recvip")) {
+@@ -20090,61 +21189,70 @@
+ args.type = "audio";
+
+ if (!strcasecmp(args.type, "audio"))
+- ast_rtp_get_peer(p->rtp, &sin);
++ ast_rtp_instance_get_remote_address(p->rtp, &sin);
+ else if (!strcasecmp(args.type, "video"))
+- ast_rtp_get_peer(p->vrtp, &sin);
++ ast_rtp_instance_get_remote_address(p->vrtp, &sin);
+ else if (!strcasecmp(args.type, "text"))
+- ast_rtp_get_peer(p->trtp, &sin);
++ ast_rtp_instance_get_remote_address(p->trtp, &sin);
+ else
+ return -1;
+
+ snprintf(buf, buflen, "%s:%d", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
+ } else if (!strcasecmp(args.param, "rtpqos")) {
+- struct ast_rtp_quality qos;
+- struct ast_rtp *rtp = p->rtp;
+-
+- memset(&qos, 0, sizeof(qos));
++ struct ast_rtp_instance *rtp = NULL;
+
+- if (ast_strlen_zero(args.type))
++ if (ast_strlen_zero(args.type)) {
+ args.type = "audio";
+- if (ast_strlen_zero(args.field))
+- args.field = "all";
+-
+- if (!strcasecmp(args.type, "AUDIO")) {
+- all = ast_rtp_get_quality(rtp = p->rtp, &qos, RTPQOS_SUMMARY);
+- } else if (!strcasecmp(args.type, "VIDEO")) {
+- all = ast_rtp_get_quality(rtp = p->vrtp, &qos, RTPQOS_SUMMARY);
+- } else if (!strcasecmp(args.type, "TEXT")) {
+- all = ast_rtp_get_quality(rtp = p->trtp, &qos, RTPQOS_SUMMARY);
++ }
++
++ if (!strcasecmp(args.type, "audio")) {
++ rtp = p->rtp;
++ } else if (!strcasecmp(args.type, "video")) {
++ rtp = p->vrtp;
++ } else if (!strcasecmp(args.type, "text")) {
++ rtp = p->trtp;
+ } else {
+- return -1;
++ return -1;
+ }
+-
+- if (!strcasecmp(args.field, "local_ssrc"))
+- snprintf(buf, buflen, "%u", qos.local_ssrc);
+- else if (!strcasecmp(args.field, "local_lostpackets"))
+- snprintf(buf, buflen, "%u", qos.local_lostpackets);
+- else if (!strcasecmp(args.field, "local_jitter"))
+- snprintf(buf, buflen, "%.0f", qos.local_jitter * 1000.0);
+- else if (!strcasecmp(args.field, "local_count"))
+- snprintf(buf, buflen, "%u", qos.local_count);
+- else if (!strcasecmp(args.field, "remote_ssrc"))
+- snprintf(buf, buflen, "%u", qos.remote_ssrc);
+- else if (!strcasecmp(args.field, "remote_lostpackets"))
+- snprintf(buf, buflen, "%u", qos.remote_lostpackets);
+- else if (!strcasecmp(args.field, "remote_jitter"))
+- snprintf(buf, buflen, "%.0f", qos.remote_jitter * 1000.0);
+- else if (!strcasecmp(args.field, "remote_count"))
+- snprintf(buf, buflen, "%u", qos.remote_count);
+- else if (!strcasecmp(args.field, "rtt"))
+- snprintf(buf, buflen, "%.0f", qos.rtt * 1000.0);
+- else if (!strcasecmp(args.field, "all"))
+- ast_copy_string(buf, all, buflen);
+- else if (!ast_rtp_get_qos(rtp, args.field, buf, buflen))
+- ;
+- else {
+- ast_log(LOG_WARNING, "Unrecognized argument '%s' to %s\n", preparse, funcname);
+- return -1;
++
++ if (ast_strlen_zero(args.field) || !strcasecmp(args.field, "all")) {
++ char quality_buf[AST_MAX_USER_FIELD], *quality;
++
++ if (!(quality = ast_rtp_instance_get_quality(rtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, quality_buf, sizeof(quality_buf)))) {
++ return -1;
++ }
++
++ ast_copy_string(buf, quality_buf, buflen);
++ return res;
++ } else {
++ struct ast_rtp_instance_stats stats;
++
++ if (ast_rtp_instance_get_stats(rtp, &stats, AST_RTP_INSTANCE_STAT_ALL)) {
++ return -1;
++ }
++
++ if (!strcasecmp(args.field, "local_ssrc")) {
++ snprintf(buf, buflen, "%u", stats.local_ssrc);
++ } else if (!strcasecmp(args.field, "local_lostpackets")) {
++ snprintf(buf, buflen, "%u", stats.rxploss);
++ } else if (!strcasecmp(args.field, "local_jitter")) {
++ snprintf(buf, buflen, "%u", stats.rxjitter);
++ } else if (!strcasecmp(args.field, "local_count")) {
++ snprintf(buf, buflen, "%u", stats.rxcount);
++ } else if (!strcasecmp(args.field, "remote_ssrc")) {
++ snprintf(buf, buflen, "%u", stats.remote_ssrc);
++ } else if (!strcasecmp(args.field, "remote_lostpackets")) {
++ snprintf(buf, buflen, "%u", stats.txploss);
++ } else if (!strcasecmp(args.field, "remote_jitter")) {
++ snprintf(buf, buflen, "%u", stats.txjitter);
++ } else if (!strcasecmp(args.field, "remote_count")) {
++ snprintf(buf, buflen, "%u", stats.txcount);
++ } else if (!strcasecmp(args.field, "rtt")) {
++ snprintf(buf, buflen, "%u", stats.rtt);
++ } else {
++ ast_log(LOG_WARNING, "Unrecognized argument '%s' to %s\n", preparse, funcname);
++ return -1;
++ }
+ }
+ } else {
+ res = -1;
+@@ -20176,10 +21284,10 @@
+
+ /* Get RTCP quality before end of call */
+ if (p->do_history || p->owner) {
+- struct ast_channel *bridge = p->owner ? ast_bridged_channel(p->owner) : NULL;
+- char *videoqos, *textqos;
++ char quality_buf[AST_MAX_USER_FIELD], *quality;
++ struct ast_channel *bridge = p->owner ? ast_bridged_channel(p->owner) : NULL;
+
+- /* We need to get the lock on bridge because ast_rtp_set_vars will attempt
++ /* We need to get the lock on bridge because ast_rtp_instance_set_stats_vars will attempt
+ * to lock the bridge. This may get hairy...
+ */
+ while (bridge && ast_channel_trylock(bridge)) {
+@@ -20193,51 +21301,52 @@
+ bridge = p->owner ? ast_bridged_channel(p->owner) : NULL;
+ }
+
+- if (p->rtp) {
++
++ if (p->rtp && (quality = ast_rtp_instance_get_quality(p->rtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, quality_buf, sizeof(quality_buf)))) {
+ if (p->do_history) {
+- char *audioqos,
+- *audioqos_jitter,
+- *audioqos_loss,
+- *audioqos_rtt;
++ append_history(p, "RTCPaudio", "Quality:%s", quality);
+
+- audioqos = ast_rtp_get_quality(p->rtp, NULL, RTPQOS_SUMMARY);
+- audioqos_jitter = ast_rtp_get_quality(p->rtp, NULL, RTPQOS_JITTER);
+- audioqos_loss = ast_rtp_get_quality(p->rtp, NULL, RTPQOS_LOSS);
+- audioqos_rtt = ast_rtp_get_quality(p->rtp, NULL, RTPQOS_RTT);
++ if ((quality = ast_rtp_instance_get_quality(p->rtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY_JITTER, quality_buf, sizeof(quality_buf)))) {
++ append_history(p, "RTCPaudioJitter", "Quality:%s", quality);
++ }
++ if ((quality = ast_rtp_instance_get_quality(p->rtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY_LOSS, quality_buf, sizeof(quality_buf)))) {
++ append_history(p, "RTCPaudioLoss", "Quality:%s", quality);
++ }
++ if ((quality = ast_rtp_instance_get_quality(p->rtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY_RTT, quality_buf, sizeof(quality_buf)))) {
++ append_history(p, "RTCPaudioRTT", "Quality:%s", quality);
++ }
++ }
+
+- append_history(p, "RTCPaudio", "Quality:%s", audioqos);
+- append_history(p, "RTCPaudioJitter", "Quality:%s", audioqos_jitter);
+- append_history(p, "RTCPaudioLoss", "Quality:%s", audioqos_loss);
+- append_history(p, "RTCPaudioRTT", "Quality:%s", audioqos_rtt);
+- }
+-
+ if (p->owner) {
+- ast_rtp_set_vars(p->owner, p->rtp);
++ ast_rtp_instance_set_stats_vars(p->owner, p->rtp);
+ }
++
+ }
+
+ if (bridge) {
+ struct sip_pvt *q = bridge->tech_pvt;
+
+- if (IS_SIP_TECH(bridge->tech) && q && q->rtp)
+- ast_rtp_set_vars(bridge, q->rtp);
++ if (IS_SIP_TECH(bridge->tech) && q && q->rtp) {
++ ast_rtp_instance_set_stats_vars(bridge, q->rtp);
++ }
+ ast_channel_unlock(bridge);
+ }
+
+- if (p->vrtp) {
+- videoqos = ast_rtp_get_quality(p->vrtp, NULL, RTPQOS_SUMMARY);
+- if (p->do_history)
+- append_history(p, "RTCPvideo", "Quality:%s", videoqos);
+- if (p->owner)
+- pbx_builtin_setvar_helper(p->owner, "RTPVIDEOQOS", videoqos);
++ if (p->vrtp && (quality = ast_rtp_instance_get_quality(p->vrtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, quality_buf, sizeof(quality_buf)))) {
++ if (p->do_history) {
++ append_history(p, "RTCPvideo", "Quality:%s", quality);
++ }
++ if (p->owner) {
++ pbx_builtin_setvar_helper(p->owner, "RTPVIDEOQOS", quality);
++ }
+ }
+-
+- if (p->trtp) {
+- textqos = ast_rtp_get_quality(p->trtp, NULL, RTPQOS_SUMMARY);
+- if (p->do_history)
+- append_history(p, "RTCPtext", "Quality:%s", textqos);
+- if (p->owner)
+- pbx_builtin_setvar_helper(p->owner, "RTPTEXTQOS", textqos);
++ if (p->trtp && (quality = ast_rtp_instance_get_quality(p->trtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, quality_buf, sizeof(quality_buf)))) {
++ if (p->do_history) {
++ append_history(p, "RTCPtext", "Quality:%s", quality);
++ }
++ if (p->owner) {
++ pbx_builtin_setvar_helper(p->owner, "RTPTEXTQOS", quality);
++ }
+ }
+ }
+
+@@ -20304,7 +21413,7 @@
+ }
+
+ /*! \brief Handle incoming SUBSCRIBE request */
+-static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, int seqno, char *e)
++static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, int seqno, const char *e)
+ {
+ int gotdest = 0;
+ int res = 0;
+@@ -20435,16 +21544,20 @@
+ make_our_tag(p->tag, sizeof(p->tag));
+
+ if (!strcmp(event, "presence") || !strcmp(event, "dialog")) { /* Presence, RFC 3842 */
++ unsigned int pidf_xml;
++
+ if (authpeer) /* We do not need the authpeer any more */
+ unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 2)");
+
+ /* Header from Xten Eye-beam Accept: multipart/related, application/rlmi+xml, application/pidf+xml, application/xpidf+xml */
+- /* Polycom phones only handle xpidf+xml, even if they say they can
+- handle pidf+xml as well
+- */
+- if (strstr(p->useragent, "Polycom")) {
++
++ pidf_xml = strstr(acceptheader, "application/pidf+xml") ? 1 : 0;
++
++ /* Older versions of Polycom firmware will claim pidf+xml, but really
++ * they only support xpidf+xml. */
++ if (pidf_xml && strstr(p->useragent, "Polycom")) {
+ p->subscribed = XPIDF_XML;
+- } else if (strstr(acceptheader, "application/pidf+xml")) {
++ } else if (pidf_xml) {
+ p->subscribed = PIDF_XML; /* RFC 3863 format */
+ } else if (strstr(acceptheader, "application/dialog-info+xml")) {
+ p->subscribed = DIALOG_INFO_XML;
+@@ -20624,7 +21737,7 @@
+ }
+
+ /*! \brief Handle incoming REGISTER request */
+-static int handle_request_register(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, char *e)
++static int handle_request_register(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, const char *e)
+ {
+ enum check_auth_result res;
+
+@@ -20692,7 +21805,7 @@
+ int respid;
+ int res = 0;
+ int debug = sip_debug_test_pvt(p);
+- char *e;
++ const char *e;
+ int error = 0;
+
+ /* Get Method and Cseq */
+@@ -20734,10 +21847,10 @@
+ */
+ int ret = 0;
+
+- if (p->ocseq < seqno && seqno != p->lastnoninvite) {
++ if (p->ocseq < seqno && p->lastinvite != seqno && p->lastnoninvite != seqno) {
+ ast_debug(1, "Ignoring out of order response %d (expecting %d)\n", seqno, p->ocseq);
+ ret = -1;
+- } else if (p->ocseq != seqno && seqno != p->lastnoninvite) {
++ } else if (p->ocseq != seqno && p->lastinvite != seqno && p->lastnoninvite != seqno) {
+ /* ignore means "don't do anything with it" but still have to
+ * respond appropriately.
+ * But in this case this is a response already, so we really
+@@ -20869,6 +21982,9 @@
+ case SIP_NOTIFY:
+ res = handle_request_notify(p, req, sin, seqno, e);
+ break;
++ case SIP_UPDATE:
++ res = handle_request_update(p, req);
++ break;
+ case SIP_ACK:
+ /* Make sure we don't ignore this */
+ if (seqno == p->pendinginvite) {
+@@ -21029,8 +22145,8 @@
+ }
+
+ req.len = res;
+- req.socket.fd = sipsock;
+- req.socket.type = SIP_TRANSPORT_UDP;
++ req.socket.fd = sipsock;
++ set_socket_transport(&req.socket, SIP_TRANSPORT_UDP);
+ req.socket.tcptls_session = NULL;
+ req.socket.port = bindaddr.sin_port;
+
+@@ -21378,13 +22494,13 @@
+ p = dialog_ref(peer->mwipvt, "sip_send_mwi_to_peer: Setting dialog ptr p from peer->mwipvt-- should this be done?");
+ } else {
+ /* Build temporary dialog for this message */
+- if (!(p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY)))
++ if (!(p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY, NULL)))
+ return -1;
+ /* If we don't set the socket type to 0, then create_addr_from_peer will fail immediately if the peer
+ * uses any transport other than UDP. We set the type to 0 here and then let create_addr_from_peer copy
+ * the peer's socket information to the sip_pvt we just allocated
+ */
+- p->socket.type = 0;
++ set_socket_transport(&p->socket, 0);
+ if (create_addr_from_peer(p, peer)) {
+ /* Maybe they're not registered, etc. */
+ dialog_unlink_all(p, TRUE, TRUE);
+@@ -21393,10 +22509,15 @@
+ return 0;
+ }
+ /* Recalculate our side, and recalculate Call ID */
+- ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip);
++ ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip, p);
+ build_via(p);
+ ao2_t_unlink(dialogs, p, "About to change the callid -- remove the old name");
+ build_callid_pvt(p);
++ if (!ast_strlen_zero(peer->mwi_from)) {
++ ast_string_field_set(p, mwi_from, peer->mwi_from);
++ } else if (!ast_strlen_zero(default_mwi_from)) {
++ ast_string_field_set(p, mwi_from, default_mwi_from);
++ }
+ ao2_t_link(dialogs, p, "Linking in under new name");
+ /* Destroy this session after 32 secs */
+ sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
+@@ -21426,15 +22547,8 @@
+ return;
+
+ /* If we have no timers set, return now */
+- if ((ast_rtp_get_rtpkeepalive(dialog->rtp) == 0) && (ast_rtp_get_rtptimeout(dialog->rtp) == 0) && (ast_rtp_get_rtpholdtimeout(dialog->rtp) == 0))
++ if (!ast_rtp_instance_get_timeout(dialog->rtp) && !ast_rtp_instance_get_hold_timeout(dialog->rtp)) {
+ return;
+-
+- /* Check AUDIO RTP keepalives */
+- if (dialog->lastrtptx && ast_rtp_get_rtpkeepalive(dialog->rtp) &&
+- (t > dialog->lastrtptx + ast_rtp_get_rtpkeepalive(dialog->rtp))) {
+- /* Need to send an empty RTP packet */
+- dialog->lastrtptx = time(NULL);
+- ast_rtp_sendcng(dialog->rtp, 0);
+ }
+
+ /*! \todo Check video RTP keepalives
+@@ -21444,16 +22558,10 @@
+ */
+
+ /* Check AUDIO RTP timers */
+- if (dialog->lastrtprx && (ast_rtp_get_rtptimeout(dialog->rtp) || ast_rtp_get_rtpholdtimeout(dialog->rtp)) &&
+- (t > dialog->lastrtprx + ast_rtp_get_rtptimeout(dialog->rtp))) {
+-
+- /* Might be a timeout now -- see if we're on hold */
+- struct sockaddr_in sin;
+- ast_rtp_get_peer(dialog->rtp, &sin);
+- if (!ast_test_flag(&dialog->flags[1], SIP_PAGE2_CALL_ONHOLD) || (ast_rtp_get_rtpholdtimeout(dialog->rtp) &&
+- (t > dialog->lastrtprx + ast_rtp_get_rtpholdtimeout(dialog->rtp)))) {
++ if (dialog->lastrtprx && (ast_rtp_instance_get_timeout(dialog->rtp) || ast_rtp_instance_get_hold_timeout(dialog->rtp)) && (t > dialog->lastrtprx + ast_rtp_instance_get_timeout(dialog->rtp))) {
++ if (!ast_test_flag(&dialog->flags[1], SIP_PAGE2_CALL_ONHOLD) || (ast_rtp_instance_get_hold_timeout(dialog->rtp) && (t > dialog->lastrtprx + ast_rtp_instance_get_hold_timeout(dialog->rtp)))) {
+ /* Needs a hangup */
+- if (ast_rtp_get_rtptimeout(dialog->rtp)) {
++ if (ast_rtp_instance_get_timeout(dialog->rtp)) {
+ while (dialog->owner && ast_channel_trylock(dialog->owner)) {
+ sip_pvt_unlock(dialog);
+ usleep(1);
+@@ -21468,11 +22576,11 @@
+ has already been requested and we don't want to
+ repeatedly request hangups
+ */
+- ast_rtp_set_rtptimeout(dialog->rtp, 0);
+- ast_rtp_set_rtpholdtimeout(dialog->rtp, 0);
++ ast_rtp_instance_set_timeout(dialog->rtp, 0);
++ ast_rtp_instance_set_hold_timeout(dialog->rtp, 0);
+ if (dialog->vrtp) {
+- ast_rtp_set_rtptimeout(dialog->vrtp, 0);
+- ast_rtp_set_rtpholdtimeout(dialog->vrtp, 0);
++ ast_rtp_instance_set_timeout(dialog->vrtp, 0);
++ ast_rtp_instance_set_hold_timeout(dialog->vrtp, 0);
+ }
+ }
+ }
+@@ -21959,7 +23067,7 @@
+ peer->call = dialog_unref(peer->call, "unref dialog peer->call");
+ /* peer->call = sip_destroy(peer->call); */
+ }
+- if (!(p = sip_alloc(NULL, NULL, 0, SIP_OPTIONS))) {
++ if (!(p = sip_alloc(NULL, NULL, 0, SIP_OPTIONS, NULL))) {
+ return -1;
+ }
+ peer->call = dialog_ref(p, "copy sip alloc from p to peer->call");
+@@ -21980,7 +23088,7 @@
+ ast_string_field_set(p, tohost, ast_inet_ntoa(peer->addr.sin_addr));
+
+ /* Recalculate our side, and recalculate Call ID */
+- ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip);
++ ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip, p);
+ build_via(p);
+ ao2_t_unlink(dialogs, p, "About to change the callid -- remove the old name");
+ build_callid_pvt(p);
+@@ -22154,7 +23262,7 @@
+ }
+ ast_debug(1, "Asked to create a SIP channel with formats: %s\n", ast_getformatname_multiple(tmp, sizeof(tmp), oldformat));
+
+- if (!(p = sip_alloc(NULL, NULL, 0, SIP_INVITE))) {
++ if (!(p = sip_alloc(NULL, NULL, 0, SIP_INVITE, NULL))) {
+ ast_log(LOG_ERROR, "Unable to build sip pvt data for '%s' (Out of memory or socket error)\n", dest);
+ *cause = AST_CAUSE_SWITCH_CONGESTION;
+ return NULL;
+@@ -22223,8 +23331,7 @@
+ host = tmp;
+ }
+
+- p->socket.fd = -1;
+- p->socket.type = transport;
++ set_socket_transport(&p->socket, transport);
+
+ /* We now have
+ host = peer name, DNS host name or DNS domain (for SRV)
+@@ -22242,7 +23349,7 @@
+ if (ast_strlen_zero(p->peername) && ext)
+ ast_string_field_set(p, peername, ext);
+ /* Recalculate our side, and recalculate Call ID */
+- ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip);
++ ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip, p);
+ build_via(p);
+ ao2_t_unlink(dialogs, p, "About to change the callid -- remove the old name");
+ build_callid_pvt(p);
+@@ -22326,7 +23433,19 @@
+ ast_set2_flag(&flags[0], ast_true(v->value), SIP_TRUSTRPID);
+ } else if (!strcasecmp(v->name, "sendrpid")) {
+ ast_set_flag(&mask[0], SIP_SENDRPID);
+- ast_set2_flag(&flags[0], ast_true(v->value), SIP_SENDRPID);
++ if (!strcasecmp(v->value, "pai")) {
++ ast_set_flag(&flags[0], SIP_SENDRPID_PAI);
++ } else if (!strcasecmp(v->value, "rpid")) {
++ ast_set_flag(&flags[0], SIP_SENDRPID_RPID);
++ } else if (ast_true(v->value)) {
++ ast_set_flag(&flags[0], SIP_SENDRPID_RPID);
++ }
++ } else if (!strcasecmp(v->name, "rpid_update")) {
++ ast_set_flag(&mask[1], SIP_PAGE2_RPID_UPDATE);
++ ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_RPID_UPDATE);
++ } else if (!strcasecmp(v->name, "rpid_immediate")) {
++ ast_set_flag(&mask[1], SIP_PAGE2_RPID_IMMEDIATE);
++ ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_RPID_IMMEDIATE);
+ } else if (!strcasecmp(v->name, "g726nonstandard")) {
+ ast_set_flag(&mask[0], SIP_G726_NONSTANDARD);
+ ast_set2_flag(&flags[0], ast_true(v->value), SIP_G726_NONSTANDARD);
+@@ -22623,8 +23742,7 @@
+ peer->expire = -1;
+ peer->pokeexpire = -1;
+ peer->addr.sin_port = htons(STANDARD_SIP_PORT);
+- peer->socket.type = SIP_TRANSPORT_UDP;
+- peer->socket.fd = -1;
++ set_socket_transport(&peer->socket, SIP_TRANSPORT_UDP);
+ }
+ peer->type = SIP_TYPE_PEER;
+ ast_copy_flags(&peer->flags[0], &global_flags[0], SIP_FLAGS_TO_COPY);
+@@ -22634,6 +23752,7 @@
+ ast_string_field_set(peer, language, default_language);
+ ast_string_field_set(peer, mohinterpret, default_mohinterpret);
+ ast_string_field_set(peer, mohsuggest, default_mohsuggest);
++ ast_string_field_set(peer, engine, default_engine);
+ peer->addr.sin_family = AF_INET;
+ peer->defaddr.sin_family = AF_INET;
+ peer->capability = global_capability;
+@@ -22861,6 +23980,8 @@
+ ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
+ ast_string_field_set(peer, cid_name, cid_name);
+ ast_string_field_set(peer, cid_num, cid_num);
++ } else if (!strcasecmp(v->name, "mwi_from")) {
++ ast_string_field_set(peer, mwi_from, v->value);
+ } else if (!strcasecmp(v->name, "fullname")) {
+ ast_string_field_set(peer, cid_name, v->value);
+ } else if (!strcasecmp(v->name, "cid_number")) {
+@@ -22984,6 +24105,8 @@
+ ast_string_field_set(peer, mohsuggest, v->value);
+ } else if (!strcasecmp(v->name, "parkinglot")) {
+ ast_string_field_set(peer, parkinglot, v->value);
++ } else if (!strcasecmp(v->name, "rtp_engine")) {
++ ast_string_field_set(peer, engine, v->value);
+ } else if (!strcasecmp(v->name, "mailbox")) {
+ add_peer_mailboxes(peer, v->value);
+ } else if (!strcasecmp(v->name, "hasvoicemail")) {
+@@ -23010,6 +24133,8 @@
+ int error = ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, FALSE);
+ if (error)
+ ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value);
++ } else if (!strcasecmp(v->name, "preferred_codec_only")) {
++ ast_set2_flag(&peer->flags[1], ast_true(v->value), SIP_PAGE2_PREFERRED_CODEC);
+ } else if (!strcasecmp(v->name, "registertrying")) {
+ ast_set2_flag(&peer->flags[1], ast_true(v->value), SIP_PAGE2_REGISTERTRYING);
+ } else if (!strcasecmp(v->name, "autoframing")) {
+@@ -23128,7 +24253,7 @@
+ if (((peer->socket.type != peer->default_outbound_transport) && (peer->expire == -1)) ||
+ !(peer->socket.type & peer->transports) || !(peer->socket.type)) {
+
+- set_peer_transport(peer, peer->default_outbound_transport);
++ set_socket_transport(&peer->socket, peer->default_outbound_transport);
+ }
+
+ if (fullcontact->used > 0) {
+@@ -23308,21 +24433,21 @@
+ /* First, destroy all outstanding registry calls */
+ /* This is needed, since otherwise active registry entries will not be destroyed */
+ ASTOBJ_CONTAINER_TRAVERSE(&regl, 1, do { /* regl is locked */
+-
+- /* avoid a deadlock in the unlink_all call, if iterator->call's (a dialog) registry entry
+- is this registry entry. In other words, if the dialog we are pointing to points back to
+- us, then if we get a lock on this object, and try to UNREF it, we will deadlock, because
+- we already ... NO. This is not the problem. */
++
+ ASTOBJ_RDLOCK(iterator); /* now regl is locked, and the object is also locked */
+ if (iterator->call) {
+ ast_debug(3, "Destroying active SIP dialog for registry %s@%s\n", iterator->username, iterator->hostname);
+ /* This will also remove references to the registry */
+ dialog_unlink_all(iterator->call, TRUE, TRUE);
+ iterator->call = dialog_unref(iterator->call, "remove iterator->call from registry traversal");
+- /* iterator->call = sip_destroy(iterator->call); */
+ }
++ if (iterator->expire > -1) {
++ AST_SCHED_DEL_UNREF(sched, iterator->expire, registry_unref(iterator, "reg ptr unref from reload config"));
++ }
++ if (iterator->timeout > -1) {
++ AST_SCHED_DEL_UNREF(sched, iterator->timeout, registry_unref(iterator, "reg ptr unref from reload config"));
++ }
+ ASTOBJ_UNLOCK(iterator);
+-
+ } while(0));
+
+ /* Then, actually destroy users and registry */
+@@ -23330,20 +24455,21 @@
+ ast_debug(4, "--------------- Done destroying registry list\n");
+ ao2_t_callback(peers, OBJ_NODATA, peer_markall_func, NULL, "callback to mark all peers");
+ }
+-
++
+ /* Reset certificate handling for TLS sessions */
+ if (reason != CHANNEL_MODULE_LOAD) {
+ ast_free(default_tls_cfg.certfile);
++ ast_free(default_tls_cfg.pvtfile);
+ ast_free(default_tls_cfg.cipher);
+ ast_free(default_tls_cfg.cafile);
+ ast_free(default_tls_cfg.capath);
+ }
+ default_tls_cfg.certfile = ast_strdup(AST_CERTFILE); /*XXX Not sure if this is useful */
++ default_tls_cfg.pvtfile = ast_strdup("");
+ default_tls_cfg.cipher = ast_strdup("");
+ default_tls_cfg.cafile = ast_strdup("");
+ default_tls_cfg.capath = ast_strdup("");
+
+-
+ /* Initialize copy of current global_regcontext for later use in removing stale contexts */
+ ast_copy_string(oldcontexts, global_regcontext, sizeof(oldcontexts));
+ oldregcontext = oldcontexts;
+@@ -23403,6 +24529,7 @@
+ ast_copy_string(default_notifymime, DEFAULT_NOTIFYMIME, sizeof(default_notifymime));
+ ast_copy_string(sip_cfg.realm, S_OR(ast_config_AST_SYSTEM_NAME, DEFAULT_REALM), sizeof(sip_cfg.realm));
+ ast_copy_string(default_callerid, DEFAULT_CALLERID, sizeof(default_callerid));
++ ast_copy_string(default_mwi_from, DEFAULT_MWI_FROM, sizeof(default_mwi_from));
+ sip_cfg.compactheaders = DEFAULT_COMPACTHEADERS;
+ global_reg_timeout = DEFAULT_REGISTRATION_TIMEOUT;
+ global_regattempts_max = 0;
+@@ -23444,6 +24571,7 @@
+ ast_set_flag(&global_flags[0], SIP_DTMF_RFC2833); /*!< Default DTMF setting: RFC2833 */
+ ast_set_flag(&global_flags[0], SIP_NAT_RFC3581); /*!< NAT support if requested by device with rport */
+ ast_set_flag(&global_flags[0], SIP_CAN_REINVITE); /*!< Allow re-invites */
++ ast_copy_string(default_engine, DEFAULT_ENGINE, sizeof(default_engine));
+
+ /* Debugging settings, always default to off */
+ dumphistory = FALSE;
+@@ -23478,13 +24606,18 @@
+ if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
+ continue;
+
++ /* handle tls conf */
++ if (!ast_tls_read_conf(&default_tls_cfg, &sip_tls_desc, v->name, v->value)) {
++ continue;
++ }
++
+ if (!strcasecmp(v->name, "context")) {
+ ast_copy_string(sip_cfg.default_context, v->value, sizeof(sip_cfg.default_context));
+ } else if (!strcasecmp(v->name, "subscribecontext")) {
+ ast_copy_string(sip_cfg.default_subscribecontext, v->value, sizeof(sip_cfg.default_subscribecontext));
+- } else if (!strcasecmp(v->name, "callcounter")) {
++ } else if (!strcasecmp(v->name, "callcounter")) {
+ global_callcounter = ast_true(v->value) ? 1 : 0;
+- } else if (!strcasecmp(v->name, "allowguest")) {
++ } else if (!strcasecmp(v->name, "allowguest")) {
+ sip_cfg.allowguest = ast_true(v->value) ? 1 : 0;
+ } else if (!strcasecmp(v->name, "realm")) {
+ ast_copy_string(sip_cfg.realm, v->value, sizeof(sip_cfg.realm));
+@@ -23502,7 +24635,7 @@
+ } else if (!strcasecmp(v->name, "allowtransfer")) {
+ sip_cfg.allowtransfer = ast_true(v->value) ? TRANSFER_OPENFORALL : TRANSFER_CLOSED;
+ } else if (!strcasecmp(v->name, "rtcachefriends")) {
+- ast_set2_flag(&global_flags[1], ast_true(v->value), SIP_PAGE2_RTCACHEFRIENDS);
++ ast_set2_flag(&global_flags[1], ast_true(v->value), SIP_PAGE2_RTCACHEFRIENDS);
+ } else if (!strcasecmp(v->name, "rtsavesysname")) {
+ sip_cfg.rtsave_sysname = ast_true(v->value);
+ } else if (!strcasecmp(v->name, "rtupdate")) {
+@@ -23525,7 +24658,7 @@
+ while ((trans = strsep(&val, ","))) {
+ trans = ast_skip_blanks(trans);
+
+- if (!strncasecmp(trans, "udp", 3))
++ if (!strncasecmp(trans, "udp", 3))
+ default_transports |= SIP_TRANSPORT_UDP;
+ else if (!strncasecmp(trans, "tcp", 3))
+ default_transports |= SIP_TRANSPORT_TCP;
+@@ -23546,28 +24679,6 @@
+ ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of %s\n", v->name, v->value, v->lineno, config);
+ sip_tcp_desc.local_address.sin_family = family;
+ ast_debug(2, "Setting TCP socket address to %s\n", v->value);
+- } else if (!strcasecmp(v->name, "tlsenable")) {
+- default_tls_cfg.enabled = ast_true(v->value) ? TRUE : FALSE;
+- sip_tls_desc.local_address.sin_family = AF_INET;
+- } else if (!strcasecmp(v->name, "tlscertfile")) {
+- ast_free(default_tls_cfg.certfile);
+- default_tls_cfg.certfile = ast_strdup(v->value);
+- } else if (!strcasecmp(v->name, "tlscipher")) {
+- ast_free(default_tls_cfg.cipher);
+- default_tls_cfg.cipher = ast_strdup(v->value);
+- } else if (!strcasecmp(v->name, "tlscafile")) {
+- ast_free(default_tls_cfg.cafile);
+- default_tls_cfg.cafile = ast_strdup(v->value);
+- } else if (!strcasecmp(v->name, "tlscapath")) {
+- ast_free(default_tls_cfg.capath);
+- default_tls_cfg.capath = ast_strdup(v->value);
+- } else if (!strcasecmp(v->name, "tlsverifyclient")) {
+- ast_set2_flag(&default_tls_cfg.flags, ast_true(v->value), AST_SSL_VERIFY_CLIENT);
+- } else if (!strcasecmp(v->name, "tlsdontverifyserver")) {
+- ast_set2_flag(&default_tls_cfg.flags, ast_true(v->value), AST_SSL_DONT_VERIFY_SERVER);
+- } else if (!strcasecmp(v->name, "tlsbindaddr")) {
+- if (ast_parse_arg(v->value, PARSE_INADDR, &sip_tls_desc.local_address))
+- ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of %s\n", v->name, v->value, v->lineno, config);
+ } else if (!strcasecmp(v->name, "dynamic_exclude_static") || !strcasecmp(v->name, "dynamic_excludes_static")) {
+ global_dynamic_exclude_static = ast_true(v->value);
+ } else if (!strcasecmp(v->name, "contactpermit") || !strcasecmp(v->name, "contactdeny")) {
+@@ -23584,7 +24695,7 @@
+ i = 0;
+ ast_set2_flag(&global_flags[1], i || ast_true(v->value), SIP_PAGE2_RTAUTOCLEAR);
+ } else if (!strcasecmp(v->name, "usereqphone")) {
+- ast_set2_flag(&global_flags[0], ast_true(v->value), SIP_USEREQPHONE);
++ ast_set2_flag(&global_flags[0], ast_true(v->value), SIP_USEREQPHONE);
+ } else if (!strcasecmp(v->name, "relaxdtmf")) {
+ global_relaxdtmf = ast_true(v->value);
+ } else if (!strcasecmp(v->name, "vmexten")) {
+@@ -23643,6 +24754,8 @@
+ sip_cfg.regextenonqualify = ast_true(v->value);
+ } else if (!strcasecmp(v->name, "callerid")) {
+ ast_copy_string(default_callerid, v->value, sizeof(default_callerid));
++ } else if (!strcasecmp(v->name, "mwi_from")) {
++ ast_copy_string(default_mwi_from, v->value, sizeof(default_mwi_from));
+ } else if (!strcasecmp(v->name, "fromdomain")) {
+ ast_copy_string(default_fromdomain, v->value, sizeof(default_fromdomain));
+ } else if (!strcasecmp(v->name, "outboundproxy")) {
+@@ -23758,6 +24871,8 @@
+ int error = ast_parse_allow_disallow(&default_prefs, &global_capability, v->value, FALSE);
+ if (error)
+ ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value);
++ } else if (!strcasecmp(v->name, "preferred_codec_only")) {
++ ast_set2_flag(&global_flags[1], ast_true(v->value), SIP_PAGE2_PREFERRED_CODEC);
+ } else if (!strcasecmp(v->name, "autoframing")) {
+ global_autoframing = ast_true(v->value);
+ } else if (!strcasecmp(v->name, "allowexternaldomains")) {
+@@ -24182,165 +25297,183 @@
+ return 0;
+ }
+
+-/*! \brief Returns null if we can't reinvite audio (part of RTP interface) */
+-static enum ast_rtp_get_result sip_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
++static enum ast_rtp_glue_result sip_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
+ {
+- struct sip_pvt *p = NULL;
+- enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL;
++ struct sip_pvt *p = NULL;
++ enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_LOCAL;
+
+- if (!(p = chan->tech_pvt))
+- return AST_RTP_GET_FAILED;
+-
+- sip_pvt_lock(p);
+- if (!(p->rtp)) {
+- sip_pvt_unlock(p);
+- return AST_RTP_GET_FAILED;
++ if (!(p = chan->tech_pvt)) {
++ return AST_RTP_GLUE_RESULT_FORBID;
+ }
+
+- *rtp = p->rtp;
++ sip_pvt_lock(p);
++ if (!(p->rtp)) {
++ sip_pvt_unlock(p);
++ return AST_RTP_GLUE_RESULT_FORBID;
++ }
+
+- if (ast_rtp_getnat(*rtp) && !ast_test_flag(&p->flags[0], SIP_CAN_REINVITE_NAT))
+- res = AST_RTP_TRY_PARTIAL;
+- else if (ast_test_flag(&p->flags[0], SIP_CAN_REINVITE))
+- res = AST_RTP_TRY_NATIVE;
+- else if (ast_test_flag(&global_jbconf, AST_JB_FORCED))
+- res = AST_RTP_GET_FAILED;
++ ao2_ref(p->rtp, +1);
++ *instance = p->rtp;
+
+- sip_pvt_unlock(p);
++ if (ast_test_flag(&p->flags[0], SIP_CAN_REINVITE | SIP_CAN_REINVITE_NAT)) {
++ res = AST_RTP_GLUE_RESULT_REMOTE;
++ } else if (ast_test_flag(&global_jbconf, AST_JB_FORCED)) {
++ res = AST_RTP_GLUE_RESULT_FORBID;
++ }
+
+- return res;
++ sip_pvt_unlock(p);
++
++ return res;
+ }
+
+-/*! \brief Returns null if we can't reinvite video (part of RTP interface) */
+-static enum ast_rtp_get_result sip_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
++static enum ast_rtp_glue_result sip_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
+ {
+ struct sip_pvt *p = NULL;
+- enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL;
+-
+- if (!(p = chan->tech_pvt))
+- return AST_RTP_GET_FAILED;
++ enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_FORBID;
+
++ if (!(p = chan->tech_pvt)) {
++ return AST_RTP_GLUE_RESULT_FORBID;
++ }
++
+ sip_pvt_lock(p);
+ if (!(p->vrtp)) {
+ sip_pvt_unlock(p);
+- return AST_RTP_GET_FAILED;
++ return AST_RTP_GLUE_RESULT_FORBID;
+ }
+
+- *rtp = p->vrtp;
++ ao2_ref(p->vrtp, +1);
++ *instance = p->vrtp;
+
+- if (ast_test_flag(&p->flags[0], SIP_CAN_REINVITE))
+- res = AST_RTP_TRY_NATIVE;
++ if (ast_test_flag(&p->flags[0], SIP_CAN_REINVITE)) {
++ res = AST_RTP_GLUE_RESULT_REMOTE;
++ }
+
+ sip_pvt_unlock(p);
+
+ return res;
+ }
+
+-/*! \brief Returns null if we can't reinvite text (part of RTP interface) */
+-static enum ast_rtp_get_result sip_get_trtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
++static enum ast_rtp_glue_result sip_get_trtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
+ {
+- struct sip_pvt *p = NULL;
+- enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL;
+-
+- if (!(p = chan->tech_pvt))
+- return AST_RTP_GET_FAILED;
++ struct sip_pvt *p = NULL;
++ enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_FORBID;
+
+- sip_pvt_lock(p);
+- if (!(p->trtp)) {
+- sip_pvt_unlock(p);
+- return AST_RTP_GET_FAILED;
+- }
++ if (!(p = chan->tech_pvt)) {
++ return AST_RTP_GLUE_RESULT_FORBID;
++ }
+
+- *rtp = p->trtp;
++ sip_pvt_lock(p);
++ if (!(p->trtp)) {
++ sip_pvt_unlock(p);
++ return AST_RTP_GLUE_RESULT_FORBID;
++ }
+
+- if (ast_test_flag(&p->flags[0], SIP_CAN_REINVITE))
+- res = AST_RTP_TRY_NATIVE;
++ ao2_ref(p->trtp, +1);
++ *instance = p->trtp;
+
+- sip_pvt_unlock(p);
++ if (ast_test_flag(&p->flags[0], SIP_CAN_REINVITE)) {
++ res = AST_RTP_GLUE_RESULT_REMOTE;
++ }
+
+- return res;
++ sip_pvt_unlock(p);
++
++ return res;
+ }
+
+-/*! \brief Set the RTP peer for this call */
+-static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active)
++static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *instance, struct ast_rtp_instance *vinstance, struct ast_rtp_instance *tinstance, int codecs, int nat_active)
+ {
+- struct sip_pvt *p;
+- int changed = 0;
++ struct sip_pvt *p;
++ int changed = 0;
+
+- p = chan->tech_pvt;
+- if (!p)
+- return -1;
++ p = chan->tech_pvt;
++ if (!p)
++ return -1;
+
+ /* Disable early RTP bridge */
+ if (!ast_bridged_channel(chan) && !sip_cfg.directrtpsetup) /* We are in early state */
+ return 0;
+
+- sip_pvt_lock(p);
+- if (p->alreadygone) {
+- /* If we're destroyed, don't bother */
+- sip_pvt_unlock(p);
+- return 0;
+- }
++ sip_pvt_lock(p);
++ if (p->alreadygone) {
++ /* If we're destroyed, don't bother */
++ sip_pvt_unlock(p);
++ return 0;
++ }
+
+- /* if this peer cannot handle reinvites of the media stream to devices
+- that are known to be behind a NAT, then stop the process now
++ /* if this peer cannot handle reinvites of the media stream to devices
++ that are known to be behind a NAT, then stop the process now
+ */
+- if (nat_active && !ast_test_flag(&p->flags[0], SIP_CAN_REINVITE_NAT)) {
+- sip_pvt_unlock(p);
+- return 0;
+- }
++ if (nat_active && !ast_test_flag(&p->flags[0], SIP_CAN_REINVITE_NAT)) {
++ sip_pvt_unlock(p);
++ return 0;
++ }
+
+- if (rtp) {
+- changed |= ast_rtp_get_peer(rtp, &p->redirip);
+- } else if (p->redirip.sin_addr.s_addr || ntohs(p->redirip.sin_port) != 0) {
+- memset(&p->redirip, 0, sizeof(p->redirip));
+- changed = 1;
+- }
+- if (vrtp) {
+- changed |= ast_rtp_get_peer(vrtp, &p->vredirip);
+- } else if (p->vredirip.sin_addr.s_addr || ntohs(p->vredirip.sin_port) != 0) {
+- memset(&p->vredirip, 0, sizeof(p->vredirip));
+- changed = 1;
+- }
+- if (trtp) {
+- changed |= ast_rtp_get_peer(trtp, &p->tredirip);
+- } else if (p->tredirip.sin_addr.s_addr || ntohs(p->tredirip.sin_port) != 0) {
+- memset(&p->tredirip, 0, sizeof(p->tredirip));
+- changed = 1;
+- }
+- if (codecs && (p->redircodecs != codecs)) {
+- p->redircodecs = codecs;
+- changed = 1;
+- }
+- if (changed && !ast_test_flag(&p->flags[0], SIP_GOTREFER) && !ast_test_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER)) {
+- if (chan->_state != AST_STATE_UP) { /* We are in early state */
+- if (p->do_history)
+- append_history(p, "ExtInv", "Initial invite sent with remote bridge proposal.");
+- ast_debug(1, "Early remote bridge setting SIP '%s' - Sending media to %s\n", p->callid, ast_inet_ntoa(rtp ? p->redirip.sin_addr : p->ourip.sin_addr));
+- } else if (!p->pendinginvite) { /* We are up, and have no outstanding invite */
+- ast_debug(3, "Sending reinvite on SIP '%s' - It's audio soon redirected to IP %s\n", p->callid, ast_inet_ntoa(rtp ? p->redirip.sin_addr : p->ourip.sin_addr));
+- transmit_reinvite_with_sdp(p, FALSE, FALSE);
+- } else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) {
+- ast_debug(3, "Deferring reinvite on SIP '%s' - It's audio will be redirected to IP %s\n", p->callid, ast_inet_ntoa(rtp ? p->redirip.sin_addr : p->ourip.sin_addr));
+- /* We have a pending Invite. Send re-invite when we're done with the invite */
+- ast_set_flag(&p->flags[0], SIP_NEEDREINVITE);
+- }
+- }
+- /* Reset lastrtprx timer */
+- p->lastrtprx = p->lastrtptx = time(NULL);
+- sip_pvt_unlock(p);
+- return 0;
++ if (instance) {
++ changed |= ast_rtp_instance_get_remote_address(instance, &p->redirip);
++ } else if (p->redirip.sin_addr.s_addr || ntohs(p->redirip.sin_port) != 0) {
++ memset(&p->redirip, 0, sizeof(p->redirip));
++ changed = 1;
++ }
++ if (vinstance) {
++ changed |= ast_rtp_instance_get_remote_address(vinstance, &p->vredirip);
++ } else if (p->vredirip.sin_addr.s_addr || ntohs(p->vredirip.sin_port) != 0) {
++ memset(&p->vredirip, 0, sizeof(p->vredirip));
++ changed = 1;
++ }
++ if (tinstance) {
++ changed |= ast_rtp_instance_get_remote_address(tinstance, &p->tredirip);
++ } else if (p->tredirip.sin_addr.s_addr || ntohs(p->tredirip.sin_port) != 0) {
++ memset(&p->tredirip, 0, sizeof(p->tredirip));
++ changed = 1;
++ }
++ if (codecs && (p->redircodecs != codecs)) {
++ p->redircodecs = codecs;
++ changed = 1;
++ }
++ if (changed && !ast_test_flag(&p->flags[0], SIP_GOTREFER) && !ast_test_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER)) {
++ if (chan->_state != AST_STATE_UP) { /* We are in early state */
++ if (p->do_history)
++ append_history(p, "ExtInv", "Initial invite sent with remote bridge proposal.");
++ ast_debug(1, "Early remote bridge setting SIP '%s' - Sending media to %s\n", p->callid, ast_inet_ntoa(instance ? p->redirip.sin_addr : p->ourip.sin_addr));
++ } else if (!p->pendinginvite) { /* We are up, and have no outstanding invite */
++ ast_debug(3, "Sending reinvite on SIP '%s' - It's audio soon redirected to IP %s\n", p->callid, ast_inet_ntoa(instance ? p->redirip.sin_addr : p->ourip.sin_addr));
++ transmit_reinvite_with_sdp(p, FALSE, FALSE);
++ } else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) {
++ ast_debug(3, "Deferring reinvite on SIP '%s' - It's audio will be redirected to IP %s\n", p->callid, ast_inet_ntoa(instance ? p->redirip.sin_addr : p->ourip.sin_addr));
++ /* We have a pending Invite. Send re-invite when we're done with the invite */
++ ast_set_flag(&p->flags[0], SIP_NEEDREINVITE);
++ }
++ }
++ /* Reset lastrtprx timer */
++ p->lastrtprx = p->lastrtptx = time(NULL);
++ sip_pvt_unlock(p);
++ return 0;
+ }
+
++static int sip_get_codec(struct ast_channel *chan)
++{
++ struct sip_pvt *p = chan->tech_pvt;
++ return p->peercapability ? p->peercapability : p->capability;
++}
++
++static struct ast_rtp_glue sip_rtp_glue = {
++ .type = "SIP",
++ .get_rtp_info = sip_get_rtp_peer,
++ .get_vrtp_info = sip_get_vrtp_peer,
++ .get_trtp_info = sip_get_trtp_peer,
++ .update_peer = sip_set_rtp_peer,
++ .get_codec = sip_get_codec,
++};
++
+ static char *app_dtmfmode = "SIPDtmfMode";
+ static char *app_sipaddheader = "SIPAddHeader";
+ static char *app_sipremoveheader = "SIPRemoveHeader";
+
+ /*! \brief Set the DTMFmode for an outbound SIP call (application) */
+-static int sip_dtmfmode(struct ast_channel *chan, void *data)
++static int sip_dtmfmode(struct ast_channel *chan, const char *data)
+ {
+ struct sip_pvt *p;
+- char *mode = data;
++ const char *mode = data;
+
+ if (!data) {
+ ast_log(LOG_WARNING, "This application requires the argument: info, inband, rfc2833\n");
+@@ -24377,17 +25510,12 @@
+ } else
+ ast_log(LOG_WARNING, "I don't know about this dtmf mode: %s\n", mode);
+ if (p->rtp)
+- ast_rtp_setdtmf(p->rtp, ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
+- if (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) {
+- if (!p->vad) {
+- p->vad = ast_dsp_new();
+- ast_dsp_set_features(p->vad, DSP_FEATURE_DIGIT_DETECT);
+- }
++ ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_DTMF, ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
++ if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) ||
++ (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) {
++ enable_digit_detect(p);
+ } else {
+- if (p->vad) {
+- ast_dsp_free(p->vad);
+- p->vad = NULL;
+- }
++ disable_digit_detect(p);
+ }
+ sip_pvt_unlock(p);
+ ast_channel_unlock(chan);
+@@ -24395,12 +25523,13 @@
+ }
+
+ /*! \brief Add a SIP header to an outbound INVITE */
+-static int sip_addheader(struct ast_channel *chan, void *data)
++static int sip_addheader(struct ast_channel *chan, const char *data)
+ {
+ int no = 0;
+ int ok = FALSE;
+ char varbuf[30];
+- char *inbuf = data, *subbuf;
++ const char *inbuf = data;
++ char *subbuf;
+
+ if (ast_strlen_zero(inbuf)) {
+ ast_log(LOG_WARNING, "This application requires the argument: Header\n");
+@@ -24434,7 +25563,7 @@
+ }
+
+ /*! \brief Remove SIP headers added previously with SipAddHeader application */
+-static int sip_removeheader(struct ast_channel *chan, void *data)
++static int sip_removeheader(struct ast_channel *chan, const char *data)
+ {
+ struct ast_var_t *newvariable;
+ struct varshead *headp;
+@@ -24521,17 +25650,15 @@
+
+ sip_scheddestroy(p, SIP_TRANS_TIMEOUT); /* Make sure we stop send this reply. */
+ sip_alreadygone(p);
++
++ if (p->owner) {
++ enum ast_control_transfer message = AST_TRANSFER_SUCCESS;
++ ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message));
++ }
+ /* hangup here */
+ return 0;
+ }
+
+-/*! \brief Return SIP UA's codec (part of the RTP interface) */
+-static int sip_get_codec(struct ast_channel *chan)
+-{
+- struct sip_pvt *p = chan->tech_pvt;
+- return p->jointcapability ? p->jointcapability : p->capability;
+-}
+-
+ /*! \brief Send a poke to all known peers */
+ static void sip_poke_all_peers(void)
+ {
+@@ -24739,12 +25866,12 @@
+ /* Register all CLI functions for SIP */
+ ast_cli_register_multiple(cli_sip, ARRAY_LEN(cli_sip));
+
+- /* Tell the RTP subdriver that we're here */
+- ast_rtp_proto_register(&sip_rtp);
+-
+ /* Tell the UDPTL subdriver that we're here */
+ ast_udptl_proto_register(&sip_udptl);
+
++ /* Tell the RTP engine about our RTP glue */
++ ast_rtp_glue_register(&sip_rtp_glue);
++
+ /* Register dialplan applications */
+ ast_register_application_xml(app_dtmfmode, sip_dtmfmode);
+ ast_register_application_xml(app_sipaddheader, sip_addheader);
+@@ -24757,16 +25884,11 @@
+ ast_custom_function_register(&checksipdomain_function);
+
+ /* Register manager commands */
+- ast_manager_register2("SIPpeers", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_sip_show_peers,
+- "List SIP peers (text format)", mandescr_show_peers);
+- ast_manager_register2("SIPshowpeer", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_sip_show_peer,
+- "Show SIP peer (text format)", mandescr_show_peer);
+- ast_manager_register2("SIPqualifypeer", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_sip_qualify_peer,
+- "Show SIP peer (text format)", mandescr_show_peer); /*! \todo Fix this XXX This must be all wrong XXXX */
+- ast_manager_register2("SIPshowregistry", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_show_registry,
+- "Show SIP registrations (text format)", mandescr_show_registry);
+- ast_manager_register2("SIPnotify", EVENT_FLAG_SYSTEM, manager_sipnotify,
+- "Send a SIP notify", mandescr_sipnotify);
++ ast_manager_register_xml("SIPpeers", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_sip_show_peers);
++ ast_manager_register_xml("SIPshowpeer", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_sip_show_peer);
++ ast_manager_register_xml("SIPqualifypeer", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_sip_qualify_peer);
++ ast_manager_register_xml("SIPshowregistry", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_show_registry);
++ ast_manager_register_xml("SIPnotify", EVENT_FLAG_SYSTEM, manager_sipnotify);
+ sip_poke_all_peers();
+ sip_send_all_registers();
+ sip_send_all_mwi_subscriptions();
+@@ -24816,12 +25938,12 @@
+ /* Unregister CLI commands */
+ ast_cli_unregister_multiple(cli_sip, ARRAY_LEN(cli_sip));
+
+- /* Disconnect from the RTP subsystem */
+- ast_rtp_proto_unregister(&sip_rtp);
+-
+ /* Disconnect from UDPTL */
+ ast_udptl_proto_unregister(&sip_udptl);
+
++ /* Disconnect from RTP engine */
++ ast_rtp_glue_unregister(&sip_rtp_glue);
++
+ /* Unregister AMI actions */
+ ast_manager_unregister("SIPpeers");
+ ast_manager_unregister("SIPshowpeer");
+@@ -24880,6 +26002,8 @@
+
+ if (default_tls_cfg.certfile)
+ ast_free(default_tls_cfg.certfile);
++ if (default_tls_cfg.pvtfile)
++ ast_free(default_tls_cfg.pvtfile);
+ if (default_tls_cfg.cipher)
+ ast_free(default_tls_cfg.cipher);
+ if (default_tls_cfg.cafile)
+Index: channels/chan_agent.c
+===================================================================
+--- a/channels/chan_agent.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/channels/chan_agent.c (.../trunk) (revision 202568)
+@@ -52,7 +52,6 @@
+ #include "asterisk/pbx.h"
+ #include "asterisk/sched.h"
+ #include "asterisk/io.h"
+-#include "asterisk/rtp.h"
+ #include "asterisk/acl.h"
+ #include "asterisk/callerid.h"
+ #include "asterisk/file.h"
+@@ -157,9 +156,6 @@
+ <enum name="mohclass">
+ <para>MusicOnHold class</para>
+ </enum>
+- <enum name="exten">
+- <para>The callback extension for the Agent (AgentCallbackLogin)</para>
+- </enum>
+ <enum name="channel">
+ <para>The name of the active channel for the Agent (AgentLogin)</para>
+ </enum>
+@@ -168,6 +164,34 @@
+ </syntax>
+ <description />
+ </function>
++ <manager name="Agents" language="en_US">
++ <synopsis>
++ Lists agents and their status.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ </syntax>
++ <description>
++ <para>Will list info about all possible agents.</para>
++ </description>
++ </manager>
++ <manager name="AgentLogoff" language="en_US">
++ <synopsis>
++ Sets an agent as no longer logged in.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Agent" required="true">
++ <para>Agent ID of the agent to log off.</para>
++ </parameter>
++ <parameter name="Soft">
++ <para>Set to <literal>true</literal> to not hangup existing calls.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Sets an agent as no longer logged in.</para>
++ </description>
++ </manager>
+ ***/
+
+ static const char tdesc[] = "Call Agent Proxy Channel";
+@@ -176,16 +200,6 @@
+ static const char app[] = "AgentLogin";
+ static const char app3[] = "AgentMonitorOutgoing";
+
+-static const char mandescr_agents[] =
+-"Description: Will list info about all possible agents.\n"
+-"Variables: NONE\n";
+-
+-static const char mandescr_agent_logoff[] =
+-"Description: Sets an agent as no longer logged in.\n"
+-"Variables: (Names marked with * are required)\n"
+-" *Agent: Agent ID of the agent to log off\n"
+-" Soft: Set to 'true' to not hangup existing calls\n";
+-
+ static char moh[80] = "default";
+
+ #define AST_MAX_AGENT 80 /*!< Agent ID or Password max length */
+@@ -195,9 +209,6 @@
+ static const char pa_family[] = "Agents"; /*!< Persistent Agents astdb family */
+ #define PA_MAX_LEN 2048 /*!< The maximum length of each persistent member agent database entry */
+
+-static int persistent_agents = 0; /*!< queues.conf [general] option */
+-static void dump_agents(void);
+-
+ #define DEFAULT_ACCEPTDTMF '#'
+ #define DEFAULT_ENDDTMF '*'
+
+@@ -258,7 +269,6 @@
+ ast_cond_t app_complete_cond;
+ volatile int app_sleep_cond; /**< Sleep condition for the login app */
+ struct ast_channel *owner; /**< Agent */
+- char loginchan[80]; /**< channel they logged in from */
+ char logincallerid[80]; /**< Caller ID they had when they logged in */
+ struct ast_channel *chan; /**< Channel we use */
+ unsigned int flags; /**< Flags show if settings were applied with channel vars */
+@@ -302,7 +312,6 @@
+ /*--- Forward declarations */
+ static struct ast_channel *agent_request(const char *type, int format, void *data, int *cause);
+ static int agent_devicestate(void *data);
+-static void agent_logoff_maintenance(struct agent_pvt *p, char *loginchan, long logintime, const char *uniqueid, char *logcommand);
+ static int agent_digit_begin(struct ast_channel *ast, char digit);
+ static int agent_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
+ static int agent_call(struct ast_channel *ast, char *dest, int timeout);
+@@ -315,7 +324,6 @@
+ static int agent_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen);
+ static int agent_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
+ static struct ast_channel *agent_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge);
+-static void set_agentbycallerid(const char *callerid, const char *agent);
+ static char *complete_agent_logoff_cmd(const char *line, const char *word, int pos, int state);
+ static struct ast_channel* agent_get_base_channel(struct ast_channel *chan);
+ static int agent_set_base_channel(struct ast_channel *chan, struct ast_channel *base);
+@@ -464,8 +472,9 @@
+ /* Release ownership of the agent to other threads (presumably running the login app). */
+ p->app_lock_flag = 0;
+ ast_cond_signal(&p->app_complete_cond);
+- if (chan)
+- ast_channel_free(chan);
++ if (chan) {
++ chan = ast_channel_release(chan);
++ }
+ if (p->dead) {
+ ast_mutex_destroy(&p->lock);
+ ast_mutex_destroy(&p->app_lock);
+@@ -521,7 +530,6 @@
+ struct agent_pvt *p = ast->tech_pvt;
+ struct ast_frame *f = NULL;
+ static struct ast_frame answer_frame = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
+- const char *status;
+ int cur_time = time(NULL);
+ ast_mutex_lock(&p->lock);
+ CHECK_FORMATS(ast, p);
+@@ -535,33 +543,9 @@
+ } else
+ f = &ast_null_frame;
+ if (!f) {
+- /* If there's a channel, hang it up (if it's on a callback) make it NULL */
++ /* If there's a channel, make it NULL */
+ if (p->chan) {
+ p->chan->_bridge = NULL;
+- /* Note that we don't hangup if it's not a callback because Asterisk will do it
+- for us when the PBX instance that called login finishes */
+- if (!ast_strlen_zero(p->loginchan)) {
+- if (p->chan)
+- ast_debug(1, "Bridge on '%s' being cleared (2)\n", p->chan->name);
+- if (p->owner->_state != AST_STATE_UP) {
+- int howlong = cur_time - p->start;
+- if (p->autologoff && howlong >= p->autologoff) {
+- p->loginstart = 0;
+- ast_log(LOG_NOTICE, "Agent '%s' didn't answer/confirm within %d seconds (waited %d)\n", p->name, p->autologoff, howlong);
+- agent_logoff_maintenance(p, p->loginchan, (cur_time = p->loginstart), ast->uniqueid, "Autologoff");
+- }
+- }
+- status = pbx_builtin_getvar_helper(p->chan, "CHANLOCALSTATUS");
+- if (autologoffunavail && status && !strcasecmp(status, "CHANUNAVAIL")) {
+- long logintime = cur_time - p->loginstart;
+- p->loginstart = 0;
+- ast_log(LOG_NOTICE, "Agent read: '%s' is not available now, auto logoff\n", p->name);
+- agent_logoff_maintenance(p, p->loginchan, logintime, ast->uniqueid, "Chanunavail");
+- }
+- ast_hangup(p->chan);
+- if (p->wrapuptime && p->acknowledged)
+- p->lastdisc = ast_tvadd(ast_tvnow(), ast_samp2tv(p->wrapuptime, 1000));
+- }
+ p->chan = NULL;
+ ast_devstate_changed(AST_DEVICE_UNAVAILABLE, "Agent/%s", p->agent);
+ p->acknowledged = 0;
+@@ -577,7 +561,6 @@
+ int howlong = cur_time - p->start;
+ if (p->autologoff && (howlong >= p->autologoff)) {
+ ast_log(LOG_NOTICE, "Agent '%s' didn't answer/confirm within %d seconds (waited %d)\n", p->name, p->autologoff, howlong);
+- agent_logoff_maintenance(p, p->loginchan, (cur_time - p->loginstart), ast->uniqueid, "Autologoff");
+ agent_logoff(p->agent, 0);
+ }
+ }
+@@ -766,17 +749,6 @@
+ if (newstate)
+ ast_setstate(ast, newstate);
+ return res;
+- } else if (!ast_strlen_zero(p->loginchan)) {
+- time(&p->start);
+- /* Call on this agent */
+- ast_verb(3, "outgoing agentcall, to agent '%s', on '%s'\n", p->agent, p->chan->name);
+- ast_set_callerid(p->chan,
+- ast->cid.cid_num, ast->cid.cid_name, NULL);
+- ast_channel_inherit_variables(ast, p->chan);
+- res = ast_call(p->chan, p->loginchan, 0);
+- CLEANUP(ast,p);
+- ast_mutex_unlock(&p->lock);
+- return res;
+ }
+ ast_verb(3, "agent_call, call to agent '%s' call on '%s'\n", p->agent, p->chan->name);
+ ast_debug(3, "Playing beep, lang '%s'\n", p->chan->language);
+@@ -805,9 +777,9 @@
+ }
+ if(!res) {
+ /* Call is immediately up, or might need ack */
+- if (p->ackcall > 1)
++ if (p->ackcall) {
+ newstate = AST_STATE_RINGING;
+- else {
++ } else {
+ newstate = AST_STATE_UP;
+ if (recordagentcalls)
+ agent_start_monitoring(ast, 0);
+@@ -822,19 +794,6 @@
+ return res;
+ }
+
+-/*! \brief store/clear the global variable that stores agentid based on the callerid */
+-static void set_agentbycallerid(const char *callerid, const char *agent)
+-{
+- char buf[AST_MAX_BUF];
+-
+- /* if there is no Caller ID, nothing to do */
+- if (ast_strlen_zero(callerid))
+- return;
+-
+- snprintf(buf, sizeof(buf), "%s_%s", GETAGENTBYCALLERID, callerid);
+- pbx_builtin_setvar_helper(NULL, buf, agent);
+-}
+-
+ /*! \brief return the channel or base channel if one exists. This function assumes the channel it is called on is already locked */
+ struct ast_channel* agent_get_base_channel(struct ast_channel *chan)
+ {
+@@ -873,7 +832,7 @@
+ {
+ struct agent_pvt *p = ast->tech_pvt;
+ int howlong = 0;
+- const char *status;
++
+ ast_mutex_lock(&p->lock);
+ p->owner = NULL;
+ ast->tech_pvt = NULL;
+@@ -898,37 +857,7 @@
+ if (p->chan) {
+ p->chan->_bridge = NULL;
+ /* If they're dead, go ahead and hang up on the agent now */
+- if (!ast_strlen_zero(p->loginchan)) {
+- /* Store last disconnect time */
+- if (p->wrapuptime)
+- p->lastdisc = ast_tvadd(ast_tvnow(), ast_samp2tv(p->wrapuptime, 1000));
+- else
+- p->lastdisc = ast_tv(0,0);
+- if (p->chan) {
+- status = pbx_builtin_getvar_helper(p->chan, "CHANLOCALSTATUS");
+- if (autologoffunavail && status && !strcasecmp(status, "CHANUNAVAIL")) {
+- long logintime = time(NULL) - p->loginstart;
+- p->loginstart = 0;
+- ast_log(LOG_NOTICE, "Agent hangup: '%s' is not available now, auto logoff\n", p->name);
+- agent_logoff_maintenance(p, p->loginchan, logintime, ast->uniqueid, "Chanunavail");
+- }
+- /* Recognize the hangup and pass it along immediately */
+- ast_hangup(p->chan);
+- p->chan = NULL;
+- ast_devstate_changed(AST_DEVICE_UNAVAILABLE, "Agent/%s", p->agent);
+- }
+- ast_debug(1, "Hungup, howlong is %d, autologoff is %d\n", howlong, p->autologoff);
+- if ((p->deferlogoff) || (howlong && p->autologoff && (howlong > p->autologoff))) {
+- long logintime = time(NULL) - p->loginstart;
+- p->loginstart = 0;
+- if (!p->deferlogoff)
+- ast_log(LOG_NOTICE, "Agent '%s' didn't answer/confirm within %d seconds (waited %d)\n", p->name, p->autologoff, howlong);
+- p->deferlogoff = 0;
+- agent_logoff_maintenance(p, p->loginchan, logintime, ast->uniqueid, "Autologoff");
+- if (persistent_agents)
+- dump_agents();
+- }
+- } else if (p->dead) {
++ if (p->dead) {
+ ast_channel_lock(p->chan);
+ ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT);
+ ast_channel_unlock(p->chan);
+@@ -944,10 +873,7 @@
+
+ /* Only register a device state change if the agent is still logged in */
+ if (!p->loginstart) {
+- p->loginchan[0] = '\0';
+ p->logincallerid[0] = '\0';
+- if (persistent_agents)
+- dump_agents();
+ } else {
+ ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Agent/%s", p->agent);
+ }
+@@ -975,10 +901,8 @@
+ ast_mutex_unlock(&p->lock);
+ }
+ /* Release ownership of the agent to other threads (presumably running the login app). */
+- if (ast_strlen_zero(p->loginchan)) {
+- p->app_lock_flag = 0;
+- ast_cond_signal(&p->app_complete_cond);
+- }
++ p->app_lock_flag = 0;
++ ast_cond_signal(&p->app_complete_cond);
+ }
+ return 0;
+ }
+@@ -1115,7 +1039,7 @@
+ alreadylocked = p->app_lock_flag;
+ p->app_lock_flag = 1;
+
+- if(ast_strlen_zero(p->loginchan) && alreadylocked) {
++ if (alreadylocked) {
+ if (p->chan) {
+ ast_queue_frame(p->chan, &ast_null_frame);
+ ast_mutex_unlock(&p->lock); /* For other thread to read the condition. */
+@@ -1126,24 +1050,12 @@
+ p->owner = NULL;
+ tmp->tech_pvt = NULL;
+ p->app_sleep_cond = 1;
+- ast_channel_free( tmp );
++ tmp = ast_channel_release(tmp);
+ ast_mutex_unlock(&p->lock); /* For other thread to read the condition. */
+ p->app_lock_flag = 0;
+ ast_cond_signal(&p->app_complete_cond);
+ return NULL;
+ }
+- } else if (!ast_strlen_zero(p->loginchan)) {
+- if (p->chan)
+- ast_queue_frame(p->chan, &ast_null_frame);
+- if (!p->chan) {
+- ast_log(LOG_WARNING, "Agent disconnected while we were connecting the call\n");
+- p->owner = NULL;
+- tmp->tech_pvt = NULL;
+- p->app_sleep_cond = 1;
+- ast_channel_free( tmp );
+- ast_mutex_unlock(&p->lock); /* For other thread to read the condition. */
+- return NULL;
+- }
+ }
+ if (p->chan)
+ ast_indicate(p->chan, AST_CONTROL_UNHOLD);
+@@ -1162,7 +1074,6 @@
+ struct ast_config *ucfg;
+ struct ast_variable *v;
+ struct agent_pvt *p;
+- const char *general_val;
+ const char *catname;
+ const char *hasagent;
+ int genhasagent;
+@@ -1205,8 +1116,6 @@
+ savecallsin[0] = '\0';
+
+ /* Read in [general] section for persistence */
+- if ((general_val = ast_variable_retrieve(cfg, "general", "persistentagents")))
+- persistent_agents = ast_true(general_val);
+ multiplelogin = ast_true(ast_variable_retrieve(cfg, "general", "multiplelogin"));
+
+ /* Read in the [agents] section */
+@@ -1222,12 +1131,9 @@
+ if (autologoff < 0)
+ autologoff = 0;
+ } else if (!strcasecmp(v->name, "ackcall")) {
+- if (!strcasecmp(v->value, "always"))
+- ackcall = 2;
+- else if (ast_true(v->value))
++ if (ast_true(v->value) || !strcasecmp(v->value, "always")) {
+ ackcall = 1;
+- else
+- ackcall = 0;
++ }
+ } else if (!strcasecmp(v->name, "endcall")) {
+ endcall = ast_true(v->value);
+ } else if (!strcasecmp(v->name, "acceptdtmf")) {
+@@ -1354,7 +1260,7 @@
+ if (needlock)
+ AST_LIST_UNLOCK(&agents);
+ if (parent && chan) {
+- if (newlyavailable->ackcall > 1) {
++ if (newlyavailable->ackcall) {
+ /* Don't do beep here */
+ res = 0;
+ } else {
+@@ -1452,8 +1358,7 @@
+ AST_LIST_LOCK(&agents);
+ AST_LIST_TRAVERSE(&agents, p, list) {
+ ast_mutex_lock(&p->lock);
+- if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent)) &&
+- ast_strlen_zero(p->loginchan)) {
++ if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent))) {
+ if (p->chan)
+ hasagent++;
+ now = ast_tvnow();
+@@ -1476,23 +1381,16 @@
+ AST_LIST_TRAVERSE(&agents, p, list) {
+ ast_mutex_lock(&p->lock);
+ if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent))) {
+- if (p->chan || !ast_strlen_zero(p->loginchan))
++ if (p->chan) {
+ hasagent++;
++ }
+ now = ast_tvnow();
+-#if 0
+- ast_log(LOG_NOTICE, "Time now: %ld, Time of lastdisc: %ld\n", now.tv_sec, p->lastdisc.tv_sec);
+-#endif
+ if (!p->lastdisc.tv_sec || (now.tv_sec >= p->lastdisc.tv_sec)) {
+ p->lastdisc = ast_tv(0, 0);
+ /* Agent must be registered, but not have any active call, and not be in a waiting state */
+ if (!p->owner && p->chan) {
+ /* Could still get a fixed agent */
+ 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);
+- if (p->chan)
+- chan = agent_new(p, AST_STATE_DOWN);
+ }
+ if (chan) {
+ ast_mutex_unlock(&p->lock);
+@@ -1545,7 +1443,6 @@
+ {
+ const char *id = astman_get_header(m,"ActionID");
+ char idText[256] = "";
+- char chanbuf[256];
+ struct agent_pvt *p;
+ char *username = NULL;
+ char *loginChan = NULL;
+@@ -1571,16 +1468,7 @@
+ /* Set a default status. It 'should' get changed. */
+ status = "AGENT_UNKNOWN";
+
+- if (!ast_strlen_zero(p->loginchan) && !p->chan) {
+- loginChan = p->loginchan;
+- talkingto = "n/a";
+- talkingtoChan = "n/a";
+- status = "AGENT_IDLE";
+- if (p->acknowledged) {
+- snprintf(chanbuf, sizeof(chanbuf), " %s (Confirmed)", p->loginchan);
+- loginChan = chanbuf;
+- }
+- } else if (p->chan) {
++ if (p->chan) {
+ loginChan = ast_strdupa(p->chan->name);
+ if (p->owner && p->owner->_bridge) {
+ talkingto = p->chan->cid.cid_num;
+@@ -1621,49 +1509,9 @@
+ return 0;
+ }
+
+-static void agent_logoff_maintenance(struct agent_pvt *p, char *loginchan, long logintime, const char *uniqueid, char *logcommand)
+-{
+- char *tmp = NULL;
+- char agent[AST_MAX_AGENT];
+-
+- if (!ast_strlen_zero(logcommand))
+- tmp = logcommand;
+- else
+- tmp = ast_strdupa("");
+-
+- snprintf(agent, sizeof(agent), "Agent/%s", p->agent);
+-
+- if (!ast_strlen_zero(uniqueid)) {
+- manager_event(EVENT_FLAG_AGENT, "Agentcallbacklogoff",
+- "Agent: %s\r\n"
+- "Reason: %s\r\n"
+- "Loginchan: %s\r\n"
+- "Logintime: %ld\r\n"
+- "Uniqueid: %s\r\n",
+- p->agent, tmp, loginchan, logintime, uniqueid);
+- } else {
+- manager_event(EVENT_FLAG_AGENT, "Agentcallbacklogoff",
+- "Agent: %s\r\n"
+- "Reason: %s\r\n"
+- "Loginchan: %s\r\n"
+- "Logintime: %ld\r\n",
+- p->agent, tmp, loginchan, logintime);
+- }
+-
+- ast_queue_log("NONE", ast_strlen_zero(uniqueid) ? "NONE" : uniqueid, agent, "AGENTCALLBACKLOGOFF", "%s|%ld|%s", loginchan, logintime, tmp);
+- set_agentbycallerid(p->logincallerid, NULL);
+- p->loginchan[0] ='\0';
+- p->logincallerid[0] = '\0';
+- ast_devstate_changed(AST_DEVICE_UNAVAILABLE, "Agent/%s", p->agent);
+- if (persistent_agents)
+- dump_agents();
+-
+-}
+-
+ static int agent_logoff(const char *agent, int soft)
+ {
+ struct agent_pvt *p;
+- long logintime;
+ int ret = -1; /* Return -1 if no agent if found */
+
+ AST_LIST_LOCK(&agents);
+@@ -1693,10 +1541,6 @@
+ ast_mutex_unlock(&p->lock);
+ } else
+ p->deferlogoff = 1;
+- } else {
+- logintime = time(NULL) - p->loginstart;
+- p->loginstart = 0;
+- agent_logoff_maintenance(p, p->loginchan, logintime, NULL, "CommandLogoff");
+ }
+ break;
+ }
+@@ -1709,7 +1553,7 @@
+ static char *agent_logoff_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+ {
+ int ret;
+- char *agent;
++ const char *agent;
+
+ switch (cmd) {
+ case CLI_INIT:
+@@ -1838,15 +1682,6 @@
+ else
+ strcpy(talkingto, " is idle");
+ online_agents++;
+- } else if (!ast_strlen_zero(p->loginchan)) {
+- if (ast_tvdiff_ms(ast_tvnow(), p->lastdisc) > 0 || !(p->lastdisc.tv_sec))
+- snprintf(location, sizeof(location) - 20, "available at '%s'", p->loginchan);
+- else
+- snprintf(location, sizeof(location) - 20, "wrapping up at '%s'", p->loginchan);
+- talkingto[0] = '\0';
+- online_agents++;
+- if (p->acknowledged)
+- strncat(location, " (Confirmed)", sizeof(location) - strlen(location) - 1);
+ } else {
+ strcpy(location, "not logged in");
+ talkingto[0] = '\0';
+@@ -1912,13 +1747,6 @@
+ strcpy(talkingto, " is idle");
+ agent_status = 1;
+ online_agents++;
+- } else if (!ast_strlen_zero(p->loginchan)) {
+- snprintf(location, sizeof(location) - 20, "available at '%s'", p->loginchan);
+- talkingto[0] = '\0';
+- agent_status = 1;
+- online_agents++;
+- if (p->acknowledged)
+- strncat(location, " (Confirmed)", sizeof(location) - strlen(location) - 1);
+ }
+ if (!ast_strlen_zero(p->moh))
+ snprintf(music, sizeof(music), " (musiconhold is '%s')", p->moh);
+@@ -1957,7 +1785,7 @@
+ * \returns
+ * \sa agentmonitoroutgoing_exec(), load_module().
+ */
+-static int login_exec(struct ast_channel *chan, void *data)
++static int login_exec(struct ast_channel *chan, const char *data)
+ {
+ int res=0;
+ int tries = 0;
+@@ -2066,12 +1894,11 @@
+
+ /* Set Channel Specific Agent Overrides */
+ if (!ast_strlen_zero(pbx_builtin_getvar_helper(chan, "AGENTACKCALL"))) {
+- if (!strcasecmp(pbx_builtin_getvar_helper(chan, "AGENTACKCALL"), "always"))
+- p->ackcall = 2;
+- else if (ast_true(pbx_builtin_getvar_helper(chan, "AGENTACKCALL")))
++ if (ast_true(pbx_builtin_getvar_helper(chan, "AGENTACKCALL"))) {
+ p->ackcall = 1;
+- else
++ } else {
+ p->ackcall = 0;
++ }
+ tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTACKCALL");
+ ast_verb(3, "Saw variable AGENTACKCALL=%s, setting ackcall to: %d for Agent '%s'.\n", tmpoptions, p->ackcall, p->agent);
+ ast_set_flag(p, AGENT_FLAG_ACKCALL);
+@@ -2117,7 +1944,6 @@
+ long logintime;
+ snprintf(agent, sizeof(agent), "Agent/%s", p->agent);
+
+- p->loginchan[0] = '\0';
+ p->logincallerid[0] = '\0';
+ p->acknowledged = 0;
+
+@@ -2160,10 +1986,11 @@
+ ast_getformatname(chan->readformat), ast_getformatname(chan->writeformat));
+ /* Login this channel and wait for it to go away */
+ p->chan = chan;
+- if (p->ackcall > 1)
++ if (p->ackcall) {
+ check_beep(p, 0);
+- else
++ } else {
+ check_availability(p, 0);
++ }
+ ast_mutex_unlock(&p->lock);
+ AST_LIST_UNLOCK(&agents);
+ ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Agent/%s", p->agent);
+@@ -2188,10 +2015,11 @@
+ ast_debug(1, "Wrapup time for %s expired!\n", p->agent);
+ p->lastdisc = ast_tv(0, 0);
+ ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Agent/%s", p->agent);
+- if (p->ackcall > 1)
++ if (p->ackcall) {
+ check_beep(p, 0);
+- else
++ } else {
+ check_availability(p, 0);
++ }
+ }
+ }
+ ast_mutex_unlock(&p->lock);
+@@ -2204,11 +2032,12 @@
+ ast_mutex_unlock(&p->app_lock);
+ ast_mutex_lock(&p->lock);
+ ast_mutex_unlock(&p->lock);
+- if (p->ackcall > 1)
++ if (p->ackcall) {
+ res = agent_ack_sleep(p);
+- else
++ } else {
+ res = ast_safe_sleep_conditional( chan, 1000, agent_cont_sleep, p );
+- if ((p->ackcall > 1) && (res == 1)) {
++ }
++ if (p->ackcall && (res == 1)) {
+ AST_LIST_LOCK(&agents);
+ ast_mutex_lock(&p->lock);
+ check_availability(p, 0);
+@@ -2285,7 +2114,7 @@
+ * \returns
+ * \sa login_exec(), load_module().
+ */
+-static int agentmonitoroutgoing_exec(struct ast_channel *chan, void *data)
++static int agentmonitoroutgoing_exec(struct ast_channel *chan, const char *data)
+ {
+ int exitifnoagentid = 0;
+ int nowarnings = 0;
+@@ -2335,84 +2164,6 @@
+ return 0;
+ }
+
+-/*!
+- * \brief Dump AgentCallbackLogin agents to the ASTdb database for persistence
+- */
+-static void dump_agents(void)
+-{
+- struct agent_pvt *cur_agent = NULL;
+- char buf[256];
+-
+- AST_LIST_TRAVERSE(&agents, cur_agent, list) {
+- if (cur_agent->chan)
+- continue;
+-
+- if (!ast_strlen_zero(cur_agent->loginchan)) {
+- snprintf(buf, sizeof(buf), "%s;%s", cur_agent->loginchan, cur_agent->logincallerid);
+- if (ast_db_put(pa_family, cur_agent->agent, buf))
+- ast_log(LOG_WARNING, "failed to create persistent entry in ASTdb for %s!\n", buf);
+- else
+- ast_debug(1, "Saved Agent: %s on %s\n", cur_agent->agent, cur_agent->loginchan);
+- } else {
+- /* Delete - no agent or there is an error */
+- ast_db_del(pa_family, cur_agent->agent);
+- }
+- }
+-}
+-
+-/*!
+- * \brief Reload the persistent agents from astdb.
+- */
+-static void reload_agents(void)
+-{
+- char *agent_num;
+- struct ast_db_entry *db_tree;
+- struct ast_db_entry *entry;
+- struct agent_pvt *cur_agent;
+- char agent_data[256];
+- char *parse;
+- char *agent_chan;
+- char *agent_callerid;
+-
+- db_tree = ast_db_gettree(pa_family, NULL);
+-
+- AST_LIST_LOCK(&agents);
+- for (entry = db_tree; entry; entry = entry->next) {
+- agent_num = entry->key + strlen(pa_family) + 2;
+- AST_LIST_TRAVERSE(&agents, cur_agent, list) {
+- ast_mutex_lock(&cur_agent->lock);
+- if (strcmp(agent_num, cur_agent->agent) == 0)
+- break;
+- ast_mutex_unlock(&cur_agent->lock);
+- }
+- if (!cur_agent) {
+- ast_db_del(pa_family, agent_num);
+- continue;
+- } else
+- ast_mutex_unlock(&cur_agent->lock);
+- if (!ast_db_get(pa_family, agent_num, agent_data, sizeof(agent_data)-1)) {
+- ast_debug(1, "Reload Agent from AstDB: %s on %s\n", cur_agent->agent, agent_data);
+- parse = agent_data;
+- agent_chan = strsep(&parse, ";");
+- agent_callerid = strsep(&parse, ";");
+- ast_copy_string(cur_agent->loginchan, agent_chan, sizeof(cur_agent->loginchan));
+- if (agent_callerid) {
+- ast_copy_string(cur_agent->logincallerid, agent_callerid, sizeof(cur_agent->logincallerid));
+- set_agentbycallerid(cur_agent->logincallerid, cur_agent->agent);
+- } else
+- cur_agent->logincallerid[0] = '\0';
+- if (cur_agent->loginstart == 0)
+- time(&cur_agent->loginstart);
+- ast_devstate_changed(AST_DEVICE_UNKNOWN, "Agent/%s", cur_agent->agent);
+- }
+- }
+- AST_LIST_UNLOCK(&agents);
+- if (db_tree) {
+- ast_log(LOG_NOTICE, "Agents successfully reloaded from database.\n");
+- ast_db_freetree(db_tree);
+- }
+-}
+-
+ /*! \brief Part of PBX channel interface */
+ static int agent_devicestate(void *data)
+ {
+@@ -2441,7 +2192,7 @@
+ } else {
+ if (res == AST_DEVICE_BUSY)
+ res = AST_DEVICE_INUSE;
+- if (p->chan || !ast_strlen_zero(p->loginchan)) {
++ if (p->chan) {
+ if (res == AST_DEVICE_INVALID)
+ res = AST_DEVICE_UNKNOWN;
+ } else if (res == AST_DEVICE_INVALID)
+@@ -2506,8 +2257,9 @@
+
+ if (!strcasecmp(args.item, "status")) {
+ char *status = "LOGGEDOUT";
+- if (agent->chan || !ast_strlen_zero(agent->loginchan))
+- status = "LOGGEDIN";
++ if (agent->chan) {
++ status = "LOGGEDIN";
++ }
+ ast_copy_string(buf, status, len);
+ } else if (!strcasecmp(args.item, "password"))
+ ast_copy_string(buf, agent->password, len);
+@@ -2522,15 +2274,16 @@
+ if (tmp)
+ *tmp = '\0';
+ }
+- } else if (!strcasecmp(args.item, "exten"))
+- ast_copy_string(buf, agent->loginchan, len);
++ } else if (!strcasecmp(args.item, "exten")) {
++ buf[0] = '\0';
++ }
+
+ AST_LIST_UNLOCK(&agents);
+
+ return 0;
+ }
+
+-struct ast_custom_function agent_function = {
++static struct ast_custom_function agent_function = {
+ .name = "AGENT",
+ .read = function_agent,
+ };
+@@ -2553,15 +2306,13 @@
+ /* Read in the config */
+ if (!read_agent_config(0))
+ return AST_MODULE_LOAD_DECLINE;
+- if (persistent_agents)
+- reload_agents();
+ /* Dialplan applications */
+ ast_register_application_xml(app, login_exec);
+ ast_register_application_xml(app3, agentmonitoroutgoing_exec);
+
+ /* Manager commands */
+- ast_manager_register2("Agents", EVENT_FLAG_AGENT, action_agents, "Lists agents and their status", mandescr_agents);
+- ast_manager_register2("AgentLogoff", EVENT_FLAG_AGENT, action_agent_logoff, "Sets an agent as no longer logged in", mandescr_agent_logoff);
++ ast_manager_register_xml("Agents", EVENT_FLAG_AGENT, action_agents);
++ ast_manager_register_xml("AgentLogoff", EVENT_FLAG_AGENT, action_agent_logoff);
+
+ /* CLI Commands */
+ ast_cli_register_multiple(cli_agents, ARRAY_LEN(cli_agents));
+@@ -2574,11 +2325,7 @@
+
+ static int reload(void)
+ {
+- if (!read_agent_config(1)) {
+- if (persistent_agents)
+- reload_agents();
+- }
+- return 0;
++ return read_agent_config(1);
+ }
+
+ static int unload_module(void)
+Index: channels/chan_console.c
+===================================================================
+--- a/channels/chan_console.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/channels/chan_console.c (.../trunk) (revision 202568)
+@@ -797,6 +797,7 @@
+ if (pvt->owner) { /* already in a call */
+ int i;
+ struct ast_frame f = { AST_FRAME_DTMF, 0 };
++ const char *s;
+
+ if (a->argc == e->args) { /* argument is mandatory here */
+ ast_cli(a->fd, "Already in a call. You can only dial digits until you hangup.\n");
+@@ -837,8 +838,7 @@
+ } else
+ ast_cli(a->fd, "No such extension '%s' in context '%s'\n", mye, myc);
+
+- if (s)
+- free(s);
++ free(s);
+
+ unref_pvt(pvt);
+
+@@ -883,7 +883,7 @@
+
+ static char *cli_console_mute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+ {
+- char *s;
++ const char *s;
+ struct console_pvt *pvt = get_active_pvt();
+ char *res = CLI_SUCCESS;
+
+Index: channels/Makefile
+===================================================================
+--- a/channels/Makefile (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/channels/Makefile (.../trunk) (revision 202568)
+@@ -69,6 +69,7 @@
+ rm -f h323/Makefile
+
+ $(if $(filter chan_iax2,$(EMBEDDED_MODS)),modules.link,chan_iax2.so): iax2-parser.o iax2-provision.o
++$(if $(filter chan_dahdi,$(EMBEDDED_MODS)),modules.link,chan_dahdi.so): sig_analog.o
+
+ ifneq ($(filter chan_h323,$(EMBEDDED_MODS)),)
+ modules.link: h323/libchanh323.a
+Index: channels/chan_iax2.c
+===================================================================
+--- a/channels/chan_iax2.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/channels/chan_iax2.c (.../trunk) (revision 202568)
+@@ -88,6 +88,7 @@
+ #include "asterisk/event.h"
+ #include "asterisk/astobj2.h"
+ #include "asterisk/timing.h"
++#include "asterisk/taskprocessor.h"
+
+ #include "iax2.h"
+ #include "iax2-parser.h"
+@@ -174,6 +175,47 @@
+ </syntax>
+ <description />
+ </function>
++ <manager name="IAXpeers" language="en_US">
++ <synopsis>
++ List IAX peers.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ </syntax>
++ <description>
++ </description>
++ </manager>
++ <manager name="IAXpeerlist" language="en_US">
++ <synopsis>
++ List IAX Peers.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ </syntax>
++ <description>
++ <para>List all the IAX peers.</para>
++ </description>
++ </manager>
++ <manager name="IAXnetstats" language="en_US">
++ <synopsis>
++ Show IAX Netstats.
++ </synopsis>
++ <syntax />
++ <description>
++ <para>Show IAX channels network statistics.</para>
++ </description>
++ </manager>
++ <manager name="IAXregistry" language="en_US">
++ <synopsis>
++ Show IAX registrations.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ </syntax>
++ <description>
++ <para>Show IAX registrations.</para>
++ </description>
++ </manager>
+ ***/
+
+ /* Define SCHED_MULTITHREADED to run the scheduler in a special
+@@ -212,10 +254,10 @@
+
+ /*! \brief Maximum transmission unit for the UDP packet in the trunk not to be
+ fragmented. This is based on 1516 - ethernet - ip - udp - iax minus one g711 frame = 1240 */
+-#define MAX_TRUNK_MTU 1240
++#define MAX_TRUNK_MTU 1240
+
+-static int global_max_trunk_mtu; /*!< Maximum MTU, 0 if not used */
+-static int trunk_timed, trunk_untimed, trunk_maxmtu, trunk_nmaxmtu ; /*!< Trunk MTU statistics */
++static int global_max_trunk_mtu; /*!< Maximum MTU, 0 if not used */
++static int trunk_timed, trunk_untimed, trunk_maxmtu, trunk_nmaxmtu ; /*!< Trunk MTU statistics */
+
+ #define DEFAULT_CONTEXT "default"
+
+@@ -263,27 +305,27 @@
+ static struct ast_netsock_list *outsock; /*!< used if sourceaddress specified and bindaddr == INADDR_ANY */
+ static int defaultsockfd = -1;
+
+-int (*iax2_regfunk)(const char *username, int onoff) = NULL;
++static int (*iax2_regfunk)(const char *username, int onoff) = NULL;
+
+ /* Ethernet, etc */
+-#define IAX_CAPABILITY_FULLBANDWIDTH 0xFFFF
++#define IAX_CAPABILITY_FULLBANDWIDTH 0xFFFF
+ /* T1, maybe ISDN */
+-#define IAX_CAPABILITY_MEDBANDWIDTH (IAX_CAPABILITY_FULLBANDWIDTH & \
+- ~AST_FORMAT_SLINEAR & \
+- ~AST_FORMAT_SLINEAR16 & \
+- ~AST_FORMAT_SIREN7 & \
+- ~AST_FORMAT_SIREN14 & \
+- ~AST_FORMAT_ULAW & \
+- ~AST_FORMAT_ALAW & \
+- ~AST_FORMAT_G722)
++#define IAX_CAPABILITY_MEDBANDWIDTH (IAX_CAPABILITY_FULLBANDWIDTH & \
++ ~AST_FORMAT_SLINEAR & \
++ ~AST_FORMAT_SLINEAR16 & \
++ ~AST_FORMAT_SIREN7 & \
++ ~AST_FORMAT_SIREN14 & \
++ ~AST_FORMAT_ULAW & \
++ ~AST_FORMAT_ALAW & \
++ ~AST_FORMAT_G722)
+ /* A modem */
+-#define IAX_CAPABILITY_LOWBANDWIDTH (IAX_CAPABILITY_MEDBANDWIDTH & \
+- ~AST_FORMAT_G726 & \
+- ~AST_FORMAT_G726_AAL2 & \
+- ~AST_FORMAT_ADPCM)
++#define IAX_CAPABILITY_LOWBANDWIDTH (IAX_CAPABILITY_MEDBANDWIDTH & \
++ ~AST_FORMAT_G726 & \
++ ~AST_FORMAT_G726_AAL2 & \
++ ~AST_FORMAT_ADPCM)
+
+-#define IAX_CAPABILITY_LOWFREE (IAX_CAPABILITY_LOWBANDWIDTH & \
+- ~AST_FORMAT_G723_1)
++#define IAX_CAPABILITY_LOWFREE (IAX_CAPABILITY_LOWBANDWIDTH & \
++ ~AST_FORMAT_G723_1)
+
+
+ #define DEFAULT_MAXMS 2000 /* Must be faster than 2 seconds by default */
+@@ -292,7 +334,7 @@
+
+ /* if a pvt has encryption setup done and is running on the call */
+ #define IAX_CALLENCRYPTED(pvt) \
+- (ast_test_flag(pvt, IAX_ENCRYPTED) && ast_test_flag(pvt, IAX_KEYPOPULATED))
++ (ast_test_flag64(pvt, IAX_ENCRYPTED) && ast_test_flag64(pvt, IAX_KEYPOPULATED))
+
+ #define IAX_DEBUGDIGEST(msg, key) do { \
+ int idx; \
+@@ -332,7 +374,7 @@
+ static int delayreject = 0;
+ static int iax2_encryption = 0;
+
+-static struct ast_flags globalflags = { 0 };
++static struct ast_flags64 globalflags = { 0 };
+
+ static pthread_t netthreadid = AST_PTHREADT_NULL;
+
+@@ -347,40 +389,39 @@
+ struct iax2_context *next;
+ };
+
+-enum iax2_flags {
+- IAX_HASCALLERID = (1 << 0), /*!< CallerID has been specified */
+- IAX_DELME = (1 << 1), /*!< Needs to be deleted */
+- IAX_TEMPONLY = (1 << 2), /*!< Temporary (realtime) */
+- IAX_TRUNK = (1 << 3), /*!< Treat as a trunk */
+- IAX_NOTRANSFER = (1 << 4), /*!< Don't native bridge */
+- IAX_USEJITTERBUF = (1 << 5), /*!< Use jitter buffer */
+- IAX_DYNAMIC = (1 << 6), /*!< dynamic peer */
+- IAX_SENDANI = (1 << 7), /*!< Send ANI along with CallerID */
+- /* (1 << 8) is currently unused due to the deprecation of an old option. Go ahead, take it! */
+- IAX_ALREADYGONE = (1 << 9), /*!< Already disconnected */
+- IAX_PROVISION = (1 << 10), /*!< This is a provisioning request */
+- IAX_QUELCH = (1 << 11), /*!< Whether or not we quelch audio */
+- IAX_ENCRYPTED = (1 << 12), /*!< Whether we should assume encrypted tx/rx */
+- IAX_KEYPOPULATED = (1 << 13), /*!< Whether we have a key populated */
+- IAX_CODEC_USER_FIRST = (1 << 14), /*!< are we willing to let the other guy choose the codec? */
+- IAX_CODEC_NOPREFS = (1 << 15), /*!< Force old behaviour by turning off prefs */
+- IAX_CODEC_NOCAP = (1 << 16), /*!< only consider requested format and ignore capabilities*/
+- IAX_RTCACHEFRIENDS = (1 << 17), /*!< let realtime stay till your reload */
+- IAX_RTUPDATE = (1 << 18), /*!< Send a realtime update */
+- IAX_RTAUTOCLEAR = (1 << 19), /*!< erase me on expire */
+- IAX_FORCEJITTERBUF = (1 << 20), /*!< Force jitterbuffer, even when bridged to a channel that can take jitter */
+- IAX_RTIGNOREREGEXPIRE = (1 << 21), /*!< When using realtime, ignore registration expiration */
+- IAX_TRUNKTIMESTAMPS = (1 << 22), /*!< Send trunk timestamps */
+- IAX_TRANSFERMEDIA = (1 << 23), /*!< When doing IAX2 transfers, transfer media only */
+- IAX_MAXAUTHREQ = (1 << 24), /*!< Maximum outstanding AUTHREQ restriction is in place */
+- IAX_DELAYPBXSTART = (1 << 25), /*!< Don't start a PBX on the channel until the peer sends us a
+- response, so that we've achieved a three-way handshake with
+- them before sending voice or anything else*/
+- IAX_ALLOWFWDOWNLOAD = (1 << 26), /*!< Allow the FWDOWNL command? */
+- IAX_IMMEDIATE = (1 << 27), /*!< Allow immediate off-hook to extension s */
+- IAX_FORCE_ENCRYPT = (1 << 28), /*!< Forces call encryption, if encryption not possible hangup */
+-};
+
++#define IAX_HASCALLERID (uint64_t)(1 << 0) /*!< CallerID has been specified */
++#define IAX_DELME (uint64_t)(1 << 1) /*!< Needs to be deleted */
++#define IAX_TEMPONLY (uint64_t)(1 << 2) /*!< Temporary (realtime) */
++#define IAX_TRUNK (uint64_t)(1 << 3) /*!< Treat as a trunk */
++#define IAX_NOTRANSFER (uint64_t)(1 << 4) /*!< Don't native bridge */
++#define IAX_USEJITTERBUF (uint64_t)(1 << 5) /*!< Use jitter buffer */
++#define IAX_DYNAMIC (uint64_t)(1 << 6) /*!< dynamic peer */
++#define IAX_SENDANI (uint64_t)(1 << 7) /*!< Send ANI along with CallerID */
++#define IAX_RTSAVE_SYSNAME (uint64_t)(1 << 8) /*!< Save Systname on Realtime Updates */
++#define IAX_ALREADYGONE (uint64_t)(1 << 9) /*!< Already disconnected */
++#define IAX_PROVISION (uint64_t)(1 << 10) /*!< This is a provisioning request */
++#define IAX_QUELCH (uint64_t)(1 << 11) /*!< Whether or not we quelch audio */
++#define IAX_ENCRYPTED (uint64_t)(1 << 12) /*!< Whether we should assume encrypted tx/rx */
++#define IAX_KEYPOPULATED (uint64_t)(1 << 13) /*!< Whether we have a key populated */
++#define IAX_CODEC_USER_FIRST (uint64_t)(1 << 14) /*!< are we willing to let the other guy choose the codec? */
++#define IAX_CODEC_NOPREFS (uint64_t)(1 << 15) /*!< Force old behaviour by turning off prefs */
++#define IAX_CODEC_NOCAP (uint64_t)(1 << 16) /*!< only consider requested format and ignore capabilities*/
++#define IAX_RTCACHEFRIENDS (uint64_t)(1 << 17) /*!< let realtime stay till your reload */
++#define IAX_RTUPDATE (uint64_t)(1 << 18) /*!< Send a realtime update */
++#define IAX_RTAUTOCLEAR (uint64_t)(1 << 19) /*!< erase me on expire */
++#define IAX_FORCEJITTERBUF (uint64_t)(1 << 20) /*!< Force jitterbuffer, even when bridged to a channel that can take jitter */
++#define IAX_RTIGNOREREGEXPIRE (uint64_t)(1 << 21) /*!< When using realtime, ignore registration expiration */
++#define IAX_TRUNKTIMESTAMPS (uint64_t)(1 << 22) /*!< Send trunk timestamps */
++#define IAX_TRANSFERMEDIA (uint64_t)(1 << 23) /*!< When doing IAX2 transfers, transfer media only */
++#define IAX_MAXAUTHREQ (uint64_t)(1 << 24) /*!< Maximum outstanding AUTHREQ restriction is in place */
++#define IAX_DELAYPBXSTART (uint64_t)(1 << 25) /*!< Don't start a PBX on the channel until the peer sends us a response, so that we've achieved a three-way handshake with them before sending voice or anything else */
++#define IAX_ALLOWFWDOWNLOAD (uint64_t)(1 << 26) /*!< Allow the FWDOWNL command? */
++#define IAX_IMMEDIATE (uint64_t)(1 << 27) /*!< Allow immediate off-hook to extension s */
++#define IAX_SENDCONNECTEDLINE (uint64_t)(1 << 28) /*!< Allow sending of connected line updates */
++#define IAX_RECVCONNECTEDLINE (uint64_t)(1 << 29) /*!< Allow receiving of connected line updates */
++#define IAX_FORCE_ENCRYPT (uint64_t)(1 << 30) /*!< Forces call encryption, if encryption not possible hangup */
++
+ static int global_rtautoclear = 120;
+
+ static int reload_config(void);
+@@ -399,12 +440,12 @@
+ AST_STRING_FIELD(cid_name);
+ AST_STRING_FIELD(parkinglot); /*!< Default parkinglot for device */
+ );
+-
++
+ int authmethods;
+ int encmethods;
+ int amaflags;
+ int adsi;
+- unsigned int flags;
++ uint64_t flags;
+ int capability;
+ int maxauthreq; /*!< Maximum allowed outstanding AUTHREQs */
+ int curauthreq; /*!< Current number of outstanding AUTHREQs */
+@@ -442,7 +483,7 @@
+ int sockfd; /*!< Socket to use for transmission */
+ struct in_addr mask;
+ int adsi;
+- unsigned int flags;
++ uint64_t flags;
+
+ /* Dynamic Registration fields */
+ struct sockaddr_in defaddr; /*!< Default address if there is one */
+@@ -543,10 +584,10 @@
+
+ /* Don't retry more frequently than every 10 ms, or less frequently than every 5 seconds */
+ #define MIN_RETRY_TIME 100
+-#define MAX_RETRY_TIME 10000
++#define MAX_RETRY_TIME 10000
+
+-#define MAX_JITTER_BUFFER 50
+-#define MIN_JITTER_BUFFER 10
++#define MAX_JITTER_BUFFER 50
++#define MIN_JITTER_BUFFER 10
+
+ #define DEFAULT_TRUNKDATA 640 * 10 /*!< 40ms, uncompressed linear * 10 channels */
+
+@@ -632,7 +673,7 @@
+ /*! The jitterbuffer */
+ jitterbuf *jb;
+ /*! active jb read scheduler id */
+- int jbid;
++ int jbid;
+ /*! LAG */
+ int lag;
+ /*! Error, as discovered by the manager */
+@@ -714,7 +755,7 @@
+ /*! Associated peer for poking */
+ struct iax2_peer *peerpoke;
+ /*! IAX_ flags */
+- unsigned int flags;
++ uint64_t flags;
+ int adsi;
+
+ /*! Transferring status */
+@@ -733,7 +774,7 @@
+
+ /*! Who we are bridged to */
+ unsigned short bridgecallno;
+-
++
+ int pingid; /*!< Transmit PING request */
+ int lagid; /*!< Retransmit lag request */
+ int autoid; /*!< Auto hangup for Dialplan requestor */
+@@ -765,9 +806,13 @@
+ * \note The contents of this list do not need to be explicitly destroyed
+ * on module unload. This is because all active calls are destroyed, and
+ * all frames in this queue will get destroyed as a part of that process.
++ *
++ * \note Contents protected by the iaxsl[] locks
+ */
+-static AST_LIST_HEAD_STATIC(frame_queue, iax_frame);
++static AST_LIST_HEAD_NOLOCK(, iax_frame) frame_queue[IAX_MAX_CALLS];
+
++static struct ast_taskprocessor *transmit_processor;
++
+ /*!
+ * This module will get much higher performance when doing a lot of
+ * user and peer lookups if the number of buckets is increased from 1.
+@@ -824,7 +869,7 @@
+ static struct iax2_peer *realtime_peer(const char *peername, struct sockaddr_in *sin);
+
+ static int ast_cli_netstats(struct mansession *s, int fd, int limit_fmt);
+-static char *complete_iax2_peers(const char *line, const char *word, int pos, int state, int flags);
++static char *complete_iax2_peers(const char *line, const char *word, int pos, int state, uint64_t flags);
+ static char *complete_iax2_unregister(const char *line, const char *word, int pos, int state);
+
+ enum iax2_thread_iostate {
+@@ -1045,7 +1090,7 @@
+ static int iax2_hangup(struct ast_channel *c);
+ static int iax2_indicate(struct ast_channel *c, int condition, const void *data, size_t datalen);
+ static int iax2_poke_peer(struct iax2_peer *peer, int heldcall);
+-static int iax2_provision(struct sockaddr_in *end, int sockfd, char *dest, const char *template, int force);
++static int iax2_provision(struct sockaddr_in *end, int sockfd, const char *dest, const char *template, int force);
+ static int iax2_send(struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned int ts, int seqno, int now, int transfer, int final);
+ static int iax2_sendhtml(struct ast_channel *c, int subclass, const char *data, int datalen);
+ static int iax2_sendimage(struct ast_channel *c, struct ast_frame *img);
+@@ -1545,7 +1590,7 @@
+ static void iax2_destroy_helper(struct chan_iax2_pvt *pvt)
+ {
+ /* Decrement AUTHREQ count if needed */
+- if (ast_test_flag(pvt, IAX_MAXAUTHREQ)) {
++ if (ast_test_flag64(pvt, IAX_MAXAUTHREQ)) {
+ struct iax2_user *user;
+ struct iax2_user tmp_user = {
+ .name = pvt->username,
+@@ -1554,10 +1599,10 @@
+ user = ao2_find(users, &tmp_user, OBJ_POINTER);
+ if (user) {
+ ast_atomic_fetchadd_int(&user->curauthreq, -1);
+- user_unref(user);
++ user_unref(user);
+ }
+
+- ast_clear_flag(pvt, IAX_MAXAUTHREQ);
++ ast_clear_flag64(pvt, IAX_MAXAUTHREQ);
+ }
+ /* No more pings or lagrq's */
+ AST_SCHED_DEL_SPINLOCK(ast_sched_thread_get_context(sched), pvt->pingid, &iaxsl[pvt->callno]);
+@@ -1595,21 +1640,19 @@
+ struct iax_frame *cur = NULL;
+
+ ast_mutex_lock(&iaxsl[pvt->callno]);
++
+ iax2_destroy_helper(pvt);
+- ast_mutex_unlock(&iaxsl[pvt->callno]);
+
+ /* Already gone */
+- ast_set_flag(pvt, IAX_ALREADYGONE);
++ ast_set_flag64(pvt, IAX_ALREADYGONE);
+
+- AST_LIST_LOCK(&frame_queue);
+- AST_LIST_TRAVERSE(&frame_queue, cur, list) {
++ AST_LIST_TRAVERSE(&frame_queue[pvt->callno], cur, list) {
+ /* Cancel any pending transmissions */
+- if (cur->callno == pvt->callno) {
+- cur->retries = -1;
+- }
++ cur->retries = -1;
+ }
+- AST_LIST_UNLOCK(&frame_queue);
+
++ ast_mutex_unlock(&iaxsl[pvt->callno]);
++
+ if (pvt->reg) {
+ pvt->reg->callno = 0;
+ }
+@@ -1954,7 +1997,7 @@
+ break;
+ }
+ ast_mutex_unlock(&iaxsl[x]);
+-
++
+ if (x == start - 1) {
+ break;
+ }
+@@ -1980,7 +2023,7 @@
+ iaxs[x]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, (void *)(long)x);
+ iaxs[x]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, (void *)(long)x);
+ iaxs[x]->amaflags = amaflags;
+- ast_copy_flags(iaxs[x], &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_FORCE_ENCRYPT);
++ ast_copy_flags64(iaxs[x], &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE | IAX_FORCE_ENCRYPT);
+ ast_string_field_set(iaxs[x], accountcode, accountcode);
+ ast_string_field_set(iaxs[x], mohinterpret, mohinterpret);
+ ast_string_field_set(iaxs[x], mohsuggest, mohsuggest);
+@@ -2202,7 +2245,7 @@
+ return -1;
+ }
+ fwh = (struct ast_iax2_firmware_header*)mmap(NULL, stbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+- if (fwh == (void *) -1) {
++ if (fwh == MAP_FAILED) {
+ ast_log(LOG_WARNING, "mmap failed: %s\n", strerror(errno));
+ close(fd);
+ return -1;
+@@ -2367,7 +2410,7 @@
+ struct iax_frame *fr = data;
+ fr->retrans = -1;
+ ast_clear_flag(&fr->af, AST_FRFLAG_HAS_TIMING_INFO);
+- if (iaxs[fr->callno] && !ast_test_flag(iaxs[fr->callno], IAX_ALREADYGONE))
++ if (iaxs[fr->callno] && !ast_test_flag64(iaxs[fr->callno], IAX_ALREADYGONE))
+ iax2_queue_frame(fr->callno, &fr->af);
+ /* Free our iax frame */
+ iax2_frame_free(fr);
+@@ -2466,9 +2509,9 @@
+ if (!pvt)
+ return -1;
+
+- if (!ast_test_flag(pvt, IAX_ALREADYGONE)) {
++ if (!ast_test_flag64(pvt, IAX_ALREADYGONE)) {
+ iax2_destroy_helper(pvt);
+- ast_set_flag(pvt, IAX_ALREADYGONE);
++ ast_set_flag64(pvt, IAX_ALREADYGONE);
+ }
+
+ if ((c = pvt->owner)) {
+@@ -2630,17 +2673,16 @@
+ f->retries = -1;
+ freeme = 1;
+ }
+- if (callno)
+- ast_mutex_unlock(&iaxsl[callno]);
+- /* Do not try again */
++
+ if (freeme) {
+ /* Don't attempt delivery, just remove it from the queue */
+- AST_LIST_LOCK(&frame_queue);
+- AST_LIST_REMOVE(&frame_queue, f, list);
+- AST_LIST_UNLOCK(&frame_queue);
++ AST_LIST_REMOVE(&frame_queue[callno], f, list);
++ ast_mutex_unlock(&iaxsl[callno]);
+ f->retrans = -1;
+ /* Free the IAX frame */
+ iax2_frame_free(f);
++ } else if (callno) {
++ ast_mutex_unlock(&iaxsl[callno]);
+ }
+ }
+
+@@ -2657,7 +2699,7 @@
+ {
+ struct iax2_peer *peer = NULL;
+ struct iax2_user *user = NULL;
+- static char *choices[] = { "all", NULL };
++ static const char * const choices[] = { "all", NULL };
+ char *cmplt;
+
+ switch (cmd) {
+@@ -2688,8 +2730,8 @@
+ user = find_user(a->argv[3]);
+ if (peer || user) {
+ if (peer) {
+- if (ast_test_flag(peer, IAX_RTCACHEFRIENDS)) {
+- ast_set_flag(peer, IAX_RTAUTOCLEAR);
++ if (ast_test_flag64(peer, IAX_RTCACHEFRIENDS)) {
++ ast_set_flag64(peer, IAX_RTAUTOCLEAR);
+ expire_registry(peer_ref(peer));
+ ast_cli(a->fd, "Peer %s was removed from the cache.\n", a->argv[3]);
+ } else {
+@@ -2698,8 +2740,8 @@
+ peer_unref(peer);
+ }
+ if (user) {
+- if (ast_test_flag(user, IAX_RTCACHEFRIENDS)) {
+- ast_set_flag(user, IAX_RTAUTOCLEAR);
++ if (ast_test_flag64(user, IAX_RTCACHEFRIENDS)) {
++ ast_set_flag64(user, IAX_RTAUTOCLEAR);
+ ast_cli(a->fd, "User %s was removed from the cache.\n", a->argv[3]);
+ } else {
+ ast_cli(a->fd, "User %s is not eligible for this operation.\n", a->argv[3]);
+@@ -2864,8 +2906,8 @@
+ ast_cli(a->fd, " Context : %s\n", peer->context);
+ ast_cli(a->fd, " Parking lot : %s\n", peer->parkinglot);
+ ast_cli(a->fd, " Mailbox : %s\n", peer->mailbox);
+- ast_cli(a->fd, " Dynamic : %s\n", ast_test_flag(peer, IAX_DYNAMIC) ? "Yes" : "No");
+- ast_cli(a->fd, " Trunk : %s\n", ast_test_flag(peer, IAX_TRUNK) ? "Yes" : "No");
++ ast_cli(a->fd, " Dynamic : %s\n", ast_test_flag64(peer, IAX_DYNAMIC) ? "Yes" : "No");
++ ast_cli(a->fd, " Trunk : %s\n", ast_test_flag64(peer, IAX_TRUNK) ? "Yes" : "No");
+ ast_cli(a->fd, " Encryption : %s\n", peer->encmethods ? ast_str_buffer(encmethods) : "No");
+ ast_cli(a->fd, " Callerid : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "<unspecified>"));
+ ast_cli(a->fd, " Expire : %d\n", peer->expire);
+@@ -2905,7 +2947,7 @@
+ return CLI_SUCCESS;
+ }
+
+-static char *complete_iax2_peers(const char *line, const char *word, int pos, int state, int flags)
++static char *complete_iax2_peers(const char *line, const char *word, int pos, int state, uint64_t flags)
+ {
+ int which = 0;
+ struct iax2_peer *peer;
+@@ -2916,7 +2958,7 @@
+ i = ao2_iterator_init(peers, 0);
+ while ((peer = ao2_iterator_next(&i))) {
+ if (!strncasecmp(peer->name, word, wordlen) && ++which > state
+- && (!flags || ast_test_flag(peer, flags))) {
++ && (!flags || ast_test_flag64(peer, flags))) {
+ res = ast_strdup(peer->name);
+ peer_unref(peer);
+ break;
+@@ -2930,7 +2972,7 @@
+ static char *handle_cli_iax2_show_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+ {
+ struct iax_frame *cur;
+- int cnt = 0, dead = 0, final = 0;
++ int cnt = 0, dead = 0, final = 0, i = 0;
+
+ switch (cmd) {
+ case CLI_INIT:
+@@ -2946,15 +2988,17 @@
+ if (a->argc != 3)
+ return CLI_SHOWUSAGE;
+
+- AST_LIST_LOCK(&frame_queue);
+- AST_LIST_TRAVERSE(&frame_queue, cur, list) {
+- if (cur->retries < 0)
+- dead++;
+- if (cur->final)
+- final++;
+- cnt++;
++ for (i = 0; i < ARRAY_LEN(frame_queue); i++) {
++ ast_mutex_lock(&iaxsl[i]);
++ AST_LIST_TRAVERSE(&frame_queue[i], cur, list) {
++ if (cur->retries < 0)
++ dead++;
++ if (cur->final)
++ final++;
++ cnt++;
++ }
++ ast_mutex_unlock(&iaxsl[i]);
+ }
+- AST_LIST_UNLOCK(&frame_queue);
+
+ ast_cli(a->fd, " IAX Statistics\n");
+ ast_cli(a->fd, "---------------------\n");
+@@ -3188,7 +3232,7 @@
+
+ /* queue the frame: For consistency, we would call __do_deliver here, but __do_deliver wants an iax_frame,
+ * which we'd need to malloc, and then it would free it. That seems like a drag */
+- if (!ast_test_flag(iaxs[callno], IAX_ALREADYGONE)) {
++ if (!ast_test_flag64(iaxs[callno], IAX_ALREADYGONE)) {
+ iax2_queue_frame(callno, &af);
+ /* iax2_queue_frame() could cause the call to disappear */
+ pvt = iaxs[callno];
+@@ -3258,7 +3302,7 @@
+ type = JB_TYPE_SILENCE;
+ }
+
+- if ( (!ast_test_flag(iaxs[fr->callno], IAX_USEJITTERBUF)) ) {
++ if ( (!ast_test_flag64(iaxs[fr->callno], IAX_USEJITTERBUF)) ) {
+ if (tsout)
+ *tsout = fr->ts;
+ __do_deliver(fr);
+@@ -3270,7 +3314,7 @@
+
+ /* if the user hasn't requested we force the use of the jitterbuffer, and we're bridged to
+ * a channel that can accept jitter, then flush and suspend the jb, and send this frame straight through */
+- if ( (!ast_test_flag(iaxs[fr->callno], IAX_FORCEJITTERBUF)) && owner && bridge && (bridge->tech->properties & AST_CHAN_TP_WANTSJITTER) ) {
++ if ( (!ast_test_flag64(iaxs[fr->callno], IAX_FORCEJITTERBUF)) && owner && bridge && (bridge->tech->properties & AST_CHAN_TP_WANTSJITTER) ) {
+ jb_frame frame;
+
+ /* deliver any frames in the jb */
+@@ -3311,23 +3355,39 @@
+ return 0;
+ }
+
+-static int iax2_transmit(struct iax_frame *fr)
++static int transmit_frame(void *data)
+ {
+- /* Lock the queue and place this packet at the end */
+- /* By setting this to 0, the network thread will send it for us, and
+- queue retransmission if necessary */
+- fr->sentyet = 0;
+- AST_LIST_LOCK(&frame_queue);
+- AST_LIST_INSERT_TAIL(&frame_queue, fr, list);
+- AST_LIST_UNLOCK(&frame_queue);
+- /* Wake up the network and scheduler thread */
+- if (netthreadid != AST_PTHREADT_NULL)
+- pthread_kill(netthreadid, SIGURG);
+- ast_sched_thread_poke(sched);
++ struct iax_frame *fr = data;
++
++ ast_mutex_lock(&iaxsl[fr->callno]);
++
++ fr->sentyet = 1;
++
++ if (iaxs[fr->callno]) {
++ send_packet(fr);
++ }
++
++ if (fr->retries < 0) {
++ ast_mutex_unlock(&iaxsl[fr->callno]);
++ /* No retransmit requested */
++ iax_frame_free(fr);
++ } else {
++ /* We need reliable delivery. Schedule a retransmission */
++ AST_LIST_INSERT_TAIL(&frame_queue[fr->callno], fr, list);
++ ast_mutex_unlock(&iaxsl[fr->callno]);
++ fr->retries++;
++ fr->retrans = iax2_sched_add(sched, fr->retrytime, attempt_transmit, fr);
++ }
++
+ return 0;
+ }
+
++static int iax2_transmit(struct iax_frame *fr)
++{
++ fr->sentyet = 0;
+
++ return ast_taskprocessor_push(transmit_processor, transmit_frame, fr);
++}
+
+ static int iax2_digit_begin(struct ast_channel *c, char digit)
+ {
+@@ -3422,8 +3482,8 @@
+ if (!var)
+ return NULL;
+
+- peer = build_peer(peername, var, NULL, ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS) ? 0 : 1);
+-
++ peer = build_peer(peername, var, NULL, ast_test_flag64((&globalflags), IAX_RTCACHEFRIENDS) ? 0 : 1);
++
+ if (!peer) {
+ ast_variables_destroy(var);
+ return NULL;
+@@ -3455,27 +3515,27 @@
+ if (!peer)
+ return NULL;
+
+- if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) {
+- ast_copy_flags(peer, &globalflags, IAX_RTAUTOCLEAR|IAX_RTCACHEFRIENDS);
+- if (ast_test_flag(peer, IAX_RTAUTOCLEAR)) {
+- if (peer->expire > -1) {
+- if (!ast_sched_thread_del(sched, peer->expire)) {
+- peer->expire = -1;
+- peer_unref(peer);
+- }
+- }
+- peer->expire = iax2_sched_add(sched, (global_rtautoclear) * 1000, expire_registry, peer_ref(peer));
+- if (peer->expire == -1)
+- peer_unref(peer);
++ if (ast_test_flag64((&globalflags), IAX_RTCACHEFRIENDS)) {
++ ast_copy_flags64(peer, &globalflags, IAX_RTAUTOCLEAR|IAX_RTCACHEFRIENDS);
++ if (ast_test_flag64(peer, IAX_RTAUTOCLEAR)) {
++ if (peer->expire > -1) {
++ if (!ast_sched_thread_del(sched, peer->expire)) {
++ peer->expire = -1;
++ peer_unref(peer);
++ }
++ }
++ peer->expire = iax2_sched_add(sched, (global_rtautoclear) * 1000, expire_registry, peer_ref(peer));
++ if (peer->expire == -1)
++ peer_unref(peer);
+ }
+ ao2_link(peers, peer);
+- if (ast_test_flag(peer, IAX_DYNAMIC))
++ if (ast_test_flag64(peer, IAX_DYNAMIC))
+ reg_source_db(peer);
+ } else {
+- ast_set_flag(peer, IAX_TEMPONLY);
++ ast_set_flag64(peer, IAX_TEMPONLY);
+ }
+
+- if (!ast_test_flag(&globalflags, IAX_RTIGNOREREGEXPIRE) && dynamic) {
++ if (!ast_test_flag64(&globalflags, IAX_RTIGNOREREGEXPIRE) && dynamic) {
+ time(&nowtime);
+ if ((nowtime - regseconds) > IAX_DEFAULT_REG_EXPIRE) {
+ memset(&peer->addr, 0, sizeof(peer->addr));
+@@ -3546,18 +3606,18 @@
+ tmp = tmp->next;
+ }
+
+- user = build_user(username, var, NULL, !ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS));
++ user = build_user(username, var, NULL, !ast_test_flag64((&globalflags), IAX_RTCACHEFRIENDS));
+
+ ast_variables_destroy(var);
+
+ if (!user)
+ return NULL;
+
+- if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) {
+- ast_set_flag(user, IAX_RTCACHEFRIENDS);
++ if (ast_test_flag64((&globalflags), IAX_RTCACHEFRIENDS)) {
++ ast_set_flag64(user, IAX_RTCACHEFRIENDS);
+ ao2_link(users, user);
+ } else {
+- ast_set_flag(user, IAX_TEMPONLY);
++ ast_set_flag64(user, IAX_TEMPONLY);
+ }
+
+ return user;
+@@ -3567,17 +3627,24 @@
+ {
+ char port[10];
+ char regseconds[20];
+-
++ const char *sysname = ast_config_AST_SYSTEM_NAME;
++ char *syslabel = NULL;
++
++ if (ast_strlen_zero(sysname)) /* No system name, disable this */
++ sysname = NULL;
++ else if (ast_test_flag64(&globalflags, IAX_RTSAVE_SYSNAME))
++ syslabel = "regserver";
++
+ snprintf(regseconds, sizeof(regseconds), "%d", (int)regtime);
+ snprintf(port, sizeof(port), "%d", ntohs(sin->sin_port));
+ ast_update_realtime("iaxpeers", "name", peername,
+ "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", port,
+- "regseconds", regseconds, SENTINEL);
++ "regseconds", regseconds, syslabel, sysname, SENTINEL); /* note syslable can be NULL */
+ }
+
+ struct create_addr_info {
+ int capability;
+- unsigned int flags;
++ uint64_t flags;
+ int maxtime;
+ int encmethods;
+ int found;
+@@ -3588,6 +3655,8 @@
+ char outkey[80];
+ char timezone[80];
+ char prefs[32];
++ char cid_num[80];
++ char cid_name[80];
+ char context[AST_MAX_CONTEXT];
+ char peercontext[AST_MAX_CONTEXT];
+ char mohinterpret[MAX_MUSICCLASS];
+@@ -3600,7 +3669,7 @@
+ int res = -1;
+ struct ast_codec_pref ourprefs;
+
+- ast_clear_flag(cai, IAX_SENDANI | IAX_TRUNK);
++ ast_clear_flag64(cai, IAX_SENDANI | IAX_TRUNK);
+ cai->sockfd = defaultsockfd;
+ cai->maxtime = 0;
+ sin->sin_family = AF_INET;
+@@ -3631,7 +3700,7 @@
+ if (peer->maxms && ((peer->lastms > peer->maxms) || (peer->lastms < 0)))
+ goto return_unref;
+
+- ast_copy_flags(cai, peer, IAX_SENDANI | IAX_TRUNK | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_FORCE_ENCRYPT);
++ ast_copy_flags64(cai, peer, IAX_SENDANI | IAX_TRUNK | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE | IAX_FORCE_ENCRYPT);
+ cai->maxtime = peer->maxms;
+ cai->capability = peer->capability;
+ cai->encmethods = peer->encmethods;
+@@ -3649,6 +3718,8 @@
+ ast_copy_string(cai->username, peer->username, sizeof(cai->username));
+ ast_copy_string(cai->timezone, peer->zonetag, sizeof(cai->timezone));
+ ast_copy_string(cai->outkey, peer->outkey, sizeof(cai->outkey));
++ ast_copy_string(cai->cid_num, peer->cid_num, sizeof(cai->cid_num));
++ ast_copy_string(cai->cid_name, peer->cid_name, sizeof(cai->cid_name));
+ ast_copy_string(cai->mohinterpret, peer->mohinterpret, sizeof(cai->mohinterpret));
+ ast_copy_string(cai->mohsuggest, peer->mohsuggest, sizeof(cai->mohsuggest));
+ if (ast_strlen_zero(peer->dbsecret)) {
+@@ -3838,7 +3909,7 @@
+ ast_log(LOG_WARNING, "No address associated with '%s'\n", pds.peer);
+ return -1;
+ }
+- if (ast_strlen_zero(cai.secret) && ast_test_flag(iaxs[callno], IAX_FORCE_ENCRYPT)) {
++ if (ast_strlen_zero(cai.secret) && ast_test_flag64(iaxs[callno], IAX_FORCE_ENCRYPT)) {
+ ast_log(LOG_WARNING, "Call terminated. No secret given and force encrypt enabled\n");
+ return -1;
+ }
+@@ -3857,8 +3928,8 @@
+ if (pds.port)
+ sin.sin_port = htons(atoi(pds.port));
+
+- l = c->cid.cid_num;
+- n = c->cid.cid_name;
++ l = c->connected.id.number;
++ n = c->connected.id.name;
+
+ /* Now build request */
+ memset(&ied, 0, sizeof(ied));
+@@ -3875,21 +3946,21 @@
+
+ if (l) {
+ iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, l);
+- iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres);
++ iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->connected.id.number_presentation);
+ } else {
+ if (n)
+- iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres);
++ iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->connected.id.number_presentation);
+ else
+ iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, AST_PRES_NUMBER_NOT_AVAILABLE);
+ }
+
+- iax_ie_append_byte(&ied, IAX_IE_CALLINGTON, c->cid.cid_ton);
++ iax_ie_append_byte(&ied, IAX_IE_CALLINGTON, c->connected.id.number_type);
+ iax_ie_append_short(&ied, IAX_IE_CALLINGTNS, c->cid.cid_tns);
+
+ if (n)
+ iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, n);
+- if (ast_test_flag(iaxs[callno], IAX_SENDANI) && c->cid.cid_ani)
+- iax_ie_append_str(&ied, IAX_IE_CALLING_ANI, c->cid.cid_ani);
++ if (ast_test_flag64(iaxs[callno], IAX_SENDANI) && c->connected.ani)
++ iax_ie_append_str(&ied, IAX_IE_CALLING_ANI, c->connected.ani);
+
+ if (!ast_strlen_zero(c->language))
+ iax_ie_append_str(&ied, IAX_IE_LANGUAGE, c->language);
+@@ -3999,7 +4070,7 @@
+ ast_mutex_lock(&iaxsl[callno]);
+ if (callno && iaxs[callno]) {
+ ast_debug(1, "We're hanging up %s now...\n", c->name);
+- alreadygone = ast_test_flag(iaxs[callno], IAX_ALREADYGONE);
++ alreadygone = ast_test_flag64(iaxs[callno], IAX_ALREADYGONE);
+ /* Send the hangup unless we have had a transmission error or are already gone */
+ iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, (unsigned char)c->hangupcause);
+ if (!iaxs[callno]->error && !alreadygone) {
+@@ -4068,6 +4139,10 @@
+ /* these two cannot be sent, because they require a result */
+ errno = ENOSYS;
+ return -1;
++ case AST_OPTION_FORMAT_READ:
++ case AST_OPTION_FORMAT_WRITE:
++ case AST_OPTION_MAKE_COMPATIBLE:
++ return -1;
+ case AST_OPTION_OPRMODE:
+ errno = EINVAL;
+ return -1;
+@@ -4150,8 +4225,8 @@
+
+ if (IAX_CALLENCRYPTED(iaxs[callno0]) || IAX_CALLENCRYPTED(iaxs[callno1])) {
+ ast_debug(1, "transfers are not supported for encrypted calls at this time");
+- ast_set_flag(iaxs[callno0], IAX_NOTRANSFER);
+- ast_set_flag(iaxs[callno1], IAX_NOTRANSFER);
++ ast_set_flag64(iaxs[callno0], IAX_NOTRANSFER);
++ ast_set_flag64(iaxs[callno1], IAX_NOTRANSFER);
+ return 0;
+ }
+
+@@ -4257,10 +4332,10 @@
+ return AST_BRIDGE_FAILED_NOWARN;
+ }
+ /* check if transfered and if we really want native bridging */
+- if (!transferstarted && !ast_test_flag(iaxs[callno0], IAX_NOTRANSFER) && !ast_test_flag(iaxs[callno1], IAX_NOTRANSFER)) {
++ if (!transferstarted && !ast_test_flag64(iaxs[callno0], IAX_NOTRANSFER) && !ast_test_flag64(iaxs[callno1], IAX_NOTRANSFER)) {
+ /* Try the transfer */
+ if (iax2_start_transfer(callno0, callno1, (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) ||
+- ast_test_flag(iaxs[callno0], IAX_TRANSFERMEDIA) | ast_test_flag(iaxs[callno1], IAX_TRANSFERMEDIA)))
++ ast_test_flag64(iaxs[callno0], IAX_TRANSFERMEDIA) | ast_test_flag64(iaxs[callno1], IAX_TRANSFERMEDIA)))
+ ast_log(LOG_WARNING, "Unable to start the transfer\n");
+ transferstarted = 1;
+ }
+@@ -4385,6 +4460,11 @@
+ ast_moh_stop(c);
+ goto done;
+ }
++ break;
++ case AST_CONTROL_CONNECTED_LINE:
++ if (!ast_test_flag64(pvt, IAX_SENDCONNECTEDLINE))
++ goto done;
++ break;
+ }
+
+ res = send_command(pvt, AST_FRAME_CONTROL, condition, 0, data, datalen, -1);
+@@ -4400,6 +4480,7 @@
+ unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
+ struct iax_ie_data ied = { "", };
+ char tmp[256], *context;
++ enum ast_control_transfer message = AST_TRANSFER_SUCCESS;
+ ast_copy_string(tmp, dest, sizeof(tmp));
+ context = strchr(tmp, '@');
+ if (context) {
+@@ -4410,6 +4491,7 @@
+ if (context)
+ iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, context);
+ ast_debug(1, "Transferring '%s' to '%s'\n", c->name, dest);
++ ast_queue_control_data(c, AST_CONTROL_TRANSFER, &message, sizeof(message));
+ return send_command_locked(callno, AST_FRAME_IAX, IAX_COMMAND_TRANSFER, 0, ied.buf, ied.pos, -1);
+ }
+
+@@ -4423,7 +4505,7 @@
+ while ((peer = ao2_iterator_next(&i))) {
+ if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) &&
+ (peer->addr.sin_port == sin.sin_port)) {
+- res = ast_test_flag(peer, IAX_TRUNK);
++ res = ast_test_flag64(peer, IAX_TRUNK);
+ peer_unref(peer);
+ break;
+ }
+@@ -4453,7 +4535,7 @@
+ if (tmp) {
+ /* unlock and relock iaxsl[callno] to preserve locking order */
+ ast_mutex_unlock(&iaxsl[callno]);
+- ast_channel_free(tmp);
++ tmp = ast_channel_release(tmp);
+ ast_mutex_lock(&iaxsl[callno]);
+ }
+ return NULL;
+@@ -4835,7 +4917,7 @@
+
+ /* Append to meta frame */
+ ptr = tpeer->trunkdata + IAX2_TRUNK_PREFACE + tpeer->trunkdatalen;
+- if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS)) {
++ if (ast_test_flag64(&globalflags, IAX_TRUNKTIMESTAMPS)) {
+ mtm = (struct ast_iax2_meta_trunk_mini *)ptr;
+ mtm->len = htons(f->datalen);
+ mtm->mini.callno = htons(pvt->callno);
+@@ -5038,7 +5120,7 @@
+ static int decrypt_frame(int callno, struct ast_iax2_full_hdr *fh, struct ast_frame *f, int *datalen)
+ {
+ int res=-1;
+- if (!ast_test_flag(iaxs[callno], IAX_KEYPOPULATED)) {
++ if (!ast_test_flag64(iaxs[callno], IAX_KEYPOPULATED)) {
+ /* Search for possible keys, given secrets */
+ struct MD5Context md5;
+ unsigned char digest[16];
+@@ -5054,7 +5136,7 @@
+ build_encryption_keys(digest, iaxs[callno]);
+ res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen);
+ if (!res) {
+- ast_set_flag(iaxs[callno], IAX_KEYPOPULATED);
++ ast_set_flag64(iaxs[callno], IAX_KEYPOPULATED);
+ break;
+ }
+ }
+@@ -5110,7 +5192,7 @@
+ iax2_key_rotate(pvt);
+ }
+
+- if ((ast_test_flag(pvt, IAX_TRUNK) ||
++ if ((ast_test_flag64(pvt, IAX_TRUNK) ||
+ (((fts & 0xFFFF0000L) == (lastsent & 0xFFFF0000L)) ||
+ ((fts & 0xFFFF0000L) == ((lastsent + 0x10000) & 0xFFFF0000L))))
+ /* High two bytes are the same on timestamp, or sending on a trunk */ &&
+@@ -5151,7 +5233,7 @@
+ if (now) {
+ fr = &frb.fr2;
+ } else
+- fr = iax_frame_new(DIRECTION_OUTGRESS, ast_test_flag(pvt, IAX_ENCRYPTED) ? f->datalen + 32 : f->datalen, (f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_VIDEO));
++ fr = iax_frame_new(DIRECTION_OUTGRESS, ast_test_flag64(pvt, IAX_ENCRYPTED) ? f->datalen + 32 : f->datalen, (f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_VIDEO));
+ if (!fr) {
+ ast_log(LOG_WARNING, "Out of memory\n");
+ return -1;
+@@ -5208,8 +5290,8 @@
+ pvt->svoiceformat = f->subclass;
+ else if (f->frametype == AST_FRAME_VIDEO)
+ pvt->svideoformat = f->subclass & ~0x1;
+- if (ast_test_flag(pvt, IAX_ENCRYPTED)) {
+- if (ast_test_flag(pvt, IAX_KEYPOPULATED)) {
++ if (ast_test_flag64(pvt, IAX_ENCRYPTED)) {
++ if (ast_test_flag64(pvt, IAX_KEYPOPULATED)) {
+ if (fr->transfer)
+ iax_outputframe(fr, NULL, 2, &pvt->transfer, fr->datalen - sizeof(struct ast_iax2_full_hdr));
+ else
+@@ -5228,7 +5310,7 @@
+ } else
+ res = iax2_transmit(fr);
+ } else {
+- if (ast_test_flag(pvt, IAX_TRUNK)) {
++ if (ast_test_flag64(pvt, IAX_TRUNK)) {
+ iax2_trunk_queue(pvt, fr);
+ res = 0;
+ } else if (fr->af.frametype == AST_FRAME_VIDEO) {
+@@ -5256,8 +5338,8 @@
+ fr->retries = -1;
+ if (pvt->transferring == TRANSFER_MEDIAPASS)
+ fr->transfer = 1;
+- if (ast_test_flag(pvt, IAX_ENCRYPTED)) {
+- if (ast_test_flag(pvt, IAX_KEYPOPULATED)) {
++ if (ast_test_flag64(pvt, IAX_ENCRYPTED)) {
++ if (ast_test_flag64(pvt, IAX_KEYPOPULATED)) {
+ encrypt_frame(&pvt->ecx, (struct ast_iax2_full_hdr *)mh, pvt->semirand, &fr->datalen);
+ } else
+ ast_log(LOG_WARNING, "Supposed to send packet encrypted, but no key?\n");
+@@ -5313,21 +5395,21 @@
+ user_unref(user), user = ao2_iterator_next(&i)) {
+ if (havepattern && regexec(&regexbuf, user->name, 0, NULL, 0))
+ continue;
+-
++
+ if (!ast_strlen_zero(user->secret)) {
+- ast_copy_string(auth,user->secret, sizeof(auth));
++ ast_copy_string(auth,user->secret, sizeof(auth));
+ } else if (!ast_strlen_zero(user->inkeys)) {
+- snprintf(auth, sizeof(auth), "Key: %-15.15s ", user->inkeys);
+- } else
++ snprintf(auth, sizeof(auth), "Key: %-15.15s ", user->inkeys);
++ } else
+ ast_copy_string(auth, "-no secret-", sizeof(auth));
+-
+- if(ast_test_flag(user,IAX_CODEC_NOCAP))
++
++ if(ast_test_flag64(user, IAX_CODEC_NOCAP))
+ pstr = "REQ Only";
+- else if(ast_test_flag(user,IAX_CODEC_NOPREFS))
++ else if(ast_test_flag64(user, IAX_CODEC_NOPREFS))
+ pstr = "Disabled";
+ else
+- pstr = ast_test_flag(user,IAX_CODEC_USER_FIRST) ? "Caller" : "Host";
+-
++ pstr = ast_test_flag64(user, IAX_CODEC_USER_FIRST) ? "Caller" : "Host";
++
+ ast_cli(a->fd, FORMAT2, user->name, auth, user->authmethods,
+ user->contexts ? user->contexts->context : DEFAULT_CONTEXT,
+ user->ha ? "Yes" : "No", pstr);
+@@ -5341,7 +5423,7 @@
+ #undef FORMAT2
+ }
+
+-static int __iax2_show_peers(int manager, int fd, struct mansession *s, int argc, char *argv[])
++static int __iax2_show_peers(int manager, int fd, struct mansession *s, const int argc, const char * const argv[])
+ {
+ regex_t regexbuf;
+ int havepattern = 0;
+@@ -5441,17 +5523,17 @@
+ name,
+ peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "-none-",
+ ntohs(peer->addr.sin_port),
+- ast_test_flag(peer, IAX_DYNAMIC) ? "yes" : "no",
+- ast_test_flag(peer, IAX_TRUNK) ? "yes" : "no",
++ ast_test_flag64(peer, IAX_DYNAMIC) ? "yes" : "no",
++ ast_test_flag64(peer, IAX_TRUNK) ? "yes" : "no",
+ peer->encmethods ? ast_str_buffer(encmethods) : "no",
+ status);
+ } else {
+ ast_cli(fd, FORMAT, name,
+ peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
+- ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
++ ast_test_flag64(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
+ nm,
+ ntohs(peer->addr.sin_port),
+- ast_test_flag(peer, IAX_TRUNK) ? "(T)" : " ",
++ ast_test_flag64(peer, IAX_TRUNK) ? "(T)" : " ",
+ peer->encmethods ? "(E)" : " ",
+ status,
+ term);
+@@ -5672,14 +5754,14 @@
+ /*! \brief callback to display iax peers in manager */
+ static int manager_iax2_show_peers(struct mansession *s, const struct message *m)
+ {
+- char *a[] = { "iax2", "show", "users" };
++ static const char * const a[] = { "iax2", "show", "peers" };
+ const char *id = astman_get_header(m,"ActionID");
+ char idtext[256] = "";
+
+ if (!ast_strlen_zero(id))
+ snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
+ astman_send_ack(s, m, "Peer status list will follow");
+- return __iax2_show_peers(1, -1, s, 3, a );
++ return __iax2_show_peers(1, -1, s, 3, a);
+ }
+
+ /*! \brief callback to display iax peers in manager format */
+@@ -5714,8 +5796,8 @@
+ ast_copy_string(nm, ast_inet_ntoa(peer->mask), sizeof(nm));
+ astman_append(s, "Mask: %s\r\n", nm);
+ astman_append(s, "Port: %d\r\n", ntohs(peer->addr.sin_port));
+- astman_append(s, "Dynamic: %s\r\n", ast_test_flag(peer, IAX_DYNAMIC) ? "Yes" : "No");
+- astman_append(s, "Trunk: %s\r\n", ast_test_flag(peer, IAX_TRUNK) ? "Yes" : "No");
++ astman_append(s, "Dynamic: %s\r\n", ast_test_flag64(peer, IAX_DYNAMIC) ? "Yes" : "No");
++ astman_append(s, "Trunk: %s\r\n", ast_test_flag64(peer, IAX_TRUNK) ? "Yes" : "No");
+ astman_append(s, "Encryption: %s\r\n", peer->encmethods ? ast_str_buffer(encmethods) : "No");
+ peer_status(peer, status, sizeof(status));
+ astman_append(s, "Status: %s\r\n\r\n", status);
+@@ -5868,7 +5950,7 @@
+ if (iaxs[x]) {
+ int lag, jitter, localdelay;
+ jb_info jbinfo;
+- if (ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) {
++ if (ast_test_flag64(iaxs[x], IAX_USEJITTERBUF)) {
+ jb_getinfo(iaxs[x]->jb, &jbinfo);
+ jitter = jbinfo.jitter;
+ localdelay = jbinfo.current - jbinfo.min;
+@@ -5921,7 +6003,7 @@
+ iax_frame_subclass2str(iaxs[x]->first_iax_message & ~MARK_IAX_SUBCLASS_TX, first_message, sizeof(first_message));
+ iax_frame_subclass2str(iaxs[x]->last_iax_message & ~MARK_IAX_SUBCLASS_TX, last_message, sizeof(last_message));
+
+- if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) {
++ if(ast_test_flag64(iaxs[x], IAX_USEJITTERBUF)) {
+ jb_getinfo(iaxs[x]->jb, &jbinfo);
+ localjitter = jbinfo.jitter;
+ localdelay = jbinfo.current - jbinfo.min;
+@@ -6121,12 +6203,12 @@
+ if (iaxs[callno]) {
+ /* If there's an outstanding error, return failure now */
+ if (!iaxs[callno]->error) {
+- if (ast_test_flag(iaxs[callno], IAX_ALREADYGONE))
++ if (ast_test_flag64(iaxs[callno], IAX_ALREADYGONE))
+ res = 0;
+ /* Don't waste bandwidth sending null frames */
+ else if (f->frametype == AST_FRAME_NULL)
+ res = 0;
+- else if ((f->frametype == AST_FRAME_VOICE) && ast_test_flag(iaxs[callno], IAX_QUELCH))
++ else if ((f->frametype == AST_FRAME_VOICE) && ast_test_flag64(iaxs[callno], IAX_QUELCH))
+ res = 0;
+ else if (!ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED))
+ res = 0;
+@@ -6347,15 +6429,15 @@
+ }
+ /* If a max AUTHREQ restriction is in place, activate it */
+ if (user->maxauthreq > 0)
+- ast_set_flag(iaxs[callno], IAX_MAXAUTHREQ);
++ ast_set_flag64(iaxs[callno], IAX_MAXAUTHREQ);
+ iaxs[callno]->prefs = user->prefs;
+- ast_copy_flags(iaxs[callno], user, IAX_CODEC_USER_FIRST | IAX_IMMEDIATE | IAX_CODEC_NOPREFS | IAX_CODEC_NOCAP | IAX_FORCE_ENCRYPT);
++ ast_copy_flags64(iaxs[callno], user, IAX_CODEC_USER_FIRST | IAX_IMMEDIATE | IAX_CODEC_NOPREFS | IAX_CODEC_NOCAP | IAX_FORCE_ENCRYPT);
+ iaxs[callno]->encmethods = user->encmethods;
+ /* Store the requested username if not specified */
+ if (ast_strlen_zero(iaxs[callno]->username))
+ ast_string_field_set(iaxs[callno], username, user->name);
+ /* Store whether this is a trunked call, too, of course, and move if appropriate */
+- ast_copy_flags(iaxs[callno], user, IAX_TRUNK);
++ ast_copy_flags64(iaxs[callno], user, IAX_TRUNK);
+ iaxs[callno]->capability = user->capability;
+ /* And use the default context */
+ if (ast_strlen_zero(iaxs[callno]->context)) {
+@@ -6370,7 +6452,7 @@
+ iaxs[callno]->authmethods = user->authmethods;
+ iaxs[callno]->adsi = user->adsi;
+ /* If the user has callerid, override the remote caller id. */
+- if (ast_test_flag(user, IAX_HASCALLERID)) {
++ if (ast_test_flag64(user, IAX_HASCALLERID)) {
+ iaxs[callno]->calling_tns = 0;
+ iaxs[callno]->calling_ton = 0;
+ ast_string_field_set(iaxs[callno], cid_num, user->cid_num);
+@@ -6392,7 +6474,7 @@
+ iaxs[callno]->amaflags = user->amaflags;
+ if (!ast_strlen_zero(user->language))
+ ast_string_field_set(iaxs[callno], language, user->language);
+- ast_copy_flags(iaxs[callno], user, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
++ ast_copy_flags64(iaxs[callno], user, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
+ /* Keep this check last */
+ if (!ast_strlen_zero(user->dbsecret)) {
+ char *family, *key=NULL;
+@@ -6424,7 +6506,7 @@
+ res = 0;
+ }
+ }
+- ast_set2_flag(iaxs[callno], iax2_getpeertrunk(*sin), IAX_TRUNK);
++ ast_set2_flag64(iaxs[callno], iax2_getpeertrunk(*sin), IAX_TRUNK);
+ return res;
+ }
+
+@@ -6478,7 +6560,7 @@
+ memset(&ied, 0, sizeof(ied));
+
+ /* If an AUTHREQ restriction is in place, make sure we can send an AUTHREQ back */
+- if (ast_test_flag(p, IAX_MAXAUTHREQ)) {
++ if (ast_test_flag64(p, IAX_MAXAUTHREQ)) {
+ struct iax2_user *user, tmp_user = {
+ .name = p->username,
+ };
+@@ -6516,7 +6598,7 @@
+ res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREQ, 0, ied.buf, ied.pos, -1);
+
+ if (p->encmethods)
+- ast_set_flag(p, IAX_ENCRYPTED);
++ ast_set_flag64(p, IAX_ENCRYPTED);
+
+ return res;
+ }
+@@ -6538,14 +6620,14 @@
+ }
+ user = ao2_find(users, &tmp_user, OBJ_POINTER);
+ if (user) {
+- if (ast_test_flag(p, IAX_MAXAUTHREQ)) {
++ if (ast_test_flag64(p, IAX_MAXAUTHREQ)) {
+ ast_atomic_fetchadd_int(&user->curauthreq, -1);
+- ast_clear_flag(p, IAX_MAXAUTHREQ);
++ ast_clear_flag64(p, IAX_MAXAUTHREQ);
+ }
+ ast_string_field_set(p, host, user->name);
+ user = user_unref(user);
+ }
+- if (ast_test_flag(p, IAX_FORCE_ENCRYPT) && !p->encmethods) {
++ if (ast_test_flag64(p, IAX_FORCE_ENCRYPT) && !p->encmethods) {
+ ast_log(LOG_NOTICE, "Call Terminated, Incomming call is unencrypted while force encrypt is enabled.");
+ return res;
+ }
+@@ -6663,7 +6745,7 @@
+ goto return_unref;
+ }
+
+- if (!ast_test_flag(p, IAX_DYNAMIC)) {
++ if (!ast_test_flag64(p, IAX_DYNAMIC)) {
+ if (authdebug)
+ ast_log(LOG_NOTICE, "Peer '%s' is not dynamic (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr));
+ goto return_unref;
+@@ -6885,8 +6967,8 @@
+ }
+
+ if (ies->encmethods) {
+- ast_set_flag(p, IAX_ENCRYPTED | IAX_KEYPOPULATED);
+- } else if (ast_test_flag(iaxs[callno], IAX_FORCE_ENCRYPT)) {
++ ast_set_flag64(p, IAX_ENCRYPTED | IAX_KEYPOPULATED);
++ } else if (ast_test_flag64(iaxs[callno], IAX_FORCE_ENCRYPT)) {
+ ast_log(LOG_NOTICE, "Call initiated without encryption while forceencryption=yes option is set");
+ return -1; /* if force encryption is yes, and no encryption methods, then return -1 to hangup */
+ }
+@@ -7072,16 +7154,13 @@
+ pvt->lastsent = 0;
+ pvt->nextpred = 0;
+ pvt->pingtime = DEFAULT_RETRY_TIME;
+- AST_LIST_LOCK(&frame_queue);
+- AST_LIST_TRAVERSE(&frame_queue, cur, list) {
++ AST_LIST_TRAVERSE(&frame_queue[callno], cur, list) {
+ /* We must cancel any packets that would have been transmitted
+ because now we're talking to someone new. It's okay, they
+ were transmitted to someone that didn't care anyway. */
+- if (callno == cur->callno)
+- cur->retries = -1;
++ cur->retries = -1;
+ }
+- AST_LIST_UNLOCK(&frame_queue);
+- return 0;
++ return 0;
+ }
+
+ /*! \brief Acknowledgment received for OUR registration */
+@@ -7258,21 +7337,21 @@
+ peer->expire = -1;
+
+ ast_debug(1, "Expiring registration for peer '%s'\n", peer->name);
+- if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(peer, IAX_TEMPONLY|IAX_RTCACHEFRIENDS)))
++ if (ast_test_flag64((&globalflags), IAX_RTUPDATE) && (ast_test_flag64(peer, IAX_TEMPONLY|IAX_RTCACHEFRIENDS)))
+ realtime_update_peer(peer->name, &peer->addr, 0);
+ manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: IAX2\r\nPeer: IAX2/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", peer->name);
+ /* Reset the address */
+ memset(&peer->addr, 0, sizeof(peer->addr));
+ /* Reset expiry value */
+ peer->expiry = min_reg_expire;
+- if (!ast_test_flag(peer, IAX_TEMPONLY))
++ if (!ast_test_flag64(peer, IAX_TEMPONLY))
+ ast_db_del("IAX/Registry", peer->name);
+ register_peer_exten(peer, 0);
+ ast_devstate_changed(AST_DEVICE_UNAVAILABLE, "IAX2/%s", peer->name); /* Activate notification */
+ if (iax2_regfunk)
+ iax2_regfunk(peer->name, 0);
+
+- if (ast_test_flag(peer, IAX_RTAUTOCLEAR))
++ if (ast_test_flag64(peer, IAX_RTAUTOCLEAR))
+ unlink_peer(peer);
+
+ peer_unref(peer);
+@@ -7294,7 +7373,7 @@
+ char data[80];
+ struct in_addr in;
+ char *c, *d;
+- if (!ast_test_flag(p, IAX_TEMPONLY) && (!ast_db_get("IAX/Registry", p->name, data, sizeof(data)))) {
++ if (!ast_test_flag64(p, IAX_TEMPONLY) && (!ast_db_get("IAX/Registry", p->name, data, sizeof(data)))) {
+ c = strchr(data, ':');
+ if (c) {
+ *c = '\0';
+@@ -7364,7 +7443,7 @@
+ if (!iaxs[callno])
+ goto return_unref;
+
+- if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(p, IAX_TEMPONLY|IAX_RTCACHEFRIENDS))) {
++ if (ast_test_flag64((&globalflags), IAX_RTUPDATE) && (ast_test_flag64(p, IAX_TEMPONLY|IAX_RTCACHEFRIENDS))) {
+ if (sin->sin_addr.s_addr) {
+ time_t nowtime;
+ time(&nowtime);
+@@ -7379,14 +7458,14 @@
+ /* Stash the IP address from which they registered */
+ memcpy(&p->addr, sin, sizeof(p->addr));
+ snprintf(data, sizeof(data), "%s:%d:%d", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), p->expiry);
+- if (!ast_test_flag(p, IAX_TEMPONLY) && sin->sin_addr.s_addr) {
++ if (!ast_test_flag64(p, IAX_TEMPONLY) && sin->sin_addr.s_addr) {
+ ast_db_put("IAX/Registry", p->name, data);
+ ast_verb(3, "Registered IAX2 '%s' (%s) at %s:%d\n", p->name,
+ ast_test_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED) ? "AUTHENTICATED" : "UNAUTHENTICATED", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
+ manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: IAX2\r\nPeer: IAX2/%s\r\nPeerStatus: Registered\r\n", p->name);
+ register_peer_exten(p, 1);
+ ast_devstate_changed(AST_DEVICE_UNKNOWN, "IAX2/%s", p->name); /* Activate notification */
+- } else if (!ast_test_flag(p, IAX_TEMPONLY)) {
++ } else if (!ast_test_flag64(p, IAX_TEMPONLY)) {
+ ast_verb(3, "Unregistered IAX2 '%s' (%s)\n", p->name,
+ ast_test_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED) ? "AUTHENTICATED" : "UNAUTHENTICATED");
+ manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: IAX2\r\nPeer: IAX2/%s\r\nPeerStatus: Unregistered\r\n", p->name);
+@@ -7470,7 +7549,7 @@
+
+ iax_ie_append_short(&ied, IAX_IE_MSGCOUNT, msgcount);
+ }
+- if (ast_test_flag(p, IAX_HASCALLERID)) {
++ if (ast_test_flag64(p, IAX_HASCALLERID)) {
+ iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, p->cid_num);
+ iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, p->cid_name);
+ }
+@@ -7687,16 +7766,13 @@
+ {
+ struct iax_frame *f;
+
+- AST_LIST_LOCK(&frame_queue);
+- AST_LIST_TRAVERSE(&frame_queue, f, list) {
++ AST_LIST_TRAVERSE(&frame_queue[callno], f, list) {
+ /* Send a copy immediately */
+- if ((f->callno == callno) && iaxs[f->callno] &&
+- ((unsigned char ) (f->oseqno - last) < 128) &&
+- (f->retries >= 0)) {
++ if (((unsigned char) (f->oseqno - last) < 128) &&
++ (f->retries >= 0)) {
+ send_packet(f);
+ }
+ }
+- AST_LIST_UNLOCK(&frame_queue);
+ }
+
+ static void __iax2_poke_peer_s(const void *data)
+@@ -7734,7 +7810,7 @@
+ /* We're actually sending a frame, so fill the meta trunk header and meta header */
+ meta->zeros = 0;
+ meta->metacmd = IAX_META_TRUNK;
+- if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS))
++ if (ast_test_flag64(&globalflags, IAX_TRUNKTIMESTAMPS))
+ meta->cmddata = IAX_META_TRUNK_MINI;
+ else
+ meta->cmddata = IAX_META_TRUNK_SUPERMINI;
+@@ -7972,9 +8048,6 @@
+ return -1;
+ }
+
+-
+-static int iax2_provision(struct sockaddr_in *end, int sockfd, char *dest, const char *template, int force);
+-
+ static int check_provisioning(struct sockaddr_in *sin, int sockfd, char *si, unsigned int ver)
+ {
+ unsigned int ourver;
+@@ -8052,7 +8125,7 @@
+
+ ast_mutex_lock(&iaxsl[callno]);
+ if (iaxs[callno] && iaxs[callno]->owner && iaxs[callno]->owner->name) {
+- if(ast_test_flag(iaxs[callno], IAX_USEJITTERBUF)) {
++ if(ast_test_flag64(iaxs[callno], IAX_USEJITTERBUF)) {
+ jb_getinfo(iaxs[callno]->jb, &jbinfo);
+ localjitter = jbinfo.jitter;
+ localdelay = jbinfo.current - jbinfo.min;
+@@ -8518,7 +8591,7 @@
+ /* Deal with POKE/PONG without allocating a callno */
+ if (f.frametype == AST_FRAME_IAX && f.subclass == IAX_COMMAND_POKE) {
+ /* Reply back with a PONG, but don't care about the result. */
+- send_apathetic_reply(1, ntohs(fh->scallno), &sin, IAX_COMMAND_PONG, ntohs(fh->ts), fh->iseqno + 1);
++ send_apathetic_reply(1, ntohs(fh->scallno), &sin, IAX_COMMAND_PONG, ntohl(fh->ts), fh->iseqno + 1);
+ return 1;
+ } else if (f.frametype == AST_FRAME_IAX && f.subclass == IAX_COMMAND_ACK && dcallno == 1) {
+ /* Ignore */
+@@ -8577,7 +8650,7 @@
+ ast_mutex_unlock(&iaxsl[fr->callno]);
+ return 1;
+ }
+- if (ast_test_flag(iaxs[fr->callno], IAX_ENCRYPTED)) {
++ if (ast_test_flag64(iaxs[fr->callno], IAX_ENCRYPTED)) {
+ if (decrypt_frame(fr->callno, fh, &f, &res)) {
+ ast_log(LOG_NOTICE, "Packet Decrypt Failed!\n");
+ ast_mutex_unlock(&iaxsl[fr->callno]);
+@@ -8713,17 +8786,15 @@
+ if (iaxdebug)
+ ast_debug(1, "Cancelling transmission of packet %d\n", x);
+ call_to_destroy = 0;
+- AST_LIST_LOCK(&frame_queue);
+- AST_LIST_TRAVERSE(&frame_queue, cur, list) {
++ AST_LIST_TRAVERSE(&frame_queue[fr->callno], cur, list) {
+ /* If it's our call, and our timestamp, mark -1 retries */
+- if ((fr->callno == cur->callno) && (x == cur->oseqno)) {
++ if (x == cur->oseqno) {
+ cur->retries = -1;
+ /* Destroy call if this is the end */
+ if (cur->final)
+ call_to_destroy = fr->callno;
+ }
+ }
+- AST_LIST_UNLOCK(&frame_queue);
+ if (call_to_destroy) {
+ if (iaxdebug)
+ ast_debug(1, "Really destroying %d, having been acked on final message\n", call_to_destroy);
+@@ -8780,8 +8851,8 @@
+ if ((f.frametype == AST_FRAME_VOICE) ||
+ (f.frametype == AST_FRAME_VIDEO) ||
+ (f.frametype == AST_FRAME_IAX)) {
+- if (ast_test_flag(iaxs[fr->callno], IAX_DELAYPBXSTART)) {
+- ast_clear_flag(iaxs[fr->callno], IAX_DELAYPBXSTART);
++ if (ast_test_flag64(iaxs[fr->callno], IAX_DELAYPBXSTART)) {
++ ast_clear_flag64(iaxs[fr->callno], IAX_DELAYPBXSTART);
+ if (!ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->chosenformat)) {
+ ast_mutex_unlock(&iaxsl[fr->callno]);
+ return 1;
+@@ -8928,7 +8999,7 @@
+ iaxs[fr->callno]->owner->uniqueid);
+ }
+
+- ast_set_flag(iaxs[fr->callno], IAX_QUELCH);
++ ast_set_flag64(iaxs[fr->callno], IAX_QUELCH);
+ if (ies.musiconhold) {
+ if (iaxs[fr->callno]->owner && ast_bridged_channel(iaxs[fr->callno]->owner)) {
+ const char *moh_suggest = iaxs[fr->callno]->mohsuggest;
+@@ -8946,7 +9017,7 @@
+ case IAX_COMMAND_UNQUELCH:
+ if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) {
+ /* Generate Manager Unhold event, if necessary*/
+- if (iaxs[fr->callno]->owner && ast_test_flag(iaxs[fr->callno], IAX_QUELCH)) {
++ if (iaxs[fr->callno]->owner && ast_test_flag64(iaxs[fr->callno], IAX_QUELCH)) {
+ manager_event(EVENT_FLAG_CALL, "Hold",
+ "Status: Off\r\n"
+ "Channel: %s\r\n"
+@@ -8955,7 +9026,7 @@
+ iaxs[fr->callno]->owner->uniqueid);
+ }
+
+- ast_clear_flag(iaxs[fr->callno], IAX_QUELCH);
++ ast_clear_flag64(iaxs[fr->callno], IAX_QUELCH);
+ if (iaxs[fr->callno]->owner && ast_bridged_channel(iaxs[fr->callno]->owner)) {
+ iax2_queue_control_data(fr->callno, AST_CONTROL_UNHOLD, NULL, 0);
+ if (!iaxs[fr->callno]) {
+@@ -8968,13 +9039,12 @@
+ case IAX_COMMAND_TXACC:
+ if (iaxs[fr->callno]->transferring == TRANSFER_BEGIN) {
+ /* Ack the packet with the given timestamp */
+- AST_LIST_LOCK(&frame_queue);
+- AST_LIST_TRAVERSE(&frame_queue, cur, list) {
++ AST_LIST_TRAVERSE(&frame_queue[fr->callno], cur, list) {
+ /* Cancel any outstanding txcnt's */
+- if ((fr->callno == cur->callno) && (cur->transfer))
++ if (cur->transfer) {
+ cur->retries = -1;
++ }
+ }
+- AST_LIST_UNLOCK(&frame_queue);
+ memset(&ied1, 0, sizeof(ied1));
+ iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->callno);
+ send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXREADY, 0, ied1.buf, ied1.pos, -1);
+@@ -8995,7 +9065,7 @@
+ }
+ }
+ /* 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)) {
++ if (ast_test_flag64(iaxs[fr->callno], IAX_TRUNK)) {
+ int new_callno;
+ if ((new_callno = make_trunk(fr->callno, 1)) != -1)
+ fr->callno = new_callno;
+@@ -9010,7 +9080,7 @@
+ ast_log(LOG_NOTICE, "Rejected connect attempt from %s, who was trying to reach '%s@%s'\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->exten, iaxs[fr->callno]->context);
+ break;
+ }
+- if (ast_strlen_zero(iaxs[fr->callno]->secret) && ast_test_flag(iaxs[fr->callno], IAX_FORCE_ENCRYPT)) {
++ if (ast_strlen_zero(iaxs[fr->callno]->secret) && ast_test_flag64(iaxs[fr->callno], IAX_FORCE_ENCRYPT)) {
+ auth_fail(fr->callno, IAX_COMMAND_REJECT);
+ ast_log(LOG_WARNING, "Rejected connect attempt. No secret present while force encrypt enabled.\n");
+ break;
+@@ -9050,8 +9120,8 @@
+ } 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)) {
++ if(ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOPREFS)) {
++ if(ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOCAP)) {
+ using_prefs = "reqonly";
+ } else {
+ using_prefs = "disabled";
+@@ -9067,7 +9137,7 @@
+ ast_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0);
+ if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 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)) {
++ if (ast_test_flag64(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) {
+ pref = iaxs[fr->callno]->rprefs;
+ using_prefs = "caller";
+ } else {
+@@ -9075,13 +9145,13 @@
+ }
+ } else
+ pref = iaxs[fr->callno]->prefs;
+-
++
+ format = ast_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability, 0);
+ ast_codec_pref_string(&iaxs[fr->callno]->rprefs, 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))
++ if(!ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOCAP))
+ format = iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability;
+ if (!format) {
+ memset(&ied0, 0, sizeof(ied0));
+@@ -9093,19 +9163,19 @@
+ return 1;
+ }
+ if (authdebug) {
+- if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP))
++ if(ast_test_flag64(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(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(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(ast_test_flag64(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";
++ if(ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOPREFS)) {
++ using_prefs = ast_test_flag64(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");
+@@ -9114,16 +9184,15 @@
+ using_prefs = "mine";
+ if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) {
+ /* Do the opposite of what we tried above. */
+- if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) {
+- pref = iaxs[fr->callno]->prefs;
++ if (ast_test_flag64(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) {
++ pref = iaxs[fr->callno]->prefs;
+ } else {
+ pref = iaxs[fr->callno]->rprefs;
+ 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);
++ format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability);
+ }
+ }
+
+@@ -9139,7 +9208,7 @@
+ }
+ 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(sin.sin_addr), iaxs[fr->callno]->peerformat, iaxs[fr->callno]->peercapability, iaxs[fr->callno]->capability);
+- ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE);
++ ast_set_flag64(iaxs[fr->callno], IAX_ALREADYGONE);
+ break;
+ }
+ }
+@@ -9168,9 +9237,9 @@
+ host_pref_buf,
+ VERBOSE_PREFIX_4,
+ using_prefs);
+-
++
+ iaxs[fr->callno]->chosenformat = format;
+- ast_set_flag(iaxs[fr->callno], IAX_DELAYPBXSTART);
++ ast_set_flag64(iaxs[fr->callno], IAX_DELAYPBXSTART);
+ } else {
+ ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD);
+ /* If this is a TBD call, we're ready but now what... */
+@@ -9205,7 +9274,7 @@
+ }
+ break;
+ case IAX_COMMAND_HANGUP:
+- ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE);
++ ast_set_flag64(iaxs[fr->callno], IAX_ALREADYGONE);
+ ast_debug(1, "Immediately destroying %d, having received hangup\n", fr->callno);
+ /* Set hangup cause according to remote */
+ if (ies.causecode && iaxs[fr->callno]->owner)
+@@ -9219,7 +9288,7 @@
+ if (ies.causecode && iaxs[fr->callno]->owner)
+ iaxs[fr->callno]->owner->hangupcause = ies.causecode;
+
+- if (!ast_test_flag(iaxs[fr->callno], IAX_PROVISION)) {
++ if (!ast_test_flag64(iaxs[fr->callno], IAX_PROVISION)) {
+ if (iaxs[fr->callno]->owner && authdebug)
+ ast_log(LOG_WARNING, "Call rejected by %s: %s\n",
+ ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr),
+@@ -9230,7 +9299,7 @@
+ /* Send ack immediately, before we destroy */
+ send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK,
+ fr->ts, NULL, 0, fr->iseqno);
+- if (!ast_test_flag(iaxs[fr->callno], IAX_PROVISION))
++ if (!ast_test_flag64(iaxs[fr->callno], IAX_PROVISION))
+ iaxs[fr->callno]->error = EPERM;
+ iax2_destroy(fr->callno);
+ break;
+@@ -9278,7 +9347,7 @@
+ /* Ignore if call is already up or needs authentication or is a TBD */
+ if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD | IAX_STATE_AUTHENTICATED))
+ break;
+- if (ast_test_flag(iaxs[fr->callno], IAX_PROVISION)) {
++ if (ast_test_flag64(iaxs[fr->callno], IAX_PROVISION)) {
+ /* 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(fr->callno);
+@@ -9479,8 +9548,8 @@
+ }
+ } 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)) {
++ if(ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOPREFS)) {
++ if(ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOCAP)) {
+ using_prefs = "reqonly";
+ } else {
+ using_prefs = "disabled";
+@@ -9494,7 +9563,7 @@
+ if (ies.codec_prefs)
+ ast_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0);
+ if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) {
+- if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) {
++ if (ast_test_flag64(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) {
+ pref = iaxs[fr->callno]->rprefs;
+ using_prefs = "caller";
+ } else {
+@@ -9502,19 +9571,18 @@
+ }
+ } else /* if no codec_prefs IE do it the old way */
+ pref = iaxs[fr->callno]->prefs;
+-
+ format = ast_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability, 0);
+ ast_codec_pref_string(&iaxs[fr->callno]->rprefs, 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)) {
++ if(!ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOCAP)) {
+ ast_debug(1, "We don't do requested format %s, falling back to peer capability %d\n", ast_getformatname(iaxs[fr->callno]->peerformat), iaxs[fr->callno]->peercapability);
+ format = iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability;
+ }
+ if (!format) {
+ if (authdebug) {
+- if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP))
++ if(ast_test_flag64(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(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(sin.sin_addr), iaxs[fr->callno]->peerformat, iaxs[fr->callno]->peercapability, iaxs[fr->callno]->capability);
+@@ -9529,14 +9597,14 @@
+ }
+ } else {
+ /* Pick one... */
+- if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) {
++ if(ast_test_flag64(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";
++ if(ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOPREFS)) {
++ using_prefs = ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOCAP) ? "reqonly" : "disabled";
+ memset(&pref, 0, sizeof(pref));
+- format = ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP) ?
++ format = ast_test_flag64(iaxs[fr->callno], IAX_CODEC_NOCAP) ?
+ iaxs[fr->callno]->peerformat : ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability);
+ strcpy(caller_pref_buf,"disabled");
+ strcpy(host_pref_buf,"disabled");
+@@ -9544,8 +9612,8 @@
+ using_prefs = "mine";
+ if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) {
+ /* Do the opposite of what we tried above. */
+- if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) {
+- pref = iaxs[fr->callno]->prefs;
++ if (ast_test_flag64(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) {
++ pref = iaxs[fr->callno]->prefs;
+ } else {
+ pref = iaxs[fr->callno]->rprefs;
+ using_prefs = "caller";
+@@ -9558,7 +9626,7 @@
+ if (!format) {
+ ast_log(LOG_ERROR, "No best format in 0x%x???\n", iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability);
+ if (authdebug) {
+- if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP))
++ if(ast_test_flag64(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(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(sin.sin_addr), iaxs[fr->callno]->peerformat, iaxs[fr->callno]->peercapability, iaxs[fr->callno]->capability);
+@@ -9641,7 +9709,7 @@
+ ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD);
+ /* If this is a TBD call, we're ready but now what... */
+ ast_verb(3, "Accepted AUTHENTICATED TBD call from %s\n", ast_inet_ntoa(sin.sin_addr));
+- if (ast_test_flag(iaxs[fr->callno], IAX_IMMEDIATE)) {
++ if (ast_test_flag64(iaxs[fr->callno], IAX_IMMEDIATE)) {
+ goto immediatedial;
+ }
+ }
+@@ -9840,8 +9908,8 @@
+
+ iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_RELEASED;
+ iaxs[fr->callno]->transferring = TRANSFER_RELEASED;
+- ast_set_flag(iaxs[iaxs[fr->callno]->bridgecallno], IAX_ALREADYGONE);
+- ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE);
++ ast_set_flag64(iaxs[iaxs[fr->callno]->bridgecallno], IAX_ALREADYGONE);
++ ast_set_flag64(iaxs[fr->callno], IAX_ALREADYGONE);
+
+ /* Stop doing lag & ping requests */
+ stop_stuff(fr->callno);
+@@ -9874,13 +9942,12 @@
+ break;
+ case IAX_COMMAND_TXMEDIA:
+ if (iaxs[fr->callno]->transferring == TRANSFER_READY) {
+- AST_LIST_LOCK(&frame_queue);
+- AST_LIST_TRAVERSE(&frame_queue, cur, list) {
++ AST_LIST_TRAVERSE(&frame_queue[fr->callno], cur, list) {
+ /* Cancel any outstanding frames and start anew */
+- if ((fr->callno == cur->callno) && (cur->transfer))
++ if (cur->transfer) {
+ cur->retries = -1;
++ }
+ }
+- AST_LIST_UNLOCK(&frame_queue);
+ /* Start sending our media to the transfer address, but otherwise leave the call as-is */
+ iaxs[fr->callno]->transferring = TRANSFER_MEDIAPASS;
+ }
+@@ -9906,7 +9973,7 @@
+ break;
+ case IAX_COMMAND_FWDOWNL:
+ /* Firmware download */
+- if (!ast_test_flag(&globalflags, IAX_ALLOWFWDOWNLOAD)) {
++ if (!ast_test_flag64(&globalflags, IAX_ALLOWFWDOWNLOAD)) {
+ send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_UNSUPPORT, 0, NULL, 0, -1);
+ break;
+ }
+@@ -10006,6 +10073,31 @@
+ ast_mutex_unlock(&iaxsl[fr->callno]);
+ return 1;
+ }
++ /* Don't allow connected line updates unless we are configured to */
++ if (f.frametype == AST_FRAME_CONTROL && f.subclass == AST_CONTROL_CONNECTED_LINE) {
++ struct ast_party_connected_line connected;
++
++ if (!ast_test_flag64(iaxs[fr->callno], IAX_RECVCONNECTEDLINE)) {
++ ast_mutex_unlock(&iaxsl[fr->callno]);
++ return 1;
++ }
++
++ /* Initialize defaults */
++ ast_party_connected_line_init(&connected);
++ connected.id.number_presentation = iaxs[fr->callno]->calling_pres;
++
++ if (!ast_connected_line_parse_data(f.data.ptr, f.datalen, &connected)) {
++ ast_string_field_set(iaxs[fr->callno], cid_num, connected.id.number);
++ ast_string_field_set(iaxs[fr->callno], cid_name, connected.id.name);
++ iaxs[fr->callno]->calling_pres = connected.id.number_presentation;
++
++ if (iaxs[fr->callno]->owner) {
++ ast_set_callerid(iaxs[fr->callno]->owner, S_OR(connected.id.number, ""), S_OR(connected.id.name, ""), NULL);
++ iaxs[fr->callno]->owner->cid.cid_pres = connected.id.number_presentation;
++ }
++ }
++ ast_party_connected_line_free(&connected);
++ }
+ /* Common things */
+ f.src = "IAX2";
+ f.mallocd = 0;
+@@ -10243,7 +10335,7 @@
+ return 0;
+ }
+
+-static int iax2_provision(struct sockaddr_in *end, int sockfd, char *dest, const char *template, int force)
++static int iax2_provision(struct sockaddr_in *end, int sockfd, const char *dest, const char *template, int force)
+ {
+ /* Returns 1 if provisioned, -1 if not able to find destination, or 0 if no provisioning
+ is found for template */
+@@ -10281,7 +10373,7 @@
+ /* Schedule autodestruct in case they don't ever give us anything back */
+ iaxs[callno]->autoid = iax2_sched_replace(iaxs[callno]->autoid,
+ sched, 15000, auto_hangup, (void *)(long)callno);
+- ast_set_flag(iaxs[callno], IAX_PROVISION);
++ ast_set_flag64(iaxs[callno], IAX_PROVISION);
+ /* Got a call number now, so go ahead and send the provisioning information */
+ send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PROVISION, 0, ied.buf, ied.pos, -1);
+ }
+@@ -10295,7 +10387,7 @@
+ /*! iax2provision
+ \ingroup applications
+ */
+-static int iax2_prov_app(struct ast_channel *chan, void *data)
++static int iax2_prov_app(struct ast_channel *chan, const char *data)
+ {
+ int res;
+ char *sdata;
+@@ -10501,7 +10593,7 @@
+ memset(&cai, 0, sizeof(cai));
+ cai.capability = iax2_capability;
+
+- ast_copy_flags(&cai, &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
++ ast_copy_flags64(&cai, &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
+
+ /* Populate our address from the given */
+ if (create_addr(pds.peer, NULL, &sin, &cai)) {
+@@ -10520,8 +10612,8 @@
+ }
+
+ /* If this is a trunk, update it now */
+- ast_copy_flags(iaxs[callno], &cai, IAX_TRUNK | IAX_SENDANI | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
+- if (ast_test_flag(&cai, IAX_TRUNK)) {
++ ast_copy_flags64(iaxs[callno], &cai, IAX_TRUNK | IAX_SENDANI | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
++ if (ast_test_flag64(&cai, IAX_TRUNK)) {
+ int new_callno;
+ if ((new_callno = make_trunk(callno, 1)) != -1)
+ callno = new_callno;
+@@ -10559,66 +10651,18 @@
+
+ static void *network_thread(void *ignore)
+ {
+- /* Our job is simple: Send queued messages, retrying if necessary. Read frames
+- from the network, and queue them for delivery to the channels */
+- int res, count, wakeup;
+- struct iax_frame *f;
+-
+- if (timer)
++ if (timer) {
+ ast_io_add(io, ast_timer_fd(timer), timing_read, AST_IO_IN | AST_IO_PRI, NULL);
+-
+- for(;;) {
+- pthread_testcancel();
++ }
+
+- /* Go through the queue, sending messages which have not yet been
+- sent, and scheduling retransmissions if appropriate */
+- AST_LIST_LOCK(&frame_queue);
+- count = 0;
+- wakeup = -1;
+- AST_LIST_TRAVERSE_SAFE_BEGIN(&frame_queue, f, list) {
+- if (f->sentyet)
+- continue;
+-
+- /* Try to lock the pvt, if we can't... don't fret - defer it till later */
+- if (ast_mutex_trylock(&iaxsl[f->callno])) {
+- wakeup = 1;
+- continue;
+- }
+-
+- f->sentyet = 1;
+-
+- if (iaxs[f->callno]) {
+- send_packet(f);
+- count++;
+- }
+-
+- ast_mutex_unlock(&iaxsl[f->callno]);
+-
+- if (f->retries < 0) {
+- /* This is not supposed to be retransmitted */
+- AST_LIST_REMOVE_CURRENT(list);
+- /* Free the iax frame */
+- iax_frame_free(f);
+- } else {
+- /* We need reliable delivery. Schedule a retransmission */
+- f->retries++;
+- f->retrans = iax2_sched_add(sched, f->retrytime, attempt_transmit, f);
+- }
+- }
+- AST_LIST_TRAVERSE_SAFE_END;
+- AST_LIST_UNLOCK(&frame_queue);
+-
++ for (;;) {
+ pthread_testcancel();
+- if (count >= 20)
+- ast_debug(1, "chan_iax2: Sent %d queued outbound frames all at once\n", count);
++ /* Wake up once a second just in case SIGURG was sent while
++ * we weren't in poll(), to make sure we don't hang when trying
++ * to unload. */
++ ast_io_wait(io, 1000);
++ }
+
+- /* Now do the IO, and run scheduled tasks */
+- res = ast_io_wait(io, wakeup);
+- if (res >= 0) {
+- if (res >= 20)
+- ast_debug(1, "chan_iax2: ast_io_wait ran %d I/Os all at once\n", res);
+- }
+- }
+ return NULL;
+ }
+
+@@ -10810,7 +10854,7 @@
+
+ if (!temponly) {
+ peer = ao2_find(peers, &tmp_peer, OBJ_POINTER);
+- if (peer && !ast_test_flag(peer, IAX_DELME))
++ if (peer && !ast_test_flag64(peer, IAX_DELME))
+ firstpass = 0;
+ }
+
+@@ -10831,7 +10875,7 @@
+
+ if (peer) {
+ if (firstpass) {
+- ast_copy_flags(peer, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_FORCE_ENCRYPT);
++ ast_copy_flags64(peer, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE | IAX_FORCE_ENCRYPT);
+ peer->encmethods = iax2_encryption;
+ peer->adsi = adsi;
+ ast_string_field_set(peer,secret,"");
+@@ -10847,7 +10891,7 @@
+ peer->pokefreqnotok = DEFAULT_FREQ_NOTOK;
+ ast_string_field_set(peer,context,"");
+ ast_string_field_set(peer,peercontext,"");
+- ast_clear_flag(peer, IAX_HASCALLERID);
++ ast_clear_flag64(peer, IAX_HASCALLERID);
+ ast_string_field_set(peer, cid_name, "");
+ ast_string_field_set(peer, cid_num, "");
+ ast_string_field_set(peer, mohinterpret, mohinterpret);
+@@ -10874,42 +10918,42 @@
+ } else if (!strcasecmp(v->name, "dbsecret")) {
+ ast_string_field_set(peer, dbsecret, v->value);
+ } else if (!strcasecmp(v->name, "trunk")) {
+- ast_set2_flag(peer, ast_true(v->value), IAX_TRUNK);
+- if (ast_test_flag(peer, IAX_TRUNK) && !timer) {
++ ast_set2_flag64(peer, ast_true(v->value), IAX_TRUNK);
++ if (ast_test_flag64(peer, IAX_TRUNK) && !timer) {
+ ast_log(LOG_WARNING, "Unable to support trunking on peer '%s' without a timing interface\n", peer->name);
+- ast_clear_flag(peer, IAX_TRUNK);
++ ast_clear_flag64(peer, IAX_TRUNK);
+ }
+ } else if (!strcasecmp(v->name, "auth")) {
+ peer->authmethods = get_auth_methods(v->value);
+ } else if (!strcasecmp(v->name, "encryption")) {
+ peer->encmethods |= get_encrypt_methods(v->value);
+ if (!peer->encmethods) {
+- ast_clear_flag(peer, IAX_FORCE_ENCRYPT);
++ ast_clear_flag64(peer, IAX_FORCE_ENCRYPT);
+ }
+ } else if (!strcasecmp(v->name, "forceencryption")) {
+ if (ast_false(v->value)) {
+- ast_clear_flag(peer, IAX_FORCE_ENCRYPT);
++ ast_clear_flag64(peer, IAX_FORCE_ENCRYPT);
+ } else {
+ peer->encmethods |= get_encrypt_methods(v->value);
+ if (peer->encmethods) {
+- ast_set_flag(peer, IAX_FORCE_ENCRYPT);
++ ast_set_flag64(peer, IAX_FORCE_ENCRYPT);
+ }
+ }
+ } else if (!strcasecmp(v->name, "transfer")) {
+ if (!strcasecmp(v->value, "mediaonly")) {
+- ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA);
++ ast_set_flags_to64(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA);
+ } else if (ast_true(v->value)) {
+- ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0);
+- } else
+- ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER);
++ ast_set_flags_to64(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0);
++ } else
++ ast_set_flags_to64(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER);
+ } else if (!strcasecmp(v->name, "jitterbuffer")) {
+- ast_set2_flag(peer, ast_true(v->value), IAX_USEJITTERBUF);
++ ast_set2_flag64(peer, ast_true(v->value), IAX_USEJITTERBUF);
+ } else if (!strcasecmp(v->name, "forcejitterbuffer")) {
+- ast_set2_flag(peer, ast_true(v->value), IAX_FORCEJITTERBUF);
++ ast_set2_flag64(peer, ast_true(v->value), IAX_FORCEJITTERBUF);
+ } else if (!strcasecmp(v->name, "host")) {
+ if (!strcasecmp(v->value, "dynamic")) {
+ /* They'll register with us */
+- ast_set_flag(peer, IAX_DYNAMIC);
++ ast_set_flag64(peer, IAX_DYNAMIC);
+ if (!found) {
+ /* Initialize stuff iff we're not found, otherwise
+ we keep going with what we had */
+@@ -10923,7 +10967,7 @@
+ } else {
+ /* Non-dynamic. Make sure we become that way if we're not */
+ ast_sched_thread_del(sched, peer->expire);
+- ast_clear_flag(peer, IAX_DYNAMIC);
++ ast_clear_flag64(peer, IAX_DYNAMIC);
+ if (ast_dnsmgr_lookup(v->value, &peer->addr, &peer->dnsmgr, srvlookup ? "_iax._udp" : NULL))
+ return peer_unref(peer);
+ if (!peer->addr.sin_port)
+@@ -10949,7 +10993,7 @@
+ } else if (!strcasecmp(v->name, "peercontext")) {
+ ast_string_field_set(peer, peercontext, v->value);
+ } else if (!strcasecmp(v->name, "port")) {
+- if (ast_test_flag(peer, IAX_DYNAMIC))
++ if (ast_test_flag64(peer, IAX_DYNAMIC))
+ peer->defaddr.sin_port = htons(atoi(v->value));
+ else
+ peer->addr.sin_port = htons(atoi(v->value));
+@@ -10970,15 +11014,15 @@
+ ast_string_field_set(peer, cid_name, "");
+ ast_string_field_set(peer, cid_num, "");
+ }
+- ast_set_flag(peer, IAX_HASCALLERID);
++ ast_set_flag64(peer, IAX_HASCALLERID);
+ } else if (!strcasecmp(v->name, "fullname")) {
+ ast_string_field_set(peer, cid_name, S_OR(v->value, ""));
+- ast_set_flag(peer, IAX_HASCALLERID);
++ ast_set_flag64(peer, IAX_HASCALLERID);
+ } else if (!strcasecmp(v->name, "cid_number")) {
+ ast_string_field_set(peer, cid_num, S_OR(v->value, ""));
+- ast_set_flag(peer, IAX_HASCALLERID);
++ ast_set_flag64(peer, IAX_HASCALLERID);
+ } else if (!strcasecmp(v->name, "sendani")) {
+- ast_set2_flag(peer, ast_true(v->value), IAX_SENDANI);
++ ast_set2_flag64(peer, ast_true(v->value), IAX_SENDANI);
+ } else if (!strcasecmp(v->name, "inkeys")) {
+ ast_string_field_set(peer, inkeys, v->value);
+ } else if (!strcasecmp(v->name, "outkey")) {
+@@ -11006,6 +11050,18 @@
+ ast_string_field_set(peer, zonetag, v->value);
+ } else if (!strcasecmp(v->name, "adsi")) {
+ peer->adsi = ast_true(v->value);
++ } else if (!strcasecmp(v->name, "connectedline")) {
++ if (ast_true(v->value)) {
++ ast_set_flag64(peer, IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
++ } else if (!strcasecmp(v->value, "send")) {
++ ast_clear_flag64(peer, IAX_RECVCONNECTEDLINE);
++ ast_set_flag64(peer, IAX_SENDCONNECTEDLINE);
++ } else if (!strcasecmp(v->value, "receive")) {
++ ast_clear_flag64(peer, IAX_SENDCONNECTEDLINE);
++ ast_set_flag64(peer, IAX_RECVCONNECTEDLINE);
++ } else {
++ ast_clear_flag64(peer, IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
++ }
+ }/* else if (strcasecmp(v->name,"type")) */
+ /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
+ v = v->next;
+@@ -11016,7 +11072,7 @@
+ }
+ if (!peer->authmethods)
+ peer->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT;
+- ast_clear_flag(peer, IAX_DELME);
++ ast_clear_flag64(peer, IAX_DELME);
+ /* Make sure these are IPv4 addresses */
+ peer->addr.sin_family = AF_INET;
+ }
+@@ -11070,7 +11126,7 @@
+
+ if (!temponly) {
+ user = ao2_find(users, &tmp_user, OBJ_POINTER);
+- if (user && !ast_test_flag(user, IAX_DELME))
++ if (user && !ast_test_flag64(user, IAX_DELME))
+ firstpass = 0;
+ }
+
+@@ -11104,8 +11160,8 @@
+ user->adsi = adsi;
+ ast_string_field_set(user, name, name);
+ ast_string_field_set(user, language, language);
+- ast_copy_flags(user, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_CODEC_USER_FIRST | IAX_CODEC_NOPREFS | IAX_CODEC_NOCAP | IAX_FORCE_ENCRYPT);
+- ast_clear_flag(user, IAX_HASCALLERID);
++ ast_copy_flags64(user, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_CODEC_USER_FIRST | IAX_CODEC_NOPREFS | IAX_CODEC_NOCAP | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE | IAX_FORCE_ENCRYPT);
++ ast_clear_flag64(user, IAX_HASCALLERID);
+ ast_string_field_set(user, cid_name, "");
+ ast_string_field_set(user, cid_num, "");
+ ast_string_field_set(user, accountcode, accountcode);
+@@ -11144,49 +11200,49 @@
+ } else if (!strcasecmp(v->name, "disallow")) {
+ ast_parse_allow_disallow(&user->prefs, &user->capability,v->value, 0);
+ } else if (!strcasecmp(v->name, "trunk")) {
+- ast_set2_flag(user, ast_true(v->value), IAX_TRUNK);
+- if (ast_test_flag(user, IAX_TRUNK) && !timer) {
++ ast_set2_flag64(user, ast_true(v->value), IAX_TRUNK);
++ if (ast_test_flag64(user, IAX_TRUNK) && !timer) {
+ ast_log(LOG_WARNING, "Unable to support trunking on user '%s' without a timing interface\n", user->name);
+- ast_clear_flag(user, IAX_TRUNK);
++ ast_clear_flag64(user, IAX_TRUNK);
+ }
+ } else if (!strcasecmp(v->name, "auth")) {
+ user->authmethods = get_auth_methods(v->value);
+ } else if (!strcasecmp(v->name, "encryption")) {
+ user->encmethods |= get_encrypt_methods(v->value);
+ if (!user->encmethods) {
+- ast_clear_flag(user, IAX_FORCE_ENCRYPT);
++ ast_clear_flag64(user, IAX_FORCE_ENCRYPT);
+ }
+ } else if (!strcasecmp(v->name, "forceencryption")) {
+ if (ast_false(v->value)) {
+- ast_clear_flag(user, IAX_FORCE_ENCRYPT);
++ ast_clear_flag64(user, IAX_FORCE_ENCRYPT);
+ } else {
+ user->encmethods |= get_encrypt_methods(v->value);
+ if (user->encmethods) {
+- ast_set_flag(user, IAX_FORCE_ENCRYPT);
++ ast_set_flag64(user, IAX_FORCE_ENCRYPT);
+ }
+ }
+ } else if (!strcasecmp(v->name, "transfer")) {
+ if (!strcasecmp(v->value, "mediaonly")) {
+- ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA);
++ ast_set_flags_to64(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA);
+ } else if (ast_true(v->value)) {
+- ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0);
+- } else
+- ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER);
++ ast_set_flags_to64(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0);
++ } else
++ ast_set_flags_to64(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER);
+ } else if (!strcasecmp(v->name, "codecpriority")) {
+ if(!strcasecmp(v->value, "caller"))
+- ast_set_flag(user, IAX_CODEC_USER_FIRST);
++ ast_set_flag64(user, IAX_CODEC_USER_FIRST);
+ else if(!strcasecmp(v->value, "disabled"))
+- ast_set_flag(user, IAX_CODEC_NOPREFS);
++ ast_set_flag64(user, IAX_CODEC_NOPREFS);
+ else if(!strcasecmp(v->value, "reqonly")) {
+- ast_set_flag(user, IAX_CODEC_NOCAP);
+- ast_set_flag(user, IAX_CODEC_NOPREFS);
++ ast_set_flag64(user, IAX_CODEC_NOCAP);
++ ast_set_flag64(user, IAX_CODEC_NOPREFS);
+ }
+ } else if (!strcasecmp(v->name, "immediate")) {
+- ast_set2_flag(user, ast_true(v->value), IAX_IMMEDIATE);
++ ast_set2_flag64(user, ast_true(v->value), IAX_IMMEDIATE);
+ } else if (!strcasecmp(v->name, "jitterbuffer")) {
+- ast_set2_flag(user, ast_true(v->value), IAX_USEJITTERBUF);
++ ast_set2_flag64(user, ast_true(v->value), IAX_USEJITTERBUF);
+ } else if (!strcasecmp(v->name, "forcejitterbuffer")) {
+- ast_set2_flag(user, ast_true(v->value), IAX_FORCEJITTERBUF);
++ ast_set2_flag64(user, ast_true(v->value), IAX_FORCEJITTERBUF);
+ } else if (!strcasecmp(v->name, "dbsecret")) {
+ ast_string_field_set(user, dbsecret, v->value);
+ } else if (!strcasecmp(v->name, "secret")) {
+@@ -11203,29 +11259,29 @@
+ ast_callerid_split(v->value, name2, sizeof(name2), num2, sizeof(num2));
+ ast_string_field_set(user, cid_name, name2);
+ ast_string_field_set(user, cid_num, num2);
+- ast_set_flag(user, IAX_HASCALLERID);
++ ast_set_flag64(user, IAX_HASCALLERID);
+ } else {
+- ast_clear_flag(user, IAX_HASCALLERID);
++ ast_clear_flag64(user, IAX_HASCALLERID);
+ ast_string_field_set(user, cid_name, "");
+ ast_string_field_set(user, cid_num, "");
+ }
+ } else if (!strcasecmp(v->name, "fullname")) {
+ if (!ast_strlen_zero(v->value)) {
+ ast_string_field_set(user, cid_name, v->value);
+- ast_set_flag(user, IAX_HASCALLERID);
++ ast_set_flag64(user, IAX_HASCALLERID);
+ } else {
+ ast_string_field_set(user, cid_name, "");
+ if (ast_strlen_zero(user->cid_num))
+- ast_clear_flag(user, IAX_HASCALLERID);
++ ast_clear_flag64(user, IAX_HASCALLERID);
+ }
+ } else if (!strcasecmp(v->name, "cid_number")) {
+ if (!ast_strlen_zero(v->value)) {
+ ast_string_field_set(user, cid_num, v->value);
+- ast_set_flag(user, IAX_HASCALLERID);
++ ast_set_flag64(user, IAX_HASCALLERID);
+ } else {
+ ast_string_field_set(user, cid_num, "");
+ if (ast_strlen_zero(user->cid_name))
+- ast_clear_flag(user, IAX_HASCALLERID);
++ ast_clear_flag64(user, IAX_HASCALLERID);
+ }
+ } else if (!strcasecmp(v->name, "accountcode")) {
+ ast_string_field_set(user, accountcode, v->value);
+@@ -11252,6 +11308,18 @@
+ user->maxauthreq = 0;
+ } else if (!strcasecmp(v->name, "adsi")) {
+ user->adsi = ast_true(v->value);
++ } else if (!strcasecmp(v->name, "connectedline")) {
++ if (ast_true(v->value)) {
++ ast_set_flag64(user, IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
++ } else if (!strcasecmp(v->value, "send")) {
++ ast_clear_flag64(user, IAX_RECVCONNECTEDLINE);
++ ast_set_flag64(user, IAX_SENDCONNECTEDLINE);
++ } else if (!strcasecmp(v->value, "receive")) {
++ ast_clear_flag64(user, IAX_SENDCONNECTEDLINE);
++ ast_set_flag64(user, IAX_RECVCONNECTEDLINE);
++ } else {
++ ast_clear_flag64(user, IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
++ }
+ }/* else if (strcasecmp(v->name,"type")) */
+ /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
+ v = v->next;
+@@ -11271,7 +11339,7 @@
+ user->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT;
+ }
+ }
+- ast_clear_flag(user, IAX_DELME);
++ ast_clear_flag64(user, IAX_DELME);
+ }
+ cleanup:
+ if (oldha)
+@@ -11285,7 +11353,7 @@
+ {
+ struct iax2_peer *peer = obj;
+
+- ast_set_flag(peer, IAX_DELME);
++ ast_set_flag64(peer, IAX_DELME);
+
+ return 0;
+ }
+@@ -11294,7 +11362,7 @@
+ {
+ struct iax2_user *user = obj;
+
+- ast_set_flag(user, IAX_DELME);
++ ast_set_flag64(user, IAX_DELME);
+
+ return 0;
+ }
+@@ -11335,7 +11403,7 @@
+
+ i = ao2_iterator_init(users, 0);
+ while ((user = ao2_iterator_next(&i))) {
+- if (ast_test_flag(user, IAX_DELME) || ast_test_flag(user, IAX_RTCACHEFRIENDS)) {
++ if (ast_test_flag64(user, IAX_DELME) || ast_test_flag64(user, IAX_RTCACHEFRIENDS)) {
+ ao2_unlink(users, user);
+ }
+ user_unref(user);
+@@ -11350,7 +11418,7 @@
+
+ i = ao2_iterator_init(peers, 0);
+ while ((peer = ao2_iterator_next(&i))) {
+- if (ast_test_flag(peer, IAX_DELME) || ast_test_flag(peer, IAX_RTCACHEFRIENDS)) {
++ if (ast_test_flag64(peer, IAX_DELME) || ast_test_flag64(peer, IAX_RTCACHEFRIENDS)) {
+ unlink_peer(peer);
+ }
+ peer_unref(peer);
+@@ -11366,10 +11434,8 @@
+ trunkmaxsize = MAX_TRUNKDATA;
+ amaflags = 0;
+ delayreject = 0;
+- ast_clear_flag((&globalflags), IAX_NOTRANSFER);
+- ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA);
+- ast_clear_flag((&globalflags), IAX_USEJITTERBUF);
+- ast_clear_flag((&globalflags), IAX_FORCEJITTERBUF);
++ ast_clear_flag64((&globalflags), IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF |
++ IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
+ delete_users();
+ }
+
+@@ -11426,13 +11492,13 @@
+ set_config_destroy();
+ }
+
+- /* Reset global codec prefs */
++ /* Reset global codec prefs */
+ memset(&prefs, 0 , sizeof(struct ast_codec_pref));
+-
++
+ /* Reset Global Flags */
+ memset(&globalflags, 0, sizeof(globalflags));
+- ast_set_flag(&globalflags, IAX_RTUPDATE);
+-
++ ast_set_flag64(&globalflags, IAX_RTUPDATE);
++
+ #ifdef SO_NO_CHECK
+ nochecksums = 0;
+ #endif
+@@ -11544,67 +11610,69 @@
+ } else if (!strcasecmp(v->name, "encryption")) {
+ iax2_encryption |= get_encrypt_methods(v->value);
+ if (!iax2_encryption) {
+- ast_clear_flag((&globalflags), IAX_FORCE_ENCRYPT);
++ ast_clear_flag64((&globalflags), IAX_FORCE_ENCRYPT);
+ }
+ } else if (!strcasecmp(v->name, "forceencryption")) {
+ if (ast_false(v->value)) {
+- ast_clear_flag((&globalflags), IAX_FORCE_ENCRYPT);
++ ast_clear_flag64((&globalflags), IAX_FORCE_ENCRYPT);
+ } else {
+ iax2_encryption |= get_encrypt_methods(v->value);
+ if (iax2_encryption) {
+- ast_set_flag((&globalflags), IAX_FORCE_ENCRYPT);
++ ast_set_flag64((&globalflags), IAX_FORCE_ENCRYPT);
+ }
+ }
+ } else if (!strcasecmp(v->name, "transfer")) {
+ if (!strcasecmp(v->value, "mediaonly")) {
+- ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA);
++ ast_set_flags_to64((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA);
+ } else if (ast_true(v->value)) {
+- ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0);
+- } else
+- ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER);
++ ast_set_flags_to64((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0);
++ } else
++ ast_set_flags_to64((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER);
+ } else if (!strcasecmp(v->name, "codecpriority")) {
+ if(!strcasecmp(v->value, "caller"))
+- ast_set_flag((&globalflags), IAX_CODEC_USER_FIRST);
++ ast_set_flag64((&globalflags), IAX_CODEC_USER_FIRST);
+ else if(!strcasecmp(v->value, "disabled"))
+- ast_set_flag((&globalflags), IAX_CODEC_NOPREFS);
++ ast_set_flag64((&globalflags), IAX_CODEC_NOPREFS);
+ else if(!strcasecmp(v->value, "reqonly")) {
+- ast_set_flag((&globalflags), IAX_CODEC_NOCAP);
+- ast_set_flag((&globalflags), IAX_CODEC_NOPREFS);
++ ast_set_flag64((&globalflags), IAX_CODEC_NOCAP);
++ ast_set_flag64((&globalflags), IAX_CODEC_NOPREFS);
+ }
+ } else if (!strcasecmp(v->name, "jitterbuffer"))
+- ast_set2_flag((&globalflags), ast_true(v->value), IAX_USEJITTERBUF);
++ ast_set2_flag64((&globalflags), ast_true(v->value), IAX_USEJITTERBUF);
+ else if (!strcasecmp(v->name, "forcejitterbuffer"))
+- ast_set2_flag((&globalflags), ast_true(v->value), IAX_FORCEJITTERBUF);
++ ast_set2_flag64((&globalflags), ast_true(v->value), IAX_FORCEJITTERBUF);
+ else if (!strcasecmp(v->name, "delayreject"))
+ delayreject = ast_true(v->value);
+ else if (!strcasecmp(v->name, "allowfwdownload"))
+- ast_set2_flag((&globalflags), ast_true(v->value), IAX_ALLOWFWDOWNLOAD);
++ ast_set2_flag64((&globalflags), ast_true(v->value), IAX_ALLOWFWDOWNLOAD);
+ else if (!strcasecmp(v->name, "rtcachefriends"))
+- ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTCACHEFRIENDS);
++ ast_set2_flag64((&globalflags), ast_true(v->value), IAX_RTCACHEFRIENDS);
+ else if (!strcasecmp(v->name, "rtignoreregexpire"))
+- ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTIGNOREREGEXPIRE);
++ ast_set2_flag64((&globalflags), ast_true(v->value), IAX_RTIGNOREREGEXPIRE);
+ else if (!strcasecmp(v->name, "rtupdate"))
+- ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTUPDATE);
++ ast_set2_flag64((&globalflags), ast_true(v->value), IAX_RTUPDATE);
++ else if (!strcasecmp(v->name, "rtsavesysname"))
++ ast_set2_flag64((&globalflags), ast_true(v->value), IAX_RTSAVE_SYSNAME);
+ else if (!strcasecmp(v->name, "trunktimestamps"))
+- ast_set2_flag(&globalflags, ast_true(v->value), IAX_TRUNKTIMESTAMPS);
++ ast_set2_flag64(&globalflags, ast_true(v->value), IAX_TRUNKTIMESTAMPS);
+ else if (!strcasecmp(v->name, "rtautoclear")) {
+ int i = atoi(v->value);
+ if(i > 0)
+ global_rtautoclear = i;
+ else
+ i = 0;
+- ast_set2_flag((&globalflags), i || ast_true(v->value), IAX_RTAUTOCLEAR);
++ ast_set2_flag64((&globalflags), i || ast_true(v->value), IAX_RTAUTOCLEAR);
+ } else if (!strcasecmp(v->name, "trunkfreq")) {
+ trunkfreq = atoi(v->value);
+ if (trunkfreq < 10)
+ trunkfreq = 10;
+ } else if (!strcasecmp(v->name, "trunkmtu")) {
+ mtuv = atoi(v->value);
+- if (mtuv == 0 )
+- global_max_trunk_mtu = 0;
+- else if (mtuv >= 172 && mtuv < 4000)
+- global_max_trunk_mtu = mtuv;
+- else
++ if (mtuv == 0 )
++ global_max_trunk_mtu = 0;
++ else if (mtuv >= 172 && mtuv < 4000)
++ global_max_trunk_mtu = mtuv;
++ else
+ ast_log(LOG_NOTICE, "trunkmtu value out of bounds (%d) at line %d\n",
+ mtuv, v->lineno);
+ } else if (!strcasecmp(v->name, "trunkmaxsize")) {
+@@ -11674,6 +11742,18 @@
+ adsi = ast_true(v->value);
+ } else if (!strcasecmp(v->name, "srvlookup")) {
+ srvlookup = ast_true(v->value);
++ } else if (!strcasecmp(v->name, "connectedline")) {
++ if (ast_true(v->value)) {
++ ast_set_flag64((&globalflags), IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
++ } else if (!strcasecmp(v->value, "send")) {
++ ast_clear_flag64((&globalflags), IAX_RECVCONNECTEDLINE);
++ ast_set_flag64((&globalflags), IAX_SENDCONNECTEDLINE);
++ } else if (!strcasecmp(v->value, "receive")) {
++ ast_clear_flag64((&globalflags), IAX_SENDCONNECTEDLINE);
++ ast_set_flag64((&globalflags), IAX_RECVCONNECTEDLINE);
++ } else {
++ ast_clear_flag64((&globalflags), IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
++ }
+ } /*else if (strcasecmp(v->name,"type")) */
+ /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
+ v = v->next;
+@@ -11728,7 +11808,7 @@
+ }
+ peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0);
+ if (peer) {
+- if (ast_test_flag(peer, IAX_DYNAMIC))
++ if (ast_test_flag64(peer, IAX_DYNAMIC))
+ reg_source_db(peer);
+ ao2_link(peers, peer);
+ peer = peer_unref(peer);
+@@ -11774,7 +11854,7 @@
+ if (!strcasecmp(utype, "peer") || !strcasecmp(utype, "friend")) {
+ peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0);
+ if (peer) {
+- if (ast_test_flag(peer, IAX_DYNAMIC))
++ if (ast_test_flag64(peer, IAX_DYNAMIC))
+ reg_source_db(peer);
+ ao2_link(peers, peer);
+ peer = peer_unref(peer);
+@@ -12211,7 +12291,7 @@
+ } else if (!strcasecmp(colname, "expire")) {
+ snprintf(buf, len, "%d", peer->expire);
+ } else if (!strcasecmp(colname, "dynamic")) {
+- ast_copy_string(buf, (ast_test_flag(peer, IAX_DYNAMIC) ? "yes" : "no"), len);
++ ast_copy_string(buf, (ast_test_flag64(peer, IAX_DYNAMIC) ? "yes" : "no"), len);
+ } else if (!strcasecmp(colname, "callerid_name")) {
+ ast_copy_string(buf, peer->cid_name, len);
+ } else if (!strcasecmp(colname, "callerid_num")) {
+@@ -12242,7 +12322,7 @@
+ return 0;
+ }
+
+-struct ast_custom_function iaxpeer_function = {
++static struct ast_custom_function iaxpeer_function = {
+ .name = "IAXPEER",
+ .read = function_iaxpeer,
+ };
+@@ -12495,19 +12575,14 @@
+ struct ast_context *con;
+ int x;
+
+- /* Make sure threads do not hold shared resources when they are canceled */
+-
+- /* Grab the sched lock resource to keep it away from threads about to die */
+- /* Cancel the network thread, close the net socket */
+ if (netthreadid != AST_PTHREADT_NULL) {
+- AST_LIST_LOCK(&frame_queue);
+ pthread_cancel(netthreadid);
+- AST_LIST_UNLOCK(&frame_queue);
++ pthread_kill(netthreadid, SIGURG);
+ pthread_join(netthreadid, NULL);
+ }
+
+ sched = ast_sched_thread_destroy(sched);
+-
++
+ /* Call for all threads to halt */
+ AST_LIST_LOCK(&idle_list);
+ while ((thread = AST_LIST_REMOVE_HEAD(&idle_list, list)))
+@@ -12558,6 +12633,7 @@
+ if (timer) {
+ ast_timer_close(timer);
+ }
++ transmit_processor = ast_taskprocessor_unreference(transmit_processor);
+
+ con = ast_context_find(regcontext);
+ if (con)
+@@ -12626,19 +12702,23 @@
+ struct iax2_registry *reg = NULL;
+
+ peers = ao2_container_alloc(MAX_PEER_BUCKETS, peer_hash_cb, peer_cmp_cb);
+- if (!peers)
++ if (!peers) {
+ return AST_MODULE_LOAD_FAILURE;
++ }
++
+ users = ao2_container_alloc(MAX_USER_BUCKETS, user_hash_cb, user_cmp_cb);
+ if (!users) {
+ ao2_ref(peers, -1);
+ return AST_MODULE_LOAD_FAILURE;
+ }
++
+ iax_peercallno_pvts = ao2_container_alloc(IAX_MAX_CALLS, pvt_hash_cb, pvt_cmp_cb);
+ if (!iax_peercallno_pvts) {
+ ao2_ref(peers, -1);
+ ao2_ref(users, -1);
+ return AST_MODULE_LOAD_FAILURE;
+ }
++
+ iax_transfercallno_pvts = ao2_container_alloc(IAX_MAX_CALLS, transfercallno_pvt_hash_cb, transfercallno_pvt_cmp_cb);
+ if (!iax_transfercallno_pvts) {
+ ao2_ref(peers, -1);
+@@ -12646,6 +12726,16 @@
+ ao2_ref(iax_peercallno_pvts, -1);
+ return AST_MODULE_LOAD_FAILURE;
+ }
++
++ transmit_processor = ast_taskprocessor_get("iax2_transmit", TPS_REF_DEFAULT);
++ if (!transmit_processor) {
++ ao2_ref(peers, -1);
++ ao2_ref(users, -1);
++ ao2_ref(iax_peercallno_pvts, -1);
++ ao2_ref(iax_transfercallno_pvts, -1);
++ return AST_MODULE_LOAD_FAILURE;
++ }
++
+ ast_custom_function_register(&iaxpeer_function);
+ ast_custom_function_register(&iaxvar_function);
+
+@@ -12691,10 +12781,10 @@
+
+ ast_register_application_xml(papp, iax2_prov_app);
+
+- ast_manager_register( "IAXpeers", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_iax2_show_peers, "List IAX Peers" );
+- ast_manager_register( "IAXpeerlist", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_iax2_show_peer_list, "List IAX Peers" );
+- ast_manager_register( "IAXnetstats", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_iax2_show_netstats, "Show IAX Netstats" );
+- ast_manager_register( "IAXregistry", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_iax2_show_registry, "Show IAX registrations");
++ ast_manager_register_xml("IAXpeers", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_iax2_show_peers);
++ ast_manager_register_xml("IAXpeerlist", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_iax2_show_peer_list);
++ ast_manager_register_xml("IAXnetstats", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_iax2_show_netstats);
++ ast_manager_register_xml("IAXregistry", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_iax2_show_registry);
+
+ if ((timer = ast_timer_open())) {
+ ast_timer_set_rate(timer, trunkfreq);
+Index: channels/chan_oss.c
+===================================================================
+--- a/channels/chan_oss.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/channels/chan_oss.c (.../trunk) (revision 202568)
+@@ -305,7 +305,7 @@
+ };
+
+ /*! forward declaration */
+-static struct chan_oss_pvt *find_desc(char *dev);
++static struct chan_oss_pvt *find_desc(const char *dev);
+
+ static char *oss_active; /*!< the active device */
+
+@@ -367,7 +367,7 @@
+ /*!
+ * \brief returns a pointer to the descriptor with the given name
+ */
+-static struct chan_oss_pvt *find_desc(char *dev)
++static struct chan_oss_pvt *find_desc(const char *dev)
+ {
+ struct chan_oss_pvt *o = NULL;
+
+@@ -1075,7 +1075,8 @@
+
+ static char *console_dial(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+ {
+- char *s = NULL, *mye = NULL, *myc = NULL;
++ char *s = NULL;
++ char *mye = NULL, *myc = NULL;
+ struct chan_oss_pvt *o = find_desc(oss_active);
+
+ if (cmd == CLI_INIT) {
+@@ -1092,6 +1093,7 @@
+ if (o->owner) { /* already in a call */
+ int i;
+ struct ast_frame f = { AST_FRAME_DTMF, 0 };
++ const char *s;
+
+ if (a->argc == e->args) { /* argument is mandatory here */
+ ast_cli(a->fd, "Already in a call. You can only dial digits until you hangup.\n");
+@@ -1126,7 +1128,7 @@
+ static char *console_mute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+ {
+ struct chan_oss_pvt *o = find_desc(oss_active);
+- char *s;
++ const char *s;
+ int toggle = 0;
+
+ if (cmd == CLI_INIT) {
+Index: channels/chan_misdn.c
+===================================================================
+--- a/channels/chan_misdn.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/channels/chan_misdn.c (.../trunk) (revision 202568)
+@@ -1,6 +1,6 @@
+ /*
+ * Asterisk -- An open source telephony toolkit.
+- *
++ *
+ * Copyright (C) 2004 - 2006, Christian Richter
+ *
+ * Christian Richter <crich@beronet.com>
+@@ -29,6 +29,26 @@
+ * \ingroup channel_drivers
+ */
+
++/*!
++ * \note
++ * To use the CCBS/CCNR supplementary service feature and other
++ * supplementary services using FACILITY messages requires a
++ * modified version of mISDN.
++ *
++ * \note
++ * The latest modified mISDN v1.1.x based version is available at:
++ * http://svn.digium.com/svn/thirdparty/mISDN/trunk
++ * http://svn.digium.com/svn/thirdparty/mISDNuser/trunk
++ *
++ * \note
++ * Taged versions of the modified mISDN code are available under:
++ * http://svn.digium.com/svn/thirdparty/mISDN/tags
++ * http://svn.digium.com/svn/thirdparty/mISDNuser/tags
++ */
++
++/* Define to enable cli commands to generate canned CCBS messages. */
++// #define CCBS_TEST_MESSAGES 1
++
+ /*** MODULEINFO
+ <depend>isdnnet</depend>
+ <depend>misdn</depend>
+@@ -47,6 +67,8 @@
+ #include <signal.h>
+ #include <sys/file.h>
+ #include <semaphore.h>
++#include <ctype.h>
++#include <time.h>
+
+ #include "asterisk/channel.h"
+ #include "asterisk/config.h"
+@@ -72,7 +94,7 @@
+ #include "chan_misdn_config.h"
+ #include "isdn_lib.h"
+
+-char global_tracefile[BUFFERSIZE + 1];
++static char global_tracefile[BUFFERSIZE + 1];
+
+ static int g_config_initialized = 0;
+
+@@ -88,8 +110,6 @@
+ ast_mutex_t mutexjb;
+ };
+
+-
+-
+ /*! \brief allocates the jb-structure and initialize the elements */
+ struct misdn_jb *misdn_jb_init(int size, int upper_threshold);
+
+@@ -111,8 +131,167 @@
+
+ /* BEGIN: chan_misdn.h */
+
+-ast_mutex_t release_lock;
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*
++ * This timeout duration is to clean up any call completion records that
++ * are forgotten about by the switch.
++ */
++#define MISDN_CC_RECORD_AGE_MAX (6UL * 60 * 60) /* seconds */
+
++#define MISDN_CC_REQUEST_WAIT_MAX 5 /* seconds */
++
++/*!
++ * \brief Caller that initialized call completion services
++ *
++ * \details
++ * This data is the payload for a datastore that is put on the channel that
++ * initializes call completion services. This datastore is set to be inherited
++ * by the outbound mISDN channel. When one of these channels hangs up, the
++ * channel pointer will be set to NULL. That way, we can ensure that we do not
++ * touch this channel after it gets destroyed.
++ */
++struct misdn_cc_caller {
++ /*! \brief The channel that initialized call completion services */
++ struct ast_channel *chan;
++};
++
++struct misdn_cc_notify {
++ /*! \brief Dialplan: Notify extension priority */
++ int priority;
++
++ /*! \brief Dialplan: Notify extension context */
++ char context[AST_MAX_CONTEXT];
++
++ /*! \brief Dialplan: Notify extension number (User-A) */
++ char exten[AST_MAX_EXTENSION];
++};
++
++/*! \brief mISDN call completion record */
++struct misdn_cc_record {
++ /*! \brief Call completion record linked list */
++ AST_LIST_ENTRY(misdn_cc_record) list;
++
++ /*! \brief Time the record was created. */
++ time_t time_created;
++
++ /*! \brief MISDN_CC_RECORD_ID value */
++ long record_id;
++
++ /*!
++ * \brief Logical Layer 1 port associated with this
++ * call completion record
++ */
++ int port;
++
++ /*! \brief TRUE if point-to-point mode (CCBS-T/CCNR-T mode) */
++ int ptp;
++
++ /*! \brief Mode specific parameters */
++ union {
++ /*! \brief point-to-point specific parameters. */
++ struct {
++ /*!
++ * \brief Call-completion signaling link.
++ * NULL if signaling link not established.
++ */
++ struct misdn_bchannel *bc;
++
++ /*!
++ * \brief TRUE if we requested the request retention option
++ * to be enabled.
++ */
++ int requested_retention;
++
++ /*!
++ * \brief TRUE if the request retention option is enabled.
++ */
++ int retention_enabled;
++ } ptp;
++
++ /*! \brief point-to-multi-point specific parameters. */
++ struct {
++ /*! \brief CallLinkageID (valid when port determined) */
++ int linkage_id;
++
++ /*! \breif CCBSReference (valid when activated is TRUE) */
++ int reference_id;
++
++ /*! \brief globalRecall(0), specificRecall(1) */
++ int recall_mode;
++ } ptmp;
++ } mode;
++
++ /*! \brief TRUE if call completion activated */
++ int activated;
++
++ /*! \brief Outstanding message ID (valid when outstanding_message) */
++ int invoke_id;
++
++ /*! \brief TRUE if waiting for a response from a message (invoke_id is valid) */
++ int outstanding_message;
++
++ /*! \brief TRUE if activation has been requested */
++ int activation_requested;
++
++ /*!
++ * \brief TRUE if User-A is free
++ * \note PTMP - Used to answer CCBSStatusRequest.
++ * PTP - Determines how to respond to CCBS_T_RemoteUserFree.
++ */
++ int party_a_free;
++
++ /*! \brief Error code received from last outstanding message. */
++ enum FacErrorCode error_code;
++
++ /*! \brief Reject code received from last outstanding message. */
++ enum FacRejectCode reject_code;
++
++ /*!
++ * \brief Saved struct misdn_bchannel call information when
++ * attempted to call User-B
++ */
++ struct {
++ /*! \brief User-A caller id information */
++ struct misdn_party_id caller;
++
++ /*! \brief User-B number information */
++ struct misdn_party_dialing dialed;
++
++ /*! \brief The BC, HLC (optional) and LLC (optional) contents from the SETUP message. */
++ struct Q931_Bc_Hlc_Llc setup_bc_hlc_llc;
++
++ /*! \brief SETUP message bearer capability field code value */
++ int capability;
++
++ /*! \brief TRUE if call made in digital HDLC mode */
++ int hdlc;
++ } redial;
++
++ /*! \brief Dialplan location to indicate User-B free and User-A is free */
++ struct misdn_cc_notify remote_user_free;
++
++ /*! \brief Dialplan location to indicate User-B free and User-A is busy */
++ struct misdn_cc_notify b_free;
++};
++
++/*! \brief mISDN call completion record database */
++static AST_LIST_HEAD_STATIC(misdn_cc_records_db, misdn_cc_record);
++/*! \brief Next call completion record ID to use */
++static __u16 misdn_cc_record_id;
++/*! \brief Next invoke ID to use */
++static __s16 misdn_invoke_id;
++
++static const char misdn_no_response_from_network[] = "No response from network";
++static const char misdn_cc_record_not_found[] = "Call completion record not found";
++
++/* mISDN channel variable names */
++#define MISDN_CC_RECORD_ID "MISDN_CC_RECORD_ID"
++#define MISDN_CC_STATUS "MISDN_CC_STATUS"
++#define MISDN_ERROR_MSG "MISDN_ERROR_MSG"
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++static ast_mutex_t release_lock;
++
+ enum misdn_chan_state {
+ MISDN_NOTHING = 0, /*!< at beginning */
+ MISDN_WAITING4DIGS, /*!< when waiting for info */
+@@ -126,7 +305,7 @@
+ MISDN_ALERTING, /*!< when Alerting */
+ MISDN_BUSY, /*!< when BUSY */
+ MISDN_CONNECTED, /*!< when connected */
+- MISDN_PRECONNECTED, /*!< when connected */
++ MISDN_PRECONNECTED, /*!< when connected (Noone sets this state) */
+ MISDN_DISCONNECTED, /*!< when connected */
+ MISDN_RELEASED, /*!< when connected */
+ MISDN_BRIDGED, /*!< when bridged */
+@@ -135,21 +314,22 @@
+ MISDN_HUNGUP_FROM_AST, /*!< when DISCONNECT/RELEASE/REL_COMP came out of misdn_hangup */
+ MISDN_HOLDED, /*!< when on hold */
+ MISDN_HOLD_DISCONNECT, /*!< when on hold */
+-
+ };
+
++/*! Asterisk created the channel (outgoing call) */
+ #define ORG_AST 1
++/*! mISDN created the channel (incoming call) */
+ #define ORG_MISDN 2
+
+ struct hold_info {
+ /*!
+- * \brief Logical port the channel call record is HOLDED on
+- * because the B channel is no longer associated.
++ * \brief Logical port the channel call record is HOLDED on
++ * because the B channel is no longer associated.
+ */
+ int port;
+
+ /*!
+- * \brief Original B channel number the HOLDED call was using.
++ * \brief Original B channel number the HOLDED call was using.
+ * \note Used only for debug display messages.
+ */
+ int channel;
+@@ -159,18 +339,18 @@
+ * \brief Channel call record structure
+ */
+ struct chan_list {
+- /*!
++ /*!
+ * \brief The "allowed_bearers" string read in from /etc/asterisk/misdn.conf
+ */
+ char allowed_bearers[BUFFERSIZE + 1];
+-
+- /*!
++
++ /*!
+ * \brief State of the channel
+ */
+ enum misdn_chan_state state;
+
+- /*!
+- * \brief TRUE if a hangup needs to be queued
++ /*!
++ * \brief TRUE if a hangup needs to be queued
+ * \note This is a debug flag only used to catch calls to hangup_chan() that are already hungup.
+ */
+ int need_queue_hangup;
+@@ -184,30 +364,30 @@
+ * \brief TRUE if we could send an AST_CONTROL_BUSY if needed.
+ */
+ int need_busy;
+-
++
+ /*!
+ * \brief Who originally created this channel. ORG_AST or ORG_MISDN
+ */
+ int originator;
+
+- /*!
++ /*!
+ * \brief TRUE of we are not to respond immediately to a SETUP message. Check the dialplan first.
+ * \note The "noautorespond_on_setup" boolean read in from /etc/asterisk/misdn.conf
+ */
+ int noautorespond_on_setup;
+-
++
+ int norxtone; /*!< Boolean assigned values but the value is not used. */
+
+ /*!
+ * \brief TRUE if we are not to generate tones (Playtones)
+ */
+- int notxtone;
++ int notxtone;
+
+ /*!
+ * \brief TRUE if echo canceller is enabled. Value is toggled.
+ */
+ int toggle_ec;
+-
++
+ /*!
+ * \brief TRUE if you want to send Tone Indications to an incoming
+ * ISDN channel on a TE Port.
+@@ -222,8 +402,8 @@
+ int ignore_dtmf;
+
+ /*!
+- * \brief Pipe file descriptor handles array.
+- * Read from pipe[0], write to pipe[1]
++ * \brief Pipe file descriptor handles array.
++ * Read from pipe[0], write to pipe[1]
+ */
+ int pipe[2];
+
+@@ -282,48 +462,56 @@
+ /*!
+ * \brief Allocated jitterbuffer controller
+ * \note misdn_jb_init() creates the jitterbuffer.
+- * \note Must use misdn_jb_destroy() to clean up.
++ * \note Must use misdn_jb_destroy() to clean up.
+ */
+ struct misdn_jb *jb;
+-
++
+ /*!
+ * \brief Allocated DSP controller
+ * \note ast_dsp_new() creates the DSP controller.
+- * \note Must use ast_dsp_free() to clean up.
++ * \note Must use ast_dsp_free() to clean up.
+ */
+ struct ast_dsp *dsp;
+
+ /*!
+ * \brief Allocated audio frame sample translator
+ * \note ast_translator_build_path() creates the translator path.
+- * \note Must use ast_translator_free_path() to clean up.
++ * \note Must use ast_translator_free_path() to clean up.
+ */
+ struct ast_trans_pvt *trans;
+-
++
+ /*!
+ * \brief Associated Asterisk channel structure.
+ */
+ struct ast_channel * ast;
+
+- //int dummy; /* Not used */
+-
+ /*!
+ * \brief Associated B channel structure.
+ */
+ struct misdn_bchannel *bc;
+
++#if defined(AST_MISDN_ENHANCEMENTS)
+ /*!
++ * \brief Peer channel for which call completion was initialized.
++ */
++ struct misdn_cc_caller *peer;
++
++ /*! \brief Associated call completion record ID (-1 if not associated) */
++ long record_id;
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++ /*!
+ * \brief HOLDED channel information
+ */
+ struct hold_info hold_info;
+
+- /*!
+- * \brief From associated B channel: Layer 3 process ID
+- * \note Used to find the HOLDED channel call record when retrieving a call.
++ /*!
++ * \brief From associated B channel: Layer 3 process ID
++ * \note Used to find the HOLDED channel call record when retrieving a call.
+ */
+ unsigned int l3id;
+
+- /*!
++ /*!
+ * \brief From associated B channel: B Channel mISDN driver layer ID from mISDN_get_layerid()
+ * \note Used only for debug display messages.
+ */
+@@ -341,10 +529,6 @@
+ */
+ char mohinterpret[MAX_MUSICCLASS];
+
+-#if 0
+- int zero_read_cnt; /* Not used */
+-#endif
+-
+ /*!
+ * \brief Number of outgoing audio frames dropped since last debug gripe message.
+ */
+@@ -363,24 +547,24 @@
+ int nttimeout;
+
+ /*!
+- * \brief Other channel call record PID
+- * \note Value imported from Asterisk environment variable MISDN_PID
++ * \brief Other channel call record PID
++ * \note Value imported from Asterisk environment variable MISDN_PID
+ */
+ int other_pid;
+
+ /*!
+ * \brief Bridged other channel call record
+- * \note Pointer set when other_pid imported from Asterisk environment
++ * \note Pointer set when other_pid imported from Asterisk environment
+ * variable MISDN_PID by either side.
+ */
+ struct chan_list *other_ch;
+
+ /*!
+ * \brief Tone zone sound used for dialtone generation.
+- * \note Used as a boolean. Non-NULL to prod generation if enabled.
++ * \note Used as a boolean. Non-NULL to prod generation if enabled.
+ */
+ struct ast_tone_zone_sound *ts;
+-
++
+ /*!
+ * \brief Enables overlap dialing for the set amount of seconds. (0 = Disabled)
+ * \note The "overlapdial" value read in from /etc/asterisk/misdn.conf
+@@ -402,18 +586,10 @@
+ */
+ struct timeval overlap_tv;
+
+-#if 0
+- struct chan_list *peer; /* Not used */
+-#endif
+-
+ /*!
+ * \brief Next channel call record in the list.
+ */
+ struct chan_list *next;
+-#if 0
+- struct chan_list *prev; /* Not used */
+- struct chan_list *first; /* Not used */
+-#endif
+ };
+
+
+@@ -424,13 +600,14 @@
+ void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
+ static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame);
+
+-static struct robin_list {
++struct robin_list {
+ char *group;
+ int port;
+ int channel;
+ struct robin_list *next;
+ struct robin_list *prev;
+-} *robin = NULL;
++};
++static struct robin_list *robin = NULL;
+
+
+ static inline void free_robin_list_r(struct robin_list *r)
+@@ -450,7 +627,7 @@
+ robin = NULL;
+ }
+
+-static struct robin_list* get_robin_position(char *group)
++static struct robin_list *get_robin_position(char *group)
+ {
+ struct robin_list *new;
+ struct robin_list *iter = robin;
+@@ -481,13 +658,12 @@
+ __attribute__((format(printf, 3, 4)));
+
+ static struct ast_channel *misdn_new(struct chan_list *cl, int state, char *exten, char *callerid, int format, int port, int c);
+-static void send_digit_to_chan(struct chan_list *cl, char digit );
++static void send_digit_to_chan(struct chan_list *cl, char digit);
+
+ static void hangup_chan(struct chan_list *ch);
+ static int pbx_start_chan(struct chan_list *ch);
+
+ #define MISDN_ASTERISK_TECH_PVT(ast) ast->tech_pvt
+-#define MISDN_ASTERISK_PVT(ast) 1
+
+ #include "asterisk/strings.h"
+
+@@ -507,13 +683,11 @@
+ static int *misdn_in_calls;
+ static int *misdn_out_calls;
+
+-struct chan_list dummy_cl;
+-
+ /*!
+ * \brief Global channel call record list head.
+ */
+-struct chan_list *cl_te=NULL;
+-ast_mutex_t cl_te_lock;
++static struct chan_list *cl_te=NULL;
++static ast_mutex_t cl_te_lock;
+
+ static enum event_response_e
+ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data);
+@@ -533,13 +707,17 @@
+ static int stop_bc_tones(struct chan_list *cl);
+ static void release_chan(struct misdn_bchannel *bc);
+
+-static int misdn_check_l2l1(struct ast_channel *chan, void *data);
+-static int misdn_set_opt_exec(struct ast_channel *chan, void *data);
+-static int misdn_facility_exec(struct ast_channel *chan, void *data);
++#if defined(AST_MISDN_ENHANCEMENTS)
++static const char misdn_command_name[] = "misdn_command";
++static int misdn_command_exec(struct ast_channel *chan, const char *data);
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++static int misdn_check_l2l1(struct ast_channel *chan, const char *data);
++static int misdn_set_opt_exec(struct ast_channel *chan, const char *data);
++static int misdn_facility_exec(struct ast_channel *chan, const char *data);
+
+ int chan_misdn_jb_empty(struct misdn_bchannel *bc, char *buf, int len);
+
+-void debug_numplan(int port, int numplan, char *type);
++void debug_numtype(int port, int numtype, char *type);
+
+ int add_out_calls(int port);
+ int add_in_calls(int port);
+@@ -555,34 +733,1583 @@
+
+ /*************** Helpers *****************/
+
+-static struct chan_list * get_chan_by_ast(struct ast_channel *ast)
++static struct chan_list *get_chan_by_ast(struct ast_channel *ast)
+ {
+ struct chan_list *tmp;
+-
++
+ for (tmp = cl_te; tmp; tmp = tmp->next) {
+ if (tmp->ast == ast) {
+ return tmp;
+ }
+ }
+-
++
+ return NULL;
+ }
+
+-static struct chan_list * get_chan_by_ast_name(char *name)
++static struct chan_list *get_chan_by_ast_name(const char *name)
+ {
+ struct chan_list *tmp;
+-
++
+ for (tmp = cl_te; tmp; tmp = tmp->next) {
+ if (tmp->ast && strcmp(tmp->ast->name, name) == 0) {
+ return tmp;
+ }
+ }
+-
++
+ return NULL;
+ }
+
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Destroy the misdn_cc_ds_info datastore payload
++ *
++ * \param[in] data the datastore payload, a reference to an misdn_cc_caller
++ *
++ * \details
++ * Since the payload is a reference to an astobj2 object, we just decrement its
++ * reference count. Before doing so, we NULL out the channel pointer inside of
++ * the misdn_cc_caller instance. This function will be called in one of two
++ * cases. In both cases, we no longer need the channel pointer:
++ *
++ * - The original channel that initialized call completion services, the same
++ * channel that is stored here, has been destroyed early. This could happen
++ * if it transferred the mISDN channel, for example.
++ *
++ * - The mISDN channel that had this datastore inherited on to it is now being
++ * destroyed. If this is the case, then the call completion events have
++ * already occurred and the appropriate channel variables have already been
++ * set on the original channel that requested call completion services.
++ *
++ * \return Nothing
++ */
++static void misdn_cc_ds_destroy(void *data)
++{
++ struct misdn_cc_caller *cc_caller = data;
+
++ ao2_lock(cc_caller);
++ cc_caller->chan = NULL;
++ ao2_unlock(cc_caller);
+
++ ao2_ref(cc_caller, -1);
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Duplicate the misdn_cc_ds_info datastore payload
++ *
++ * \param[in] data the datastore payload, a reference to an misdn_cc_caller
++ *
++ * \details
++ * All we need to do is bump the reference count and return the same instance.
++ *
++ * \return A reference to an instance of a misdn_cc_caller
++ */
++static void *misdn_cc_ds_duplicate(void *data)
++{
++ struct misdn_cc_caller *cc_caller = data;
++
++ ao2_ref(cc_caller, +1);
++
++ return cc_caller;
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++static const struct ast_datastore_info misdn_cc_ds_info = {
++ .type = "misdn_cc",
++ .destroy = misdn_cc_ds_destroy,
++ .duplicate = misdn_cc_ds_duplicate,
++};
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Set a channel var on the peer channel for call completion services
++ *
++ * \param[in] peer The peer that initialized call completion services
++ * \param[in] var The variable name to set
++ * \param[in] value The variable value to set
++ *
++ * This function may be called from outside of the channel thread. It handles
++ * the fact that the peer channel may be hung up and destroyed at any time.
++ *
++ * \return nothing
++ */
++static void misdn_cc_set_peer_var(struct misdn_cc_caller *peer, const char *var,
++ const char *value)
++{
++ ao2_lock(peer);
++
++ /*! \todo XXX This nastiness can go away once ast_channel is ref counted! */
++ while (peer->chan && ast_channel_trylock(peer->chan)) {
++ ao2_unlock(peer);
++ sched_yield();
++ ao2_lock(peer);
++ }
++
++ if (peer->chan) {
++ pbx_builtin_setvar_helper(peer->chan, var, value);
++ ast_channel_unlock(peer->chan);
++ }
++
++ ao2_unlock(peer);
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Get a reference to the CC caller if it exists
++ */
++static struct misdn_cc_caller *misdn_cc_caller_get(struct ast_channel *chan)
++{
++ struct ast_datastore *datastore;
++ struct misdn_cc_caller *cc_caller;
++
++ ast_channel_lock(chan);
++
++ if (!(datastore = ast_channel_datastore_find(chan, &misdn_cc_ds_info, NULL))) {
++ ast_channel_unlock(chan);
++ return NULL;
++ }
++
++ ao2_ref(datastore->data, +1);
++ cc_caller = datastore->data;
++
++ ast_channel_unlock(chan);
++
++ return cc_caller;
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Find the call completion record given the record id.
++ *
++ * \param record_id
++ *
++ * \retval pointer to found call completion record
++ * \retval NULL if not found
++ *
++ * \note Assumes the misdn_cc_records_db lock is already obtained.
++ */
++static struct misdn_cc_record *misdn_cc_find_by_id(long record_id)
++{
++ struct misdn_cc_record *current;
++
++ AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
++ if (current->record_id == record_id) {
++ /* Found the record */
++ break;
++ }
++ }
++
++ return current;
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Find the call completion record given the port and call linkage id.
++ *
++ * \param port Logical port number
++ * \param linkage_id Call linkage ID number from switch.
++ *
++ * \retval pointer to found call completion record
++ * \retval NULL if not found
++ *
++ * \note Assumes the misdn_cc_records_db lock is already obtained.
++ */
++static struct misdn_cc_record *misdn_cc_find_by_linkage(int port, int linkage_id)
++{
++ struct misdn_cc_record *current;
++
++ AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
++ if (current->port == port
++ && !current->ptp
++ && current->mode.ptmp.linkage_id == linkage_id) {
++ /* Found the record */
++ break;
++ }
++ }
++
++ return current;
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Find the call completion record given the port and outstanding invocation id.
++ *
++ * \param port Logical port number
++ * \param invoke_id Outstanding message invocation ID number.
++ *
++ * \retval pointer to found call completion record
++ * \retval NULL if not found
++ *
++ * \note Assumes the misdn_cc_records_db lock is already obtained.
++ */
++static struct misdn_cc_record *misdn_cc_find_by_invoke(int port, int invoke_id)
++{
++ struct misdn_cc_record *current;
++
++ AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
++ if (current->outstanding_message
++ && current->invoke_id == invoke_id
++ && current->port == port) {
++ /* Found the record */
++ break;
++ }
++ }
++
++ return current;
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Find the call completion record given the port and CCBS reference id.
++ *
++ * \param port Logical port number
++ * \param reference_id CCBS reference ID number from switch.
++ *
++ * \retval pointer to found call completion record
++ * \retval NULL if not found
++ *
++ * \note Assumes the misdn_cc_records_db lock is already obtained.
++ */
++static struct misdn_cc_record *misdn_cc_find_by_reference(int port, int reference_id)
++{
++ struct misdn_cc_record *current;
++
++ AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
++ if (current->activated
++ && current->port == port
++ && !current->ptp
++ && current->mode.ptmp.reference_id == reference_id) {
++ /* Found the record */
++ break;
++ }
++ }
++
++ return current;
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Find the call completion record given the B channel pointer
++ *
++ * \param bc B channel control structure pointer.
++ *
++ * \retval pointer to found call completion record
++ * \retval NULL if not found
++ *
++ * \note Assumes the misdn_cc_records_db lock is already obtained.
++ */
++static struct misdn_cc_record *misdn_cc_find_by_bc(const struct misdn_bchannel *bc)
++{
++ struct misdn_cc_record *current;
++
++ if (bc) {
++ AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
++ if (current->ptp
++ && current->mode.ptp.bc == bc) {
++ /* Found the record */
++ break;
++ }
++ }
++ } else {
++ current = NULL;
++ }
++
++ return current;
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Delete the given call completion record
++ *
++ * \param doomed Call completion record to destroy
++ *
++ * \return Nothing
++ *
++ * \note Assumes the misdn_cc_records_db lock is already obtained.
++ */
++static void misdn_cc_delete(struct misdn_cc_record *doomed)
++{
++ struct misdn_cc_record *current;
++
++ AST_LIST_TRAVERSE_SAFE_BEGIN(&misdn_cc_records_db, current, list) {
++ if (current == doomed) {
++ AST_LIST_REMOVE_CURRENT(list);
++ ast_free(current);
++ return;
++ }
++ }
++ AST_LIST_TRAVERSE_SAFE_END;
++
++ /* The doomed node is not in the call completion database */
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Delete all old call completion records
++ *
++ * \return Nothing
++ *
++ * \note Assumes the misdn_cc_records_db lock is already obtained.
++ */
++static void misdn_cc_remove_old(void)
++{
++ struct misdn_cc_record *current;
++ time_t now;
++
++ now = time(NULL);
++ AST_LIST_TRAVERSE_SAFE_BEGIN(&misdn_cc_records_db, current, list) {
++ if (MISDN_CC_RECORD_AGE_MAX < now - current->time_created) {
++ if (current->ptp && current->mode.ptp.bc) {
++ /* Close the old call-completion signaling link */
++ current->mode.ptp.bc->fac_out.Function = Fac_None;
++ current->mode.ptp.bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
++ misdn_lib_send_event(current->mode.ptp.bc, EVENT_RELEASE_COMPLETE);
++ }
++
++ /* Remove the old call completion record */
++ AST_LIST_REMOVE_CURRENT(list);
++ ast_free(current);
++ }
++ }
++ AST_LIST_TRAVERSE_SAFE_END;
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Allocate the next record id.
++ *
++ * \retval New record id on success.
++ * \retval -1 on error.
++ *
++ * \note Assumes the misdn_cc_records_db lock is already obtained.
++ */
++static long misdn_cc_record_id_new(void)
++{
++ long record_id;
++ long first_id;
++
++ record_id = ++misdn_cc_record_id;
++ first_id = record_id;
++ while (misdn_cc_find_by_id(record_id)) {
++ record_id = ++misdn_cc_record_id;
++ if (record_id == first_id) {
++ /*
++ * We have a resource leak.
++ * We should never need to allocate 64k records.
++ */
++ chan_misdn_log(0, 0, " --> ERROR Too many call completion records!\n");
++ record_id = -1;
++ break;
++ }
++ }
++
++ return record_id;
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Create a new call completion record
++ *
++ * \retval pointer to new call completion record
++ * \retval NULL if failed
++ *
++ * \note Assumes the misdn_cc_records_db lock is already obtained.
++ */
++static struct misdn_cc_record *misdn_cc_new(void)
++{
++ struct misdn_cc_record *cc_record;
++ long record_id;
++
++ misdn_cc_remove_old();
++
++ cc_record = ast_calloc(1, sizeof(*cc_record));
++ if (cc_record) {
++ record_id = misdn_cc_record_id_new();
++ if (record_id < 0) {
++ ast_free(cc_record);
++ return NULL;
++ }
++
++ /* Initialize the new record */
++ cc_record->record_id = record_id;
++ cc_record->port = -1;/* Invalid port so it will never be found this way */
++ cc_record->invoke_id = ++misdn_invoke_id;
++ cc_record->party_a_free = 1;/* Default User-A as free */
++ cc_record->error_code = FacError_None;
++ cc_record->reject_code = FacReject_None;
++ cc_record->time_created = time(NULL);
++
++ /* Insert the new record into the database */
++ AST_LIST_INSERT_HEAD(&misdn_cc_records_db, cc_record, list);
++ }
++ return cc_record;
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Destroy the call completion record database
++ *
++ * \return Nothing
++ */
++static void misdn_cc_destroy(void)
++{
++ struct misdn_cc_record *current;
++
++ while ((current = AST_LIST_REMOVE_HEAD(&misdn_cc_records_db, list))) {
++ /* Do a misdn_cc_delete(current) inline */
++ ast_free(current);
++ }
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Initialize the call completion record database
++ *
++ * \return Nothing
++ */
++static void misdn_cc_init(void)
++{
++ misdn_cc_record_id = 0;
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Check the status of an outstanding invocation request.
++ *
++ * \param data Points to an integer containing the call completion record id.
++ *
++ * \retval 0 if got a response.
++ * \retval -1 if no response yet.
++ */
++static int misdn_cc_response_check(void *data)
++{
++ int not_responded;
++ struct misdn_cc_record *cc_record;
++
++ AST_LIST_LOCK(&misdn_cc_records_db);
++ cc_record = misdn_cc_find_by_id(*(long *) data);
++ if (cc_record) {
++ if (cc_record->outstanding_message) {
++ not_responded = -1;
++ } else {
++ not_responded = 0;
++ }
++ } else {
++ /* No record so there is no response to check. */
++ not_responded = 0;
++ }
++ AST_LIST_UNLOCK(&misdn_cc_records_db);
++
++ return not_responded;
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Wait for a response from the switch for an outstanding
++ * invocation request.
++ *
++ * \param chan Asterisk channel to operate upon.
++ * \param wait_seconds Number of seconds to wait
++ * \param record_id Call completion record ID.
++ *
++ * \return Nothing
++ */
++static void misdn_cc_response_wait(struct ast_channel *chan, int wait_seconds, long record_id)
++{
++ unsigned count;
++
++ for (count = 2 * MISDN_CC_REQUEST_WAIT_MAX; count--;) {
++ /* Sleep in 500 ms increments */
++ if (ast_safe_sleep_conditional(chan, 500, misdn_cc_response_check, &record_id) != 0) {
++ /* We got hung up or our response came in. */
++ break;
++ }
++ }
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Convert the mISDN reject code to a string
++ *
++ * \param code mISDN reject code.
++ *
++ * \return The mISDN reject code as a string
++ */
++static const char *misdn_to_str_reject_code(enum FacRejectCode code)
++{
++ static const struct {
++ enum FacRejectCode code;
++ char *name;
++ } arr[] = {
++/* *INDENT-OFF* */
++ { FacReject_None, "No reject occurred" },
++ { FacReject_Unknown, "Unknown reject code" },
++
++ { FacReject_Gen_UnrecognizedComponent, "General: Unrecognized Component" },
++ { FacReject_Gen_MistypedComponent, "General: Mistyped Component" },
++ { FacReject_Gen_BadlyStructuredComponent, "General: Badly Structured Component" },
++
++ { FacReject_Inv_DuplicateInvocation, "Invoke: Duplicate Invocation" },
++ { FacReject_Inv_UnrecognizedOperation, "Invoke: Unrecognized Operation" },
++ { FacReject_Inv_MistypedArgument, "Invoke: Mistyped Argument" },
++ { FacReject_Inv_ResourceLimitation, "Invoke: Resource Limitation" },
++ { FacReject_Inv_InitiatorReleasing, "Invoke: Initiator Releasing" },
++ { FacReject_Inv_UnrecognizedLinkedID, "Invoke: Unrecognized Linked ID" },
++ { FacReject_Inv_LinkedResponseUnexpected, "Invoke: Linked Response Unexpected" },
++ { FacReject_Inv_UnexpectedChildOperation, "Invoke: Unexpected Child Operation" },
++
++ { FacReject_Res_UnrecognizedInvocation, "Result: Unrecognized Invocation" },
++ { FacReject_Res_ResultResponseUnexpected, "Result: Result Response Unexpected" },
++ { FacReject_Res_MistypedResult, "Result: Mistyped Result" },
++
++ { FacReject_Err_UnrecognizedInvocation, "Error: Unrecognized Invocation" },
++ { FacReject_Err_ErrorResponseUnexpected, "Error: Error Response Unexpected" },
++ { FacReject_Err_UnrecognizedError, "Error: Unrecognized Error" },
++ { FacReject_Err_UnexpectedError, "Error: Unexpected Error" },
++ { FacReject_Err_MistypedParameter, "Error: Mistyped Parameter" },
++/* *INDENT-ON* */
++ };
++
++ unsigned index;
++
++ for (index = 0; index < ARRAY_LEN(arr); ++index) {
++ if (arr[index].code == code) {
++ return arr[index].name;
++ }
++ }
++
++ return "unknown";
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Convert the mISDN error code to a string
++ *
++ * \param code mISDN error code.
++ *
++ * \return The mISDN error code as a string
++ */
++static const char *misdn_to_str_error_code(enum FacErrorCode code)
++{
++ static const struct {
++ enum FacErrorCode code;
++ char *name;
++ } arr[] = {
++/* *INDENT-OFF* */
++ { FacError_None, "No error occurred" },
++ { FacError_Unknown, "Unknown OID error code" },
++
++ { FacError_Gen_NotSubscribed, "General: Not Subscribed" },
++ { FacError_Gen_NotAvailable, "General: Not Available" },
++ { FacError_Gen_NotImplemented, "General: Not Implemented" },
++ { FacError_Gen_InvalidServedUserNr, "General: Invalid Served User Number" },
++ { FacError_Gen_InvalidCallState, "General: Invalid Call State" },
++ { FacError_Gen_BasicServiceNotProvided, "General: Basic Service Not Provided" },
++ { FacError_Gen_NotIncomingCall, "General: Not Incoming Call" },
++ { FacError_Gen_SupplementaryServiceInteractionNotAllowed,"General: Supplementary Service Interaction Not Allowed" },
++ { FacError_Gen_ResourceUnavailable, "General: Resource Unavailable" },
++
++ { FacError_Div_InvalidDivertedToNr, "Diversion: Invalid Diverted To Number" },
++ { FacError_Div_SpecialServiceNr, "Diversion: Special Service Number" },
++ { FacError_Div_DiversionToServedUserNr, "Diversion: Diversion To Served User Number" },
++ { FacError_Div_IncomingCallAccepted, "Diversion: Incoming Call Accepted" },
++ { FacError_Div_NumberOfDiversionsExceeded, "Diversion: Number Of Diversions Exceeded" },
++ { FacError_Div_NotActivated, "Diversion: Not Activated" },
++ { FacError_Div_RequestAlreadyAccepted, "Diversion: Request Already Accepted" },
++
++ { FacError_AOC_NoChargingInfoAvailable, "AOC: No Charging Info Available" },
++
++ { FacError_CCBS_InvalidCallLinkageID, "CCBS: Invalid Call Linkage ID" },
++ { FacError_CCBS_InvalidCCBSReference, "CCBS: Invalid CCBS Reference" },
++ { FacError_CCBS_LongTermDenial, "CCBS: Long Term Denial" },
++ { FacError_CCBS_ShortTermDenial, "CCBS: Short Term Denial" },
++ { FacError_CCBS_IsAlreadyActivated, "CCBS: Is Already Activated" },
++ { FacError_CCBS_AlreadyAccepted, "CCBS: Already Accepted" },
++ { FacError_CCBS_OutgoingCCBSQueueFull, "CCBS: Outgoing CCBS Queue Full" },
++ { FacError_CCBS_CallFailureReasonNotBusy, "CCBS: Call Failure Reason Not Busy" },
++ { FacError_CCBS_NotReadyForCall, "CCBS: Not Ready For Call" },
++
++ { FacError_CCBS_T_LongTermDenial, "CCBS-T: Long Term Denial" },
++ { FacError_CCBS_T_ShortTermDenial, "CCBS-T: Short Term Denial" },
++
++ { FacError_ECT_LinkIdNotAssignedByNetwork, "ECT: Link ID Not Assigned By Network" },
++/* *INDENT-ON* */
++ };
++
++ unsigned index;
++
++ for (index = 0; index < ARRAY_LEN(arr); ++index) {
++ if (arr[index].code == code) {
++ return arr[index].name;
++ }
++ }
++
++ return "unknown";
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Convert mISDN redirecting reason to diversion reason.
++ *
++ * \param reason mISDN redirecting reason code.
++ *
++ * \return Supported diversion reason code.
++ */
++static unsigned misdn_to_diversion_reason(enum mISDN_REDIRECTING_REASON reason)
++{
++ unsigned diversion_reason;
++
++ switch (reason) {
++ case mISDN_REDIRECTING_REASON_CALL_FWD:
++ diversion_reason = 1;/* cfu */
++ break;
++ case mISDN_REDIRECTING_REASON_CALL_FWD_BUSY:
++ diversion_reason = 2;/* cfb */
++ break;
++ case mISDN_REDIRECTING_REASON_NO_REPLY:
++ diversion_reason = 3;/* cfnr */
++ break;
++ default:
++ diversion_reason = 0;/* unknown */
++ break;
++ }
++
++ return diversion_reason;
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Convert diversion reason to mISDN redirecting reason
++ *
++ * \param diversion_reason Diversion reason to convert
++ *
++ * \return Supported redirecting reason code.
++ */
++static enum mISDN_REDIRECTING_REASON diversion_reason_to_misdn(unsigned diversion_reason)
++{
++ enum mISDN_REDIRECTING_REASON reason;
++
++ switch (diversion_reason) {
++ case 1:/* cfu */
++ reason = mISDN_REDIRECTING_REASON_CALL_FWD;
++ break;
++ case 2:/* cfb */
++ reason = mISDN_REDIRECTING_REASON_CALL_FWD_BUSY;
++ break;
++ case 3:/* cfnr */
++ reason = mISDN_REDIRECTING_REASON_NO_REPLY;
++ break;
++ default:
++ reason = mISDN_REDIRECTING_REASON_UNKNOWN;
++ break;
++ }
++
++ return reason;
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Convert the mISDN presentation to PresentedNumberUnscreened type
++ *
++ * \param presentation mISDN presentation to convert
++ * \param number_present TRUE if the number is present
++ *
++ * \return PresentedNumberUnscreened type
++ */
++static unsigned misdn_to_PresentedNumberUnscreened_type(int presentation, int number_present)
++{
++ unsigned type;
++
++ switch (presentation) {
++ case 0:/* allowed */
++ if (number_present) {
++ type = 0;/* presentationAllowedNumber */
++ } else {
++ type = 2;/* numberNotAvailableDueToInterworking */
++ }
++ break;
++ case 1:/* restricted */
++ if (number_present) {
++ type = 3;/* presentationRestrictedNumber */
++ } else {
++ type = 1;/* presentationRestricted */
++ }
++ break;
++ default:
++ type = 2;/* numberNotAvailableDueToInterworking */
++ break;
++ }
++
++ return type;
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Convert the PresentedNumberUnscreened type to mISDN presentation
++ *
++ * \param type PresentedNumberUnscreened type
++ *
++ * \return mISDN presentation
++ */
++static int PresentedNumberUnscreened_to_misdn_pres(unsigned type)
++{
++ int presentation;
++
++ switch (type) {
++ default:
++ case 0:/* presentationAllowedNumber */
++ presentation = 0;/* allowed */
++ break;
++
++ case 1:/* presentationRestricted */
++ case 3:/* presentationRestrictedNumber */
++ presentation = 1;/* restricted */
++ break;
++
++ case 2:/* numberNotAvailableDueToInterworking */
++ presentation = 2;/* unavailable */
++ break;
++ }
++
++ return presentation;
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Convert the mISDN numbering plan to PartyNumber numbering plan
++ *
++ * \param number_plan mISDN numbering plan
++ *
++ * \return PartyNumber numbering plan
++ */
++static unsigned misdn_to_PartyNumber_plan(enum mISDN_NUMBER_PLAN number_plan)
++{
++ unsigned party_plan;
++
++ switch (number_plan) {
++ default:
++ case NUMPLAN_UNKNOWN:
++ party_plan = 0;/* unknown */
++ break;
++
++ case NUMPLAN_ISDN:
++ party_plan = 1;/* public */
++ break;
++
++ case NUMPLAN_DATA:
++ party_plan = 3;/* data */
++ break;
++
++ case NUMPLAN_TELEX:
++ party_plan = 4;/* telex */
++ break;
++
++ case NUMPLAN_NATIONAL:
++ party_plan = 8;/* nationalStandard */
++ break;
++
++ case NUMPLAN_PRIVATE:
++ party_plan = 5;/* private */
++ break;
++ }
++
++ return party_plan;
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Convert PartyNumber numbering plan to mISDN numbering plan
++ *
++ * \param party_plan PartyNumber numbering plan
++ *
++ * \return mISDN numbering plan
++ */
++static enum mISDN_NUMBER_PLAN PartyNumber_to_misdn_plan(unsigned party_plan)
++{
++ enum mISDN_NUMBER_PLAN number_plan;
++
++ switch (party_plan) {
++ default:
++ case 0:/* unknown */
++ number_plan = NUMPLAN_UNKNOWN;
++ break;
++ case 1:/* public */
++ number_plan = NUMPLAN_ISDN;
++ break;
++ case 3:/* data */
++ number_plan = NUMPLAN_DATA;
++ break;
++ case 4:/* telex */
++ number_plan = NUMPLAN_TELEX;
++ break;
++ case 8:/* nationalStandard */
++ number_plan = NUMPLAN_NATIONAL;
++ break;
++ case 5:/* private */
++ number_plan = NUMPLAN_PRIVATE;
++ break;
++ }
++
++ return number_plan;
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Convert mISDN type-of-number to PartyNumber public type-of-number
++ *
++ * \param ton mISDN type-of-number
++ *
++ * \return PartyNumber public type-of-number
++ */
++static unsigned misdn_to_PartyNumber_ton_public(enum mISDN_NUMBER_TYPE ton)
++{
++ unsigned party_ton;
++
++ switch (ton) {
++ default:
++ case NUMTYPE_UNKNOWN:
++ party_ton = 0;/* unknown */
++ break;
++
++ case NUMTYPE_INTERNATIONAL:
++ party_ton = 1;/* internationalNumber */
++ break;
++
++ case NUMTYPE_NATIONAL:
++ party_ton = 2;/* nationalNumber */
++ break;
++
++ case NUMTYPE_NETWORK_SPECIFIC:
++ party_ton = 3;/* networkSpecificNumber */
++ break;
++
++ case NUMTYPE_SUBSCRIBER:
++ party_ton = 4;/* subscriberNumber */
++ break;
++
++ case NUMTYPE_ABBREVIATED:
++ party_ton = 6;/* abbreviatedNumber */
++ break;
++ }
++
++ return party_ton;
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Convert the PartyNumber public type-of-number to mISDN type-of-number
++ *
++ * \param party_ton PartyNumber public type-of-number
++ *
++ * \return mISDN type-of-number
++ */
++static enum mISDN_NUMBER_TYPE PartyNumber_to_misdn_ton_public(unsigned party_ton)
++{
++ enum mISDN_NUMBER_TYPE ton;
++
++ switch (party_ton) {
++ default:
++ case 0:/* unknown */
++ ton = NUMTYPE_UNKNOWN;
++ break;
++
++ case 1:/* internationalNumber */
++ ton = NUMTYPE_INTERNATIONAL;
++ break;
++
++ case 2:/* nationalNumber */
++ ton = NUMTYPE_NATIONAL;
++ break;
++
++ case 3:/* networkSpecificNumber */
++ ton = NUMTYPE_NETWORK_SPECIFIC;
++ break;
++
++ case 4:/* subscriberNumber */
++ ton = NUMTYPE_SUBSCRIBER;
++ break;
++
++ case 6:/* abbreviatedNumber */
++ ton = NUMTYPE_ABBREVIATED;
++ break;
++ }
++
++ return ton;
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Convert mISDN type-of-number to PartyNumber private type-of-number
++ *
++ * \param ton mISDN type-of-number
++ *
++ * \return PartyNumber private type-of-number
++ */
++static unsigned misdn_to_PartyNumber_ton_private(enum mISDN_NUMBER_TYPE ton)
++{
++ unsigned party_ton;
++
++ switch (ton) {
++ default:
++ case NUMTYPE_UNKNOWN:
++ party_ton = 0;/* unknown */
++ break;
++
++ case NUMTYPE_INTERNATIONAL:
++ party_ton = 1;/* level2RegionalNumber */
++ break;
++
++ case NUMTYPE_NATIONAL:
++ party_ton = 2;/* level1RegionalNumber */
++ break;
++
++ case NUMTYPE_NETWORK_SPECIFIC:
++ party_ton = 3;/* pTNSpecificNumber */
++ break;
++
++ case NUMTYPE_SUBSCRIBER:
++ party_ton = 4;/* localNumber */
++ break;
++
++ case NUMTYPE_ABBREVIATED:
++ party_ton = 6;/* abbreviatedNumber */
++ break;
++ }
++
++ return party_ton;
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Convert the PartyNumber private type-of-number to mISDN type-of-number
++ *
++ * \param party_ton PartyNumber private type-of-number
++ *
++ * \return mISDN type-of-number
++ */
++static enum mISDN_NUMBER_TYPE PartyNumber_to_misdn_ton_private(unsigned party_ton)
++{
++ enum mISDN_NUMBER_TYPE ton;
++
++ switch (party_ton) {
++ default:
++ case 0:/* unknown */
++ ton = NUMTYPE_UNKNOWN;
++ break;
++
++ case 1:/* level2RegionalNumber */
++ ton = NUMTYPE_INTERNATIONAL;
++ break;
++
++ case 2:/* level1RegionalNumber */
++ ton = NUMTYPE_NATIONAL;
++ break;
++
++ case 3:/* pTNSpecificNumber */
++ ton = NUMTYPE_NETWORK_SPECIFIC;
++ break;
++
++ case 4:/* localNumber */
++ ton = NUMTYPE_SUBSCRIBER;
++ break;
++
++ case 6:/* abbreviatedNumber */
++ ton = NUMTYPE_ABBREVIATED;
++ break;
++ }
++
++ return ton;
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++/*!
++ * \internal
++ * \brief Convert the mISDN type of number code to a string
++ *
++ * \param number_type mISDN type of number code.
++ *
++ * \return The mISDN type of number code as a string
++ */
++static const char *misdn_to_str_ton(enum mISDN_NUMBER_TYPE number_type)
++{
++ const char *str;
++
++ switch (number_type) {
++ default:
++ case NUMTYPE_UNKNOWN:
++ str = "Unknown";
++ break;
++
++ case NUMTYPE_INTERNATIONAL:
++ str = "International";
++ break;
++
++ case NUMTYPE_NATIONAL:
++ str = "National";
++ break;
++
++ case NUMTYPE_NETWORK_SPECIFIC:
++ str = "Network Specific";
++ break;
++
++ case NUMTYPE_SUBSCRIBER:
++ str = "Subscriber";
++ break;
++
++ case NUMTYPE_ABBREVIATED:
++ str = "Abbreviated";
++ break;
++ }
++
++ return str;
++}
++
++/*!
++ * \internal
++ * \brief Convert the mISDN type of number code to Asterisk type of number code
++ *
++ * \param number_type mISDN type of number code.
++ *
++ * \return Asterisk type of number code
++ */
++static int misdn_to_ast_ton(enum mISDN_NUMBER_TYPE number_type)
++{
++ int ast_number_type;
++
++ switch (number_type) {
++ default:
++ case NUMTYPE_UNKNOWN:
++ ast_number_type = NUMTYPE_UNKNOWN << 4;
++ break;
++
++ case NUMTYPE_INTERNATIONAL:
++ ast_number_type = NUMTYPE_INTERNATIONAL << 4;
++ break;
++
++ case NUMTYPE_NATIONAL:
++ ast_number_type = NUMTYPE_NATIONAL << 4;
++ break;
++
++ case NUMTYPE_NETWORK_SPECIFIC:
++ ast_number_type = NUMTYPE_NETWORK_SPECIFIC << 4;
++ break;
++
++ case NUMTYPE_SUBSCRIBER:
++ ast_number_type = NUMTYPE_SUBSCRIBER << 4;
++ break;
++
++ case NUMTYPE_ABBREVIATED:
++ ast_number_type = NUMTYPE_ABBREVIATED << 4;
++ break;
++ }
++
++ return ast_number_type;
++}
++
++/*!
++ * \internal
++ * \brief Convert the Asterisk type of number code to mISDN type of number code
++ *
++ * \param ast_number_type Asterisk type of number code.
++ *
++ * \return mISDN type of number code
++ */
++static enum mISDN_NUMBER_TYPE ast_to_misdn_ton(unsigned ast_number_type)
++{
++ enum mISDN_NUMBER_TYPE number_type;
++
++ switch ((ast_number_type >> 4) & 0x07) {
++ default:
++ case NUMTYPE_UNKNOWN:
++ number_type = NUMTYPE_UNKNOWN;
++ break;
++
++ case NUMTYPE_INTERNATIONAL:
++ number_type = NUMTYPE_INTERNATIONAL;
++ break;
++
++ case NUMTYPE_NATIONAL:
++ number_type = NUMTYPE_NATIONAL;
++ break;
++
++ case NUMTYPE_NETWORK_SPECIFIC:
++ number_type = NUMTYPE_NETWORK_SPECIFIC;
++ break;
++
++ case NUMTYPE_SUBSCRIBER:
++ number_type = NUMTYPE_SUBSCRIBER;
++ break;
++
++ case NUMTYPE_ABBREVIATED:
++ number_type = NUMTYPE_ABBREVIATED;
++ break;
++ }
++
++ return number_type;
++}
++
++/*!
++ * \internal
++ * \brief Convert the mISDN numbering plan code to a string
++ *
++ * \param number_plan mISDN numbering plan code.
++ *
++ * \return The mISDN numbering plan code as a string
++ */
++static const char *misdn_to_str_plan(enum mISDN_NUMBER_PLAN number_plan)
++{
++ const char *str;
++
++ switch (number_plan) {
++ default:
++ case NUMPLAN_UNKNOWN:
++ str = "Unknown";
++ break;
++
++ case NUMPLAN_ISDN:
++ str = "ISDN";
++ break;
++
++ case NUMPLAN_DATA:
++ str = "Data";
++ break;
++
++ case NUMPLAN_TELEX:
++ str = "Telex";
++ break;
++
++ case NUMPLAN_NATIONAL:
++ str = "National";
++ break;
++
++ case NUMPLAN_PRIVATE:
++ str = "Private";
++ break;
++ }
++
++ return str;
++}
++
++/*!
++ * \internal
++ * \brief Convert the mISDN numbering plan code to Asterisk numbering plan code
++ *
++ * \param number_plan mISDN numbering plan code.
++ *
++ * \return Asterisk numbering plan code
++ */
++static int misdn_to_ast_plan(enum mISDN_NUMBER_PLAN number_plan)
++{
++ int ast_number_plan;
++
++ switch (number_plan) {
++ default:
++ case NUMPLAN_UNKNOWN:
++ ast_number_plan = NUMPLAN_UNKNOWN;
++ break;
++
++ case NUMPLAN_ISDN:
++ ast_number_plan = NUMPLAN_ISDN;
++ break;
++
++ case NUMPLAN_DATA:
++ ast_number_plan = NUMPLAN_DATA;
++ break;
++
++ case NUMPLAN_TELEX:
++ ast_number_plan = NUMPLAN_TELEX;
++ break;
++
++ case NUMPLAN_NATIONAL:
++ ast_number_plan = NUMPLAN_NATIONAL;
++ break;
++
++ case NUMPLAN_PRIVATE:
++ ast_number_plan = NUMPLAN_PRIVATE;
++ break;
++ }
++
++ return ast_number_plan;
++}
++
++/*!
++ * \internal
++ * \brief Convert the Asterisk numbering plan code to mISDN numbering plan code
++ *
++ * \param ast_number_plan Asterisk numbering plan code.
++ *
++ * \return mISDN numbering plan code
++ */
++static enum mISDN_NUMBER_PLAN ast_to_misdn_plan(unsigned ast_number_plan)
++{
++ enum mISDN_NUMBER_PLAN number_plan;
++
++ switch (ast_number_plan & 0x0F) {
++ default:
++ case NUMPLAN_UNKNOWN:
++ number_plan = NUMPLAN_UNKNOWN;
++ break;
++
++ case NUMPLAN_ISDN:
++ number_plan = NUMPLAN_ISDN;
++ break;
++
++ case NUMPLAN_DATA:
++ number_plan = NUMPLAN_DATA;
++ break;
++
++ case NUMPLAN_TELEX:
++ number_plan = NUMPLAN_TELEX;
++ break;
++
++ case NUMPLAN_NATIONAL:
++ number_plan = NUMPLAN_NATIONAL;
++ break;
++
++ case NUMPLAN_PRIVATE:
++ number_plan = NUMPLAN_PRIVATE;
++ break;
++ }
++
++ return number_plan;
++}
++
++/*!
++ * \internal
++ * \brief Convert the mISDN presentation code to a string
++ *
++ * \param presentation mISDN number presentation restriction code.
++ *
++ * \return The mISDN presentation code as a string
++ */
++static const char *misdn_to_str_pres(int presentation)
++{
++ const char *str;
++
++ switch (presentation) {
++ case 0:
++ str = "Allowed";
++ break;
++
++ case 1:
++ str = "Restricted";
++ break;
++
++ case 2:
++ str = "Unavailable";
++ break;
++
++ default:
++ str = "Unknown";
++ break;
++ }
++
++ return str;
++}
++
++/*!
++ * \internal
++ * \brief Convert the mISDN presentation code to Asterisk presentation code
++ *
++ * \param presentation mISDN number presentation restriction code.
++ *
++ * \return Asterisk presentation code
++ */
++static int misdn_to_ast_pres(int presentation)
++{
++ switch (presentation) {
++ default:
++ case 0:
++ presentation = AST_PRES_ALLOWED;
++ break;
++
++ case 1:
++ presentation = AST_PRES_RESTRICTED;
++ break;
++
++ case 2:
++ presentation = AST_PRES_UNAVAILABLE;
++ break;
++ }
++
++ return presentation;
++}
++
++/*!
++ * \internal
++ * \brief Convert the Asterisk presentation code to mISDN presentation code
++ *
++ * \param presentation Asterisk number presentation restriction code.
++ *
++ * \return mISDN presentation code
++ */
++static int ast_to_misdn_pres(int presentation)
++{
++ switch (presentation & AST_PRES_RESTRICTION) {
++ default:
++ case AST_PRES_ALLOWED:
++ presentation = 0;
++ break;
++
++ case AST_PRES_RESTRICTED:
++ presentation = 1;
++ break;
++
++ case AST_PRES_UNAVAILABLE:
++ presentation = 2;
++ break;
++ }
++
++ return presentation;
++}
++
++/*!
++ * \internal
++ * \brief Convert the mISDN screening code to a string
++ *
++ * \param screening mISDN number screening code.
++ *
++ * \return The mISDN screening code as a string
++ */
++static const char *misdn_to_str_screen(int screening)
++{
++ const char *str;
++
++ switch (screening) {
++ case 0:
++ str = "Unscreened";
++ break;
++
++ case 1:
++ str = "Passed Screen";
++ break;
++
++ case 2:
++ str = "Failed Screen";
++ break;
++
++ case 3:
++ str = "Network Number";
++ break;
++
++ default:
++ str = "Unknown";
++ break;
++ }
++
++ return str;
++}
++
++/*!
++ * \internal
++ * \brief Convert the mISDN screening code to Asterisk screening code
++ *
++ * \param screening mISDN number screening code.
++ *
++ * \return Asterisk screening code
++ */
++static int misdn_to_ast_screen(int screening)
++{
++ switch (screening) {
++ default:
++ case 0:
++ screening = AST_PRES_USER_NUMBER_UNSCREENED;
++ break;
++
++ case 1:
++ screening = AST_PRES_USER_NUMBER_PASSED_SCREEN;
++ break;
++
++ case 2:
++ screening = AST_PRES_USER_NUMBER_FAILED_SCREEN;
++ break;
++
++ case 3:
++ screening = AST_PRES_NETWORK_NUMBER;
++ break;
++ }
++
++ return screening;
++}
++
++/*!
++ * \internal
++ * \brief Convert the Asterisk screening code to mISDN screening code
++ *
++ * \param screening Asterisk number screening code.
++ *
++ * \return mISDN screening code
++ */
++static int ast_to_misdn_screen(int screening)
++{
++ switch (screening & AST_PRES_NUMBER_TYPE) {
++ default:
++ case AST_PRES_USER_NUMBER_UNSCREENED:
++ screening = 0;
++ break;
++
++ case AST_PRES_USER_NUMBER_PASSED_SCREEN:
++ screening = 1;
++ break;
++
++ case AST_PRES_USER_NUMBER_FAILED_SCREEN:
++ screening = 2;
++ break;
++
++ case AST_PRES_NETWORK_NUMBER:
++ screening = 3;
++ break;
++ }
++
++ return screening;
++}
++
++/*!
++ * \internal
++ * \brief Convert Asterisk redirecting reason to mISDN redirecting reason code.
++ *
++ * \param ast Asterisk redirecting reason code.
++ *
++ * \return mISDN reason code
++ */
++static enum mISDN_REDIRECTING_REASON ast_to_misdn_reason(const enum AST_REDIRECTING_REASON ast)
++{
++ unsigned index;
++
++ static const struct misdn_reasons {
++ enum AST_REDIRECTING_REASON ast;
++ enum mISDN_REDIRECTING_REASON q931;
++ } misdn_reason_table[] = {
++ /* *INDENT-OFF* */
++ { AST_REDIRECTING_REASON_UNKNOWN, mISDN_REDIRECTING_REASON_UNKNOWN },
++ { AST_REDIRECTING_REASON_USER_BUSY, mISDN_REDIRECTING_REASON_CALL_FWD_BUSY },
++ { AST_REDIRECTING_REASON_NO_ANSWER, mISDN_REDIRECTING_REASON_NO_REPLY },
++ { AST_REDIRECTING_REASON_UNAVAILABLE, mISDN_REDIRECTING_REASON_NO_REPLY },
++ { AST_REDIRECTING_REASON_UNCONDITIONAL, mISDN_REDIRECTING_REASON_CALL_FWD },
++ { AST_REDIRECTING_REASON_TIME_OF_DAY, mISDN_REDIRECTING_REASON_UNKNOWN },
++ { AST_REDIRECTING_REASON_DO_NOT_DISTURB, mISDN_REDIRECTING_REASON_UNKNOWN },
++ { AST_REDIRECTING_REASON_DEFLECTION, mISDN_REDIRECTING_REASON_DEFLECTION },
++ { AST_REDIRECTING_REASON_FOLLOW_ME, mISDN_REDIRECTING_REASON_UNKNOWN },
++ { AST_REDIRECTING_REASON_OUT_OF_ORDER, mISDN_REDIRECTING_REASON_OUT_OF_ORDER },
++ { AST_REDIRECTING_REASON_AWAY, mISDN_REDIRECTING_REASON_UNKNOWN },
++ { AST_REDIRECTING_REASON_CALL_FWD_DTE, mISDN_REDIRECTING_REASON_CALL_FWD_DTE }
++ /* *INDENT-ON* */
++ };
++
++ for (index = 0; index < ARRAY_LEN(misdn_reason_table); ++index) {
++ if (misdn_reason_table[index].ast == ast) {
++ return misdn_reason_table[index].q931;
++ }
++ }
++ return mISDN_REDIRECTING_REASON_UNKNOWN;
++}
++
++/*!
++ * \internal
++ * \brief Convert the mISDN redirecting reason to Asterisk redirecting reason code
++ *
++ * \param q931 mISDN redirecting reason code.
++ *
++ * \return Asterisk redirecting reason code
++ */
++static enum AST_REDIRECTING_REASON misdn_to_ast_reason(const enum mISDN_REDIRECTING_REASON q931)
++{
++ enum AST_REDIRECTING_REASON ast;
++
++ switch (q931) {
++ default:
++ case mISDN_REDIRECTING_REASON_UNKNOWN:
++ ast = AST_REDIRECTING_REASON_UNKNOWN;
++ break;
++
++ case mISDN_REDIRECTING_REASON_CALL_FWD_BUSY:
++ ast = AST_REDIRECTING_REASON_USER_BUSY;
++ break;
++
++ case mISDN_REDIRECTING_REASON_NO_REPLY:
++ ast = AST_REDIRECTING_REASON_NO_ANSWER;
++ break;
++
++ case mISDN_REDIRECTING_REASON_DEFLECTION:
++ ast = AST_REDIRECTING_REASON_DEFLECTION;
++ break;
++
++ case mISDN_REDIRECTING_REASON_OUT_OF_ORDER:
++ ast = AST_REDIRECTING_REASON_OUT_OF_ORDER;
++ break;
++
++ case mISDN_REDIRECTING_REASON_CALL_FWD_DTE:
++ ast = AST_REDIRECTING_REASON_CALL_FWD_DTE;
++ break;
++
++ case mISDN_REDIRECTING_REASON_CALL_FWD:
++ ast = AST_REDIRECTING_REASON_UNCONDITIONAL;
++ break;
++ }
++
++ return ast;
++}
++
++
++
+ struct allowed_bearers {
+ char *name; /*!< Bearer capability name string used in /etc/misdn.conf allowed_bearers */
+ char *display; /*!< Bearer capability displayable name */
+@@ -591,7 +2318,7 @@
+ };
+
+ /* *INDENT-OFF* */
+-static const struct allowed_bearers allowed_bearers_array[]= {
++static const struct allowed_bearers allowed_bearers_array[] = {
+ /* Name, Displayable Name Bearer Capability, Deprecated */
+ { "speech", "Speech", INFO_CAPABILITY_SPEECH, 0 },
+ { "3_1khz", "3.1KHz Audio", INFO_CAPABILITY_AUDIO_3_1K, 0 },
+@@ -610,30 +2337,594 @@
+ if (allowed_bearers_array[index].cap == cap) {
+ return allowed_bearers_array[index].display;
+ }
+- } /* end for */
++ }
+
+ return "Unknown Bearer";
+ }
+
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Fill in facility PartyNumber information
++ *
++ * \param party PartyNumber structure to fill in.
++ * \param id Information to put in PartyNumber structure.
++ *
++ * \return Nothing
++ */
++static void misdn_PartyNumber_fill(struct FacPartyNumber *party, const struct misdn_party_id *id)
++{
++ ast_copy_string((char *) party->Number, id->number, sizeof(party->Number));
++ party->LengthOfNumber = strlen((char *) party->Number);
++ party->Type = misdn_to_PartyNumber_plan(id->number_plan);
++ switch (party->Type) {
++ case 1:/* public */
++ party->TypeOfNumber = misdn_to_PartyNumber_ton_public(id->number_type);
++ break;
++ case 5:/* private */
++ party->TypeOfNumber = misdn_to_PartyNumber_ton_private(id->number_type);
++ break;
++ default:
++ party->TypeOfNumber = 0;/* Dont't care */
++ break;
++ }
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
+
+-static void print_facility(struct FacParm *fac, struct misdn_bchannel *bc)
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Extract the information from PartyNumber
++ *
++ * \param id Where to put extracted PartyNumber information
++ * \param party PartyNumber information to extract
++ *
++ * \return Nothing
++ */
++static void misdn_PartyNumber_extract(struct misdn_party_id *id, const struct FacPartyNumber *party)
+ {
++ if (party->LengthOfNumber) {
++ ast_copy_string(id->number, (char *) party->Number, sizeof(id->number));
++ id->number_plan = PartyNumber_to_misdn_plan(party->Type);
++ switch (party->Type) {
++ case 1:/* public */
++ id->number_type = PartyNumber_to_misdn_ton_public(party->TypeOfNumber);
++ break;
++ case 5:/* private */
++ id->number_type = PartyNumber_to_misdn_ton_private(party->TypeOfNumber);
++ break;
++ default:
++ id->number_type = NUMTYPE_UNKNOWN;
++ break;
++ }
++ } else {
++ /* Number not present */
++ id->number_type = NUMTYPE_UNKNOWN;
++ id->number_plan = NUMPLAN_ISDN;
++ id->number[0] = 0;
++ }
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Fill in facility Address information
++ *
++ * \param Address Address structure to fill in.
++ * \param id Information to put in Address structure.
++ *
++ * \return Nothing
++ */
++static void misdn_Address_fill(struct FacAddress *Address, const struct misdn_party_id *id)
++{
++ misdn_PartyNumber_fill(&Address->Party, id);
++
++ /* Subaddresses are not supported yet */
++ Address->Subaddress.Length = 0;
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Fill in facility PresentedNumberUnscreened information
++ *
++ * \param presented PresentedNumberUnscreened structure to fill in.
++ * \param id Information to put in PresentedNumberUnscreened structure.
++ *
++ * \return Nothing
++ */
++static void misdn_PresentedNumberUnscreened_fill(struct FacPresentedNumberUnscreened *presented, const struct misdn_party_id *id)
++{
++ presented->Type = misdn_to_PresentedNumberUnscreened_type(id->presentation, id->number[0] ? 1 : 0);
++ misdn_PartyNumber_fill(&presented->Unscreened, id);
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Extract the information from PartyNumber
++ *
++ * \param id Where to put extracted PresentedNumberUnscreened information
++ * \param presented PresentedNumberUnscreened information to extract
++ *
++ * \return Nothing
++ */
++static void misdn_PresentedNumberUnscreened_extract(struct misdn_party_id *id, const struct FacPresentedNumberUnscreened *presented)
++{
++ id->presentation = PresentedNumberUnscreened_to_misdn_pres(presented->Type);
++ id->screening = 0;/* unscreened */
++ misdn_PartyNumber_extract(id, &presented->Unscreened);
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++static const char Level_Spacing[] = " ";/* Work for up to 10 levels */
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++static void print_facility_PartyNumber(unsigned Level, const struct FacPartyNumber *Party, const struct misdn_bchannel *bc)
++{
++ if (Party->LengthOfNumber) {
++ const char *Spacing;
++
++ Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
++ chan_misdn_log(1, bc->port, " -->%s PartyNumber: Type:%d\n",
++ Spacing, Party->Type);
++ switch (Party->Type) {
++ case 0: /* Unknown PartyNumber */
++ chan_misdn_log(1, bc->port, " -->%s Unknown: %s\n",
++ Spacing, Party->Number);
++ break;
++ case 1: /* Public PartyNumber */
++ chan_misdn_log(1, bc->port, " -->%s Public TON:%d %s\n",
++ Spacing, Party->TypeOfNumber, Party->Number);
++ break;
++ case 2: /* NSAP encoded PartyNumber */
++ chan_misdn_log(1, bc->port, " -->%s NSAP: %s\n",
++ Spacing, Party->Number);
++ break;
++ case 3: /* Data PartyNumber (Not used) */
++ chan_misdn_log(1, bc->port, " -->%s Data: %s\n",
++ Spacing, Party->Number);
++ break;
++ case 4: /* Telex PartyNumber (Not used) */
++ chan_misdn_log(1, bc->port, " -->%s Telex: %s\n",
++ Spacing, Party->Number);
++ break;
++ case 5: /* Private PartyNumber */
++ chan_misdn_log(1, bc->port, " -->%s Private TON:%d %s\n",
++ Spacing, Party->TypeOfNumber, Party->Number);
++ break;
++ case 8: /* National Standard PartyNumber (Not used) */
++ chan_misdn_log(1, bc->port, " -->%s National: %s\n",
++ Spacing, Party->Number);
++ break;
++ default:
++ break;
++ }
++ }
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++static void print_facility_Subaddress(unsigned Level, const struct FacPartySubaddress *Subaddress, const struct misdn_bchannel *bc)
++{
++ if (Subaddress->Length) {
++ const char *Spacing;
++
++ Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
++ chan_misdn_log(1, bc->port, " -->%s Subaddress: Type:%d\n",
++ Spacing, Subaddress->Type);
++ switch (Subaddress->Type) {
++ case 0: /* UserSpecified */
++ if (Subaddress->u.UserSpecified.OddCountPresent) {
++ chan_misdn_log(1, bc->port, " -->%s User BCD OddCount:%d NumOctets:%d\n",
++ Spacing, Subaddress->u.UserSpecified.OddCount, Subaddress->Length);
++ } else {
++ chan_misdn_log(1, bc->port, " -->%s User: %s\n",
++ Spacing, Subaddress->u.UserSpecified.Information);
++ }
++ break;
++ case 1: /* NSAP */
++ chan_misdn_log(1, bc->port, " -->%s NSAP: %s\n",
++ Spacing, Subaddress->u.Nsap);
++ break;
++ default:
++ break;
++ }
++ }
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++static void print_facility_Address(unsigned Level, const struct FacAddress *Address, const struct misdn_bchannel *bc)
++{
++ print_facility_PartyNumber(Level, &Address->Party, bc);
++ print_facility_Subaddress(Level, &Address->Subaddress, bc);
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++static void print_facility_PresentedNumberUnscreened(unsigned Level, const struct FacPresentedNumberUnscreened *Presented, const struct misdn_bchannel *bc)
++{
++ const char *Spacing;
++
++ Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
++ chan_misdn_log(1, bc->port, " -->%s Unscreened Type:%d\n", Spacing, Presented->Type);
++ switch (Presented->Type) {
++ case 0: /* presentationAllowedNumber */
++ chan_misdn_log(1, bc->port, " -->%s Allowed:\n", Spacing);
++ print_facility_PartyNumber(Level + 2, &Presented->Unscreened, bc);
++ break;
++ case 1: /* presentationRestricted */
++ chan_misdn_log(1, bc->port, " -->%s Restricted\n", Spacing);
++ break;
++ case 2: /* numberNotAvailableDueToInterworking */
++ chan_misdn_log(1, bc->port, " -->%s Not Available\n", Spacing);
++ break;
++ case 3: /* presentationRestrictedNumber */
++ chan_misdn_log(1, bc->port, " -->%s Restricted:\n", Spacing);
++ print_facility_PartyNumber(Level + 2, &Presented->Unscreened, bc);
++ break;
++ default:
++ break;
++ }
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++static void print_facility_AddressScreened(unsigned Level, const struct FacAddressScreened *Address, const struct misdn_bchannel *bc)
++{
++ const char *Spacing;
++
++ Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
++ chan_misdn_log(1, bc->port, " -->%s ScreeningIndicator:%d\n", Spacing, Address->ScreeningIndicator);
++ print_facility_PartyNumber(Level, &Address->Party, bc);
++ print_facility_Subaddress(Level, &Address->Subaddress, bc);
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++static void print_facility_PresentedAddressScreened(unsigned Level, const struct FacPresentedAddressScreened *Presented, const struct misdn_bchannel *bc)
++{
++ const char *Spacing;
++
++ Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
++ chan_misdn_log(1, bc->port, " -->%s Screened Type:%d\n", Spacing, Presented->Type);
++ switch (Presented->Type) {
++ case 0: /* presentationAllowedAddress */
++ chan_misdn_log(1, bc->port, " -->%s Allowed:\n", Spacing);
++ print_facility_AddressScreened(Level + 2, &Presented->Address, bc);
++ break;
++ case 1: /* presentationRestricted */
++ chan_misdn_log(1, bc->port, " -->%s Restricted\n", Spacing);
++ break;
++ case 2: /* numberNotAvailableDueToInterworking */
++ chan_misdn_log(1, bc->port, " -->%s Not Available\n", Spacing);
++ break;
++ case 3: /* presentationRestrictedAddress */
++ chan_misdn_log(1, bc->port, " -->%s Restricted:\n", Spacing);
++ print_facility_AddressScreened(Level + 2, &Presented->Address, bc);
++ break;
++ default:
++ break;
++ }
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++static void print_facility_Q931_Bc_Hlc_Llc(unsigned Level, const struct Q931_Bc_Hlc_Llc *Q931ie, const struct misdn_bchannel *bc)
++{
++ const char *Spacing;
++
++ Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
++ chan_misdn_log(1, bc->port, " -->%s Q931ie:\n", Spacing);
++ if (Q931ie->Bc.Length) {
++ chan_misdn_log(1, bc->port, " -->%s Bc Len:%d\n", Spacing, Q931ie->Bc.Length);
++ }
++ if (Q931ie->Hlc.Length) {
++ chan_misdn_log(1, bc->port, " -->%s Hlc Len:%d\n", Spacing, Q931ie->Hlc.Length);
++ }
++ if (Q931ie->Llc.Length) {
++ chan_misdn_log(1, bc->port, " -->%s Llc Len:%d\n", Spacing, Q931ie->Llc.Length);
++ }
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++static void print_facility_Q931_Bc_Hlc_Llc_Uu(unsigned Level, const struct Q931_Bc_Hlc_Llc_Uu *Q931ie, const struct misdn_bchannel *bc)
++{
++ const char *Spacing;
++
++ Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
++ chan_misdn_log(1, bc->port, " -->%s Q931ie:\n", Spacing);
++ if (Q931ie->Bc.Length) {
++ chan_misdn_log(1, bc->port, " -->%s Bc Len:%d\n", Spacing, Q931ie->Bc.Length);
++ }
++ if (Q931ie->Hlc.Length) {
++ chan_misdn_log(1, bc->port, " -->%s Hlc Len:%d\n", Spacing, Q931ie->Hlc.Length);
++ }
++ if (Q931ie->Llc.Length) {
++ chan_misdn_log(1, bc->port, " -->%s Llc Len:%d\n", Spacing, Q931ie->Llc.Length);
++ }
++ if (Q931ie->UserInfo.Length) {
++ chan_misdn_log(1, bc->port, " -->%s UserInfo Len:%d\n", Spacing, Q931ie->UserInfo.Length);
++ }
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++static void print_facility_CallInformation(unsigned Level, const struct FacCallInformation *CallInfo, const struct misdn_bchannel *bc)
++{
++ const char *Spacing;
++
++ Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
++ chan_misdn_log(1, bc->port, " -->%s CCBSReference:%d\n",
++ Spacing, CallInfo->CCBSReference);
++ chan_misdn_log(1, bc->port, " -->%s AddressOfB:\n", Spacing);
++ print_facility_Address(Level + 1, &CallInfo->AddressOfB, bc);
++ print_facility_Q931_Bc_Hlc_Llc(Level, &CallInfo->Q931ie, bc);
++ if (CallInfo->SubaddressOfA.Length) {
++ chan_misdn_log(1, bc->port, " -->%s SubaddressOfA:\n", Spacing);
++ print_facility_Subaddress(Level + 1, &CallInfo->SubaddressOfA, bc);
++ }
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++static void print_facility_ServedUserNr(unsigned Level, const struct FacPartyNumber *Party, const struct misdn_bchannel *bc)
++{
++ const char *Spacing;
++
++ Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
++ if (Party->LengthOfNumber) {
++ print_facility_PartyNumber(Level, Party, bc);
++ } else {
++ chan_misdn_log(1, bc->port, " -->%s All Numbers\n", Spacing);
++ }
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++static void print_facility_IntResult(unsigned Level, const struct FacForwardingRecord *ForwardingRecord, const struct misdn_bchannel *bc)
++{
++ const char *Spacing;
++
++ Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
++ chan_misdn_log(1, bc->port, " -->%s Procedure:%d BasicService:%d\n",
++ Spacing,
++ ForwardingRecord->Procedure,
++ ForwardingRecord->BasicService);
++ chan_misdn_log(1, bc->port, " -->%s ForwardedTo:\n", Spacing);
++ print_facility_Address(Level + 1, &ForwardingRecord->ForwardedTo, bc);
++ chan_misdn_log(1, bc->port, " -->%s ServedUserNr:\n", Spacing);
++ print_facility_ServedUserNr(Level + 1, &ForwardingRecord->ServedUser, bc);
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++static void print_facility(const struct FacParm *fac, const const struct misdn_bchannel *bc)
++{
++#if defined(AST_MISDN_ENHANCEMENTS)
++ unsigned Index;
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
+ switch (fac->Function) {
+-#ifdef HAVE_MISDN_FAC_RESULT
+- case Fac_RESULT:
+- chan_misdn_log(0, bc->port, " --> Received RESULT Operation\n");
++#if defined(AST_MISDN_ENHANCEMENTS)
++ case Fac_ActivationDiversion:
++ chan_misdn_log(1, bc->port, " --> ActivationDiversion: InvokeID:%d\n",
++ fac->u.ActivationDiversion.InvokeID);
++ switch (fac->u.ActivationDiversion.ComponentType) {
++ case FacComponent_Invoke:
++ chan_misdn_log(1, bc->port, " --> Invoke: Procedure:%d BasicService:%d\n",
++ fac->u.ActivationDiversion.Component.Invoke.Procedure,
++ fac->u.ActivationDiversion.Component.Invoke.BasicService);
++ chan_misdn_log(1, bc->port, " --> ForwardedTo:\n");
++ print_facility_Address(3, &fac->u.ActivationDiversion.Component.Invoke.ForwardedTo, bc);
++ chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
++ print_facility_ServedUserNr(3, &fac->u.ActivationDiversion.Component.Invoke.ServedUser, bc);
++ break;
++ case FacComponent_Result:
++ chan_misdn_log(1, bc->port, " --> Result\n");
++ break;
++ default:
++ break;
++ }
+ break;
+-#endif
+-#ifdef HAVE_MISDN_FAC_ERROR
+- case Fac_ERROR:
+- chan_misdn_log(0, bc->port, " --> Received Error Operation\n");
+- chan_misdn_log(0, bc->port, " --> Value:%d Error:%s\n", fac->u.ERROR.errorValue, fac->u.ERROR.error);
++ case Fac_DeactivationDiversion:
++ chan_misdn_log(1, bc->port, " --> DeactivationDiversion: InvokeID:%d\n",
++ fac->u.DeactivationDiversion.InvokeID);
++ switch (fac->u.DeactivationDiversion.ComponentType) {
++ case FacComponent_Invoke:
++ chan_misdn_log(1, bc->port, " --> Invoke: Procedure:%d BasicService:%d\n",
++ fac->u.DeactivationDiversion.Component.Invoke.Procedure,
++ fac->u.DeactivationDiversion.Component.Invoke.BasicService);
++ chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
++ print_facility_ServedUserNr(3, &fac->u.DeactivationDiversion.Component.Invoke.ServedUser, bc);
++ break;
++ case FacComponent_Result:
++ chan_misdn_log(1, bc->port, " --> Result\n");
++ break;
++ default:
++ break;
++ }
+ break;
+-#endif
++ case Fac_ActivationStatusNotificationDiv:
++ chan_misdn_log(1, bc->port, " --> ActivationStatusNotificationDiv: InvokeID:%d Procedure:%d BasicService:%d\n",
++ fac->u.ActivationStatusNotificationDiv.InvokeID,
++ fac->u.ActivationStatusNotificationDiv.Procedure,
++ fac->u.ActivationStatusNotificationDiv.BasicService);
++ chan_misdn_log(1, bc->port, " --> ForwardedTo:\n");
++ print_facility_Address(2, &fac->u.ActivationStatusNotificationDiv.ForwardedTo, bc);
++ chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
++ print_facility_ServedUserNr(2, &fac->u.ActivationStatusNotificationDiv.ServedUser, bc);
++ break;
++ case Fac_DeactivationStatusNotificationDiv:
++ chan_misdn_log(1, bc->port, " --> DeactivationStatusNotificationDiv: InvokeID:%d Procedure:%d BasicService:%d\n",
++ fac->u.DeactivationStatusNotificationDiv.InvokeID,
++ fac->u.DeactivationStatusNotificationDiv.Procedure,
++ fac->u.DeactivationStatusNotificationDiv.BasicService);
++ chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
++ print_facility_ServedUserNr(2, &fac->u.DeactivationStatusNotificationDiv.ServedUser, bc);
++ break;
++ case Fac_InterrogationDiversion:
++ chan_misdn_log(1, bc->port, " --> InterrogationDiversion: InvokeID:%d\n",
++ fac->u.InterrogationDiversion.InvokeID);
++ switch (fac->u.InterrogationDiversion.ComponentType) {
++ case FacComponent_Invoke:
++ chan_misdn_log(1, bc->port, " --> Invoke: Procedure:%d BasicService:%d\n",
++ fac->u.InterrogationDiversion.Component.Invoke.Procedure,
++ fac->u.InterrogationDiversion.Component.Invoke.BasicService);
++ chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
++ print_facility_ServedUserNr(3, &fac->u.InterrogationDiversion.Component.Invoke.ServedUser, bc);
++ break;
++ case FacComponent_Result:
++ chan_misdn_log(1, bc->port, " --> Result:\n");
++ if (fac->u.InterrogationDiversion.Component.Result.NumRecords) {
++ for (Index = 0; Index < fac->u.InterrogationDiversion.Component.Result.NumRecords; ++Index) {
++ chan_misdn_log(1, bc->port, " --> IntResult[%d]:\n", Index);
++ print_facility_IntResult(3, &fac->u.InterrogationDiversion.Component.Result.List[Index], bc);
++ }
++ }
++ break;
++ default:
++ break;
++ }
++ break;
++ case Fac_DiversionInformation:
++ chan_misdn_log(1, bc->port, " --> DiversionInformation: InvokeID:%d Reason:%d BasicService:%d\n",
++ fac->u.DiversionInformation.InvokeID,
++ fac->u.DiversionInformation.DiversionReason,
++ fac->u.DiversionInformation.BasicService);
++ if (fac->u.DiversionInformation.ServedUserSubaddress.Length) {
++ chan_misdn_log(1, bc->port, " --> ServedUserSubaddress:\n");
++ print_facility_Subaddress(2, &fac->u.DiversionInformation.ServedUserSubaddress, bc);
++ }
++ if (fac->u.DiversionInformation.CallingAddressPresent) {
++ chan_misdn_log(1, bc->port, " --> CallingAddress:\n");
++ print_facility_PresentedAddressScreened(2, &fac->u.DiversionInformation.CallingAddress, bc);
++ }
++ if (fac->u.DiversionInformation.OriginalCalledPresent) {
++ chan_misdn_log(1, bc->port, " --> OriginalCalledNr:\n");
++ print_facility_PresentedNumberUnscreened(2, &fac->u.DiversionInformation.OriginalCalled, bc);
++ }
++ if (fac->u.DiversionInformation.LastDivertingPresent) {
++ chan_misdn_log(1, bc->port, " --> LastDivertingNr:\n");
++ print_facility_PresentedNumberUnscreened(2, &fac->u.DiversionInformation.LastDiverting, bc);
++ }
++ if (fac->u.DiversionInformation.LastDivertingReasonPresent) {
++ chan_misdn_log(1, bc->port, " --> LastDivertingReason:%d\n", fac->u.DiversionInformation.LastDivertingReason);
++ }
++ if (fac->u.DiversionInformation.UserInfo.Length) {
++ chan_misdn_log(1, bc->port, " --> UserInfo Length:%d\n", fac->u.DiversionInformation.UserInfo.Length);
++ }
++ break;
++ case Fac_CallDeflection:
++ chan_misdn_log(1, bc->port, " --> CallDeflection: InvokeID:%d\n",
++ fac->u.CallDeflection.InvokeID);
++ switch (fac->u.CallDeflection.ComponentType) {
++ case FacComponent_Invoke:
++ chan_misdn_log(1, bc->port, " --> Invoke:\n");
++ if (fac->u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent) {
++ chan_misdn_log(1, bc->port, " --> PresentationAllowed:%d\n",
++ fac->u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser);
++ }
++ chan_misdn_log(1, bc->port, " --> DeflectionAddress:\n");
++ print_facility_Address(3, &fac->u.CallDeflection.Component.Invoke.Deflection, bc);
++ break;
++ case FacComponent_Result:
++ chan_misdn_log(1, bc->port, " --> Result\n");
++ break;
++ default:
++ break;
++ }
++ break;
++ case Fac_CallRerouteing:
++ chan_misdn_log(1, bc->port, " --> CallRerouteing: InvokeID:%d\n",
++ fac->u.CallRerouteing.InvokeID);
++ switch (fac->u.CallRerouteing.ComponentType) {
++ case FacComponent_Invoke:
++ chan_misdn_log(1, bc->port, " --> Invoke: Reason:%d Counter:%d\n",
++ fac->u.CallRerouteing.Component.Invoke.ReroutingReason,
++ fac->u.CallRerouteing.Component.Invoke.ReroutingCounter);
++ chan_misdn_log(1, bc->port, " --> CalledAddress:\n");
++ print_facility_Address(3, &fac->u.CallRerouteing.Component.Invoke.CalledAddress, bc);
++ print_facility_Q931_Bc_Hlc_Llc_Uu(2, &fac->u.CallRerouteing.Component.Invoke.Q931ie, bc);
++ chan_misdn_log(1, bc->port, " --> LastReroutingNr:\n");
++ print_facility_PresentedNumberUnscreened(3, &fac->u.CallRerouteing.Component.Invoke.LastRerouting, bc);
++ chan_misdn_log(1, bc->port, " --> SubscriptionOption:%d\n",
++ fac->u.CallRerouteing.Component.Invoke.SubscriptionOption);
++ if (fac->u.CallRerouteing.Component.Invoke.CallingPartySubaddress.Length) {
++ chan_misdn_log(1, bc->port, " --> CallingParty:\n");
++ print_facility_Subaddress(3, &fac->u.CallRerouteing.Component.Invoke.CallingPartySubaddress, bc);
++ }
++ break;
++ case FacComponent_Result:
++ chan_misdn_log(1, bc->port, " --> Result\n");
++ break;
++ default:
++ break;
++ }
++ break;
++ case Fac_InterrogateServedUserNumbers:
++ chan_misdn_log(1, bc->port, " --> InterrogateServedUserNumbers: InvokeID:%d\n",
++ fac->u.InterrogateServedUserNumbers.InvokeID);
++ switch (fac->u.InterrogateServedUserNumbers.ComponentType) {
++ case FacComponent_Invoke:
++ chan_misdn_log(1, bc->port, " --> Invoke\n");
++ break;
++ case FacComponent_Result:
++ chan_misdn_log(1, bc->port, " --> Result:\n");
++ if (fac->u.InterrogateServedUserNumbers.Component.Result.NumRecords) {
++ for (Index = 0; Index < fac->u.InterrogateServedUserNumbers.Component.Result.NumRecords; ++Index) {
++ chan_misdn_log(1, bc->port, " --> ServedUserNr[%d]:\n", Index);
++ print_facility_PartyNumber(3, &fac->u.InterrogateServedUserNumbers.Component.Result.List[Index], bc);
++ }
++ }
++ break;
++ default:
++ break;
++ }
++ break;
++ case Fac_DivertingLegInformation1:
++ chan_misdn_log(1, bc->port, " --> DivertingLegInformation1: InvokeID:%d Reason:%d SubscriptionOption:%d\n",
++ fac->u.DivertingLegInformation1.InvokeID,
++ fac->u.DivertingLegInformation1.DiversionReason,
++ fac->u.DivertingLegInformation1.SubscriptionOption);
++ if (fac->u.DivertingLegInformation1.DivertedToPresent) {
++ chan_misdn_log(1, bc->port, " --> DivertedToNr:\n");
++ print_facility_PresentedNumberUnscreened(2, &fac->u.DivertingLegInformation1.DivertedTo, bc);
++ }
++ break;
++ case Fac_DivertingLegInformation2:
++ chan_misdn_log(1, bc->port, " --> DivertingLegInformation2: InvokeID:%d Reason:%d Count:%d\n",
++ fac->u.DivertingLegInformation2.InvokeID,
++ fac->u.DivertingLegInformation2.DiversionReason,
++ fac->u.DivertingLegInformation2.DiversionCounter);
++ if (fac->u.DivertingLegInformation2.DivertingPresent) {
++ chan_misdn_log(1, bc->port, " --> DivertingNr:\n");
++ print_facility_PresentedNumberUnscreened(2, &fac->u.DivertingLegInformation2.Diverting, bc);
++ }
++ if (fac->u.DivertingLegInformation2.OriginalCalledPresent) {
++ chan_misdn_log(1, bc->port, " --> OriginalCalledNr:\n");
++ print_facility_PresentedNumberUnscreened(2, &fac->u.DivertingLegInformation2.OriginalCalled, bc);
++ }
++ break;
++ case Fac_DivertingLegInformation3:
++ chan_misdn_log(1, bc->port, " --> DivertingLegInformation3: InvokeID:%d PresentationAllowed:%d\n",
++ fac->u.DivertingLegInformation3.InvokeID,
++ fac->u.DivertingLegInformation3.PresentationAllowedIndicator);
++ break;
++
++#else /* !defined(AST_MISDN_ENHANCEMENTS) */
++
+ case Fac_CD:
+ chan_misdn_log(1, bc->port, " --> calldeflect to: %s, presentable: %s\n", fac->u.CDeflection.DeflectedToNumber,
+ fac->u.CDeflection.PresentationAllowed ? "yes" : "no");
+ break;
++#endif /* !defined(AST_MISDN_ENHANCEMENTS) */
+ case Fac_AOCDCurrency:
+ if (fac->u.AOCDcur.chargeNotAvailable) {
+ chan_misdn_log(1, bc->port, " --> AOCD currency: charge not available\n");
+@@ -662,17 +2953,355 @@
+ fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total");
+ }
+ break;
++#if defined(AST_MISDN_ENHANCEMENTS)
++ case Fac_ERROR:
++ chan_misdn_log(1, bc->port, " --> ERROR: InvokeID:%d, Code:0x%02x\n",
++ fac->u.ERROR.invokeId, fac->u.ERROR.errorValue);
++ break;
++ case Fac_RESULT:
++ chan_misdn_log(1, bc->port, " --> RESULT: InvokeID:%d\n",
++ fac->u.RESULT.InvokeID);
++ break;
++ case Fac_REJECT:
++ if (fac->u.REJECT.InvokeIDPresent) {
++ chan_misdn_log(1, bc->port, " --> REJECT: InvokeID:%d, Code:0x%02x\n",
++ fac->u.REJECT.InvokeID, fac->u.REJECT.Code);
++ } else {
++ chan_misdn_log(1, bc->port, " --> REJECT: Code:0x%02x\n",
++ fac->u.REJECT.Code);
++ }
++ break;
++ case Fac_EctExecute:
++ chan_misdn_log(1, bc->port, " --> EctExecute: InvokeID:%d\n",
++ fac->u.EctExecute.InvokeID);
++ break;
++ case Fac_ExplicitEctExecute:
++ chan_misdn_log(1, bc->port, " --> ExplicitEctExecute: InvokeID:%d LinkID:%d\n",
++ fac->u.ExplicitEctExecute.InvokeID,
++ fac->u.ExplicitEctExecute.LinkID);
++ break;
++ case Fac_RequestSubaddress:
++ chan_misdn_log(1, bc->port, " --> RequestSubaddress: InvokeID:%d\n",
++ fac->u.RequestSubaddress.InvokeID);
++ break;
++ case Fac_SubaddressTransfer:
++ chan_misdn_log(1, bc->port, " --> SubaddressTransfer: InvokeID:%d\n",
++ fac->u.SubaddressTransfer.InvokeID);
++ print_facility_Subaddress(1, &fac->u.SubaddressTransfer.Subaddress, bc);
++ break;
++ case Fac_EctLinkIdRequest:
++ chan_misdn_log(1, bc->port, " --> EctLinkIdRequest: InvokeID:%d\n",
++ fac->u.EctLinkIdRequest.InvokeID);
++ switch (fac->u.EctLinkIdRequest.ComponentType) {
++ case FacComponent_Invoke:
++ chan_misdn_log(1, bc->port, " --> Invoke\n");
++ break;
++ case FacComponent_Result:
++ chan_misdn_log(1, bc->port, " --> Result: LinkID:%d\n",
++ fac->u.EctLinkIdRequest.Component.Result.LinkID);
++ break;
++ default:
++ break;
++ }
++ break;
++ case Fac_EctInform:
++ chan_misdn_log(1, bc->port, " --> EctInform: InvokeID:%d Status:%d\n",
++ fac->u.EctInform.InvokeID,
++ fac->u.EctInform.Status);
++ if (fac->u.EctInform.RedirectionPresent) {
++ chan_misdn_log(1, bc->port, " --> Redirection Number\n");
++ print_facility_PresentedNumberUnscreened(2, &fac->u.EctInform.Redirection, bc);
++ }
++ break;
++ case Fac_EctLoopTest:
++ chan_misdn_log(1, bc->port, " --> EctLoopTest: InvokeID:%d\n",
++ fac->u.EctLoopTest.InvokeID);
++ switch (fac->u.EctLoopTest.ComponentType) {
++ case FacComponent_Invoke:
++ chan_misdn_log(1, bc->port, " --> Invoke: CallTransferID:%d\n",
++ fac->u.EctLoopTest.Component.Invoke.CallTransferID);
++ break;
++ case FacComponent_Result:
++ chan_misdn_log(1, bc->port, " --> Result: LoopResult:%d\n",
++ fac->u.EctLoopTest.Component.Result.LoopResult);
++ break;
++ default:
++ break;
++ }
++ break;
++ case Fac_StatusRequest:
++ chan_misdn_log(1, bc->port, " --> StatusRequest: InvokeID:%d\n",
++ fac->u.StatusRequest.InvokeID);
++ switch (fac->u.StatusRequest.ComponentType) {
++ case FacComponent_Invoke:
++ chan_misdn_log(1, bc->port, " --> Invoke: Compatibility:%d\n",
++ fac->u.StatusRequest.Component.Invoke.CompatibilityMode);
++ break;
++ case FacComponent_Result:
++ chan_misdn_log(1, bc->port, " --> Result: Status:%d\n",
++ fac->u.StatusRequest.Component.Result.Status);
++ break;
++ default:
++ break;
++ }
++ break;
++ case Fac_CallInfoRetain:
++ chan_misdn_log(1, bc->port, " --> CallInfoRetain: InvokeID:%d, LinkageID:%d\n",
++ fac->u.CallInfoRetain.InvokeID, fac->u.CallInfoRetain.CallLinkageID);
++ break;
++ case Fac_CCBSDeactivate:
++ chan_misdn_log(1, bc->port, " --> CCBSDeactivate: InvokeID:%d\n",
++ fac->u.CCBSDeactivate.InvokeID);
++ switch (fac->u.CCBSDeactivate.ComponentType) {
++ case FacComponent_Invoke:
++ chan_misdn_log(1, bc->port, " --> Invoke: CCBSReference:%d\n",
++ fac->u.CCBSDeactivate.Component.Invoke.CCBSReference);
++ break;
++ case FacComponent_Result:
++ chan_misdn_log(1, bc->port, " --> Result\n");
++ break;
++ default:
++ break;
++ }
++ break;
++ case Fac_CCBSErase:
++ chan_misdn_log(1, bc->port, " --> CCBSErase: InvokeID:%d, CCBSReference:%d RecallMode:%d, Reason:%d\n",
++ fac->u.CCBSErase.InvokeID, fac->u.CCBSErase.CCBSReference,
++ fac->u.CCBSErase.RecallMode, fac->u.CCBSErase.Reason);
++ chan_misdn_log(1, bc->port, " --> AddressOfB\n");
++ print_facility_Address(2, &fac->u.CCBSErase.AddressOfB, bc);
++ print_facility_Q931_Bc_Hlc_Llc(1, &fac->u.CCBSErase.Q931ie, bc);
++ break;
++ case Fac_CCBSRemoteUserFree:
++ chan_misdn_log(1, bc->port, " --> CCBSRemoteUserFree: InvokeID:%d, CCBSReference:%d RecallMode:%d\n",
++ fac->u.CCBSRemoteUserFree.InvokeID, fac->u.CCBSRemoteUserFree.CCBSReference,
++ fac->u.CCBSRemoteUserFree.RecallMode);
++ chan_misdn_log(1, bc->port, " --> AddressOfB\n");
++ print_facility_Address(2, &fac->u.CCBSRemoteUserFree.AddressOfB, bc);
++ print_facility_Q931_Bc_Hlc_Llc(1, &fac->u.CCBSRemoteUserFree.Q931ie, bc);
++ break;
++ case Fac_CCBSCall:
++ chan_misdn_log(1, bc->port, " --> CCBSCall: InvokeID:%d, CCBSReference:%d\n",
++ fac->u.CCBSCall.InvokeID, fac->u.CCBSCall.CCBSReference);
++ break;
++ case Fac_CCBSStatusRequest:
++ chan_misdn_log(1, bc->port, " --> CCBSStatusRequest: InvokeID:%d\n",
++ fac->u.CCBSStatusRequest.InvokeID);
++ switch (fac->u.CCBSStatusRequest.ComponentType) {
++ case FacComponent_Invoke:
++ chan_misdn_log(1, bc->port, " --> Invoke: CCBSReference:%d RecallMode:%d\n",
++ fac->u.CCBSStatusRequest.Component.Invoke.CCBSReference,
++ fac->u.CCBSStatusRequest.Component.Invoke.RecallMode);
++ print_facility_Q931_Bc_Hlc_Llc(2, &fac->u.CCBSStatusRequest.Component.Invoke.Q931ie, bc);
++ break;
++ case FacComponent_Result:
++ chan_misdn_log(1, bc->port, " --> Result: Free:%d\n",
++ fac->u.CCBSStatusRequest.Component.Result.Free);
++ break;
++ default:
++ break;
++ }
++ break;
++ case Fac_CCBSBFree:
++ chan_misdn_log(1, bc->port, " --> CCBSBFree: InvokeID:%d, CCBSReference:%d RecallMode:%d\n",
++ fac->u.CCBSBFree.InvokeID, fac->u.CCBSBFree.CCBSReference,
++ fac->u.CCBSBFree.RecallMode);
++ chan_misdn_log(1, bc->port, " --> AddressOfB\n");
++ print_facility_Address(2, &fac->u.CCBSBFree.AddressOfB, bc);
++ print_facility_Q931_Bc_Hlc_Llc(1, &fac->u.CCBSBFree.Q931ie, bc);
++ break;
++ case Fac_EraseCallLinkageID:
++ chan_misdn_log(1, bc->port, " --> EraseCallLinkageID: InvokeID:%d, LinkageID:%d\n",
++ fac->u.EraseCallLinkageID.InvokeID, fac->u.EraseCallLinkageID.CallLinkageID);
++ break;
++ case Fac_CCBSStopAlerting:
++ chan_misdn_log(1, bc->port, " --> CCBSStopAlerting: InvokeID:%d, CCBSReference:%d\n",
++ fac->u.CCBSStopAlerting.InvokeID, fac->u.CCBSStopAlerting.CCBSReference);
++ break;
++ case Fac_CCBSRequest:
++ chan_misdn_log(1, bc->port, " --> CCBSRequest: InvokeID:%d\n",
++ fac->u.CCBSRequest.InvokeID);
++ switch (fac->u.CCBSRequest.ComponentType) {
++ case FacComponent_Invoke:
++ chan_misdn_log(1, bc->port, " --> Invoke: LinkageID:%d\n",
++ fac->u.CCBSRequest.Component.Invoke.CallLinkageID);
++ break;
++ case FacComponent_Result:
++ chan_misdn_log(1, bc->port, " --> Result: CCBSReference:%d RecallMode:%d\n",
++ fac->u.CCBSRequest.Component.Result.CCBSReference,
++ fac->u.CCBSRequest.Component.Result.RecallMode);
++ break;
++ default:
++ break;
++ }
++ break;
++ case Fac_CCBSInterrogate:
++ chan_misdn_log(1, bc->port, " --> CCBSInterrogate: InvokeID:%d\n",
++ fac->u.CCBSInterrogate.InvokeID);
++ switch (fac->u.CCBSInterrogate.ComponentType) {
++ case FacComponent_Invoke:
++ chan_misdn_log(1, bc->port, " --> Invoke\n");
++ if (fac->u.CCBSInterrogate.Component.Invoke.CCBSReferencePresent) {
++ chan_misdn_log(1, bc->port, " --> CCBSReference:%d\n",
++ fac->u.CCBSInterrogate.Component.Invoke.CCBSReference);
++ }
++ if (fac->u.CCBSInterrogate.Component.Invoke.AParty.LengthOfNumber) {
++ chan_misdn_log(1, bc->port, " --> AParty\n");
++ print_facility_PartyNumber(3, &fac->u.CCBSInterrogate.Component.Invoke.AParty, bc);
++ }
++ break;
++ case FacComponent_Result:
++ chan_misdn_log(1, bc->port, " --> Result: RecallMode:%d\n",
++ fac->u.CCBSInterrogate.Component.Result.RecallMode);
++ if (fac->u.CCBSInterrogate.Component.Result.NumRecords) {
++ for (Index = 0; Index < fac->u.CCBSInterrogate.Component.Result.NumRecords; ++Index) {
++ chan_misdn_log(1, bc->port, " --> CallDetails[%d]:\n", Index);
++ print_facility_CallInformation(3, &fac->u.CCBSInterrogate.Component.Result.CallDetails[Index], bc);
++ }
++ }
++ break;
++ default:
++ break;
++ }
++ break;
++ case Fac_CCNRRequest:
++ chan_misdn_log(1, bc->port, " --> CCNRRequest: InvokeID:%d\n",
++ fac->u.CCNRRequest.InvokeID);
++ switch (fac->u.CCNRRequest.ComponentType) {
++ case FacComponent_Invoke:
++ chan_misdn_log(1, bc->port, " --> Invoke: LinkageID:%d\n",
++ fac->u.CCNRRequest.Component.Invoke.CallLinkageID);
++ break;
++ case FacComponent_Result:
++ chan_misdn_log(1, bc->port, " --> Result: CCBSReference:%d RecallMode:%d\n",
++ fac->u.CCNRRequest.Component.Result.CCBSReference,
++ fac->u.CCNRRequest.Component.Result.RecallMode);
++ break;
++ default:
++ break;
++ }
++ break;
++ case Fac_CCNRInterrogate:
++ chan_misdn_log(1, bc->port, " --> CCNRInterrogate: InvokeID:%d\n",
++ fac->u.CCNRInterrogate.InvokeID);
++ switch (fac->u.CCNRInterrogate.ComponentType) {
++ case FacComponent_Invoke:
++ chan_misdn_log(1, bc->port, " --> Invoke\n");
++ if (fac->u.CCNRInterrogate.Component.Invoke.CCBSReferencePresent) {
++ chan_misdn_log(1, bc->port, " --> CCBSReference:%d\n",
++ fac->u.CCNRInterrogate.Component.Invoke.CCBSReference);
++ }
++ if (fac->u.CCNRInterrogate.Component.Invoke.AParty.LengthOfNumber) {
++ chan_misdn_log(1, bc->port, " --> AParty\n");
++ print_facility_PartyNumber(3, &fac->u.CCNRInterrogate.Component.Invoke.AParty, bc);
++ }
++ break;
++ case FacComponent_Result:
++ chan_misdn_log(1, bc->port, " --> Result: RecallMode:%d\n",
++ fac->u.CCNRInterrogate.Component.Result.RecallMode);
++ if (fac->u.CCNRInterrogate.Component.Result.NumRecords) {
++ for (Index = 0; Index < fac->u.CCNRInterrogate.Component.Result.NumRecords; ++Index) {
++ chan_misdn_log(1, bc->port, " --> CallDetails[%d]:\n", Index);
++ print_facility_CallInformation(3, &fac->u.CCNRInterrogate.Component.Result.CallDetails[Index], bc);
++ }
++ }
++ break;
++ default:
++ break;
++ }
++ break;
++ case Fac_CCBS_T_Call:
++ chan_misdn_log(1, bc->port, " --> CCBS_T_Call: InvokeID:%d\n",
++ fac->u.CCBS_T_Call.InvokeID);
++ break;
++ case Fac_CCBS_T_Suspend:
++ chan_misdn_log(1, bc->port, " --> CCBS_T_Suspend: InvokeID:%d\n",
++ fac->u.CCBS_T_Suspend.InvokeID);
++ break;
++ case Fac_CCBS_T_Resume:
++ chan_misdn_log(1, bc->port, " --> CCBS_T_Resume: InvokeID:%d\n",
++ fac->u.CCBS_T_Resume.InvokeID);
++ break;
++ case Fac_CCBS_T_RemoteUserFree:
++ chan_misdn_log(1, bc->port, " --> CCBS_T_RemoteUserFree: InvokeID:%d\n",
++ fac->u.CCBS_T_RemoteUserFree.InvokeID);
++ break;
++ case Fac_CCBS_T_Available:
++ chan_misdn_log(1, bc->port, " --> CCBS_T_Available: InvokeID:%d\n",
++ fac->u.CCBS_T_Available.InvokeID);
++ break;
++ case Fac_CCBS_T_Request:
++ chan_misdn_log(1, bc->port, " --> CCBS_T_Request: InvokeID:%d\n",
++ fac->u.CCBS_T_Request.InvokeID);
++ switch (fac->u.CCBS_T_Request.ComponentType) {
++ case FacComponent_Invoke:
++ chan_misdn_log(1, bc->port, " --> Invoke\n");
++ chan_misdn_log(1, bc->port, " --> DestinationAddress:\n");
++ print_facility_Address(3, &fac->u.CCBS_T_Request.Component.Invoke.Destination, bc);
++ print_facility_Q931_Bc_Hlc_Llc(2, &fac->u.CCBS_T_Request.Component.Invoke.Q931ie, bc);
++ if (fac->u.CCBS_T_Request.Component.Invoke.RetentionSupported) {
++ chan_misdn_log(1, bc->port, " --> RetentionSupported:1\n");
++ }
++ if (fac->u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicatorPresent) {
++ chan_misdn_log(1, bc->port, " --> PresentationAllowed:%d\n",
++ fac->u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicator);
++ }
++ if (fac->u.CCBS_T_Request.Component.Invoke.Originating.Party.LengthOfNumber) {
++ chan_misdn_log(1, bc->port, " --> OriginatingAddress:\n");
++ print_facility_Address(3, &fac->u.CCBS_T_Request.Component.Invoke.Originating, bc);
++ }
++ break;
++ case FacComponent_Result:
++ chan_misdn_log(1, bc->port, " --> Result: RetentionSupported:%d\n",
++ fac->u.CCBS_T_Request.Component.Result.RetentionSupported);
++ break;
++ default:
++ break;
++ }
++ break;
++ case Fac_CCNR_T_Request:
++ chan_misdn_log(1, bc->port, " --> CCNR_T_Request: InvokeID:%d\n",
++ fac->u.CCNR_T_Request.InvokeID);
++ switch (fac->u.CCNR_T_Request.ComponentType) {
++ case FacComponent_Invoke:
++ chan_misdn_log(1, bc->port, " --> Invoke\n");
++ chan_misdn_log(1, bc->port, " --> DestinationAddress:\n");
++ print_facility_Address(3, &fac->u.CCNR_T_Request.Component.Invoke.Destination, bc);
++ print_facility_Q931_Bc_Hlc_Llc(2, &fac->u.CCNR_T_Request.Component.Invoke.Q931ie, bc);
++ if (fac->u.CCNR_T_Request.Component.Invoke.RetentionSupported) {
++ chan_misdn_log(1, bc->port, " --> RetentionSupported:1\n");
++ }
++ if (fac->u.CCNR_T_Request.Component.Invoke.PresentationAllowedIndicatorPresent) {
++ chan_misdn_log(1, bc->port, " --> PresentationAllowed:%d\n",
++ fac->u.CCNR_T_Request.Component.Invoke.PresentationAllowedIndicator);
++ }
++ if (fac->u.CCNR_T_Request.Component.Invoke.Originating.Party.LengthOfNumber) {
++ chan_misdn_log(1, bc->port, " --> OriginatingAddress:\n");
++ print_facility_Address(3, &fac->u.CCNR_T_Request.Component.Invoke.Originating, bc);
++ }
++ break;
++ case FacComponent_Result:
++ chan_misdn_log(1, bc->port, " --> Result: RetentionSupported:%d\n",
++ fac->u.CCNR_T_Request.Component.Result.RetentionSupported);
++ break;
++ default:
++ break;
++ }
++ break;
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
+ case Fac_None:
++ /* No facility so print nothing */
++ break;
+ default:
+ chan_misdn_log(1, bc->port, " --> unknown facility\n");
+ break;
+ }
+ }
+
+-static void print_bearer(struct misdn_bchannel *bc)
++static void print_bearer(struct misdn_bchannel *bc)
+ {
+ chan_misdn_log(2, bc->port, " --> Bearer: %s\n", bearer2str(bc->capability));
+-
++
+ switch(bc->law) {
+ case INFO_CODEC_ALAW:
+ chan_misdn_log(2, bc->port, " --> Codec: Alaw\n");
+@@ -683,6 +3312,95 @@
+ }
+ }
+
++/*!
++ * \internal
++ * \brief Prefix a string to another string in place.
++ *
++ * \param str_prefix String to prefix to the main string.
++ * \param str_main String to get the prefix added to it.
++ * \param size Buffer size of the main string (Includes null terminator).
++ *
++ * \note The str_main buffer size must be greater than one.
++ *
++ * \return Nothing
++ */
++static void misdn_prefix_string(const char *str_prefix, char *str_main, size_t size)
++{
++ size_t len_over;
++ size_t len_total;
++ size_t len_main;
++ size_t len_prefix;
++
++ len_prefix = strlen(str_prefix);
++ if (!len_prefix) {
++ /* There is no prefix to prepend. */
++ return;
++ }
++ len_main = strlen(str_main);
++ len_total = len_prefix + len_main;
++ if (size <= len_total) {
++ /* We need to truncate since the buffer is too small. */
++ len_over = len_total + 1 - size;
++ if (len_over <= len_main) {
++ len_main -= len_over;
++ } else {
++ len_over -= len_main;
++ len_main = 0;
++ len_prefix -= len_over;
++ }
++ }
++ if (len_main) {
++ memmove(str_main + len_prefix, str_main, len_main);
++ }
++ memcpy(str_main, str_prefix, len_prefix);
++ str_main[len_prefix + len_main] = '\0';
++}
++
++/*!
++ * \internal
++ * \brief Add a configured prefix to the given number.
++ *
++ * \param port Logical port number
++ * \param number_type Type-of-number passed in.
++ * \param number Given number string to add prefix
++ * \param size Buffer size number string occupies.
++ *
++ * \return Nothing
++ */
++static void misdn_add_number_prefix(int port, enum mISDN_NUMBER_TYPE number_type, char *number, size_t size)
++{
++ enum misdn_cfg_elements type_prefix;
++ char num_prefix[MISDN_MAX_NUMBER_LEN];
++
++ /* Get prefix string. */
++ switch (number_type) {
++ case NUMTYPE_UNKNOWN:
++ type_prefix = MISDN_CFG_TON_PREFIX_UNKNOWN;
++ break;
++ case NUMTYPE_INTERNATIONAL:
++ type_prefix = MISDN_CFG_TON_PREFIX_INTERNATIONAL;
++ break;
++ case NUMTYPE_NATIONAL:
++ type_prefix = MISDN_CFG_TON_PREFIX_NATIONAL;
++ break;
++ case NUMTYPE_NETWORK_SPECIFIC:
++ type_prefix = MISDN_CFG_TON_PREFIX_NETWORK_SPECIFIC;
++ break;
++ case NUMTYPE_SUBSCRIBER:
++ type_prefix = MISDN_CFG_TON_PREFIX_SUBSCRIBER;
++ break;
++ case NUMTYPE_ABBREVIATED:
++ type_prefix = MISDN_CFG_TON_PREFIX_ABBREVIATED;
++ break;
++ default:
++ /* Type-of-number does not have a prefix that can be added. */
++ return;
++ }
++ misdn_cfg_get(port, type_prefix, num_prefix, sizeof(num_prefix));
++
++ misdn_prefix_string(num_prefix, number, size);
++}
++
+ static void export_aoc_vars(int originator, struct ast_channel *ast, struct misdn_bchannel *bc)
+ {
+ char buf[128];
+@@ -692,7 +3410,8 @@
+ }
+
+ if (originator == ORG_AST) {
+- if (!(ast = ast_bridged_channel(ast))) {
++ ast = ast_bridged_channel(ast);
++ if (!ast) {
+ return;
+ }
+ }
+@@ -739,14 +3458,15 @@
+ default:
+ break;
+ }
+-
++
+ bc->AOCD_need_export = 0;
+ }
+
+ /*************** Helpers END *************/
+
+ static void sighandler(int sig)
+-{}
++{
++}
+
+ static void *misdn_tasks_thread_func(void *data)
+ {
+@@ -758,7 +3478,7 @@
+ sigemptyset(&sa.sa_mask);
+ sigaddset(&sa.sa_mask, SIGUSR1);
+ sigaction(SIGUSR1, &sa, NULL);
+-
++
+ sem_post((sem_t *)data);
+
+ while (1) {
+@@ -785,11 +3505,12 @@
+ }
+
+ chan_misdn_log(4, 0, "Starting misdn_tasks thread\n");
+-
++
+ misdn_tasks = sched_context_create();
+ pthread_create(&misdn_tasks_thread, NULL, misdn_tasks_thread_func, &blocker);
+
+- while (sem_wait(&blocker) && --i);
++ while (sem_wait(&blocker) && --i) {
++ }
+ sem_destroy(&blocker);
+ }
+
+@@ -797,7 +3518,7 @@
+ {
+ if (misdn_tasks) {
+ chan_misdn_log(4, 0, "Killing misdn_tasks thread\n");
+- if ( pthread_cancel(misdn_tasks_thread) == 0 ) {
++ if (pthread_cancel(misdn_tasks_thread) == 0) {
+ cb_log(4, 0, "Joining misdn_tasks thread\n");
+ pthread_join(misdn_tasks_thread, NULL);
+ }
+@@ -841,6 +3562,7 @@
+ static int misdn_l1_task(const void *vdata)
+ {
+ const int *data = vdata;
++
+ misdn_lib_isdn_l1watcher(*data);
+ chan_misdn_log(5, *data, "L1watcher timeout\n");
+ return 1;
+@@ -867,21 +3589,22 @@
+ tv_end.tv_sec += ch->overlap_dial;
+ tv_now = ast_tvnow();
+
+- if ((diff = ast_tvdiff_ms(tv_end, tv_now)) > 100) {
++ diff = ast_tvdiff_ms(tv_end, tv_now);
++ if (100 < diff) {
+ return diff;
+ }
+
+ /* if we are 100ms near the timeout, we are satisfied.. */
+ stop_indicate(ch);
+
+- if (ast_strlen_zero(ch->bc->dad)) {
++ if (ast_strlen_zero(ch->bc->dialed.number)) {
+ dad = "s";
+- ast_copy_string(ch->ast->exten, "s", sizeof(ch->ast->exten));
++ strcpy(ch->ast->exten, dad);
+ } else {
+- dad = ch->bc->dad;
++ dad = ch->bc->dialed.number;
+ }
+
+- if (ast_exists_extension(ch->ast, ch->context, dad, 1, ch->bc->oad)) {
++ if (ast_exists_extension(ch->ast, ch->context, dad, 1, ch->bc->caller.number)) {
+ ch->state = MISDN_DIALING;
+ if (pbx_start_chan(ch) < 0) {
+ chan_misdn_log(-1, ch->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
+@@ -900,7 +3623,8 @@
+
+ static void send_digit_to_chan(struct chan_list *cl, char digit)
+ {
+- static const char *dtmf_tones[] = {
++ static const char * const dtmf_tones[] = {
++/* *INDENT-OFF* */
+ "!941+1336/100,!0/100", /* 0 */
+ "!697+1209/100,!0/100", /* 1 */
+ "!697+1336/100,!0/100", /* 2 */
+@@ -917,9 +3641,10 @@
+ "!941+1633/100,!0/100", /* D */
+ "!941+1209/100,!0/100", /* * */
+ "!941+1477/100,!0/100", /* # */
++/* *INDENT-ON* */
+ };
+- struct ast_channel *chan = cl->ast;
+-
++ struct ast_channel *chan = cl->ast;
++
+ if (digit >= '0' && digit <='9') {
+ ast_playtones_start(chan, 0, dtmf_tones[digit - '0'], 0);
+ } else if (digit >= 'A' && digit <= 'D') {
+@@ -958,8 +3683,10 @@
+ level = 1;
+ } else if (!strcasecmp(a->argv[3], "off")) {
+ level = 0;
++ } else if (isdigit(a->argv[3][0])) {
++ level = atoi(a->argv[3]);
+ } else {
+- level = atoi(a->argv[3]);
++ return CLI_SHOWUSAGE;
+ }
+
+ switch (a->argc) {
+@@ -975,7 +3702,7 @@
+ only = 1;
+ }
+ }
+-
++
+ for (i = 0; i <= max_ports; i++) {
+ misdn_debug[i] = level;
+ misdn_debug_only[i] = only;
+@@ -1251,7 +3978,9 @@
+ ast_cli(a->fd, "Unknown option: %s\n", a->argv[3]);
+ return CLI_SHOWUSAGE;
+ }
+- } else if (a->argc == 3 || onlyport == 0) {
++ }
++
++ if (a->argc == 3 || onlyport == 0) {
+ ast_cli(a->fd, "mISDN General-Config:\n");
+ for (elem = MISDN_GEN_FIRST + 1, linebreak = 1; elem < MISDN_GEN_LAST; elem++, linebreak++) {
+ misdn_cfg_get_config_string(0, elem, buffer, sizeof(buffer));
+@@ -1262,23 +3991,24 @@
+
+ if (onlyport < 0) {
+ int port = misdn_cfg_get_next_port(0);
++
+ for (; port > 0; port = misdn_cfg_get_next_port(port)) {
+ ast_cli(a->fd, "\n[PORT %d]\n", port);
+ for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
+ misdn_cfg_get_config_string(port, elem, buffer, sizeof(buffer));
+ ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
+- }
++ }
+ ast_cli(a->fd, "\n");
+ }
+ }
+-
++
+ if (onlyport > 0) {
+ if (misdn_cfg_is_port_valid(onlyport)) {
+ ast_cli(a->fd, "[PORT %d]\n", onlyport);
+ for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
+ misdn_cfg_get_config_string(onlyport, elem, buffer, sizeof(buffer));
+ ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
+- }
++ }
+ ast_cli(a->fd, "\n");
+ } else {
+ ast_cli(a->fd, "Port %d is not active!\n", onlyport);
+@@ -1293,39 +4023,41 @@
+ char txt[255];
+ };
+
+-static struct state_struct state_array[] = {
++static const struct state_struct state_array[] = {
++/* *INDENT-OFF* */
+ { MISDN_NOTHING, "NOTHING" }, /* at beginning */
+- { MISDN_WAITING4DIGS, "WAITING4DIGS" }, /* when waiting for infos */
+- { MISDN_EXTCANTMATCH, "EXTCANTMATCH" }, /* when asterisk couldn't match our ext */
+- { MISDN_INCOMING_SETUP, "INCOMING SETUP" }, /* when pbx_start */
+- { MISDN_DIALING, "DIALING" }, /* when pbx_start */
+- { MISDN_PROGRESS, "PROGRESS" }, /* when pbx_start */
+- { MISDN_PROCEEDING, "PROCEEDING" }, /* when pbx_start */
+- { MISDN_CALLING, "CALLING" }, /* when misdn_call is called */
+- { MISDN_CALLING_ACKNOWLEDGE, "CALLING_ACKNOWLEDGE" }, /* when misdn_call is called */
+- { MISDN_ALERTING, "ALERTING" }, /* when Alerting */
+- { MISDN_BUSY, "BUSY" }, /* when BUSY */
+- { MISDN_CONNECTED, "CONNECTED" }, /* when connected */
+- { MISDN_PRECONNECTED, "PRECONNECTED" }, /* when connected */
+- { MISDN_DISCONNECTED, "DISCONNECTED" }, /* when connected */
+- { MISDN_RELEASED, "RELEASED" }, /* when connected */
+- { MISDN_BRIDGED, "BRIDGED" }, /* when bridged */
++ { MISDN_WAITING4DIGS, "WAITING4DIGS" }, /* when waiting for infos */
++ { MISDN_EXTCANTMATCH, "EXTCANTMATCH" }, /* when asterisk couldn't match our ext */
++ { MISDN_INCOMING_SETUP, "INCOMING SETUP" }, /* when pbx_start */
++ { MISDN_DIALING, "DIALING" }, /* when pbx_start */
++ { MISDN_PROGRESS, "PROGRESS" }, /* when pbx_start */
++ { MISDN_PROCEEDING, "PROCEEDING" }, /* when pbx_start */
++ { MISDN_CALLING, "CALLING" }, /* when misdn_call is called */
++ { MISDN_CALLING_ACKNOWLEDGE, "CALLING_ACKNOWLEDGE" }, /* when misdn_call is called */
++ { MISDN_ALERTING, "ALERTING" }, /* when Alerting */
++ { MISDN_BUSY, "BUSY" }, /* when BUSY */
++ { MISDN_CONNECTED, "CONNECTED" }, /* when connected */
++ { MISDN_PRECONNECTED, "PRECONNECTED" }, /* when connected */
++ { MISDN_DISCONNECTED, "DISCONNECTED" }, /* when connected */
++ { MISDN_RELEASED, "RELEASED" }, /* when connected */
++ { MISDN_BRIDGED, "BRIDGED" }, /* when bridged */
+ { MISDN_CLEANING, "CLEANING" }, /* when hangup from * but we were connected before */
+- { MISDN_HUNGUP_FROM_MISDN, "HUNGUP_FROM_MISDN" }, /* when DISCONNECT/RELEASE/REL_COMP came from misdn */
+- { MISDN_HOLDED, "HOLDED" }, /* when DISCONNECT/RELEASE/REL_COMP came from misdn */
+- { MISDN_HOLD_DISCONNECT, "HOLD_DISCONNECT" }, /* when DISCONNECT/RELEASE/REL_COMP came from misdn */
++ { MISDN_HUNGUP_FROM_MISDN, "HUNGUP_FROM_MISDN" }, /* when DISCONNECT/RELEASE/REL_COMP came from misdn */
++ { MISDN_HOLDED, "HOLDED" }, /* when DISCONNECT/RELEASE/REL_COMP came from misdn */
++ { MISDN_HOLD_DISCONNECT, "HOLD_DISCONNECT" }, /* when DISCONNECT/RELEASE/REL_COMP came from misdn */
+ { MISDN_HUNGUP_FROM_AST, "HUNGUP_FROM_AST" }, /* when DISCONNECT/RELEASE/REL_COMP came out of misdn_hangup */
++/* *INDENT-ON* */
+ };
+
+-static const char *misdn_get_ch_state(struct chan_list *p)
++static const char *misdn_get_ch_state(struct chan_list *p)
+ {
+ int i;
+ static char state[8];
+-
++
+ if (!p) {
+ return NULL;
+ }
+-
++
+ for (i = 0; i < ARRAY_LEN(state_array); i++) {
+ if (state_array[i].state == p->state) {
+ return state_array[i].txt;
+@@ -1346,7 +4078,7 @@
+ ast_log(LOG_WARNING, "chan_misdn is not initialized properly, still reloading ?\n");
+ return ;
+ }
+-
++
+ free_robin_list();
+ misdn_cfg_reload();
+ misdn_cfg_update_ptp();
+@@ -1382,21 +4114,30 @@
+ return CLI_SUCCESS;
+ }
+
+-static void print_bc_info (int fd, struct chan_list *help, struct misdn_bchannel *bc)
++static void print_bc_info(int fd, struct chan_list *help, struct misdn_bchannel *bc)
+ {
+ struct ast_channel *ast = help->ast;
++
+ ast_cli(fd,
+- "* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s rad:%s ctx:%s state:%s\n",
+-
+- bc->pid, bc->port, bc->channel,
++ "* Pid:%d Port:%d Ch:%d Mode:%s Orig:%s dialed:%s\n"
++ " --> caller:\"%s\" <%s>\n"
++ " --> redirecting-from:\"%s\" <%s>\n"
++ " --> redirecting-to:\"%s\" <%s>\n"
++ " --> context:%s state:%s\n",
++ bc->pid,
++ bc->port,
++ bc->channel,
+ bc->nt ? "NT" : "TE",
+ help->originator == ORG_AST ? "*" : "I",
+- ast ? ast->exten : NULL,
+- ast ? ast->cid.cid_num : NULL,
+- bc->rad,
+- ast ? ast->context : NULL,
+- misdn_get_ch_state(help)
+- );
++ ast ? ast->exten : "",
++ (ast && ast->cid.cid_name) ? ast->cid.cid_name : "",
++ (ast && ast->cid.cid_num) ? ast->cid.cid_num : "",
++ bc->redirecting.from.name,
++ bc->redirecting.from.number,
++ bc->redirecting.to.name,
++ bc->redirecting.to.number,
++ ast ? ast->context : "",
++ misdn_get_ch_state(help));
+ if (misdn_debug[bc->port] > 0) {
+ ast_cli(fd,
+ " --> astname: %s\n"
+@@ -1419,21 +4160,18 @@
+ help->l3id,
+ help->addr,
+ bc->addr,
+- bc ? bc->l3_id : -1,
++ bc->l3_id,
+ bc->display,
+-
+ bc->active,
+ bc_state2str(bc->bc_state),
+ bearer2str(bc->capability),
+ #ifdef MISDN_1_2
+ bc->pipeline,
+ #else
+- bc->ec_enable,
++ bc->ec_enable,
+ #endif
+-
+ help->norxtone, help->notxtone,
+- bc->holded
+- );
++ bc->holded);
+ }
+ }
+
+@@ -1457,11 +4195,11 @@
+ }
+
+ help = cl_te;
+-
++
+ ast_cli(a->fd, "Channel List: %p\n", cl_te);
+
+ for (; help; help = help->next) {
+- struct misdn_bchannel *bc = help->bc;
++ struct misdn_bchannel *bc = help->bc;
+ struct ast_channel *ast = help->ast;
+ if (!ast) {
+ if (!bc) {
+@@ -1481,15 +4219,17 @@
+ if (help->state == MISDN_HOLDED) {
+ ast_cli(a->fd, "ITS A HOLDED BC:\n");
+ ast_cli(a->fd, " --> l3_id: %x\n"
+- " --> dad:%s oad:%s\n"
+- " --> hold_port: %d\n"
+- " --> hold_channel: %d\n",
+- help->l3id,
+- ast->exten,
+- ast->cid.cid_num,
+- help->hold_info.port,
+- help->hold_info.channel
+- );
++ " --> dialed:%s\n"
++ " --> caller:\"%s\" <%s>\n"
++ " --> hold_port: %d\n"
++ " --> hold_channel: %d\n",
++ help->l3id,
++ ast->exten,
++ ast->cid.cid_name ? ast->cid.cid_name : "",
++ ast->cid.cid_num ? ast->cid.cid_num : "",
++ help->hold_info.port,
++ help->hold_info.channel
++ );
+ } else {
+ ast_cli(a->fd, "* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n", ast->exten, ast->cid.cid_num);
+ }
+@@ -1523,13 +4263,13 @@
+ help = cl_te;
+
+ for (; help; help = help->next) {
+- struct misdn_bchannel *bc = help->bc;
++ struct misdn_bchannel *bc = help->bc;
+ struct ast_channel *ast = help->ast;
+-
++
+ if (bc && ast) {
+ if (!strcasecmp(ast->name, a->argv[3])) {
+ print_bc_info(a->fd, help, bc);
+- break;
++ break;
+ }
+ }
+ }
+@@ -1580,8 +4320,9 @@
+
+ ast_cli(a->fd, "BEGIN STACK_LIST:\n");
+ for (port = misdn_cfg_get_next_port(0); port > 0;
+- port = misdn_cfg_get_next_port(port)) {
++ port = misdn_cfg_get_next_port(port)) {
+ char buf[128];
++
+ get_show_stack_details(port, buf);
+ ast_cli(a->fd, " %s Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port] ? "(only)" : "");
+ }
+@@ -1610,7 +4351,7 @@
+
+ ast_cli(a->fd, "Port\tin_calls\tout_calls\n");
+ for (port = misdn_cfg_get_next_port(0); port > 0;
+- port = misdn_cfg_get_next_port(port)) {
++ port = misdn_cfg_get_next_port(port)) {
+ ast_cli(a->fd, "%d\t%d\t\t%d\n", port, misdn_in_calls[port], misdn_out_calls[port]);
+ }
+ ast_cli(a->fd, "\n");
+@@ -1639,7 +4380,7 @@
+ }
+
+ port = atoi(a->argv[3]);
+-
++
+ ast_cli(a->fd, "BEGIN STACK_LIST:\n");
+ get_show_stack_details(port, buf);
+ ast_cli(a->fd, " %s Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port] ? "(only)" : "");
+@@ -1647,15 +4388,749 @@
+ return CLI_SUCCESS;
+ }
+
++#if defined(AST_MISDN_ENHANCEMENTS) && defined(CCBS_TEST_MESSAGES)
++static const struct FacParm Fac_Msgs[] = {
++/* *INDENT-OFF* */
++ [0].Function = Fac_ERROR,
++ [0].u.ERROR.invokeId = 8,
++ [0].u.ERROR.errorValue = FacError_CCBS_AlreadyAccepted,
++
++ [1].Function = Fac_RESULT,
++ [1].u.RESULT.InvokeID = 9,
++
++ [2].Function = Fac_REJECT,
++ [2].u.REJECT.Code = FacReject_Gen_BadlyStructuredComponent,
++
++ [3].Function = Fac_REJECT,
++ [3].u.REJECT.InvokeIDPresent = 1,
++ [3].u.REJECT.InvokeID = 10,
++ [3].u.REJECT.Code = FacReject_Inv_InitiatorReleasing,
++
++ [4].Function = Fac_REJECT,
++ [4].u.REJECT.InvokeIDPresent = 1,
++ [4].u.REJECT.InvokeID = 11,
++ [4].u.REJECT.Code = FacReject_Res_MistypedResult,
++
++ [5].Function = Fac_REJECT,
++ [5].u.REJECT.InvokeIDPresent = 1,
++ [5].u.REJECT.InvokeID = 12,
++ [5].u.REJECT.Code = FacReject_Err_ErrorResponseUnexpected,
++
++ [6].Function = Fac_StatusRequest,
++ [6].u.StatusRequest.InvokeID = 13,
++ [6].u.StatusRequest.ComponentType = FacComponent_Invoke,
++ [6].u.StatusRequest.Component.Invoke.Q931ie.Bc.Length = 2,
++ [6].u.StatusRequest.Component.Invoke.Q931ie.Bc.Contents = "AB",
++ [6].u.StatusRequest.Component.Invoke.Q931ie.Llc.Length = 3,
++ [6].u.StatusRequest.Component.Invoke.Q931ie.Llc.Contents = "CDE",
++ [6].u.StatusRequest.Component.Invoke.Q931ie.Hlc.Length = 4,
++ [6].u.StatusRequest.Component.Invoke.Q931ie.Hlc.Contents = "FGHI",
++ [6].u.StatusRequest.Component.Invoke.CompatibilityMode = 1,
++
++ [7].Function = Fac_StatusRequest,
++ [7].u.StatusRequest.InvokeID = 14,
++ [7].u.StatusRequest.ComponentType = FacComponent_Result,
++ [7].u.StatusRequest.Component.Result.Status = 2,
++
++ [8].Function = Fac_CallInfoRetain,
++ [8].u.CallInfoRetain.InvokeID = 15,
++ [8].u.CallInfoRetain.CallLinkageID = 115,
++
++ [9].Function = Fac_EraseCallLinkageID,
++ [9].u.EraseCallLinkageID.InvokeID = 16,
++ [9].u.EraseCallLinkageID.CallLinkageID = 105,
++
++ [10].Function = Fac_CCBSDeactivate,
++ [10].u.CCBSDeactivate.InvokeID = 17,
++ [10].u.CCBSDeactivate.ComponentType = FacComponent_Invoke,
++ [10].u.CCBSDeactivate.Component.Invoke.CCBSReference = 2,
++
++ [11].Function = Fac_CCBSDeactivate,
++ [11].u.CCBSDeactivate.InvokeID = 18,
++ [11].u.CCBSDeactivate.ComponentType = FacComponent_Result,
++
++ [12].Function = Fac_CCBSErase,
++ [12].u.CCBSErase.InvokeID = 19,
++ [12].u.CCBSErase.Q931ie.Bc.Length = 2,
++ [12].u.CCBSErase.Q931ie.Bc.Contents = "JK",
++ [12].u.CCBSErase.AddressOfB.Party.Type = 0,
++ [12].u.CCBSErase.AddressOfB.Party.LengthOfNumber = 5,
++ [12].u.CCBSErase.AddressOfB.Party.Number = "33403",
++ [12].u.CCBSErase.AddressOfB.Subaddress.Type = 0,
++ [12].u.CCBSErase.AddressOfB.Subaddress.Length = 4,
++ [12].u.CCBSErase.AddressOfB.Subaddress.u.UserSpecified.Information = "3748",
++ [12].u.CCBSErase.RecallMode = 1,
++ [12].u.CCBSErase.CCBSReference = 102,
++ [12].u.CCBSErase.Reason = 3,
++
++ [13].Function = Fac_CCBSErase,
++ [13].u.CCBSErase.InvokeID = 20,
++ [13].u.CCBSErase.Q931ie.Bc.Length = 2,
++ [13].u.CCBSErase.Q931ie.Bc.Contents = "JK",
++ [13].u.CCBSErase.AddressOfB.Party.Type = 1,
++ [13].u.CCBSErase.AddressOfB.Party.LengthOfNumber = 11,
++ [13].u.CCBSErase.AddressOfB.Party.TypeOfNumber = 1,
++ [13].u.CCBSErase.AddressOfB.Party.Number = "18003020102",
++ [13].u.CCBSErase.AddressOfB.Subaddress.Type = 0,
++ [13].u.CCBSErase.AddressOfB.Subaddress.Length = 4,
++ [13].u.CCBSErase.AddressOfB.Subaddress.u.UserSpecified.OddCountPresent = 1,
++ [13].u.CCBSErase.AddressOfB.Subaddress.u.UserSpecified.OddCount = 1,
++ [13].u.CCBSErase.AddressOfB.Subaddress.u.UserSpecified.Information = "3748",
++ [13].u.CCBSErase.RecallMode = 1,
++ [13].u.CCBSErase.CCBSReference = 102,
++ [13].u.CCBSErase.Reason = 3,
++
++ [14].Function = Fac_CCBSErase,
++ [14].u.CCBSErase.InvokeID = 21,
++ [14].u.CCBSErase.Q931ie.Bc.Length = 2,
++ [14].u.CCBSErase.Q931ie.Bc.Contents = "JK",
++ [14].u.CCBSErase.AddressOfB.Party.Type = 2,
++ [14].u.CCBSErase.AddressOfB.Party.LengthOfNumber = 4,
++ [14].u.CCBSErase.AddressOfB.Party.Number = "1803",
++ [14].u.CCBSErase.AddressOfB.Subaddress.Type = 1,
++ [14].u.CCBSErase.AddressOfB.Subaddress.Length = 4,
++ [14].u.CCBSErase.AddressOfB.Subaddress.u.Nsap = "6492",
++ [14].u.CCBSErase.RecallMode = 1,
++ [14].u.CCBSErase.CCBSReference = 102,
++ [14].u.CCBSErase.Reason = 3,
++
++ [15].Function = Fac_CCBSErase,
++ [15].u.CCBSErase.InvokeID = 22,
++ [15].u.CCBSErase.Q931ie.Bc.Length = 2,
++ [15].u.CCBSErase.Q931ie.Bc.Contents = "JK",
++ [15].u.CCBSErase.AddressOfB.Party.Type = 3,
++ [15].u.CCBSErase.AddressOfB.Party.LengthOfNumber = 4,
++ [15].u.CCBSErase.AddressOfB.Party.Number = "1803",
++ [15].u.CCBSErase.RecallMode = 1,
++ [15].u.CCBSErase.CCBSReference = 102,
++ [15].u.CCBSErase.Reason = 3,
++
++ [16].Function = Fac_CCBSErase,
++ [16].u.CCBSErase.InvokeID = 23,
++ [16].u.CCBSErase.Q931ie.Bc.Length = 2,
++ [16].u.CCBSErase.Q931ie.Bc.Contents = "JK",
++ [16].u.CCBSErase.AddressOfB.Party.Type = 4,
++ [16].u.CCBSErase.AddressOfB.Party.LengthOfNumber = 4,
++ [16].u.CCBSErase.AddressOfB.Party.Number = "1803",
++ [16].u.CCBSErase.RecallMode = 1,
++ [16].u.CCBSErase.CCBSReference = 102,
++ [16].u.CCBSErase.Reason = 3,
++
++ [17].Function = Fac_CCBSErase,
++ [17].u.CCBSErase.InvokeID = 24,
++ [17].u.CCBSErase.Q931ie.Bc.Length = 2,
++ [17].u.CCBSErase.Q931ie.Bc.Contents = "JK",
++ [17].u.CCBSErase.AddressOfB.Party.Type = 5,
++ [17].u.CCBSErase.AddressOfB.Party.LengthOfNumber = 11,
++ [17].u.CCBSErase.AddressOfB.Party.TypeOfNumber = 4,
++ [17].u.CCBSErase.AddressOfB.Party.Number = "18003020102",
++ [17].u.CCBSErase.RecallMode = 1,
++ [17].u.CCBSErase.CCBSReference = 102,
++ [17].u.CCBSErase.Reason = 3,
++
++ [18].Function = Fac_CCBSErase,
++ [18].u.CCBSErase.InvokeID = 25,
++ [18].u.CCBSErase.Q931ie.Bc.Length = 2,
++ [18].u.CCBSErase.Q931ie.Bc.Contents = "JK",
++ [18].u.CCBSErase.AddressOfB.Party.Type = 8,
++ [18].u.CCBSErase.AddressOfB.Party.LengthOfNumber = 4,
++ [18].u.CCBSErase.AddressOfB.Party.Number = "1803",
++ [18].u.CCBSErase.RecallMode = 1,
++ [18].u.CCBSErase.CCBSReference = 102,
++ [18].u.CCBSErase.Reason = 3,
++
++ [19].Function = Fac_CCBSRemoteUserFree,
++ [19].u.CCBSRemoteUserFree.InvokeID = 26,
++ [19].u.CCBSRemoteUserFree.Q931ie.Bc.Length = 2,
++ [19].u.CCBSRemoteUserFree.Q931ie.Bc.Contents = "JK",
++ [19].u.CCBSRemoteUserFree.AddressOfB.Party.Type = 8,
++ [19].u.CCBSRemoteUserFree.AddressOfB.Party.LengthOfNumber = 4,
++ [19].u.CCBSRemoteUserFree.AddressOfB.Party.Number = "1803",
++ [19].u.CCBSRemoteUserFree.RecallMode = 1,
++ [19].u.CCBSRemoteUserFree.CCBSReference = 102,
++
++ [20].Function = Fac_CCBSCall,
++ [20].u.CCBSCall.InvokeID = 27,
++ [20].u.CCBSCall.CCBSReference = 115,
++
++ [21].Function = Fac_CCBSStatusRequest,
++ [21].u.CCBSStatusRequest.InvokeID = 28,
++ [21].u.CCBSStatusRequest.ComponentType = FacComponent_Invoke,
++ [21].u.CCBSStatusRequest.Component.Invoke.Q931ie.Bc.Length = 2,
++ [21].u.CCBSStatusRequest.Component.Invoke.Q931ie.Bc.Contents = "JK",
++ [21].u.CCBSStatusRequest.Component.Invoke.RecallMode = 1,
++ [21].u.CCBSStatusRequest.Component.Invoke.CCBSReference = 102,
++
++ [22].Function = Fac_CCBSStatusRequest,
++ [22].u.CCBSStatusRequest.InvokeID = 29,
++ [22].u.CCBSStatusRequest.ComponentType = FacComponent_Result,
++ [22].u.CCBSStatusRequest.Component.Result.Free = 1,
++
++ [23].Function = Fac_CCBSBFree,
++ [23].u.CCBSBFree.InvokeID = 30,
++ [23].u.CCBSBFree.Q931ie.Bc.Length = 2,
++ [23].u.CCBSBFree.Q931ie.Bc.Contents = "JK",
++ [23].u.CCBSBFree.AddressOfB.Party.Type = 8,
++ [23].u.CCBSBFree.AddressOfB.Party.LengthOfNumber = 4,
++ [23].u.CCBSBFree.AddressOfB.Party.Number = "1803",
++ [23].u.CCBSBFree.RecallMode = 1,
++ [23].u.CCBSBFree.CCBSReference = 14,
++
++ [24].Function = Fac_CCBSStopAlerting,
++ [24].u.CCBSStopAlerting.InvokeID = 31,
++ [24].u.CCBSStopAlerting.CCBSReference = 37,
++
++ [25].Function = Fac_CCBSRequest,
++ [25].u.CCBSRequest.InvokeID = 32,
++ [25].u.CCBSRequest.ComponentType = FacComponent_Invoke,
++ [25].u.CCBSRequest.Component.Invoke.CallLinkageID = 57,
++
++ [26].Function = Fac_CCBSRequest,
++ [26].u.CCBSRequest.InvokeID = 33,
++ [26].u.CCBSRequest.ComponentType = FacComponent_Result,
++ [26].u.CCBSRequest.Component.Result.RecallMode = 1,
++ [26].u.CCBSRequest.Component.Result.CCBSReference = 102,
++
++ [27].Function = Fac_CCBSInterrogate,
++ [27].u.CCBSInterrogate.InvokeID = 34,
++ [27].u.CCBSInterrogate.ComponentType = FacComponent_Invoke,
++ [27].u.CCBSInterrogate.Component.Invoke.AParty.Type = 8,
++ [27].u.CCBSInterrogate.Component.Invoke.AParty.LengthOfNumber = 4,
++ [27].u.CCBSInterrogate.Component.Invoke.AParty.Number = "1803",
++ [27].u.CCBSInterrogate.Component.Invoke.CCBSReferencePresent = 1,
++ [27].u.CCBSInterrogate.Component.Invoke.CCBSReference = 76,
++
++ [28].Function = Fac_CCBSInterrogate,
++ [28].u.CCBSInterrogate.InvokeID = 35,
++ [28].u.CCBSInterrogate.ComponentType = FacComponent_Invoke,
++ [28].u.CCBSInterrogate.Component.Invoke.AParty.Type = 8,
++ [28].u.CCBSInterrogate.Component.Invoke.AParty.LengthOfNumber = 4,
++ [28].u.CCBSInterrogate.Component.Invoke.AParty.Number = "1803",
++
++ [29].Function = Fac_CCBSInterrogate,
++ [29].u.CCBSInterrogate.InvokeID = 36,
++ [29].u.CCBSInterrogate.ComponentType = FacComponent_Invoke,
++ [29].u.CCBSInterrogate.Component.Invoke.CCBSReferencePresent = 1,
++ [29].u.CCBSInterrogate.Component.Invoke.CCBSReference = 76,
++
++ [30].Function = Fac_CCBSInterrogate,
++ [30].u.CCBSInterrogate.InvokeID = 37,
++ [30].u.CCBSInterrogate.ComponentType = FacComponent_Invoke,
++
++ [31].Function = Fac_CCBSInterrogate,
++ [31].u.CCBSInterrogate.InvokeID = 38,
++ [31].u.CCBSInterrogate.ComponentType = FacComponent_Result,
++ [31].u.CCBSInterrogate.Component.Result.RecallMode = 1,
++
++ [32].Function = Fac_CCBSInterrogate,
++ [32].u.CCBSInterrogate.InvokeID = 39,
++ [32].u.CCBSInterrogate.ComponentType = FacComponent_Result,
++ [32].u.CCBSInterrogate.Component.Result.RecallMode = 1,
++ [32].u.CCBSInterrogate.Component.Result.NumRecords = 1,
++ [32].u.CCBSInterrogate.Component.Result.CallDetails[0].CCBSReference = 12,
++ [32].u.CCBSInterrogate.Component.Result.CallDetails[0].Q931ie.Bc.Length = 2,
++ [32].u.CCBSInterrogate.Component.Result.CallDetails[0].Q931ie.Bc.Contents = "JK",
++ [32].u.CCBSInterrogate.Component.Result.CallDetails[0].AddressOfB.Party.Type = 8,
++ [32].u.CCBSInterrogate.Component.Result.CallDetails[0].AddressOfB.Party.LengthOfNumber = 4,
++ [32].u.CCBSInterrogate.Component.Result.CallDetails[0].AddressOfB.Party.Number = "1803",
++ [32].u.CCBSInterrogate.Component.Result.CallDetails[0].SubaddressOfA.Type = 1,
++ [32].u.CCBSInterrogate.Component.Result.CallDetails[0].SubaddressOfA.Length = 4,
++ [32].u.CCBSInterrogate.Component.Result.CallDetails[0].SubaddressOfA.u.Nsap = "6492",
++
++ [33].Function = Fac_CCBSInterrogate,
++ [33].u.CCBSInterrogate.InvokeID = 40,
++ [33].u.CCBSInterrogate.ComponentType = FacComponent_Result,
++ [33].u.CCBSInterrogate.Component.Result.RecallMode = 1,
++ [33].u.CCBSInterrogate.Component.Result.NumRecords = 2,
++ [33].u.CCBSInterrogate.Component.Result.CallDetails[0].CCBSReference = 12,
++ [33].u.CCBSInterrogate.Component.Result.CallDetails[0].Q931ie.Bc.Length = 2,
++ [33].u.CCBSInterrogate.Component.Result.CallDetails[0].Q931ie.Bc.Contents = "JK",
++ [33].u.CCBSInterrogate.Component.Result.CallDetails[0].AddressOfB.Party.Type = 8,
++ [33].u.CCBSInterrogate.Component.Result.CallDetails[0].AddressOfB.Party.LengthOfNumber = 4,
++ [33].u.CCBSInterrogate.Component.Result.CallDetails[0].AddressOfB.Party.Number = "1803",
++ [33].u.CCBSInterrogate.Component.Result.CallDetails[1].CCBSReference = 102,
++ [33].u.CCBSInterrogate.Component.Result.CallDetails[1].Q931ie.Bc.Length = 2,
++ [33].u.CCBSInterrogate.Component.Result.CallDetails[1].Q931ie.Bc.Contents = "LM",
++ [33].u.CCBSInterrogate.Component.Result.CallDetails[1].AddressOfB.Party.Type = 8,
++ [33].u.CCBSInterrogate.Component.Result.CallDetails[1].AddressOfB.Party.LengthOfNumber = 4,
++ [33].u.CCBSInterrogate.Component.Result.CallDetails[1].AddressOfB.Party.Number = "6229",
++ [33].u.CCBSInterrogate.Component.Result.CallDetails[1].AddressOfB.Subaddress.Type = 1,
++ [33].u.CCBSInterrogate.Component.Result.CallDetails[1].AddressOfB.Subaddress.Length = 4,
++ [33].u.CCBSInterrogate.Component.Result.CallDetails[1].AddressOfB.Subaddress.u.Nsap = "8592",
++ [33].u.CCBSInterrogate.Component.Result.CallDetails[1].SubaddressOfA.Type = 1,
++ [33].u.CCBSInterrogate.Component.Result.CallDetails[1].SubaddressOfA.Length = 4,
++ [33].u.CCBSInterrogate.Component.Result.CallDetails[1].SubaddressOfA.u.Nsap = "6492",
++
++ [34].Function = Fac_CCNRRequest,
++ [34].u.CCNRRequest.InvokeID = 512,
++ [34].u.CCNRRequest.ComponentType = FacComponent_Invoke,
++ [34].u.CCNRRequest.Component.Invoke.CallLinkageID = 57,
++
++ [35].Function = Fac_CCNRRequest,
++ [35].u.CCNRRequest.InvokeID = 150,
++ [35].u.CCNRRequest.ComponentType = FacComponent_Result,
++ [35].u.CCNRRequest.Component.Result.RecallMode = 1,
++ [35].u.CCNRRequest.Component.Result.CCBSReference = 102,
++
++ [36].Function = Fac_CCNRInterrogate,
++ [36].u.CCNRInterrogate.InvokeID = -129,
++ [36].u.CCNRInterrogate.ComponentType = FacComponent_Invoke,
++
++ [37].Function = Fac_CCNRInterrogate,
++ [37].u.CCNRInterrogate.InvokeID = -3,
++ [37].u.CCNRInterrogate.ComponentType = FacComponent_Result,
++ [37].u.CCNRInterrogate.Component.Result.RecallMode = 1,
++
++ [38].Function = Fac_CCBS_T_Call,
++ [38].u.EctExecute.InvokeID = 41,
++
++ [39].Function = Fac_CCBS_T_Suspend,
++ [39].u.EctExecute.InvokeID = 42,
++
++ [40].Function = Fac_CCBS_T_Resume,
++ [40].u.EctExecute.InvokeID = 43,
++
++ [41].Function = Fac_CCBS_T_RemoteUserFree,
++ [41].u.EctExecute.InvokeID = 44,
++
++ [42].Function = Fac_CCBS_T_Available,
++ [42].u.EctExecute.InvokeID = 45,
++
++ [43].Function = Fac_CCBS_T_Request,
++ [43].u.CCBS_T_Request.InvokeID = 46,
++ [43].u.CCBS_T_Request.ComponentType = FacComponent_Invoke,
++ [43].u.CCBS_T_Request.Component.Invoke.Destination.Party.Type = 8,
++ [43].u.CCBS_T_Request.Component.Invoke.Destination.Party.LengthOfNumber = 4,
++ [43].u.CCBS_T_Request.Component.Invoke.Destination.Party.Number = "6229",
++ [43].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Length = 2,
++ [43].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Contents = "LM",
++ [43].u.CCBS_T_Request.Component.Invoke.RetentionSupported = 1,
++ [43].u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicatorPresent = 1,
++ [43].u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicator = 1,
++ [43].u.CCBS_T_Request.Component.Invoke.Originating.Party.Type = 8,
++ [43].u.CCBS_T_Request.Component.Invoke.Originating.Party.LengthOfNumber = 4,
++ [43].u.CCBS_T_Request.Component.Invoke.Originating.Party.Number = "9864",
++
++ [44].Function = Fac_CCBS_T_Request,
++ [44].u.CCBS_T_Request.InvokeID = 47,
++ [44].u.CCBS_T_Request.ComponentType = FacComponent_Invoke,
++ [44].u.CCBS_T_Request.Component.Invoke.Destination.Party.Type = 8,
++ [44].u.CCBS_T_Request.Component.Invoke.Destination.Party.LengthOfNumber = 4,
++ [44].u.CCBS_T_Request.Component.Invoke.Destination.Party.Number = "6229",
++ [44].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Length = 2,
++ [44].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Contents = "LM",
++ [44].u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicatorPresent = 1,
++ [44].u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicator = 1,
++ [44].u.CCBS_T_Request.Component.Invoke.Originating.Party.Type = 8,
++ [44].u.CCBS_T_Request.Component.Invoke.Originating.Party.LengthOfNumber = 4,
++ [44].u.CCBS_T_Request.Component.Invoke.Originating.Party.Number = "9864",
++
++ [45].Function = Fac_CCBS_T_Request,
++ [45].u.CCBS_T_Request.InvokeID = 48,
++ [45].u.CCBS_T_Request.ComponentType = FacComponent_Invoke,
++ [45].u.CCBS_T_Request.Component.Invoke.Destination.Party.Type = 8,
++ [45].u.CCBS_T_Request.Component.Invoke.Destination.Party.LengthOfNumber = 4,
++ [45].u.CCBS_T_Request.Component.Invoke.Destination.Party.Number = "6229",
++ [45].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Length = 2,
++ [45].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Contents = "LM",
++ [45].u.CCBS_T_Request.Component.Invoke.Originating.Party.Type = 8,
++ [45].u.CCBS_T_Request.Component.Invoke.Originating.Party.LengthOfNumber = 4,
++ [45].u.CCBS_T_Request.Component.Invoke.Originating.Party.Number = "9864",
++
++ [46].Function = Fac_CCBS_T_Request,
++ [46].u.CCBS_T_Request.InvokeID = 49,
++ [46].u.CCBS_T_Request.ComponentType = FacComponent_Invoke,
++ [46].u.CCBS_T_Request.Component.Invoke.Destination.Party.Type = 8,
++ [46].u.CCBS_T_Request.Component.Invoke.Destination.Party.LengthOfNumber = 4,
++ [46].u.CCBS_T_Request.Component.Invoke.Destination.Party.Number = "6229",
++ [46].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Length = 2,
++ [46].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Contents = "LM",
++ [46].u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicatorPresent = 1,
++ [46].u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicator = 1,
++
++ [47].Function = Fac_CCBS_T_Request,
++ [47].u.CCBS_T_Request.InvokeID = 50,
++ [47].u.CCBS_T_Request.ComponentType = FacComponent_Invoke,
++ [47].u.CCBS_T_Request.Component.Invoke.Destination.Party.Type = 8,
++ [47].u.CCBS_T_Request.Component.Invoke.Destination.Party.LengthOfNumber = 4,
++ [47].u.CCBS_T_Request.Component.Invoke.Destination.Party.Number = "6229",
++ [47].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Length = 2,
++ [47].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Contents = "LM",
++
++ [48].Function = Fac_CCBS_T_Request,
++ [48].u.CCBS_T_Request.InvokeID = 51,
++ [48].u.CCBS_T_Request.ComponentType = FacComponent_Result,
++ [48].u.CCBS_T_Request.Component.Result.RetentionSupported = 1,
++
++ [49].Function = Fac_CCNR_T_Request,
++ [49].u.CCNR_T_Request.InvokeID = 52,
++ [49].u.CCNR_T_Request.ComponentType = FacComponent_Invoke,
++ [49].u.CCNR_T_Request.Component.Invoke.Destination.Party.Type = 8,
++ [49].u.CCNR_T_Request.Component.Invoke.Destination.Party.LengthOfNumber = 4,
++ [49].u.CCNR_T_Request.Component.Invoke.Destination.Party.Number = "6229",
++ [49].u.CCNR_T_Request.Component.Invoke.Q931ie.Bc.Length = 2,
++ [49].u.CCNR_T_Request.Component.Invoke.Q931ie.Bc.Contents = "LM",
++
++ [50].Function = Fac_CCNR_T_Request,
++ [50].u.CCNR_T_Request.InvokeID = 53,
++ [50].u.CCNR_T_Request.ComponentType = FacComponent_Result,
++ [50].u.CCNR_T_Request.Component.Result.RetentionSupported = 1,
++
++ [51].Function = Fac_EctExecute,
++ [51].u.EctExecute.InvokeID = 54,
++
++ [52].Function = Fac_ExplicitEctExecute,
++ [52].u.ExplicitEctExecute.InvokeID = 55,
++ [52].u.ExplicitEctExecute.LinkID = 23,
++
++ [53].Function = Fac_RequestSubaddress,
++ [53].u.RequestSubaddress.InvokeID = 56,
++
++ [54].Function = Fac_SubaddressTransfer,
++ [54].u.SubaddressTransfer.InvokeID = 57,
++ [54].u.SubaddressTransfer.Subaddress.Type = 1,
++ [54].u.SubaddressTransfer.Subaddress.Length = 4,
++ [54].u.SubaddressTransfer.Subaddress.u.Nsap = "6492",
++
++ [55].Function = Fac_EctLinkIdRequest,
++ [55].u.EctLinkIdRequest.InvokeID = 58,
++ [55].u.EctLinkIdRequest.ComponentType = FacComponent_Invoke,
++
++ [56].Function = Fac_EctLinkIdRequest,
++ [56].u.EctLinkIdRequest.InvokeID = 59,
++ [56].u.EctLinkIdRequest.ComponentType = FacComponent_Result,
++ [56].u.EctLinkIdRequest.Component.Result.LinkID = 76,
++
++ [57].Function = Fac_EctInform,
++ [57].u.EctInform.InvokeID = 60,
++ [57].u.EctInform.Status = 1,
++ [57].u.EctInform.RedirectionPresent = 1,
++ [57].u.EctInform.Redirection.Type = 0,
++ [57].u.EctInform.Redirection.Unscreened.Type = 8,
++ [57].u.EctInform.Redirection.Unscreened.LengthOfNumber = 4,
++ [57].u.EctInform.Redirection.Unscreened.Number = "6229",
++
++ [58].Function = Fac_EctInform,
++ [58].u.EctInform.InvokeID = 61,
++ [58].u.EctInform.Status = 1,
++ [58].u.EctInform.RedirectionPresent = 1,
++ [58].u.EctInform.Redirection.Type = 1,
++
++ [59].Function = Fac_EctInform,
++ [59].u.EctInform.InvokeID = 62,
++ [59].u.EctInform.Status = 1,
++ [59].u.EctInform.RedirectionPresent = 1,
++ [59].u.EctInform.Redirection.Type = 2,
++
++ [60].Function = Fac_EctInform,
++ [60].u.EctInform.InvokeID = 63,
++ [60].u.EctInform.Status = 1,
++ [60].u.EctInform.RedirectionPresent = 1,
++ [60].u.EctInform.Redirection.Type = 3,
++ [60].u.EctInform.Redirection.Unscreened.Type = 8,
++ [60].u.EctInform.Redirection.Unscreened.LengthOfNumber = 4,
++ [60].u.EctInform.Redirection.Unscreened.Number = "3340",
++
++ [61].Function = Fac_EctInform,
++ [61].u.EctInform.InvokeID = 64,
++ [61].u.EctInform.Status = 1,
++ [61].u.EctInform.RedirectionPresent = 0,
++
++ [62].Function = Fac_EctLoopTest,
++ [62].u.EctLoopTest.InvokeID = 65,
++ [62].u.EctLoopTest.ComponentType = FacComponent_Invoke,
++ [62].u.EctLoopTest.Component.Invoke.CallTransferID = 7,
++
++ [63].Function = Fac_EctLoopTest,
++ [63].u.EctLoopTest.InvokeID = 66,
++ [63].u.EctLoopTest.ComponentType = FacComponent_Result,
++ [63].u.EctLoopTest.Component.Result.LoopResult = 2,
++
++ [64].Function = Fac_ActivationDiversion,
++ [64].u.ActivationDiversion.InvokeID = 67,
++ [64].u.ActivationDiversion.ComponentType = FacComponent_Invoke,
++ [64].u.ActivationDiversion.Component.Invoke.Procedure = 2,
++ [64].u.ActivationDiversion.Component.Invoke.BasicService = 3,
++ [64].u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Type = 4,
++ [64].u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.LengthOfNumber = 4,
++ [64].u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Number = "1803",
++ [64].u.ActivationDiversion.Component.Invoke.ServedUser.Type = 4,
++ [64].u.ActivationDiversion.Component.Invoke.ServedUser.LengthOfNumber = 4,
++ [64].u.ActivationDiversion.Component.Invoke.ServedUser.Number = "5398",
++
++ [65].Function = Fac_ActivationDiversion,
++ [65].u.ActivationDiversion.InvokeID = 68,
++ [65].u.ActivationDiversion.ComponentType = FacComponent_Invoke,
++ [65].u.ActivationDiversion.Component.Invoke.Procedure = 1,
++ [65].u.ActivationDiversion.Component.Invoke.BasicService = 5,
++ [65].u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Type = 4,
++ [65].u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.LengthOfNumber = 4,
++ [65].u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Number = "1803",
++
++ [66].Function = Fac_ActivationDiversion,
++ [66].u.ActivationDiversion.InvokeID = 69,
++ [66].u.ActivationDiversion.ComponentType = FacComponent_Result,
++
++ [67].Function = Fac_DeactivationDiversion,
++ [67].u.DeactivationDiversion.InvokeID = 70,
++ [67].u.DeactivationDiversion.ComponentType = FacComponent_Invoke,
++ [67].u.DeactivationDiversion.Component.Invoke.Procedure = 1,
++ [67].u.DeactivationDiversion.Component.Invoke.BasicService = 5,
++
++ [68].Function = Fac_DeactivationDiversion,
++ [68].u.DeactivationDiversion.InvokeID = 71,
++ [68].u.DeactivationDiversion.ComponentType = FacComponent_Result,
++
++ [69].Function = Fac_ActivationStatusNotificationDiv,
++ [69].u.ActivationStatusNotificationDiv.InvokeID = 72,
++ [69].u.ActivationStatusNotificationDiv.Procedure = 1,
++ [69].u.ActivationStatusNotificationDiv.BasicService = 5,
++ [69].u.ActivationStatusNotificationDiv.ForwardedTo.Party.Type = 4,
++ [69].u.ActivationStatusNotificationDiv.ForwardedTo.Party.LengthOfNumber = 4,
++ [69].u.ActivationStatusNotificationDiv.ForwardedTo.Party.Number = "1803",
++
++ [70].Function = Fac_DeactivationStatusNotificationDiv,
++ [70].u.DeactivationStatusNotificationDiv.InvokeID = 73,
++ [70].u.DeactivationStatusNotificationDiv.Procedure = 1,
++ [70].u.DeactivationStatusNotificationDiv.BasicService = 5,
++
++ [71].Function = Fac_InterrogationDiversion,
++ [71].u.InterrogationDiversion.InvokeID = 74,
++ [71].u.InterrogationDiversion.ComponentType = FacComponent_Invoke,
++ [71].u.InterrogationDiversion.Component.Invoke.Procedure = 1,
++ [71].u.InterrogationDiversion.Component.Invoke.BasicService = 5,
++
++ [72].Function = Fac_InterrogationDiversion,
++ [72].u.InterrogationDiversion.InvokeID = 75,
++ [72].u.InterrogationDiversion.ComponentType = FacComponent_Invoke,
++ [72].u.InterrogationDiversion.Component.Invoke.Procedure = 1,
++
++ [73].Function = Fac_InterrogationDiversion,
++ [73].u.InterrogationDiversion.InvokeID = 76,
++ [73].u.InterrogationDiversion.ComponentType = FacComponent_Result,
++ [73].u.InterrogationDiversion.Component.Result.NumRecords = 2,
++ [73].u.InterrogationDiversion.Component.Result.List[0].Procedure = 2,
++ [73].u.InterrogationDiversion.Component.Result.List[0].BasicService = 5,
++ [73].u.InterrogationDiversion.Component.Result.List[0].ForwardedTo.Party.Type = 4,
++ [73].u.InterrogationDiversion.Component.Result.List[0].ForwardedTo.Party.LengthOfNumber = 4,
++ [73].u.InterrogationDiversion.Component.Result.List[0].ForwardedTo.Party.Number = "1803",
++ [73].u.InterrogationDiversion.Component.Result.List[1].Procedure = 1,
++ [73].u.InterrogationDiversion.Component.Result.List[1].BasicService = 3,
++ [73].u.InterrogationDiversion.Component.Result.List[1].ForwardedTo.Party.Type = 4,
++ [73].u.InterrogationDiversion.Component.Result.List[1].ForwardedTo.Party.LengthOfNumber = 4,
++ [73].u.InterrogationDiversion.Component.Result.List[1].ForwardedTo.Party.Number = "1903",
++ [73].u.InterrogationDiversion.Component.Result.List[1].ServedUser.Type = 4,
++ [73].u.InterrogationDiversion.Component.Result.List[1].ServedUser.LengthOfNumber = 4,
++ [73].u.InterrogationDiversion.Component.Result.List[1].ServedUser.Number = "5398",
++
++ [74].Function = Fac_DiversionInformation,
++ [74].u.DiversionInformation.InvokeID = 77,
++ [74].u.DiversionInformation.DiversionReason = 3,
++ [74].u.DiversionInformation.BasicService = 5,
++ [74].u.DiversionInformation.ServedUserSubaddress.Type = 1,
++ [74].u.DiversionInformation.ServedUserSubaddress.Length = 4,
++ [74].u.DiversionInformation.ServedUserSubaddress.u.Nsap = "6492",
++ [74].u.DiversionInformation.CallingAddressPresent = 1,
++ [74].u.DiversionInformation.CallingAddress.Type = 0,
++ [74].u.DiversionInformation.CallingAddress.Address.ScreeningIndicator = 3,
++ [74].u.DiversionInformation.CallingAddress.Address.Party.Type = 4,
++ [74].u.DiversionInformation.CallingAddress.Address.Party.LengthOfNumber = 4,
++ [74].u.DiversionInformation.CallingAddress.Address.Party.Number = "1803",
++ [74].u.DiversionInformation.OriginalCalledPresent = 1,
++ [74].u.DiversionInformation.OriginalCalled.Type = 1,
++ [74].u.DiversionInformation.LastDivertingPresent = 1,
++ [74].u.DiversionInformation.LastDiverting.Type = 2,
++ [74].u.DiversionInformation.LastDivertingReasonPresent = 1,
++ [74].u.DiversionInformation.LastDivertingReason = 3,
++ [74].u.DiversionInformation.UserInfo.Length = 5,
++ [74].u.DiversionInformation.UserInfo.Contents = "79828",
++
++ [75].Function = Fac_DiversionInformation,
++ [75].u.DiversionInformation.InvokeID = 78,
++ [75].u.DiversionInformation.DiversionReason = 3,
++ [75].u.DiversionInformation.BasicService = 5,
++ [75].u.DiversionInformation.CallingAddressPresent = 1,
++ [75].u.DiversionInformation.CallingAddress.Type = 1,
++ [75].u.DiversionInformation.OriginalCalledPresent = 1,
++ [75].u.DiversionInformation.OriginalCalled.Type = 2,
++ [75].u.DiversionInformation.LastDivertingPresent = 1,
++ [75].u.DiversionInformation.LastDiverting.Type = 1,
++
++ [76].Function = Fac_DiversionInformation,
++ [76].u.DiversionInformation.InvokeID = 79,
++ [76].u.DiversionInformation.DiversionReason = 2,
++ [76].u.DiversionInformation.BasicService = 3,
++ [76].u.DiversionInformation.CallingAddressPresent = 1,
++ [76].u.DiversionInformation.CallingAddress.Type = 2,
++
++ [77].Function = Fac_DiversionInformation,
++ [77].u.DiversionInformation.InvokeID = 80,
++ [77].u.DiversionInformation.DiversionReason = 3,
++ [77].u.DiversionInformation.BasicService = 5,
++ [77].u.DiversionInformation.CallingAddressPresent = 1,
++ [77].u.DiversionInformation.CallingAddress.Type = 3,
++ [77].u.DiversionInformation.CallingAddress.Address.ScreeningIndicator = 2,
++ [77].u.DiversionInformation.CallingAddress.Address.Party.Type = 4,
++ [77].u.DiversionInformation.CallingAddress.Address.Party.LengthOfNumber = 4,
++ [77].u.DiversionInformation.CallingAddress.Address.Party.Number = "1803",
++
++ [78].Function = Fac_DiversionInformation,
++ [78].u.DiversionInformation.InvokeID = 81,
++ [78].u.DiversionInformation.DiversionReason = 2,
++ [78].u.DiversionInformation.BasicService = 4,
++ [78].u.DiversionInformation.UserInfo.Length = 5,
++ [78].u.DiversionInformation.UserInfo.Contents = "79828",
++
++ [79].Function = Fac_DiversionInformation,
++ [79].u.DiversionInformation.InvokeID = 82,
++ [79].u.DiversionInformation.DiversionReason = 2,
++ [79].u.DiversionInformation.BasicService = 4,
++
++ [80].Function = Fac_CallDeflection,
++ [80].u.CallDeflection.InvokeID = 83,
++ [80].u.CallDeflection.ComponentType = FacComponent_Invoke,
++ [80].u.CallDeflection.Component.Invoke.Deflection.Party.Type = 4,
++ [80].u.CallDeflection.Component.Invoke.Deflection.Party.LengthOfNumber = 4,
++ [80].u.CallDeflection.Component.Invoke.Deflection.Party.Number = "1803",
++ [80].u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent = 1,
++ [80].u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser = 1,
++
++ [81].Function = Fac_CallDeflection,
++ [81].u.CallDeflection.InvokeID = 84,
++ [81].u.CallDeflection.ComponentType = FacComponent_Invoke,
++ [81].u.CallDeflection.Component.Invoke.Deflection.Party.Type = 4,
++ [81].u.CallDeflection.Component.Invoke.Deflection.Party.LengthOfNumber = 4,
++ [81].u.CallDeflection.Component.Invoke.Deflection.Party.Number = "1803",
++ [81].u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent = 1,
++ [81].u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser = 0,
++
++ [82].Function = Fac_CallDeflection,
++ [82].u.CallDeflection.InvokeID = 85,
++ [82].u.CallDeflection.ComponentType = FacComponent_Invoke,
++ [82].u.CallDeflection.Component.Invoke.Deflection.Party.Type = 4,
++ [82].u.CallDeflection.Component.Invoke.Deflection.Party.LengthOfNumber = 4,
++ [82].u.CallDeflection.Component.Invoke.Deflection.Party.Number = "1803",
++
++ [83].Function = Fac_CallDeflection,
++ [83].u.CallDeflection.InvokeID = 86,
++ [83].u.CallDeflection.ComponentType = FacComponent_Result,
++
++ [84].Function = Fac_CallRerouteing,
++ [84].u.CallRerouteing.InvokeID = 87,
++ [84].u.CallRerouteing.ComponentType = FacComponent_Invoke,
++ [84].u.CallRerouteing.Component.Invoke.ReroutingReason = 3,
++ [84].u.CallRerouteing.Component.Invoke.ReroutingCounter = 2,
++ [84].u.CallRerouteing.Component.Invoke.CalledAddress.Party.Type = 4,
++ [84].u.CallRerouteing.Component.Invoke.CalledAddress.Party.LengthOfNumber = 4,
++ [84].u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number = "1803",
++ [84].u.CallRerouteing.Component.Invoke.Q931ie.Bc.Length = 2,
++ [84].u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents = "RT",
++ [84].u.CallRerouteing.Component.Invoke.Q931ie.Hlc.Length = 3,
++ [84].u.CallRerouteing.Component.Invoke.Q931ie.Hlc.Contents = "RTG",
++ [84].u.CallRerouteing.Component.Invoke.Q931ie.Llc.Length = 2,
++ [84].u.CallRerouteing.Component.Invoke.Q931ie.Llc.Contents = "MY",
++ [84].u.CallRerouteing.Component.Invoke.Q931ie.UserInfo.Length = 5,
++ [84].u.CallRerouteing.Component.Invoke.Q931ie.UserInfo.Contents = "YEHAW",
++ [84].u.CallRerouteing.Component.Invoke.LastRerouting.Type = 1,
++ [84].u.CallRerouteing.Component.Invoke.SubscriptionOption = 2,
++ [84].u.CallRerouteing.Component.Invoke.CallingPartySubaddress.Type = 1,
++ [84].u.CallRerouteing.Component.Invoke.CallingPartySubaddress.Length = 4,
++ [84].u.CallRerouteing.Component.Invoke.CallingPartySubaddress.u.Nsap = "6492",
++
++ [85].Function = Fac_CallRerouteing,
++ [85].u.CallRerouteing.InvokeID = 88,
++ [85].u.CallRerouteing.ComponentType = FacComponent_Invoke,
++ [85].u.CallRerouteing.Component.Invoke.ReroutingReason = 3,
++ [85].u.CallRerouteing.Component.Invoke.ReroutingCounter = 2,
++ [85].u.CallRerouteing.Component.Invoke.CalledAddress.Party.Type = 4,
++ [85].u.CallRerouteing.Component.Invoke.CalledAddress.Party.LengthOfNumber = 4,
++ [85].u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number = "1803",
++ [85].u.CallRerouteing.Component.Invoke.Q931ie.Bc.Length = 2,
++ [85].u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents = "RT",
++ [85].u.CallRerouteing.Component.Invoke.LastRerouting.Type = 1,
++ [85].u.CallRerouteing.Component.Invoke.SubscriptionOption = 2,
++
++ [86].Function = Fac_CallRerouteing,
++ [86].u.CallRerouteing.InvokeID = 89,
++ [86].u.CallRerouteing.ComponentType = FacComponent_Invoke,
++ [86].u.CallRerouteing.Component.Invoke.ReroutingReason = 3,
++ [86].u.CallRerouteing.Component.Invoke.ReroutingCounter = 2,
++ [86].u.CallRerouteing.Component.Invoke.CalledAddress.Party.Type = 4,
++ [86].u.CallRerouteing.Component.Invoke.CalledAddress.Party.LengthOfNumber = 4,
++ [86].u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number = "1803",
++ [86].u.CallRerouteing.Component.Invoke.Q931ie.Bc.Length = 2,
++ [86].u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents = "RT",
++ [86].u.CallRerouteing.Component.Invoke.LastRerouting.Type = 2,
++
++ [87].Function = Fac_CallRerouteing,
++ [87].u.CallRerouteing.InvokeID = 90,
++ [87].u.CallRerouteing.ComponentType = FacComponent_Result,
++
++ [88].Function = Fac_InterrogateServedUserNumbers,
++ [88].u.InterrogateServedUserNumbers.InvokeID = 91,
++ [88].u.InterrogateServedUserNumbers.ComponentType = FacComponent_Invoke,
++
++ [89].Function = Fac_InterrogateServedUserNumbers,
++ [89].u.InterrogateServedUserNumbers.InvokeID = 92,
++ [89].u.InterrogateServedUserNumbers.ComponentType = FacComponent_Result,
++ [89].u.InterrogateServedUserNumbers.Component.Result.NumRecords = 2,
++ [89].u.InterrogateServedUserNumbers.Component.Result.List[0].Type = 4,
++ [89].u.InterrogateServedUserNumbers.Component.Result.List[0].LengthOfNumber = 4,
++ [89].u.InterrogateServedUserNumbers.Component.Result.List[0].Number = "1803",
++ [89].u.InterrogateServedUserNumbers.Component.Result.List[1].Type = 4,
++ [89].u.InterrogateServedUserNumbers.Component.Result.List[1].LengthOfNumber = 4,
++ [89].u.InterrogateServedUserNumbers.Component.Result.List[1].Number = "5786",
++
++ [90].Function = Fac_DivertingLegInformation1,
++ [90].u.DivertingLegInformation1.InvokeID = 93,
++ [90].u.DivertingLegInformation1.DiversionReason = 4,
++ [90].u.DivertingLegInformation1.SubscriptionOption = 1,
++ [90].u.DivertingLegInformation1.DivertedToPresent = 1,
++ [90].u.DivertingLegInformation1.DivertedTo.Type = 2,
++
++ [91].Function = Fac_DivertingLegInformation1,
++ [91].u.DivertingLegInformation1.InvokeID = 94,
++ [91].u.DivertingLegInformation1.DiversionReason = 4,
++ [91].u.DivertingLegInformation1.SubscriptionOption = 1,
++
++ [92].Function = Fac_DivertingLegInformation2,
++ [92].u.DivertingLegInformation2.InvokeID = 95,
++ [92].u.DivertingLegInformation2.DiversionCounter = 3,
++ [92].u.DivertingLegInformation2.DiversionReason = 2,
++ [92].u.DivertingLegInformation2.DivertingPresent = 1,
++ [92].u.DivertingLegInformation2.Diverting.Type = 2,
++ [92].u.DivertingLegInformation2.OriginalCalledPresent = 1,
++ [92].u.DivertingLegInformation2.OriginalCalled.Type = 1,
++
++ [93].Function = Fac_DivertingLegInformation2,
++ [93].u.DivertingLegInformation2.InvokeID = 96,
++ [93].u.DivertingLegInformation2.DiversionCounter = 3,
++ [93].u.DivertingLegInformation2.DiversionReason = 2,
++ [93].u.DivertingLegInformation2.OriginalCalledPresent = 1,
++ [93].u.DivertingLegInformation2.OriginalCalled.Type = 1,
++
++ [94].Function = Fac_DivertingLegInformation2,
++ [94].u.DivertingLegInformation2.InvokeID = 97,
++ [94].u.DivertingLegInformation2.DiversionCounter = 1,
++ [94].u.DivertingLegInformation2.DiversionReason = 2,
++
++ [95].Function = Fac_DivertingLegInformation3,
++ [95].u.DivertingLegInformation3.InvokeID = 98,
++ [95].u.DivertingLegInformation3.PresentationAllowedIndicator = 1,
++/* *INDENT-ON* */
++};
++#endif /* defined(AST_MISDN_ENHANCEMENTS) && defined(CCBS_TEST_MESSAGES) */
++
+ static char *handle_cli_misdn_send_facility(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+ {
+- char *channame;
+- char *nr;
++ const char *channame;
++ const char *nr;
+ struct chan_list *tmp;
+- int port;
+- char *served_nr;
++ int port;
++ const char *served_nr;
+ struct misdn_bchannel dummy, *bc=&dummy;
+-
++ unsigned max_len;
++
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "misdn send facility";
+@@ -1673,7 +5148,7 @@
+ if (a->argc < 5) {
+ return CLI_SHOWUSAGE;
+ }
+-
++
+ if (strstr(a->argv[3], "calldeflect")) {
+ if (a->argc < 6) {
+ ast_verbose("calldeflect requires 1 arg: ToNumber\n\n");
+@@ -1686,15 +5161,42 @@
+ tmp = get_chan_by_ast_name(channame);
+ if (!tmp) {
+ ast_verbose("Sending CD with nr %s to %s failed: Channel does not exist.\n", nr, channame);
+- return 0;
++ return 0;
+ }
+
+- if (strlen(nr) >= 15) {
+- ast_verbose("Sending CD with nr %s to %s failed: Number too long (up to 15 digits are allowed).\n", nr, channame);
+- return 0;
++#if defined(AST_MISDN_ENHANCEMENTS)
++ max_len = sizeof(tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Number) - 1;
++ if (max_len < strlen(nr)) {
++ ast_verbose("Sending CD with nr %s to %s failed: Number too long (up to %u digits are allowed).\n",
++ nr, channame, max_len);
++ return 0;
+ }
++ tmp->bc->fac_out.Function = Fac_CallDeflection;
++ tmp->bc->fac_out.u.CallDeflection.InvokeID = ++misdn_invoke_id;
++ tmp->bc->fac_out.u.CallDeflection.ComponentType = FacComponent_Invoke;
++ tmp->bc->fac_out.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent = 1;
++ tmp->bc->fac_out.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser = 0;
++ tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Type = 0;/* unknown */
++ tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.LengthOfNumber = strlen(nr);
++ strcpy((char *) tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Number, nr);
++ tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Subaddress.Length = 0;
++
++#else /* !defined(AST_MISDN_ENHANCEMENTS) */
++
++ max_len = sizeof(tmp->bc->fac_out.u.CDeflection.DeflectedToNumber) - 1;
++ if (max_len < strlen(nr)) {
++ ast_verbose("Sending CD with nr %s to %s failed: Number too long (up to %u digits are allowed).\n",
++ nr, channame, max_len);
++ return 0;
++ }
+ tmp->bc->fac_out.Function = Fac_CD;
+- ast_copy_string((char *)tmp->bc->fac_out.u.CDeflection.DeflectedToNumber, nr, sizeof(tmp->bc->fac_out.u.CDeflection.DeflectedToNumber));
++ tmp->bc->fac_out.u.CDeflection.PresentationAllowed = 0;
++ //tmp->bc->fac_out.u.CDeflection.DeflectedToSubaddress[0] = 0;
++ strcpy((char *) tmp->bc->fac_out.u.CDeflection.DeflectedToNumber, nr);
++#endif /* !defined(AST_MISDN_ENHANCEMENTS) */
++
++ /* Send message */
++ print_facility(&tmp->bc->fac_out, tmp->bc);
+ misdn_lib_send_event(tmp->bc, EVENT_FACILITY);
+ } else if (strstr(a->argv[3], "CFActivate")) {
+ if (a->argc < 7) {
+@@ -1709,31 +5211,135 @@
+
+ ast_verbose("Sending CFActivate Port:(%d) FromNr. (%s) to Nr. (%s)\n", port, served_nr, nr);
+
++#if defined(AST_MISDN_ENHANCEMENTS)
++ bc->fac_out.Function = Fac_ActivationDiversion;
++ bc->fac_out.u.ActivationDiversion.InvokeID = ++misdn_invoke_id;
++ bc->fac_out.u.ActivationDiversion.ComponentType = FacComponent_Invoke;
++ bc->fac_out.u.ActivationDiversion.Component.Invoke.BasicService = 0;/* allServices */
++ bc->fac_out.u.ActivationDiversion.Component.Invoke.Procedure = 0;/* cfu (Call Forward Unconditional) */
++ ast_copy_string((char *) bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.Number,
++ served_nr, sizeof(bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.Number));
++ bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.LengthOfNumber =
++ strlen((char *) bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.Number);
++ bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.Type = 0;/* unknown */
++ ast_copy_string((char *) bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Number,
++ nr, sizeof(bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Number));
++ bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.LengthOfNumber =
++ strlen((char *) bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Number);
++ bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Type = 0;/* unknown */
++ bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Subaddress.Length = 0;
++
++#else /* !defined(AST_MISDN_ENHANCEMENTS) */
++
+ bc->fac_out.Function = Fac_CFActivate;
+ bc->fac_out.u.CFActivate.BasicService = 0; /* All Services */
+ bc->fac_out.u.CFActivate.Procedure = 0; /* Unconditional */
+- ast_copy_string((char *)bc->fac_out.u.CFActivate.ServedUserNumber, served_nr, sizeof(bc->fac_out.u.CFActivate.ServedUserNumber));
+- ast_copy_string((char *)bc->fac_out.u.CFActivate.ForwardedToNumber, nr, sizeof(bc->fac_out.u.CFActivate.ForwardedToNumber));
++ ast_copy_string((char *) bc->fac_out.u.CFActivate.ServedUserNumber, served_nr, sizeof(bc->fac_out.u.CFActivate.ServedUserNumber));
++ ast_copy_string((char *) bc->fac_out.u.CFActivate.ForwardedToNumber, nr, sizeof(bc->fac_out.u.CFActivate.ForwardedToNumber));
++#endif /* !defined(AST_MISDN_ENHANCEMENTS) */
+
++ /* Send message */
++ print_facility(&bc->fac_out, bc);
+ misdn_lib_send_event(bc, EVENT_FACILITY);
+ } else if (strstr(a->argv[3], "CFDeactivate")) {
+-
+ if (a->argc < 6) {
+- ast_verbose("CFActivate requires 1 arg: FromNumber\n\n");
++ ast_verbose("CFDeactivate requires 1 arg: FromNumber\n\n");
+ return 0;
+ }
+ port = atoi(a->argv[4]);
+ served_nr = a->argv[5];
+-
++
+ misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
+ ast_verbose("Sending CFDeactivate Port:(%d) FromNr. (%s)\n", port, served_nr);
+
++#if defined(AST_MISDN_ENHANCEMENTS)
++ bc->fac_out.Function = Fac_DeactivationDiversion;
++ bc->fac_out.u.DeactivationDiversion.InvokeID = ++misdn_invoke_id;
++ bc->fac_out.u.DeactivationDiversion.ComponentType = FacComponent_Invoke;
++ bc->fac_out.u.DeactivationDiversion.Component.Invoke.BasicService = 0;/* allServices */
++ bc->fac_out.u.DeactivationDiversion.Component.Invoke.Procedure = 0;/* cfu (Call Forward Unconditional) */
++ ast_copy_string((char *) bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.Number,
++ served_nr, sizeof(bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.Number));
++ bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.LengthOfNumber =
++ strlen((char *) bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.Number);
++ bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.Type = 0;/* unknown */
++
++#else /* !defined(AST_MISDN_ENHANCEMENTS) */
++
+ bc->fac_out.Function = Fac_CFDeactivate;
+- bc->fac_out.u.CFDeactivate.BasicService = 0; //All Services
+- bc->fac_out.u.CFDeactivate.Procedure = 0; //Unconditional
+-
+- ast_copy_string((char *)bc->fac_out.u.CFActivate.ServedUserNumber, served_nr, sizeof(bc->fac_out.u.CFActivate.ServedUserNumber));
++ bc->fac_out.u.CFDeactivate.BasicService = 0; /* All Services */
++ bc->fac_out.u.CFDeactivate.Procedure = 0; /* Unconditional */
++ ast_copy_string((char *) bc->fac_out.u.CFActivate.ServedUserNumber, served_nr, sizeof(bc->fac_out.u.CFActivate.ServedUserNumber));
++#endif /* !defined(AST_MISDN_ENHANCEMENTS) */
++
++ /* Send message */
++ print_facility(&bc->fac_out, bc);
+ misdn_lib_send_event(bc, EVENT_FACILITY);
++#if defined(AST_MISDN_ENHANCEMENTS) && defined(CCBS_TEST_MESSAGES)
++ } else if (strstr(a->argv[3], "test")) {
++ int msg_number;
++
++ if (a->argc < 5) {
++ ast_verbose("test (<port> [<msg#>]) | (<channel-name> <msg#>)\n\n");
++ return 0;
++ }
++ port = atoi(a->argv[4]);
++
++ channame = argv[4];
++ tmp = get_chan_by_ast_name(channame);
++ if (tmp) {
++ /* We are going to send this FACILITY message out on an existing connection */
++ msg_number = atoi(argv[5]);
++ if (msg_number < ARRAY_LEN(Fac_Msgs)) {
++ tmp->bc->fac_out = Fac_Msgs[msg_number];
++
++ /* Send message */
++ print_facility(&tmp->bc->fac_out, tmp->bc);
++ misdn_lib_send_event(tmp->bc, EVENT_FACILITY);
++ } else {
++ ast_verbose("test <channel-name> <msg#>\n\n");
++ }
++ } else if (a->argc < 6) {
++ for (msg_number = 0; msg_number < ARRAY_LEN(Fac_Msgs); ++msg_number) {
++ misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
++ bc->fac_out = Fac_Msgs[msg_number];
++
++ /* Send message */
++ print_facility(&bc->fac_out, bc);
++ misdn_lib_send_event(bc, EVENT_FACILITY);
++ sleep(1);
++ }
++ } else {
++ msg_number = atoi(a->argv[5]);
++ if (msg_number < ARRAY_LEN(Fac_Msgs)) {
++ misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
++ bc->fac_out = Fac_Msgs[msg_number];
++
++ /* Send message */
++ print_facility(&bc->fac_out, bc);
++ misdn_lib_send_event(bc, EVENT_FACILITY);
++ } else {
++ ast_verbose("test <port> [<msg#>]\n\n");
++ }
++ }
++ } else if (strstr(argv[3], "register")) {
++ if (argc < 5) {
++ ast_cli(fd, "register <port>\n\n");
++ return 0;
++ }
++ port = atoi(argv[4]);
++
++ bc = misdn_lib_get_register_bc(port);
++ if (!bc) {
++ ast_cli(fd, "Could not allocate REGISTER bc struct\n\n");
++ return 0;
++ }
++ bc->fac_out = Fac_Msgs[45];
++
++ /* Send message */
++ print_facility(&bc->fac_out, bc);
++ misdn_lib_send_event(bc, EVENT_REGISTER);
++#endif /* defined(AST_MISDN_ENHANCEMENTS) && defined(CCBS_TEST_MESSAGES) */
+ }
+
+ return CLI_SUCCESS;
+@@ -1773,8 +5379,8 @@
+
+ static char *handle_cli_misdn_send_digit(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+ {
+- char *channame;
+- char *msg;
++ const char *channame;
++ const char *msg;
+ struct chan_list *tmp;
+ int i, msglen;
+
+@@ -1803,7 +5409,7 @@
+ tmp = get_chan_by_ast_name(channame);
+ if (!tmp) {
+ ast_cli(a->fd, "Sending %s to %s failed Channel does not exist\n", msg, channame);
+- return CLI_SUCCESS;
++ return CLI_SUCCESS;
+ }
+ #if 1
+ for (i = 0; i < msglen; i++) {
+@@ -1822,7 +5428,7 @@
+
+ static char *handle_cli_misdn_toggle_echocancel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+ {
+- char *channame;
++ const char *channame;
+ struct chan_list *tmp;
+
+ switch (cmd) {
+@@ -1841,9 +5447,9 @@
+ }
+
+ channame = a->argv[3];
+-
++
+ ast_cli(a->fd, "Toggling EchoCancel on %s\n", channame);
+-
++
+ tmp = get_chan_by_ast_name(channame);
+ if (!tmp) {
+ ast_cli(a->fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
+@@ -1868,8 +5474,8 @@
+
+ static char *handle_cli_misdn_send_display(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+ {
+- char *channame;
+- char *msg;
++ const char *channame;
++ const char *msg;
+ struct chan_list *tmp;
+
+ switch (cmd) {
+@@ -1893,7 +5499,7 @@
+
+ ast_cli(a->fd, "Sending %s to %s\n", msg, channame);
+ tmp = get_chan_by_ast_name(channame);
+-
++
+ if (tmp && tmp->bc) {
+ ast_copy_string(tmp->bc->display, msg, sizeof(tmp->bc->display));
+ misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
+@@ -1986,6 +5592,7 @@
+ }
+
+ static struct ast_cli_entry chan_misdn_clis[] = {
++/* *INDENT-OFF* */
+ AST_CLI_DEFINE(handle_cli_misdn_port_block, "Block the given port"),
+ AST_CLI_DEFINE(handle_cli_misdn_port_down, "Try to deactivate the L1 on the given port"),
+ AST_CLI_DEFINE(handle_cli_misdn_port_unblock, "Unblock the given port"),
+@@ -2007,26 +5614,29 @@
+ AST_CLI_DEFINE(handle_cli_misdn_set_debug, "Set Debuglevel of chan_misdn"),
+ AST_CLI_DEFINE(handle_cli_misdn_set_tics, "???"),
+ AST_CLI_DEFINE(handle_cli_misdn_toggle_echocancel, "Toggle EchoCancel on mISDN Channel"),
++/* *INDENT-ON* */
+ };
+
+ /*! \brief Updates caller ID information from config */
+-static int update_config(struct chan_list *ch, int orig)
++static void update_config(struct chan_list *ch)
+ {
+ struct ast_channel *ast;
+ struct misdn_bchannel *bc;
+- int port, hdlc = 0;
+- int pres, screen;
++ int port;
++ int hdlc = 0;
++ int pres;
++ int screen;
+
+ if (!ch) {
+ ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
+- return -1;
++ return;
+ }
+
+ ast = ch->ast;
+ bc = ch->bc;
+ if (! ast || ! bc) {
+ ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
+- return -1;
++ return;
+ }
+
+ port = bc->port;
+@@ -2034,7 +5644,6 @@
+ chan_misdn_log(7, port, "update_config: Getting Config\n");
+
+ misdn_cfg_get(port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
+-
+ if (hdlc) {
+ switch (bc->capability) {
+ case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
+@@ -2049,63 +5658,33 @@
+ misdn_cfg_get(port, MISDN_CFG_PRES, &pres, sizeof(pres));
+ misdn_cfg_get(port, MISDN_CFG_SCREEN, &screen, sizeof(screen));
+ chan_misdn_log(2, port, " --> pres: %d screen: %d\n", pres, screen);
+-
++
+ if (pres < 0 || screen < 0) {
+- chan_misdn_log(2, port, " --> pres: %x\n", ast->cid.cid_pres);
+-
+- switch (ast->cid.cid_pres & 0x60) {
+- case AST_PRES_RESTRICTED:
+- bc->pres = 1;
+- chan_misdn_log(2, port, " --> PRES: Restricted (1)\n");
+- break;
+- case AST_PRES_UNAVAILABLE:
+- bc->pres = 2;
+- chan_misdn_log(2, port, " --> PRES: Unavailable (2)\n");
+- break;
+- default:
+- bc->pres = 0;
+- chan_misdn_log(2, port, " --> PRES: Allowed (0)\n");
+- break;
+- }
++ chan_misdn_log(2, port, " --> pres: %x\n", ast->connected.id.number_presentation);
+
+- switch (ast->cid.cid_pres & 0x3) {
+- default:
+- case AST_PRES_USER_NUMBER_UNSCREENED:
+- bc->screen = 0;
+- chan_misdn_log(2, port, " --> SCREEN: Unscreened (0)\n");
+- break;
+- case AST_PRES_USER_NUMBER_PASSED_SCREEN:
+- bc->screen = 1;
+- chan_misdn_log(2, port, " --> SCREEN: Passed Screen (1)\n");
+- break;
+- case AST_PRES_USER_NUMBER_FAILED_SCREEN:
+- bc->screen = 2;
+- chan_misdn_log(2, port, " --> SCREEN: Failed Screen (2)\n");
+- break;
+- case AST_PRES_NETWORK_NUMBER:
+- bc->screen = 3;
+- chan_misdn_log(2, port, " --> SCREEN: Network Nr. (3)\n");
+- break;
+- }
++ bc->caller.presentation = ast_to_misdn_pres(ast->connected.id.number_presentation);
++ chan_misdn_log(2, port, " --> PRES: %s(%d)\n", misdn_to_str_pres(bc->caller.presentation), bc->caller.presentation);
++
++ bc->caller.screening = ast_to_misdn_screen(ast->connected.id.number_presentation);
++ chan_misdn_log(2, port, " --> SCREEN: %s(%d)\n", misdn_to_str_screen(bc->caller.screening), bc->caller.screening);
+ } else {
+- bc->screen = screen;
+- bc->pres = pres;
++ bc->caller.screening = screen;
++ bc->caller.presentation = pres;
+ }
+-
+- return 0;
+ }
+
+
+ static void config_jitterbuffer(struct chan_list *ch)
+ {
+ struct misdn_bchannel *bc = ch->bc;
+- int len = ch->jb_len, threshold = ch->jb_upper_threshold;
+-
++ int len = ch->jb_len;
++ int threshold = ch->jb_upper_threshold;
++
+ chan_misdn_log(5, bc->port, "config_jb: Called\n");
+-
+- if (! len) {
++
++ if (!len) {
+ chan_misdn_log(1, bc->port, "config_jb: Deactivating Jitterbuffer\n");
+- bc->nojitter=1;
++ bc->nojitter = 1;
+ } else {
+ if (len <= 100 || len > 8000) {
+ chan_misdn_log(0, bc->port, "config_jb: Jitterbuffer out of Bounds, setting to 1000\n");
+@@ -2116,7 +5695,7 @@
+ chan_misdn_log(0, bc->port, "config_jb: Jitterbuffer Threshold > Jitterbuffer setting to Jitterbuffer -1\n");
+ }
+
+- if ( ch->jb) {
++ if (ch->jb) {
+ cb_log(0, bc->port, "config_jb: We've got a Jitterbuffer Already on this port.\n");
+ misdn_jb_destroy(ch->jb);
+ ch->jb = NULL;
+@@ -2131,20 +5710,26 @@
+ }
+
+
+-void debug_numplan(int port, int numplan, char *type)
++void debug_numtype(int port, int numtype, char *type)
+ {
+- switch (numplan) {
+- case NUMPLAN_INTERNATIONAL:
++ switch (numtype) {
++ case NUMTYPE_UNKNOWN:
++ chan_misdn_log(2, port, " --> %s: Unknown\n", type);
++ break;
++ case NUMTYPE_INTERNATIONAL:
+ chan_misdn_log(2, port, " --> %s: International\n", type);
+ break;
+- case NUMPLAN_NATIONAL:
++ case NUMTYPE_NATIONAL:
+ chan_misdn_log(2, port, " --> %s: National\n", type);
+ break;
+- case NUMPLAN_SUBSCRIBER:
++ case NUMTYPE_NETWORK_SPECIFIC:
++ chan_misdn_log(2, port, " --> %s: Network Specific\n", type);
++ break;
++ case NUMTYPE_SUBSCRIBER:
+ chan_misdn_log(2, port, " --> %s: Subscriber\n", type);
+ break;
+- case NUMPLAN_UNKNOWN:
+- chan_misdn_log(2, port, " --> %s: Unknown\n", type);
++ case NUMTYPE_ABBREVIATED:
++ chan_misdn_log(2, port, " --> %s: Abbreviated\n", type);
+ break;
+ /* Maybe we should cut off the prefix if present ? */
+ default:
+@@ -2194,7 +5779,7 @@
+ #endif
+
+
+-static int read_config(struct chan_list *ch, int orig)
++static int read_config(struct chan_list *ch)
+ {
+ struct ast_channel *ast;
+ struct misdn_bchannel *bc;
+@@ -2218,7 +5803,7 @@
+ ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
+ return -1;
+ }
+-
++
+ port = bc->port;
+ chan_misdn_log(1, port, "read_config: Getting Config\n");
+
+@@ -2233,9 +5818,8 @@
+ misdn_cfg_get(port, MISDN_CFG_INCOMING_EARLY_AUDIO, &ch->incoming_early_audio, sizeof(ch->incoming_early_audio));
+
+ misdn_cfg_get(port, MISDN_CFG_SENDDTMF, &bc->send_dtmf, sizeof(bc->send_dtmf));
+-
++
+ misdn_cfg_get(port, MISDN_CFG_ASTDTMF, &ch->ast_dsp, sizeof(int));
+-
+ if (ch->ast_dsp) {
+ ch->ignore_dtmf = 1;
+ }
+@@ -2252,7 +5836,6 @@
+ misdn_cfg_get(port, MISDN_CFG_FAXDETECT, faxdetect, sizeof(faxdetect));
+
+ misdn_cfg_get(port, MISDN_CFG_HDLC, &hdlc, sizeof(hdlc));
+-
+ if (hdlc) {
+ switch (bc->capability) {
+ case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
+@@ -2261,7 +5844,7 @@
+ bc->hdlc = 1;
+ break;
+ }
+-
++
+ }
+ /*Initialize new Jitterbuffer*/
+ misdn_cfg_get(port, MISDN_CFG_JITTERBUFFER, &ch->jb_len, sizeof(ch->jb_len));
+@@ -2281,14 +5864,17 @@
+
+ misdn_cfg_get(bc->port, MISDN_CFG_EARLY_BCONNECT, &bc->early_bconnect, sizeof(bc->early_bconnect));
+
++ misdn_cfg_get(port, MISDN_CFG_DISPLAY_CONNECTED, &bc->display_connected, sizeof(bc->display_connected));
++ misdn_cfg_get(port, MISDN_CFG_DISPLAY_SETUP, &bc->display_setup, sizeof(bc->display_setup));
++ misdn_cfg_get(port, MISDN_CFG_OUTGOING_COLP, &bc->outgoing_colp, sizeof(bc->outgoing_colp));
++
+ misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
+ misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
+-
+ chan_misdn_log(5, port, " --> * CallGrp:%s PickupGrp:%s\n", ast_print_group(buf, sizeof(buf), cg), ast_print_group(buf2, sizeof(buf2), pg));
+ ast->pickupgroup = pg;
+ ast->callgroup = cg;
+-
+- if (orig == ORG_AST) {
++
++ if (ch->originator == ORG_AST) {
+ char callerid[BUFFERSIZE + 1];
+
+ /* ORIGINATOR Asterisk (outgoing call) */
+@@ -2301,87 +5887,53 @@
+
+ misdn_cfg_get(port, MISDN_CFG_CALLERID, callerid, sizeof(callerid));
+ if (!ast_strlen_zero(callerid)) {
+- chan_misdn_log(1, port, " --> * Setting Cid to %s\n", callerid);
+- ast_copy_string(bc->oad, callerid, sizeof(bc->oad));
++ char *cid_name = NULL;
++ char *cid_num = NULL;
++
++ ast_callerid_parse(callerid, &cid_name, &cid_num);
++ if (cid_name) {
++ ast_copy_string(bc->caller.name, cid_name, sizeof(bc->caller.name));
++ } else {
++ bc->caller.name[0] = '\0';
++ }
++ if (cid_num) {
++ ast_copy_string(bc->caller.number, cid_num, sizeof(bc->caller.number));
++ } else {
++ bc->caller.number[0] = '\0';
++ }
++ chan_misdn_log(1, port, " --> * Setting caller to \"%s\" <%s>\n", bc->caller.name, bc->caller.number);
+ }
+
+- misdn_cfg_get(port, MISDN_CFG_DIALPLAN, &bc->dnumplan, sizeof(bc->dnumplan));
+- misdn_cfg_get(port, MISDN_CFG_LOCALDIALPLAN, &bc->onumplan, sizeof(bc->onumplan));
+- misdn_cfg_get(port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(bc->cpnnumplan));
+- debug_numplan(port, bc->dnumplan, "TON");
+- debug_numplan(port, bc->onumplan, "LTON");
+- debug_numplan(port, bc->cpnnumplan, "CTON");
++ misdn_cfg_get(port, MISDN_CFG_DIALPLAN, &bc->dialed.number_type, sizeof(bc->dialed.number_type));
++ bc->dialed.number_plan = NUMPLAN_ISDN;
++ debug_numtype(port, bc->dialed.number_type, "TON");
+
+ ch->overlap_dial = 0;
+ } else {
+ /* ORIGINATOR MISDN (incoming call) */
+- char prefix[BUFFERSIZE + 1] = "";
+
+ if (strstr(faxdetect, "incoming") || strstr(faxdetect, "both")) {
+ ch->faxdetect = (strstr(faxdetect, "nojump")) ? 2 : 1;
+ }
+
+- misdn_cfg_get(port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(bc->cpnnumplan));
+- debug_numplan(port, bc->cpnnumplan, "CTON");
++ /* Add configured prefix to caller.number */
++ misdn_add_number_prefix(bc->port, bc->caller.number_type, bc->caller.number, sizeof(bc->caller.number));
+
+- switch (bc->onumplan) {
+- case NUMPLAN_INTERNATIONAL:
+- misdn_cfg_get(bc->port, MISDN_CFG_INTERNATPREFIX, prefix, sizeof(prefix));
+- break;
+-
+- case NUMPLAN_NATIONAL:
+- misdn_cfg_get(bc->port, MISDN_CFG_NATPREFIX, prefix, sizeof(prefix));
+- break;
+- default:
+- break;
++ if (ast_strlen_zero(bc->dialed.number) && !ast_strlen_zero(bc->keypad)) {
++ ast_copy_string(bc->dialed.number, bc->keypad, sizeof(bc->dialed.number));
+ }
+
+- ast_copy_string(buf, bc->oad, sizeof(buf));
+- snprintf(bc->oad, sizeof(bc->oad), "%s%s", prefix, buf);
++ /* Add configured prefix to dialed.number */
++ misdn_add_number_prefix(bc->port, bc->dialed.number_type, bc->dialed.number, sizeof(bc->dialed.number));
+
+- if (!ast_strlen_zero(bc->dad)) {
+- ast_copy_string(bc->orig_dad, bc->dad, sizeof(bc->orig_dad));
+- }
++ ast_copy_string(ast->exten, bc->dialed.number, sizeof(ast->exten));
+
+- if (ast_strlen_zero(bc->dad) && !ast_strlen_zero(bc->keypad)) {
+- ast_copy_string(bc->dad, bc->keypad, sizeof(bc->dad));
+- }
+-
+- prefix[0] = 0;
+-
+- switch (bc->dnumplan) {
+- case NUMPLAN_INTERNATIONAL:
+- misdn_cfg_get(bc->port, MISDN_CFG_INTERNATPREFIX, prefix, sizeof(prefix));
+- break;
+- case NUMPLAN_NATIONAL:
+- misdn_cfg_get(bc->port, MISDN_CFG_NATPREFIX, prefix, sizeof(prefix));
+- break;
+- default:
+- break;
+- }
+-
+- ast_copy_string(buf, bc->dad, sizeof(buf));
+- snprintf(bc->dad, sizeof(bc->dad), "%s%s", prefix, buf);
+-
+- if (strcmp(bc->dad, ast->exten)) {
+- ast_copy_string(ast->exten, bc->dad, sizeof(ast->exten));
+- }
+-
+- ast_set_callerid(ast, bc->oad, NULL, bc->oad);
+-
+- if ( !ast_strlen_zero(bc->rad) ) {
+- if (ast->cid.cid_rdnis) {
+- ast_free(ast->cid.cid_rdnis);
+- }
+- ast->cid.cid_rdnis = ast_strdup(bc->rad);
+- }
+-
+ misdn_cfg_get(bc->port, MISDN_CFG_OVERLAP_DIAL, &ch->overlap_dial, sizeof(ch->overlap_dial));
+ ast_mutex_init(&ch->overlap_tv_lock);
+ } /* ORIG MISDN END */
+
+ ch->overlap_dial_task = -1;
+-
++
+ if (ch->faxdetect || ch->ast_dsp) {
+ misdn_cfg_get(port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
+ if (!ch->dsp) {
+@@ -2401,7 +5953,289 @@
+ return 0;
+ }
+
++/*!
++ * \internal
++ * \brief Send a connected line update to the other channel
++ *
++ * \param ast Current Asterisk channel
++ * \param id Party id information to send to the other side
++ * \param source Why are we sending this update
++ *
++ * \return Nothing
++ */
++static void misdn_queue_connected_line_update(struct ast_channel *ast, const struct misdn_party_id *id, enum AST_CONNECTED_LINE_UPDATE_SOURCE source)
++{
++ struct ast_party_connected_line connected;
+
++ ast_party_connected_line_init(&connected);
++ connected.id.number = (char *) id->number;
++ connected.id.number_type = misdn_to_ast_ton(id->number_type)
++ | misdn_to_ast_plan(id->number_plan);
++ connected.id.number_presentation = misdn_to_ast_pres(id->presentation)
++ | misdn_to_ast_screen(id->screening);
++ connected.source = source;
++ ast_channel_queue_connected_line_update(ast, &connected);
++}
++
++/*!
++ * \internal
++ * \brief Get the connected line information out of the Asterisk channel.
++ *
++ * \param ast Current Asterisk channel
++ * \param bc Associated B channel
++ * \param originator Who originally created this channel. ORG_AST or ORG_MISDN
++ *
++ * \return Nothing
++ */
++static void misdn_get_connected_line(struct ast_channel *ast, struct misdn_bchannel *bc, int originator)
++{
++ int number_type;
++
++ if (originator == ORG_MISDN) {
++ /* ORIGINATOR MISDN (incoming call) */
++
++ ast_copy_string(bc->connected.name, S_OR(ast->connected.id.name, ""), sizeof(bc->connected.name));
++ ast_copy_string(bc->connected.number, S_OR(ast->connected.id.number, ""), sizeof(bc->connected.number));
++ bc->connected.presentation = ast_to_misdn_pres(ast->connected.id.number_presentation);
++ bc->connected.screening = ast_to_misdn_screen(ast->connected.id.number_presentation);
++
++ misdn_cfg_get(bc->port, MISDN_CFG_CPNDIALPLAN, &number_type, sizeof(number_type));
++ if (number_type < 0) {
++ bc->connected.number_type = ast_to_misdn_ton(ast->connected.id.number_type);
++ bc->connected.number_plan = ast_to_misdn_plan(ast->connected.id.number_type);
++ } else {
++ /* Force us to send in CONNECT message */
++ bc->connected.number_type = number_type;
++ bc->connected.number_plan = NUMPLAN_ISDN;
++ }
++ debug_numtype(bc->port, bc->connected.number_type, "CTON");
++ } else {
++ /* ORIGINATOR Asterisk (outgoing call) */
++
++ ast_copy_string(bc->caller.name, S_OR(ast->connected.id.name, ""), sizeof(bc->caller.name));
++ ast_copy_string(bc->caller.number, S_OR(ast->connected.id.number, ""), sizeof(bc->caller.number));
++ bc->caller.presentation = ast_to_misdn_pres(ast->connected.id.number_presentation);
++ bc->caller.screening = ast_to_misdn_screen(ast->connected.id.number_presentation);
++
++ misdn_cfg_get(bc->port, MISDN_CFG_LOCALDIALPLAN, &number_type, sizeof(number_type));
++ if (number_type < 0) {
++ bc->caller.number_type = ast_to_misdn_ton(ast->connected.id.number_type);
++ bc->caller.number_plan = ast_to_misdn_plan(ast->connected.id.number_type);
++ } else {
++ /* Force us to send in SETUP message */
++ bc->caller.number_type = number_type;
++ bc->caller.number_plan = NUMPLAN_ISDN;
++ }
++ debug_numtype(bc->port, bc->caller.number_type, "LTON");
++ }
++}
++
++/*!
++ * \internal
++ * \brief Notify peer that the connected line has changed.
++ *
++ * \param ast Current Asterisk channel
++ * \param bc Associated B channel
++ * \param originator Who originally created this channel. ORG_AST or ORG_MISDN
++ *
++ * \return Nothing
++ */
++static void misdn_update_connected_line(struct ast_channel *ast, struct misdn_bchannel *bc, int originator)
++{
++ struct chan_list *ch;
++
++ misdn_get_connected_line(ast, bc, originator);
++ if (originator == ORG_MISDN) {
++ bc->redirecting.to = bc->connected;
++ } else {
++ bc->redirecting.to = bc->caller;
++ }
++ switch (bc->outgoing_colp) {
++ case 1:/* restricted */
++ case 2:/* blocked */
++ bc->redirecting.to.presentation = 1;/* restricted */
++ break;
++ default:
++ break;
++ }
++
++ ch = MISDN_ASTERISK_TECH_PVT(ast);
++ if (ch->state == MISDN_CONNECTED
++ || originator != ORG_MISDN) {
++ int is_ptmp;
++
++ is_ptmp = !misdn_lib_is_ptp(bc->port);
++ if (is_ptmp) {
++ /* Send NOTIFY(transfer-active, redirecting.to data) */
++ bc->redirecting.to_changed = 1;
++ bc->notify_description_code = mISDN_NOTIFY_CODE_CALL_TRANSFER_ACTIVE;
++ misdn_lib_send_event(bc, EVENT_NOTIFY);
++#if defined(AST_MISDN_ENHANCEMENTS)
++ } else {
++ /* Send EctInform(transfer-active, redirecting.to data) */
++ bc->fac_out.Function = Fac_EctInform;
++ bc->fac_out.u.EctInform.InvokeID = ++misdn_invoke_id;
++ bc->fac_out.u.EctInform.Status = 1;/* active */
++ bc->fac_out.u.EctInform.RedirectionPresent = 1;/* Must be present when status is active */
++ misdn_PresentedNumberUnscreened_fill(&bc->fac_out.u.EctInform.Redirection,
++ &bc->redirecting.to);
++ switch (bc->outgoing_colp) {
++ case 2:/* blocked */
++ /* Block the number going out */
++ bc->fac_out.u.EctInform.Redirection.Type = 1;/* presentationRestricted */
++ break;
++ default:
++ break;
++ }
++
++ /* Send message */
++ print_facility(&bc->fac_out, bc);
++ misdn_lib_send_event(bc, EVENT_FACILITY);
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++ }
++ }
++}
++
++/*!
++ * \internal
++ * \brief Copy the redirecting information out of the Asterisk channel
++ *
++ * \param bc Associated B channel
++ * \param ast Current Asterisk channel
++ *
++ * \return Nothing
++ */
++static void misdn_copy_redirecting_from_ast(struct misdn_bchannel *bc, struct ast_channel *ast)
++{
++ ast_copy_string(bc->redirecting.from.name, S_OR(ast->redirecting.from.name, ""), sizeof(bc->redirecting.from.name));
++ ast_copy_string(bc->redirecting.from.number, S_OR(ast->cid.cid_rdnis, ""), sizeof(bc->redirecting.from.number));
++ bc->redirecting.from.presentation = ast_to_misdn_pres(ast->redirecting.from.number_presentation);
++ bc->redirecting.from.screening = ast_to_misdn_screen(ast->redirecting.from.number_presentation);
++ bc->redirecting.from.number_type = ast_to_misdn_ton(ast->redirecting.from.number_type);
++ bc->redirecting.from.number_plan = ast_to_misdn_plan(ast->redirecting.from.number_type);
++
++ ast_copy_string(bc->redirecting.to.name, S_OR(ast->redirecting.to.name, ""), sizeof(bc->redirecting.to.name));
++ ast_copy_string(bc->redirecting.to.number, S_OR(ast->redirecting.to.number, ""), sizeof(bc->redirecting.to.number));
++ bc->redirecting.to.presentation = ast_to_misdn_pres(ast->redirecting.to.number_presentation);
++ bc->redirecting.to.screening = ast_to_misdn_screen(ast->redirecting.to.number_presentation);
++ bc->redirecting.to.number_type = ast_to_misdn_ton(ast->redirecting.to.number_type);
++ bc->redirecting.to.number_plan = ast_to_misdn_plan(ast->redirecting.to.number_type);
++
++ bc->redirecting.reason = ast_to_misdn_reason(ast->redirecting.reason);
++ bc->redirecting.count = ast->redirecting.count;
++}
++
++/*!
++ * \internal
++ * \brief Copy the redirecting info into the Asterisk channel
++ *
++ * \param ast Current Asterisk channel
++ * \param redirect Associated B channel redirecting info
++ *
++ * \return Nothing
++ */
++static void misdn_copy_redirecting_to_ast(struct ast_channel *ast, const struct misdn_party_redirecting *redirect)
++{
++ struct ast_party_redirecting redirecting;
++
++ ast_party_redirecting_set_init(&redirecting, &ast->redirecting);
++
++ redirecting.from.number = (char *) redirect->from.number;
++ redirecting.from.number_type =
++ misdn_to_ast_ton(redirect->from.number_type)
++ | misdn_to_ast_plan(redirect->from.number_plan);
++ redirecting.from.number_presentation =
++ misdn_to_ast_pres(redirect->from.presentation)
++ | misdn_to_ast_screen(redirect->from.screening);
++
++ redirecting.to.number = (char *) redirect->to.number;
++ redirecting.to.number_type =
++ misdn_to_ast_ton(redirect->to.number_type)
++ | misdn_to_ast_plan(redirect->to.number_plan);
++ redirecting.to.number_presentation =
++ misdn_to_ast_pres(redirect->to.presentation)
++ | misdn_to_ast_screen(redirect->to.screening);
++
++ redirecting.reason = misdn_to_ast_reason(redirect->reason);
++ redirecting.count = redirect->count;
++
++ ast_channel_set_redirecting(ast, &redirecting);
++}
++
++/*!
++ * \internal
++ * \brief Notify peer that the redirecting information has changed.
++ *
++ * \param ast Current Asterisk channel
++ * \param bc Associated B channel
++ * \param originator Who originally created this channel. ORG_AST or ORG_MISDN
++ *
++ * \return Nothing
++ */
++static void misdn_update_redirecting(struct ast_channel *ast, struct misdn_bchannel *bc, int originator)
++{
++ int is_ptmp;
++
++ misdn_copy_redirecting_from_ast(bc, ast);
++ switch (bc->outgoing_colp) {
++ case 1:/* restricted */
++ case 2:/* blocked */
++ bc->redirecting.to.presentation = 1;/* restricted */
++ break;
++ default:
++ break;
++ }
++
++ if (originator != ORG_MISDN) {
++ return;
++ }
++
++ is_ptmp = !misdn_lib_is_ptp(bc->port);
++ if (is_ptmp) {
++ /* Send NOTIFY(call-is-diverting, redirecting.to data) */
++ bc->redirecting.to_changed = 1;
++ bc->notify_description_code = mISDN_NOTIFY_CODE_CALL_IS_DIVERTING;
++ misdn_lib_send_event(bc, EVENT_NOTIFY);
++#if defined(AST_MISDN_ENHANCEMENTS)
++ } else {
++ int match; /* TRUE if the dialed number matches the redirecting to number */
++
++ match = (strcmp(ast->exten, bc->redirecting.to.number) == 0) ? 1 : 0;
++ if (!bc->div_leg_3_tx_pending
++ || !match) {
++ /* Send DivertingLegInformation1 */
++ bc->fac_out.Function = Fac_DivertingLegInformation1;
++ bc->fac_out.u.DivertingLegInformation1.InvokeID = ++misdn_invoke_id;
++ bc->fac_out.u.DivertingLegInformation1.DiversionReason =
++ misdn_to_diversion_reason(bc->redirecting.reason);
++ bc->fac_out.u.DivertingLegInformation1.SubscriptionOption = 2;/* notificationWithDivertedToNr */
++ bc->fac_out.u.DivertingLegInformation1.DivertedToPresent = 1;
++ misdn_PresentedNumberUnscreened_fill(&bc->fac_out.u.DivertingLegInformation1.DivertedTo, &bc->redirecting.to);
++ switch (bc->outgoing_colp) {
++ case 2:/* blocked */
++ /* Block the number going out */
++ bc->fac_out.u.DivertingLegInformation1.DivertedTo.Type = 1;/* presentationRestricted */
++ break;
++ default:
++ break;
++ }
++ print_facility(&bc->fac_out, bc);
++ misdn_lib_send_event(bc, EVENT_FACILITY);
++ }
++ bc->div_leg_3_tx_pending = 0;
++
++ /* Send DivertingLegInformation3 */
++ bc->fac_out.Function = Fac_DivertingLegInformation3;
++ bc->fac_out.u.DivertingLegInformation3.InvokeID = ++misdn_invoke_id;
++ bc->fac_out.u.DivertingLegInformation3.PresentationAllowedIndicator =
++ bc->redirecting.to.presentation == 0 ? 1 : 0;
++ print_facility(&bc->fac_out, bc);
++ misdn_lib_send_event(bc, EVENT_FACILITY);
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++ }
++}
++
++
+ /*****************************/
+ /*** AST Indications Start ***/
+ /*****************************/
+@@ -2412,22 +6246,17 @@
+ int r;
+ int exceed;
+ int bridging;
+- struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(ast);
++ int number_type;
++ struct chan_list *ch;
+ struct misdn_bchannel *newbc;
+- char *dest_cp = ast_strdupa(dest);
++ char *dest_cp;
++
+ AST_DECLARE_APP_ARGS(args,
+- AST_APP_ARG(type);
+- AST_APP_ARG(ext);
+- AST_APP_ARG(opts);
++ AST_APP_ARG(intf); /* The interface token is discarded. */
++ AST_APP_ARG(ext); /* extension token */
++ AST_APP_ARG(opts); /* options token */
+ );
+
+- AST_NONSTANDARD_APP_ARGS(args, dest_cp, '/');
+-
+- if (ast_strlen_zero(args.ext)) {
+- chan_misdn_log(0, 0, "misdn_call: No Extension given!\n");
+- return -1;
+- }
+-
+ if (!ast) {
+ ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n");
+ return -1;
+@@ -2440,87 +6269,212 @@
+ return -1;
+ }
+
++ ch = MISDN_ASTERISK_TECH_PVT(ast);
+ if (!ch) {
+- ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
++ ast_log(LOG_WARNING, " --> ! misdn_call called on %s, chan_list *ch==NULL\n", ast->name);
+ ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
+ ast_setstate(ast, AST_STATE_DOWN);
+ return -1;
+ }
+-
++
+ newbc = ch->bc;
+-
+ if (!newbc) {
+- ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
++ ast_log(LOG_WARNING, " --> ! misdn_call called on %s, newbc==NULL\n", ast->name);
+ ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
+ ast_setstate(ast, AST_STATE_DOWN);
+ return -1;
+ }
+-
++
+ port = newbc->port;
+
+- if ((exceed = add_out_calls(port))) {
+- char tmp[16];
+- snprintf(tmp, sizeof(tmp), "%d", exceed);
+- pbx_builtin_setvar_helper(ast, "MAX_OVERFLOW", tmp);
+- return -1;
++#if defined(AST_MISDN_ENHANCEMENTS)
++ if ((ch->peer = misdn_cc_caller_get(ast))) {
++ chan_misdn_log(3, port, " --> Found CC caller data, peer:%s\n",
++ ch->peer->chan ? "available" : "NULL");
+ }
+-
+- chan_misdn_log(1, port, "* CALL: %s\n", dest);
+-
+- chan_misdn_log(2, port, " --> * dad:%s tech:%s ctx:%s\n", ast->exten, ast->name, ast->context);
+-
+- chan_misdn_log(3, port, " --> * adding2newbc ext %s\n", ast->exten);
+- if (ast->exten) {
++
++ if (ch->record_id != -1) {
++ struct misdn_cc_record *cc_record;
++
++ /* This is a call completion retry call */
++ AST_LIST_LOCK(&misdn_cc_records_db);
++ cc_record = misdn_cc_find_by_id(ch->record_id);
++ if (!cc_record) {
++ AST_LIST_UNLOCK(&misdn_cc_records_db);
++ ast_log(LOG_WARNING, " --> ! misdn_call called on %s, cc_record==NULL\n", ast->name);
++ ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
++ ast_setstate(ast, AST_STATE_DOWN);
++ return -1;
++ }
++
++ /* Setup calling parameters to retry the call. */
++ newbc->dialed = cc_record->redial.dialed;
++ newbc->caller = cc_record->redial.caller;
++ memset(&newbc->redirecting, 0, sizeof(newbc->redirecting));
++ newbc->capability = cc_record->redial.capability;
++ newbc->hdlc = cc_record->redial.hdlc;
++ newbc->sending_complete = 1;
++
++ if (cc_record->ptp) {
++ newbc->fac_out.Function = Fac_CCBS_T_Call;
++ newbc->fac_out.u.CCBS_T_Call.InvokeID = ++misdn_invoke_id;
++ } else {
++ newbc->fac_out.Function = Fac_CCBSCall;
++ newbc->fac_out.u.CCBSCall.InvokeID = ++misdn_invoke_id;
++ newbc->fac_out.u.CCBSCall.CCBSReference = cc_record->mode.ptmp.reference_id;
++ }
++ AST_LIST_UNLOCK(&misdn_cc_records_db);
++
++ ast_copy_string(ast->exten, newbc->dialed.number, sizeof(ast->exten));
++
++ chan_misdn_log(1, port, "* Call completion to: %s\n", newbc->dialed.number);
++ chan_misdn_log(2, port, " --> * tech:%s context:%s\n", ast->name, ast->context);
++ } else
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++ {
++ /*
++ * dest is ---v
++ * Dial(mISDN/g:group_name[/extension[/options]])
++ * Dial(mISDN/port[:preselected_channel][/extension[/options]])
++ *
++ * The dial extension could be empty if you are using MISDN_KEYPAD
++ * to control ISDN provider features.
++ */
++ dest_cp = ast_strdupa(dest);
++ AST_NONSTANDARD_APP_ARGS(args, dest_cp, '/');
++ if (!args.ext) {
++ args.ext = "";
++ }
++
++ chan_misdn_log(1, port, "* CALL: %s\n", dest);
++ chan_misdn_log(2, port, " --> * dialed:%s tech:%s context:%s\n", args.ext, ast->name, ast->context);
++
+ ast_copy_string(ast->exten, args.ext, sizeof(ast->exten));
+- ast_copy_string(newbc->dad, args.ext, sizeof(newbc->dad));
+- }
++ ast_copy_string(newbc->dialed.number, args.ext, sizeof(newbc->dialed.number));
+
+- ast_copy_string(newbc->rad, S_OR(ast->cid.cid_rdnis, ""), sizeof(newbc->rad));
++ if (ast_strlen_zero(newbc->caller.name) && !ast_strlen_zero(ast->connected.id.name)) {
++ ast_copy_string(newbc->caller.name, ast->connected.id.name, sizeof(newbc->caller.name));
++ chan_misdn_log(3, port, " --> * set caller:\"%s\" <%s>\n", newbc->caller.name, newbc->caller.number);
++ }
++ if (ast_strlen_zero(newbc->caller.number) && !ast_strlen_zero(ast->connected.id.number)) {
++ ast_copy_string(newbc->caller.number, ast->connected.id.number, sizeof(newbc->caller.number));
++ chan_misdn_log(3, port, " --> * set caller:\"%s\" <%s>\n", newbc->caller.name, newbc->caller.number);
++ }
+
+- chan_misdn_log(3, port, " --> * adding2newbc callerid %s\n", ast->cid.cid_num);
+- if (ast_strlen_zero(newbc->oad) && !ast_strlen_zero(ast->cid.cid_num)) {
+- ast_copy_string(newbc->oad, ast->cid.cid_num, sizeof(newbc->oad));
+- }
++ misdn_cfg_get(port, MISDN_CFG_LOCALDIALPLAN, &number_type, sizeof(number_type));
++ if (number_type < 0) {
++ newbc->caller.number_type = ast_to_misdn_ton(ast->connected.id.number_type);
++ newbc->caller.number_plan = ast_to_misdn_plan(ast->connected.id.number_type);
++ } else {
++ /* Force us to send in SETUP message */
++ newbc->caller.number_type = number_type;
++ newbc->caller.number_plan = NUMPLAN_ISDN;
++ }
++ debug_numtype(port, newbc->caller.number_type, "LTON");
+
+- newbc->capability = ast->transfercapability;
+- pbx_builtin_setvar_helper(ast, "TRANSFERCAPABILITY", ast_transfercapability2str(newbc->capability));
+- if ( ast->transfercapability == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) {
+- chan_misdn_log(2, port, " --> * Call with flag Digital\n");
+- }
++ newbc->capability = ast->transfercapability;
++ pbx_builtin_setvar_helper(ast, "TRANSFERCAPABILITY", ast_transfercapability2str(newbc->capability));
++ if (ast->transfercapability == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) {
++ chan_misdn_log(2, port, " --> * Call with flag Digital\n");
++ }
+
+- /* update screening and presentation */
+- update_config(ch, ORG_AST);
+-
+- /* fill in some ies from channel vary */
+- import_ch(ast, newbc, ch);
++ /* update caller screening and presentation */
++ update_config(ch);
+
+- /* Finally The Options Override Everything */
+- if (!ast_strlen_zero(args.opts)) {
+- misdn_set_opt_exec(ast, args.opts);
+- } else {
+- chan_misdn_log(2, port, "NO OPTS GIVEN\n");
+- }
++ /* fill in some ies from channel dialplan variables */
++ import_ch(ast, newbc, ch);
+
+- /*check for bridging*/
+- misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
+- if (bridging && ch->other_ch) {
++ /* Finally The Options Override Everything */
++ if (!ast_strlen_zero(args.opts)) {
++ misdn_set_opt_exec(ast, args.opts);
++ } else {
++ chan_misdn_log(2, port, "NO OPTS GIVEN\n");
++ }
++ if (newbc->set_presentation) {
++ newbc->caller.presentation = newbc->presentation;
++ }
++
++ misdn_copy_redirecting_from_ast(newbc, ast);
++ switch (newbc->outgoing_colp) {
++ case 1:/* restricted */
++ case 2:/* blocked */
++ newbc->redirecting.from.presentation = 1;/* restricted */
++ break;
++ default:
++ break;
++ }
++#if defined(AST_MISDN_ENHANCEMENTS)
++ if (newbc->redirecting.from.number[0] && misdn_lib_is_ptp(port)) {
++ /* Create DivertingLegInformation2 facility */
++ newbc->fac_out.Function = Fac_DivertingLegInformation2;
++ newbc->fac_out.u.DivertingLegInformation2.InvokeID = ++misdn_invoke_id;
++ newbc->fac_out.u.DivertingLegInformation2.DiversionCounter =
++ newbc->redirecting.count;
++ newbc->fac_out.u.DivertingLegInformation2.DiversionReason =
++ misdn_to_diversion_reason(newbc->redirecting.reason);
++ newbc->fac_out.u.DivertingLegInformation2.DivertingPresent = 1;
++ misdn_PresentedNumberUnscreened_fill(
++ &newbc->fac_out.u.DivertingLegInformation2.Diverting,
++ &newbc->redirecting.from);
++ switch (newbc->outgoing_colp) {
++ case 2:/* blocked */
++ /* Block the number going out */
++ newbc->fac_out.u.DivertingLegInformation2.Diverting.Type = 1;/* presentationRestricted */
++ break;
++ default:
++ break;
++ }
++ newbc->fac_out.u.DivertingLegInformation2.OriginalCalledPresent = 0;
++ if (1 < newbc->redirecting.count) {
++ newbc->fac_out.u.DivertingLegInformation2.OriginalCalledPresent = 1;
++ newbc->fac_out.u.DivertingLegInformation2.OriginalCalled.Type = 2;/* numberNotAvailableDueToInterworking */
++ }
++
++ /*
++ * Expect a DivertingLegInformation3 to update the COLR of the
++ * redirecting-to party we are attempting to call now.
++ */
++ newbc->div_leg_3_rx_wanted = 1;
++ }
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++ /*check for bridging*/
++ misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
++ if (bridging && ch->other_ch) {
+ #ifdef MISDN_1_2
+- chan_misdn_log(1, port, "Disabling EC (aka Pipeline) on both Sides\n");
+- *ch->bc->pipeline = 0;
+- *ch->other_ch->bc->pipeline = 0;
++ chan_misdn_log(1, port, "Disabling EC (aka Pipeline) on both Sides\n");
++ *ch->bc->pipeline = 0;
++ *ch->other_ch->bc->pipeline = 0;
+ #else
+- chan_misdn_log(1, port, "Disabling EC on both Sides\n");
+- ch->bc->ec_enable = 0;
+- ch->other_ch->bc->ec_enable = 0;
++ chan_misdn_log(1, port, "Disabling EC on both Sides\n");
++ ch->bc->ec_enable = 0;
++ ch->other_ch->bc->ec_enable = 0;
+ #endif
++ }
+ }
+
++ exceed = add_out_calls(port);
++ if (exceed != 0) {
++ char tmp[16];
++
++ snprintf(tmp, sizeof(tmp), "%d", exceed);
++ pbx_builtin_setvar_helper(ast, "MAX_OVERFLOW", tmp);
++ ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
++ ast_setstate(ast, AST_STATE_DOWN);
++ return -1;
++ }
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++ if (newbc->fac_out.Function != Fac_None) {
++ print_facility(&newbc->fac_out, newbc);
++ }
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
+ r = misdn_lib_send_event(newbc, EVENT_SETUP);
+
+ /** we should have l3id after sending setup **/
+ ch->l3id = newbc->l3_id;
+
+- if (r == -ENOCHAN ) {
++ if (r == -ENOCHAN) {
+ chan_misdn_log(0, port, " --> * Theres no Channel at the moment .. !\n");
+ chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n", newbc ? newbc->pid : -1);
+ ast->hangupcause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION;
+@@ -2538,8 +6492,8 @@
+ }
+
+ ch->state = MISDN_CALLING;
+-
+- return 0;
++
++ return 0;
+ }
+
+
+@@ -2551,9 +6505,9 @@
+ if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) {
+ return -1;
+ }
+-
++
+ chan_misdn_log(1, p ? (p->bc ? p->bc->port : 0) : 0, "* ANSWER:\n");
+-
++
+ if (!p) {
+ ast_log(LOG_WARNING, " --> Channel not connected ??\n");
+ ast_queue_hangup_with_cause(ast, AST_CAUSE_NETWORK_OUT_OF_ORDER);
+@@ -2586,11 +6540,42 @@
+ p->state = MISDN_CONNECTED;
+ stop_indicate(p);
+
+- if ( ast_strlen_zero(p->bc->cad) ) {
+- chan_misdn_log(2, p->bc->port, " --> empty cad using dad\n");
+- ast_copy_string(p->bc->cad, p->bc->dad, sizeof(p->bc->cad));
++ if (ast_strlen_zero(p->bc->connected.number)) {
++ chan_misdn_log(2,p->bc->port," --> empty connected number using dialed number\n");
++ ast_copy_string(p->bc->connected.number, p->bc->dialed.number, sizeof(p->bc->connected.number));
++
++ /*
++ * Use the misdn_set_opt() application to set the presentation
++ * before we answer or you can use the CONECTEDLINE() function
++ * to set everything before using the Answer() application.
++ */
++ p->bc->connected.presentation = p->bc->presentation;
++ p->bc->connected.screening = 0; /* unscreened */
++ p->bc->connected.number_type = p->bc->dialed.number_type;
++ p->bc->connected.number_plan = p->bc->dialed.number_plan;
+ }
+
++ switch (p->bc->outgoing_colp) {
++ case 1:/* restricted */
++ case 2:/* blocked */
++ p->bc->connected.presentation = 1;/* restricted */
++ break;
++ default:
++ break;
++ }
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++ if (p->bc->div_leg_3_tx_pending) {
++ p->bc->div_leg_3_tx_pending = 0;
++
++ /* Send DivertingLegInformation3 */
++ p->bc->fac_out.Function = Fac_DivertingLegInformation3;
++ p->bc->fac_out.u.DivertingLegInformation3.InvokeID = ++misdn_invoke_id;
++ p->bc->fac_out.u.DivertingLegInformation3.PresentationAllowedIndicator =
++ (p->bc->connected.presentation == 0) ? 1 : 0;
++ print_facility(&p->bc->fac_out, p->bc);
++ }
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
+ misdn_lib_send_event(p->bc, EVENT_CONNECT);
+ start_bc_tones(p);
+
+@@ -2615,13 +6600,13 @@
+
+ bc = p->bc;
+ chan_misdn_log(1, bc ? bc->port : 0, "* IND : Digit %c\n", digit);
+-
++
+ if (!bc) {
+ ast_log(LOG_WARNING, " --> !! Got Digit Event without having bchannel Object\n");
+ return -1;
+ }
+-
+- switch (p->state ) {
++
++ switch (p->state) {
+ case MISDN_CALLING:
+ if (strlen(bc->infos_pending) < sizeof(bc->infos_pending) - 1) {
+ strncat(bc->infos_pending, buf, sizeof(bc->infos_pending) - strlen(bc->infos_pending) - 1);
+@@ -2629,15 +6614,15 @@
+ break;
+ case MISDN_CALLING_ACKNOWLEDGE:
+ ast_copy_string(bc->info_dad, buf, sizeof(bc->info_dad));
+- if (strlen(bc->dad) < sizeof(bc->dad) - 1) {
+- strncat(bc->dad, buf, sizeof(bc->dad) - strlen(bc->dad) - 1);
++ if (strlen(bc->dialed.number) < sizeof(bc->dialed.number) - 1) {
++ strncat(bc->dialed.number, buf, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
+ }
+- ast_copy_string(p->ast->exten, bc->dad, sizeof(p->ast->exten));
++ ast_copy_string(p->ast->exten, bc->dialed.number, sizeof(p->ast->exten));
+ misdn_lib_send_event(bc, EVENT_INFORMATION);
+ break;
+ default:
+ /* Do not send Digits in CONNECTED State, when
+- * the other side is too mISDN. */
++ * the other side is also mISDN. */
+ if (p->other_ch) {
+ return 0;
+ }
+@@ -2673,48 +6658,48 @@
+ {
+ struct chan_list *p;
+
+- if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) {
++ if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) {
+ ast_log(LOG_WARNING, "Returned -1 in misdn_indication\n");
+ return -1;
+ }
+-
+- if (!p->bc ) {
++
++ if (!p->bc) {
+ chan_misdn_log(1, 0, "* IND : Indication from %s\n", ast->exten);
+ ast_log(LOG_WARNING, "Private Pointer but no bc ?\n");
+ return -1;
+ }
+-
++
+ chan_misdn_log(5, p->bc->port, "* IND : Indication [%d] from %s\n", cond, ast->exten);
+-
++
+ switch (cond) {
+ case AST_CONTROL_BUSY:
+- chan_misdn_log(1, p->bc->port, "* IND :\tbusy pid:%d\n", p->bc ? p->bc->pid : -1);
++ chan_misdn_log(1, p->bc->port, "* IND :\tbusy pid:%d\n", p->bc->pid);
+ ast_setstate(ast, AST_STATE_BUSY);
+
+ p->bc->out_cause = AST_CAUSE_USER_BUSY;
+ if (p->state != MISDN_CONNECTED) {
+ start_bc_tones(p);
+- misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
++ misdn_lib_send_event(p->bc, EVENT_DISCONNECT);
+ } else {
+ chan_misdn_log(-1, p->bc->port, " --> !! Got Busy in Connected State !?! ast:%s\n", ast->name);
+ }
+ return -1;
+ case AST_CONTROL_RING:
+- chan_misdn_log(1, p->bc->port, "* IND :\tring pid:%d\n", p->bc ? p->bc->pid : -1);
++ chan_misdn_log(1, p->bc->port, "* IND :\tring pid:%d\n", p->bc->pid);
+ return -1;
+ case AST_CONTROL_RINGING:
+- chan_misdn_log(1, p->bc->port, "* IND :\tringing pid:%d\n", p->bc ? p->bc->pid : -1);
++ chan_misdn_log(1, p->bc->port, "* IND :\tringing pid:%d\n", p->bc->pid);
+ switch (p->state) {
+ case MISDN_ALERTING:
+- chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but I was Ringing before, so ignoring it\n", p->bc ? p->bc->pid : -1);
++ chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but I was Ringing before, so ignoring it\n", p->bc->pid);
+ break;
+ case MISDN_CONNECTED:
+- chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but Connected, so just send TONE_ALERTING without state changes \n", p->bc ? p->bc->pid : -1);
++ chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but Connected, so just send TONE_ALERTING without state changes \n", p->bc->pid);
+ return -1;
+ default:
+ p->state = MISDN_ALERTING;
+- chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d\n", p->bc ? p->bc->pid : -1);
+- misdn_lib_send_event( p->bc, EVENT_ALERTING);
++ chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d\n", p->bc->pid);
++ misdn_lib_send_event(p->bc, EVENT_ALERTING);
+
+ if (p->other_ch && p->other_ch->bc) {
+ if (misdn_inband_avail(p->other_ch->bc)) {
+@@ -2728,7 +6713,7 @@
+ }
+ }
+
+- chan_misdn_log(3, p->bc->port, " --> * SEND: State Ring pid:%d\n", p->bc ? p->bc->pid : -1);
++ chan_misdn_log(3, p->bc->port, " --> * SEND: State Ring pid:%d\n", p->bc->pid);
+ ast_setstate(ast, AST_STATE_RING);
+
+ if (!p->bc->nt && (p->originator == ORG_MISDN) && !p->incoming_early_audio) {
+@@ -2739,39 +6724,39 @@
+ }
+ break;
+ case AST_CONTROL_ANSWER:
+- chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n", p->bc ? p->bc->pid : -1);
++ chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n", p->bc->pid);
+ start_bc_tones(p);
+ break;
+ case AST_CONTROL_TAKEOFFHOOK:
+- chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n", p->bc ? p->bc->pid : -1);
++ chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n", p->bc->pid);
+ return -1;
+ case AST_CONTROL_OFFHOOK:
+- chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n", p->bc ? p->bc->pid : -1);
++ chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n", p->bc->pid);
+ return -1;
+ case AST_CONTROL_FLASH:
+- chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n", p->bc ? p->bc->pid : -1);
++ chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n", p->bc->pid);
+ break;
+ case AST_CONTROL_PROGRESS:
+- chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n", p->bc ? p->bc->pid : -1);
+- misdn_lib_send_event( p->bc, EVENT_PROGRESS);
++ chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n", p->bc->pid);
++ misdn_lib_send_event(p->bc, EVENT_PROGRESS);
+ break;
+ case AST_CONTROL_PROCEEDING:
+- chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n", p->bc ? p->bc->pid : -1);
+- misdn_lib_send_event( p->bc, EVENT_PROCEEDING);
++ chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n", p->bc->pid);
++ misdn_lib_send_event(p->bc, EVENT_PROCEEDING);
+ break;
+ case AST_CONTROL_CONGESTION:
+- chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n", p->bc ? p->bc->pid : -1);
++ chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n", p->bc->pid);
+
+ p->bc->out_cause = AST_CAUSE_SWITCH_CONGESTION;
+ start_bc_tones(p);
+- misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
++ misdn_lib_send_event(p->bc, EVENT_DISCONNECT);
+
+ if (p->bc->nt) {
+ hanguptone_indicate(p);
+ }
+ break;
+ case -1 :
+- chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n", p->bc ? p->bc->pid : -1);
++ chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n", p->bc->pid);
+
+ stop_indicate(p);
+
+@@ -2780,17 +6765,26 @@
+ }
+ break;
+ case AST_CONTROL_HOLD:
+- ast_moh_start(ast, data, p->mohinterpret);
+- chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n", p->bc ? p->bc->pid : -1);
++ ast_moh_start(ast, data, p->mohinterpret);
++ chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n", p->bc->pid);
+ break;
+ case AST_CONTROL_UNHOLD:
+ ast_moh_stop(ast);
+- chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n", p->bc ? p->bc->pid : -1);
++ chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n", p->bc->pid);
+ break;
++ case AST_CONTROL_CONNECTED_LINE:
++ chan_misdn_log(1, p->bc->port, "* IND :\tconnected line update pid:%d\n", p->bc->pid);
++ misdn_update_connected_line(ast, p->bc, p->originator);
++ break;
++ case AST_CONTROL_REDIRECTING:
++ chan_misdn_log(1, p->bc->port, "* IND :\tredirecting info update pid:%d\n", p->bc->pid);
++ misdn_update_redirecting(ast, p->bc, p->originator);
++ break;
+ default:
+- chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n", cond, p->bc ? p->bc->pid : -1);
++ chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n", cond, p->bc->pid);
++ break;
+ }
+-
++
+ return 0;
+ }
+
+@@ -2815,8 +6809,10 @@
+
+ if (bc) {
+ const char *tmp;
++
+ ast_channel_lock(ast);
+- if ((tmp = pbx_builtin_getvar_helper(ast, "MISDN_USERUSER"))) {
++ tmp = pbx_builtin_getvar_helper(ast, "MISDN_USERUSER");
++ if (tmp) {
+ ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
+ strcpy(bc->uu, tmp);
+ bc->uulen = strlen(bc->uu);
+@@ -2827,16 +6823,16 @@
+ MISDN_ASTERISK_TECH_PVT(ast) = NULL;
+ p->ast = NULL;
+
+- if (ast->_state == AST_STATE_RESERVED ||
+- p->state == MISDN_NOTHING ||
+- p->state == MISDN_HOLDED ||
+- p->state == MISDN_HOLD_DISCONNECT ) {
++ if (ast->_state == AST_STATE_RESERVED ||
++ p->state == MISDN_NOTHING ||
++ p->state == MISDN_HOLDED ||
++ p->state == MISDN_HOLD_DISCONNECT) {
+
+- CLEAN_CH:
++CLEAN_CH:
+ /* between request and call */
+ ast_debug(1, "State Reserved (or nothing) => chanIsAvail\n");
+ MISDN_ASTERISK_TECH_PVT(ast) = NULL;
+-
++
+ ast_mutex_lock(&release_lock);
+ cl_dequeue_chan(&cl_te, p);
+ close(p->pipe[0]);
+@@ -2872,20 +6868,27 @@
+ if ((varcause = pbx_builtin_getvar_helper(ast, "HANGUPCAUSE")) ||
+ (varcause = pbx_builtin_getvar_helper(ast, "PRI_CAUSE"))) {
+ int tmpcause = atoi(varcause);
++
+ bc->out_cause = tmpcause ? tmpcause : AST_CAUSE_NORMAL_CLEARING;
+ }
+ ast_channel_unlock(ast);
+
+- chan_misdn_log(1, bc->port, "* IND : HANGUP\tpid:%d ctx:%s dad:%s oad:%s State:%s\n", p->bc ? p->bc->pid : -1, ast->context, ast->exten, ast->cid.cid_num, misdn_get_ch_state(p));
++ chan_misdn_log(1, bc->port,
++ "* IND : HANGUP\tpid:%d context:%s dialed:%s caller:\"%s\" <%s> State:%s\n",
++ p->bc ? p->bc->pid : -1,
++ ast->context,
++ ast->exten,
++ ast->cid.cid_name ? ast->cid.cid_name : "",
++ ast->cid.cid_num ? ast->cid.cid_num : "",
++ misdn_get_ch_state(p));
+ chan_misdn_log(3, bc->port, " --> l3id:%x\n", p->l3id);
+ chan_misdn_log(3, bc->port, " --> cause:%d\n", bc->cause);
+ chan_misdn_log(2, bc->port, " --> out_cause:%d\n", bc->out_cause);
+- chan_misdn_log(2, bc->port, " --> state:%s\n", misdn_get_ch_state(p));
+
+ switch (p->state) {
+ case MISDN_INCOMING_SETUP:
+ p->state = MISDN_CLEANING;
+- /* This is the only place in misdn_hangup, where we
++ /* This is the only place in misdn_hangup, where we
+ * can call release_chan, else it might create lot's of trouble
+ * */
+ ast_log(LOG_NOTICE, "release channel, in INCOMING_SETUP state.. no other events happened\n");
+@@ -2970,7 +6973,7 @@
+ if (bc->need_release) {
+ misdn_lib_send_event(bc, EVENT_RELEASE);
+ }
+- p->state = MISDN_CLEANING;
++ p->state = MISDN_CLEANING;
+ } else {
+ if (bc->need_disconnect) {
+ misdn_lib_send_event(bc, EVENT_DISCONNECT);
+@@ -2980,6 +6983,13 @@
+
+ p->state = MISDN_CLEANING;
+
++#if defined(AST_MISDN_ENHANCEMENTS)
++ if (p->peer) {
++ ao2_ref(p->peer, -1);
++ p->peer = NULL;
++ }
++#endif /* AST_MISDN_ENHANCEMENTS */
++
+ chan_misdn_log(3, bc->port, " --> Channel: %s hanguped new state:%s\n", ast->name, misdn_get_ch_state(p));
+
+ return 0;
+@@ -2989,7 +6999,7 @@
+ static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame)
+ {
+ struct ast_frame *f,*f2;
+-
++
+ if (tmp->trans) {
+ f2 = ast_translate(tmp->trans, frame, 0);
+ f = ast_dsp_process(tmp->ast, tmp->dsp, f2);
+@@ -3000,9 +7010,9 @@
+
+ if (!f || (f->frametype != AST_FRAME_DTMF))
+ return frame;
+-
++
+ ast_debug(1, "Detected inband DTMF digit: %c\n", f->subclass);
+-
++
+ if (tmp->faxdetect && (f->subclass == 'f')) {
+ /* Fax tone -- Handle and return NULL */
+ if (!tmp->faxhandled) {
+@@ -3035,7 +7045,7 @@
+ ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, context);
+ }
+ } else {
+- ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n", context, ast->exten);
++ ast_log(LOG_NOTICE, "Fax detected but no fax extension, context:%s exten:%s\n", context, ast->exten);
+ }
+ } else {
+ ast_debug(1, "Already in a fax extension, not redirecting\n");
+@@ -3044,12 +7054,14 @@
+ case 2:
+ ast_verb(3, "Not redirecting %s to fax extension, nojump is set.\n", ast->name);
+ break;
++ default:
++ break;
+ }
+ } else {
+ ast_debug(1, "Fax already handled\n");
+ }
+ }
+-
++
+ if (tmp->ast_dsp && (f->subclass != 'f')) {
+ chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n", f->subclass);
+ }
+@@ -3082,7 +7094,8 @@
+ FD_ZERO(&rrfs);
+ FD_SET(tmp->pipe[0], &rrfs);
+
+- if (!(t = select(FD_SETSIZE, &rrfs, NULL, NULL, &tv))) {
++ t = select(FD_SETSIZE, &rrfs, NULL, NULL, &tv);
++ if (!t) {
+ chan_misdn_log(3, tmp->bc->port, "read Select Timed out\n");
+ len = 160;
+ }
+@@ -3100,7 +7113,6 @@
+ chan_misdn_log(2, tmp->bc->port, "misdn_read: Pipe closed, hanging up\n");
+ return NULL;
+ }
+-
+ } else {
+ return NULL;
+ }
+@@ -3151,7 +7163,7 @@
+ {
+ struct chan_list *ch;
+ int i = 0;
+-
++
+ if (!ast || !(ch = MISDN_ASTERISK_TECH_PVT(ast))) {
+ return -1;
+ }
+@@ -3160,12 +7172,12 @@
+ chan_misdn_log(7, 0, "misdn_write: Returning because holded\n");
+ return 0;
+ }
+-
+- if (!ch->bc ) {
++
++ if (!ch->bc) {
+ ast_log(LOG_WARNING, "private but no bc\n");
+ return -1;
+ }
+-
++
+ if (ch->notxtone) {
+ chan_misdn_log(7, ch->bc->port, "misdn_write: Returning because notxtone\n");
+ return 0;
+@@ -3176,16 +7188,16 @@
+ chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n");
+ return 0;
+ }
+-
++
+ if (!(frame->subclass & prefformat)) {
+ chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass);
+ return 0;
+ }
+-
+
+- if (!frame->samples ) {
++
++ if (!frame->samples) {
+ chan_misdn_log(4, ch->bc->port, "misdn_write: zero write\n");
+-
++
+ if (!strcmp(frame->src,"ast_prod")) {
+ chan_misdn_log(1, ch->bc->port, "misdn_write: state (%s) prodded.\n", misdn_get_ch_state(ch));
+
+@@ -3203,10 +7215,11 @@
+ chan_misdn_log(8, ch->bc->port, "misdn_write: no addr for bc dropping:%d\n", frame->samples);
+ return 0;
+ }
+-
++
+ #ifdef MISDN_DEBUG
+ {
+- int i, max = 5 > frame->samples ? frame->samples : 5;
++ int i;
++ int max = 5 > frame->samples ? frame->samples : 5;
+
+ ast_debug(1, "write2mISDN %p %d bytes: ", p, frame->samples);
+
+@@ -3222,9 +7235,11 @@
+ break;
+ default:
+ if (!ch->dropped_frame_cnt) {
+- chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) dropping: %d frames addr:%x exten:%s cid:%s ch->state:%s bc_state:%d l3id:%x\n", frame->samples, ch->bc->addr, ast->exten, ast->cid.cid_num, misdn_get_ch_state( ch), ch->bc->bc_state, ch->bc->l3_id);
++ chan_misdn_log(5, ch->bc->port,
++ "BC not active (nor bridged) dropping: %d frames addr:%x exten:%s cid:%s ch->state:%s bc_state:%d l3id:%x\n",
++ frame->samples, ch->bc->addr, ast->exten, ast->cid.cid_num, misdn_get_ch_state(ch), ch->bc->bc_state, ch->bc->l3_id);
+ }
+-
++
+ if (++ch->dropped_frame_cnt > 100) {
+ ch->dropped_frame_cnt = 0;
+ chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) dropping: %d frames addr:%x dropped > 100 frames!\n", frame->samples, ch->bc->addr);
+@@ -3241,24 +7256,20 @@
+ cb_log(0, ch->bc->port, "Misdn Jitterbuffer Overflow.\n");
+ }
+ }
+-
++
+ } else {
+- /*transmit without jitterbuffer*/
++ /* transmit without jitterbuffer */
+ i = misdn_lib_tx2misdn_frm(ch->bc, frame->data.ptr, frame->samples);
+ }
+
+ return 0;
+ }
+
+-
+-
+-
+-static enum ast_bridge_result misdn_bridge (struct ast_channel *c0,
+- struct ast_channel *c1, int flags,
+- struct ast_frame **fo,
+- struct ast_channel **rc,
+- int timeoutms)
+-
++static enum ast_bridge_result misdn_bridge(struct ast_channel *c0,
++ struct ast_channel *c1, int flags,
++ struct ast_frame **fo,
++ struct ast_channel **rc,
++ int timeoutms)
+ {
+ struct chan_list *ch1, *ch2;
+ struct ast_channel *carr[2], *who;
+@@ -3266,13 +7277,13 @@
+ struct ast_frame *f;
+ int p1_b, p2_b;
+ int bridging;
+-
++
+ ch1 = get_chan_by_ast(c0);
+ ch2 = get_chan_by_ast(c1);
+
+ carr[0] = c0;
+ carr[1] = c1;
+-
++
+ if (!(ch1 && ch2)) {
+ return -1;
+ }
+@@ -3294,13 +7305,17 @@
+
+ ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
+
+- chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
+-
+- if (! (flags & AST_BRIDGE_DTMF_CHANNEL_0) ) {
++ chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between \"%s\" <%s> and \"%s\" <%s>\n",
++ ch1->bc->caller.name,
++ ch1->bc->caller.number,
++ ch2->bc->caller.name,
++ ch2->bc->caller.number);
++
++ if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
+ ch1->ignore_dtmf = 1;
+ }
+
+- if (! (flags & AST_BRIDGE_DTMF_CHANNEL_1) ) {
++ if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1)) {
+ ch2->ignore_dtmf = 1;
+ }
+
+@@ -3317,33 +7332,34 @@
+ if (!f || f->frametype == AST_FRAME_CONTROL) {
+ /* got hangup .. */
+
+- if (!f)
++ if (!f) {
+ chan_misdn_log(4, ch1->bc->port, "Read Null Frame\n");
+- else
++ } else {
+ chan_misdn_log(4, ch1->bc->port, "Read Frame Control class:%d\n", f->subclass);
++ }
+
+ *fo = f;
+ *rc = who;
+ break;
+ }
+-
+- if ( f->frametype == AST_FRAME_DTMF ) {
++
++ if (f->frametype == AST_FRAME_DTMF) {
+ chan_misdn_log(1, 0, "Read DTMF %d from %s\n", f->subclass, who->exten);
+
+ *fo = f;
+ *rc = who;
+ break;
+ }
+-
++
+ #if 0
+ if (f->frametype == AST_FRAME_VOICE) {
+ chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
+-
++
+ continue;
+ }
+ #endif
+
+- ast_write(who == c0 ? c1 : c0, f);
++ ast_write((who == c0) ? c1 : c0, f);
+ }
+
+ chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid + 1);
+@@ -3371,11 +7387,11 @@
+ chan_misdn_log(1, cl->bc->port, "Not sending Dialtone, because config wants it\n");
+ return 0;
+ }
+-
++
+ chan_misdn_log(3, cl->bc->port, " --> Dial\n");
+
+ cl->ts = ast_get_indication_tone(ast->zone, "dial");
+-
++
+ if (cl->ts) {
+ cl->notxtone = 0;
+ cl->norxtone = 0;
+@@ -3429,7 +7445,7 @@
+
+ cl->notxtone = 1;
+ cl->norxtone = 1;
+-
++
+ return 0;
+ }
+
+@@ -3438,59 +7454,121 @@
+ {
+ struct chan_list *cl;
+
+- if (!(cl = ast_calloc(1, sizeof(*cl)))) {
++ cl = ast_calloc(1, sizeof(*cl));
++ if (!cl) {
+ chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
+ return NULL;
+ }
+-
++
+ cl->originator = orig;
+ cl->need_queue_hangup = 1;
+ cl->need_hangup = 1;
+ cl->need_busy = 1;
+ cl->overlap_dial_task = -1;
++#if defined(AST_MISDN_ENHANCEMENTS)
++ cl->record_id = -1;
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
+
+ return cl;
+ }
+
+ static struct ast_channel *misdn_request(const char *type, int format, void *data, int *cause)
+ {
+- struct ast_channel *tmp = NULL;
++ struct ast_channel *ast;
+ char group[BUFFERSIZE + 1] = "";
+- char buf[128];
+- char *buf2 = ast_strdupa(data), *ext = NULL, *port_str;
+- char *tokb = NULL, *p = NULL;
+- int channel = 0, port = 0;
++ char dial_str[128];
++ char *dest_cp;
++ char *p = NULL;
++ int channel = 0;
++ int port = 0;
+ struct misdn_bchannel *newbc = NULL;
+ int dec = 0;
++#if defined(AST_MISDN_ENHANCEMENTS)
++ int cc_retry_call = 0; /* TRUE if this is a call completion retry call */
++ long record_id = -1;
++ struct misdn_cc_record *cc_record;
++ const char *err_msg;
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++ struct chan_list *cl;
+
+- struct chan_list *cl = init_chan_list(ORG_AST);
++ AST_DECLARE_APP_ARGS(args,
++ AST_APP_ARG(intf); /* interface token */
++ AST_APP_ARG(ext); /* extension token */
++ AST_APP_ARG(opts); /* options token */
++ );
+
+- snprintf(buf, sizeof(buf), "%s/%s", misdn_type, (char*)data);
++ snprintf(dial_str, sizeof(dial_str), "%s/%s", misdn_type, (char *) data);
+
+- port_str = strtok_r(buf2, "/", &tokb);
++ /*
++ * data is ---v
++ * Dial(mISDN/g:group_name[/extension[/options]])
++ * Dial(mISDN/port[:preselected_channel][/extension[/options]])
++ * Dial(mISDN/cc/cc-record-id)
++ *
++ * The dial extension could be empty if you are using MISDN_KEYPAD
++ * to control ISDN provider features.
++ */
++ dest_cp = ast_strdupa(data);
++ AST_NONSTANDARD_APP_ARGS(args, dest_cp, '/');
++ if (!args.ext) {
++ args.ext = "";
++ }
+
+- ext = strtok_r(NULL, "/", &tokb);
+-
+- if (port_str) {
+- if (port_str[0] == 'g' && port_str[1] == ':' ) {
++ if (!ast_strlen_zero(args.intf)) {
++ if (args.intf[0] == 'g' && args.intf[1] == ':') {
+ /* We make a group call lets checkout which ports are in my group */
+- port_str += 2;
+- ast_copy_string(group, port_str, sizeof(group));
++ args.intf += 2;
++ ast_copy_string(group, args.intf, sizeof(group));
+ chan_misdn_log(2, 0, " --> Group Call group: %s\n", group);
+- } else if ((p = strchr(port_str, ':'))) {
++#if defined(AST_MISDN_ENHANCEMENTS)
++ } else if (strcmp(args.intf, "cc") == 0) {
++ cc_retry_call = 1;
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++ } else if ((p = strchr(args.intf, ':'))) {
+ /* we have a preselected channel */
+- *p = 0;
+- channel = atoi(++p);
+- port = atoi(port_str);
++ *p++ = 0;
++ channel = atoi(p);
++ port = atoi(args.intf);
+ chan_misdn_log(2, port, " --> Call on preselected Channel (%d).\n", channel);
+ } else {
+- port = atoi(port_str);
++ port = atoi(args.intf);
+ }
+ } else {
+- ast_log(LOG_WARNING, " --> ! IND : CALL dad:%s WITHOUT PORT/Group, check extensions.conf\n", ext);
++ ast_log(LOG_WARNING, " --> ! IND : Dial(%s) WITHOUT Port or Group, check extensions.conf\n", dial_str);
+ return NULL;
+ }
+
++#if defined(AST_MISDN_ENHANCEMENTS)
++ if (cc_retry_call) {
++ if (ast_strlen_zero(args.ext)) {
++ ast_log(LOG_WARNING, " --> ! IND : Dial(%s) WITHOUT cc-record-id, check extensions.conf\n", dial_str);
++ return NULL;
++ }
++ if (!isdigit(*args.ext)) {
++ ast_log(LOG_WARNING, " --> ! IND : Dial(%s) cc-record-id must be a number.\n", dial_str);
++ return NULL;
++ }
++ record_id = atol(args.ext);
++
++ AST_LIST_LOCK(&misdn_cc_records_db);
++ cc_record = misdn_cc_find_by_id(record_id);
++ if (!cc_record) {
++ AST_LIST_UNLOCK(&misdn_cc_records_db);
++ err_msg = misdn_cc_record_not_found;
++ ast_log(LOG_WARNING, " --> ! IND : Dial(%s) %s.\n", dial_str, err_msg);
++ return NULL;
++ }
++ if (!cc_record->activated) {
++ AST_LIST_UNLOCK(&misdn_cc_records_db);
++ err_msg = "Call completion has not been activated";
++ ast_log(LOG_WARNING, " --> ! IND : Dial(%s) %s.\n", dial_str, err_msg);
++ return NULL;
++ }
++ port = cc_record->port;
++ AST_LIST_UNLOCK(&misdn_cc_records_db);
++ }
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
+ if (misdn_cfg_is_group_method(group, METHOD_STANDARD_DEC)) {
+ chan_misdn_log(4, port, " --> STARTING STANDARD DEC...\n");
+ dec = 1;
+@@ -3524,9 +7602,10 @@
+ if (port >= port_start) {
+ next_chan = 1;
+ }
+-
++
+ if (port <= port_start && next_chan) {
+- int maxbchans=misdn_lib_get_maxchans(port);
++ int maxbchans = misdn_lib_get_maxchans(port);
++
+ if (++robin_channel >= maxbchans) {
+ robin_channel = 1;
+ }
+@@ -3538,13 +7617,14 @@
+ if (!strcasecmp(cfg_group, group)) {
+ int port_up;
+ int check;
++
+ misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(check));
+ port_up = misdn_lib_port_up(port, check);
+
+ if (check && !port_up) {
+ chan_misdn_log(1, port, "L1 is not Up on this Port\n");
+ }
+-
++
+ if (check && port_up < 0) {
+ ast_log(LOG_WARNING, "This port (%d) is blocked\n", port);
+ }
+@@ -3564,37 +7644,38 @@
+ }
+ }
+ } while (!newbc && robin_channel != rr->channel);
+- } else {
++ } else {
+ for (port = misdn_cfg_get_next_port(0); port > 0;
+- port = misdn_cfg_get_next_port(port)) {
+-
++ port = misdn_cfg_get_next_port(port)) {
+ misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
+
+ chan_misdn_log(3, port, "Group [%s] Port [%d]\n", group, port);
+ if (!strcasecmp(cfg_group, group)) {
+ int port_up;
+ int check;
++
+ misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(check));
+ port_up = misdn_lib_port_up(port, check);
+
+ chan_misdn_log(4, port, "portup:%d\n", port_up);
+
+ if (port_up > 0) {
+- if ((newbc = misdn_lib_get_free_bc(port, 0, 0, dec))) {
++ newbc = misdn_lib_get_free_bc(port, 0, 0, dec);
++ if (newbc) {
+ break;
+ }
+ }
+ }
+ }
+ }
+-
++
+ /* Group dial failed ?*/
+ if (!newbc) {
+- ast_log(LOG_WARNING,
+- "Could not Dial out on group '%s'.\n"
+- "\tEither the L2 and L1 on all of these ports where DOWN (see 'show application misdn_check_l2l1')\n"
+- "\tOr there was no free channel on none of the ports\n\n"
+- , group);
++ ast_log(LOG_WARNING,
++ "Could not Dial out on group '%s'.\n"
++ "\tEither the L2 and L1 on all of these ports where DOWN (see 'show application misdn_check_l2l1')\n"
++ "\tOr there was no free channel on none of the ports\n\n",
++ group);
+ return NULL;
+ }
+ } else {
+@@ -3603,42 +7684,48 @@
+ chan_misdn_log(1, port, " --> preselected_channel: %d\n", channel);
+ }
+ newbc = misdn_lib_get_free_bc(port, channel, 0, dec);
+-
+ if (!newbc) {
+- ast_log(LOG_WARNING, "Could not create channel on port:%d with extensions:%s\n", port, ext);
++ ast_log(LOG_WARNING, "Could not create channel on port:%d for Dial(%s)\n", port, dial_str);
+ return NULL;
+ }
+ }
+-
+
+ /* create ast_channel and link all the objects together */
++ cl = init_chan_list(ORG_AST);
++ if (!cl) {
++ ast_log(LOG_ERROR, "Could not create call record for Dial(%s)\n", dial_str);
++ return NULL;
++ }
+ cl->bc = newbc;
+-
+- tmp = misdn_new(cl, AST_STATE_RESERVED, ext, NULL, format, port, channel);
+- if (!tmp) {
+- ast_log(LOG_ERROR, "Could not create Asterisk object\n");
++
++ ast = misdn_new(cl, AST_STATE_RESERVED, args.ext, NULL, format, port, channel);
++ if (!ast) {
++ ast_log(LOG_ERROR, "Could not create Asterisk channel for Dial(%s)\n", dial_str);
+ return NULL;
+ }
++ cl->ast = ast;
+
+- cl->ast = tmp;
+-
++#if defined(AST_MISDN_ENHANCEMENTS)
++ cl->record_id = record_id;
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
+ /* register chan in local list */
+ cl_queue_chan(&cl_te, cl);
+-
++
+ /* fill in the config into the objects */
+- read_config(cl, ORG_AST);
++ read_config(cl);
+
+ /* important */
+ cl->need_hangup = 0;
+-
+- return tmp;
++
++ return ast;
+ }
+
+
+ static int misdn_send_text(struct ast_channel *chan, const char *text)
+ {
+ struct chan_list *tmp = chan->tech_pvt;
+-
++
+ if (tmp && tmp->bc) {
+ ast_copy_string(tmp->bc->display, text, sizeof(tmp->bc->display));
+ misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
+@@ -3646,19 +7733,19 @@
+ ast_log(LOG_WARNING, "No chan_list but send_text request?\n");
+ return -1;
+ }
+-
++
+ return 0;
+ }
+
+ static struct ast_channel_tech misdn_tech = {
+- .type = "mISDN",
++ .type = misdn_type,
+ .description = "Channel driver for mISDN Support (Bri/Pri)",
+ .capabilities = AST_FORMAT_ALAW ,
+ .requester = misdn_request,
+ .send_digit_begin = misdn_digit_begin,
+ .send_digit_end = misdn_digit_end,
+ .call = misdn_call,
+- .bridge = misdn_bridge,
++ .bridge = misdn_bridge,
+ .hangup = misdn_hangup,
+ .answer = misdn_answer,
+ .read = misdn_read,
+@@ -3670,7 +7757,7 @@
+ };
+
+ static struct ast_channel_tech misdn_tech_wo_bridge = {
+- .type = "mISDN",
++ .type = misdn_type,
+ .description = "Channel driver for mISDN Support (Bri/Pri)",
+ .capabilities = AST_FORMAT_ALAW ,
+ .requester = misdn_request,
+@@ -3690,16 +7777,17 @@
+
+ static int glob_channel = 0;
+
+-static void update_name(struct ast_channel *tmp, int port, int c)
++static void update_name(struct ast_channel *tmp, int port, int c)
+ {
+ int chan_offset = 0;
+ int tmp_port = misdn_cfg_get_next_port(0);
+ char newname[255];
++
+ for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
+ if (tmp_port == port) {
+ break;
+ }
+- chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2;
++ chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2;
+ }
+ if (c < 0) {
+ c = 0;
+@@ -3708,7 +7796,9 @@
+ snprintf(newname, sizeof(newname), "%s/%d-", misdn_type, chan_offset + c);
+ if (strncmp(tmp->name, newname, strlen(newname))) {
+ snprintf(newname, sizeof(newname), "%s/%d-u%d", misdn_type, chan_offset + c, glob_channel++);
++ ast_channel_lock(tmp);
+ ast_change_name(tmp, newname);
++ ast_channel_unlock(tmp);
+ chan_misdn_log(3, port, " --> updating channel name to [%s]\n", tmp->name);
+ }
+ }
+@@ -3737,7 +7827,7 @@
+
+ tmp = ast_channel_alloc(1, state, cid_num, cid_name, "", exten, "", 0, "%s/%s%d-u%d", misdn_type, c ? "" : "tmp", chan_offset + c, glob_channel++);
+ if (tmp) {
+- chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n", exten, callerid);
++ chan_misdn_log(2, 0, " --> * NEW CHANNEL dialed:%s caller:%s\n", exten, callerid);
+
+ tmp->nativeformats = prefformat;
+
+@@ -3745,11 +7835,10 @@
+ tmp->rawreadformat = format;
+ tmp->writeformat = format;
+ tmp->rawwriteformat = format;
+-
++
+ tmp->tech_pvt = chlist;
+
+ misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
+-
+ tmp->tech = bridging ? &misdn_tech : &misdn_tech_wo_bridge;
+
+ tmp->writeformat = format;
+@@ -3779,20 +7868,25 @@
+ } else {
+ chan_misdn_log(-1, 0, "Unable to allocate channel structure\n");
+ }
+-
++
+ return tmp;
+ }
+
+ static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc)
+ {
+ struct chan_list *help = list;
++
+ for (; help; help = help->next) {
+ if (help->bc == bc) {
+ return help;
+ }
+ }
+
+- chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n", bc->oad, bc->dad);
++ chan_misdn_log(6, bc->port,
++ "$$$ find_chan_by_bc: No channel found for dialed:%s caller:\"%s\" <%s>\n",
++ bc->dialed.number,
++ bc->caller.name,
++ bc->caller.number);
+
+ return NULL;
+ }
+@@ -3800,13 +7894,14 @@
+ static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid)
+ {
+ struct chan_list *help = list;
++
+ for (; help; help = help->next) {
+ if (help->bc && (help->bc->pid == pid)) {
+ return help;
+ }
+ }
+
+- chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n", pid);
++ chan_misdn_log(6, 0, "$$$ find_chan_by_pid: No channel found for pid:%d\n", pid);
+
+ return NULL;
+ }
+@@ -3819,21 +7914,29 @@
+ return NULL;
+ }
+
+- chan_misdn_log(6, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n", bc->channel, bc->oad, bc->dad);
++ chan_misdn_log(6, bc->port, "$$$ find_holded: channel:%d dialed:%s caller:\"%s\" <%s>\n",
++ bc->channel,
++ bc->dialed.number,
++ bc->caller.name,
++ bc->caller.number);
+ for (; help; help = help->next) {
+ chan_misdn_log(4, bc->port, "$$$ find_holded: --> holded:%d channel:%d\n", help->state == MISDN_HOLDED, help->hold_info.channel);
+- if ((help->state == MISDN_HOLDED) &&
++ if ((help->state == MISDN_HOLDED) &&
+ (help->hold_info.port == bc->port)) {
+ return help;
+ }
+ }
+- chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n", bc->oad, bc->dad);
++ chan_misdn_log(6, bc->port,
++ "$$$ find_holded: No channel found for dialed:%s caller:\"%s\" <%s>\n",
++ bc->dialed.number,
++ bc->caller.name,
++ bc->caller.number);
+
+ return NULL;
+ }
+
+
+-static struct chan_list *find_holded_l3(struct chan_list *list, unsigned long l3_id, int w)
++static struct chan_list *find_holded_l3(struct chan_list *list, unsigned long l3_id, int w)
+ {
+ struct chan_list *help = list;
+
+@@ -3850,20 +7953,20 @@
+ static void cl_queue_chan(struct chan_list **list, struct chan_list *chan)
+ {
+ chan_misdn_log(4, chan->bc ? chan->bc->port : 0, "* Queuing chan %p\n", chan);
+-
++
+ ast_mutex_lock(&cl_te_lock);
+ if (!*list) {
+ *list = chan;
+ } else {
+ struct chan_list *help = *list;
+- for (; help->next; help = help->next);
++ for (; help->next; help = help->next);
+ help->next = chan;
+ }
+ chan->next = NULL;
+ ast_mutex_unlock(&cl_te_lock);
+ }
+
+-static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan)
++static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan)
+ {
+ struct chan_list *help;
+
+@@ -3879,13 +7982,13 @@
+ ast_mutex_unlock(&cl_te_lock);
+ return;
+ }
+-
++
+ if (*list == chan) {
+ *list = (*list)->next;
+ ast_mutex_unlock(&cl_te_lock);
+ return;
+ }
+-
++
+ for (help = *list; help->next; help = help->next) {
+ if (help->next == chan) {
+ help->next = help->next->next;
+@@ -3893,7 +7996,7 @@
+ return;
+ }
+ }
+-
++
+ ast_mutex_unlock(&cl_te_lock);
+ }
+
+@@ -3902,7 +8005,7 @@
+
+ static int pbx_start_chan(struct chan_list *ch)
+ {
+- int ret = ast_pbx_start(ch->ast);
++ int ret = ast_pbx_start(ch->ast);
+
+ ch->need_hangup = (ret >= 0) ? 0 : 1;
+
+@@ -3911,12 +8014,14 @@
+
+ static void hangup_chan(struct chan_list *ch)
+ {
+- int port = ch ? (ch->bc ? ch->bc->port : 0) : 0;
++ int port;
++
+ if (!ch) {
+ cb_log(1, 0, "Cannot hangup chan, no ch\n");
+ return;
+ }
+
++ port = ch->bc ? ch->bc->port : 0;
+ cb_log(5, port, "hangup_chan called\n");
+
+ if (ch->need_hangup) {
+@@ -3948,25 +8053,24 @@
+ }
+
+ /** Isdn asks us to release channel, pendant to misdn_hangup **/
+-static void release_chan(struct misdn_bchannel *bc) {
+- struct ast_channel *ast = NULL;
++static void release_chan(struct misdn_bchannel *bc)
++{
+ struct chan_list *ch;
++ struct ast_channel *ast;
+
+ ast_mutex_lock(&release_lock);
+- if (!(ch = find_chan_by_bc(cl_te, bc))) {
++
++ ch = find_chan_by_bc(cl_te, bc);
++ if (!ch) {
+ chan_misdn_log(1, bc->port, "release_chan: Ch not found!\n");
+ ast_mutex_unlock(&release_lock);
+ return;
+ }
+
+- if (ch->ast) {
+- ast = ch->ast;
+- }
+-
+ chan_misdn_log(5, bc->port, "release_chan: bc with l3id: %x\n", bc->l3_id);
+
+ /* releasing jitterbuffer */
+- if (ch->jb ) {
++ if (ch->jb) {
+ misdn_jb_destroy(ch->jb);
+ ch->jb = NULL;
+ } else {
+@@ -3984,35 +8088,39 @@
+ }
+
+ if (ch->originator == ORG_AST) {
+- misdn_out_calls[bc->port]--;
++ --misdn_out_calls[bc->port];
+ } else {
+- misdn_in_calls[bc->port]--;
++ --misdn_in_calls[bc->port];
+ }
+
+- if (ch) {
+- close(ch->pipe[0]);
+- close(ch->pipe[1]);
++ close(ch->pipe[0]);
++ close(ch->pipe[1]);
+
+- if (ast && MISDN_ASTERISK_TECH_PVT(ast)) {
+- chan_misdn_log(1, bc->port, "* RELEASING CHANNEL pid:%d ctx:%s dad:%s oad:%s state: %s\n", bc ? bc->pid : -1, ast->context, ast->exten, ast->cid.cid_num, misdn_get_ch_state(ch));
+- chan_misdn_log(3, bc->port, " --> * State Down\n");
+- MISDN_ASTERISK_TECH_PVT(ast) = NULL;
++ ast = ch->ast;
++ if (ast && MISDN_ASTERISK_TECH_PVT(ast)) {
++ chan_misdn_log(1, bc->port,
++ "* RELEASING CHANNEL pid:%d context:%s dialed:%s caller:\"%s\" <%s> state: %s\n",
++ bc->pid,
++ ast->context,
++ ast->exten,
++ ast->cid.cid_name ? ast->cid.cid_name : "",
++ ast->cid.cid_num ? ast->cid.cid_num : "",
++ misdn_get_ch_state(ch));
++ chan_misdn_log(3, bc->port, " --> * State Down\n");
++ MISDN_ASTERISK_TECH_PVT(ast) = NULL;
+
+- if (ast->_state != AST_STATE_RESERVED) {
+- chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
+- ast_setstate(ast, AST_STATE_DOWN);
+- }
++ if (ast->_state != AST_STATE_RESERVED) {
++ chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
++ ast_setstate(ast, AST_STATE_DOWN);
+ }
++ }
+
+- ch->state = MISDN_CLEANING;
+- cl_dequeue_chan(&cl_te, ch);
++ ch->state = MISDN_CLEANING;
++ cl_dequeue_chan(&cl_te, ch);
+
+- ast_free(ch);
+- } else {
+- /* chan is already cleaned, so exiting */
+- }
++ ast_free(ch);
++
+ ast_mutex_unlock(&release_lock);
+-/*** release end **/
+ }
+
+ static void misdn_transfer_bc(struct chan_list *tmp_ch, struct chan_list *holded_chan)
+@@ -4040,25 +8148,28 @@
+
+ if (!ch->noautorespond_on_setup) {
+ if (bc->nt) {
+- int ret;
+- ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
++ misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
+ } else {
+- int ret;
+- if ( misdn_lib_is_ptp(bc->port)) {
+- ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
++ if (misdn_lib_is_ptp(bc->port)) {
++ misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
+ } else {
+- ret = misdn_lib_send_event(bc, EVENT_PROCEEDING );
++ misdn_lib_send_event(bc, EVENT_PROCEEDING);
+ }
+ }
+ } else {
+ ch->state = MISDN_INCOMING_SETUP;
+ }
+
+- chan_misdn_log(1, bc->port, "* Starting Ast ctx:%s dad:%s oad:%s with 's' extension\n", ast->context, ast->exten, ast->cid.cid_num);
+-
+- strncpy(ast->exten, "s", 2);
+-
+- if (!ast_canmatch_extension(ast, ast->context, ast->exten, 1, bc->oad) || pbx_start_chan(ch) < 0) {
++ chan_misdn_log(1, bc->port,
++ "* Starting Ast context:%s dialed:%s caller:\"%s\" <%s> with 's' extension\n",
++ ast->context,
++ ast->exten,
++ ast->cid.cid_name ? ast->cid.cid_name : "",
++ ast->cid.cid_num ? ast->cid.cid_num : "");
++
++ strcpy(ast->exten, "s");
++
++ if (!ast_canmatch_extension(ast, ast->context, ast->exten, 1, bc->caller.number) || pbx_start_chan(ch) < 0) {
+ ast = NULL;
+ bc->out_cause = AST_CAUSE_UNALLOCATED;
+ hangup_chan(ch);
+@@ -4066,9 +8177,9 @@
+
+ misdn_lib_send_event(bc, bc->nt ? EVENT_RELEASE_COMPLETE : EVENT_DISCONNECT);
+ }
+-
+-
+- while (!ast_strlen_zero(predial) ) {
++
++
++ while (!ast_strlen_zero(predial)) {
+ fr.frametype = AST_FRAME_DTMF;
+ fr.subclass = *predial;
+ fr.src = NULL;
+@@ -4079,7 +8190,7 @@
+ fr.offset = 0;
+ fr.delivery = ast_tv(0,0);
+
+- if (ch->ast && MISDN_ASTERISK_PVT(ch->ast) && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
++ if (ch->ast && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
+ ast_queue_frame(ch->ast, &fr);
+ }
+ predial++;
+@@ -4119,7 +8230,7 @@
+ *
+ chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Congestion pid:%d\n", bc ? bc->pid : -1);
+ ch->state = MISDN_BUSY;
+-
++
+ ast_queue_control(ast, AST_CONTROL_CONGESTION);
+ */
+ break;
+@@ -4134,11 +8245,11 @@
+ }
+
+ chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Busy pid:%d\n", bc ? bc->pid : -1);
+-
++
+ ast_queue_control(ast, AST_CONTROL_BUSY);
+-
++
+ ch->need_busy = 0;
+-
++
+ break;
+ }
+ }
+@@ -4185,6 +8296,7 @@
+ void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
+ {
+ char tmp[32];
++
+ chan_misdn_log(3, bc->port, " --> EXPORT_PID: pid:%d\n", bc->pid);
+ snprintf(tmp, sizeof(tmp), "%d", bc->pid);
+ pbx_builtin_setvar_helper(chan, "_MISDN_PID", tmp);
+@@ -4211,7 +8323,7 @@
+ int add_in_calls(int port)
+ {
+ int max_in_calls;
+-
++
+ misdn_cfg_get(port, MISDN_CFG_MAX_IN, &max_in_calls, sizeof(max_in_calls));
+ misdn_in_calls[port]++;
+
+@@ -4219,14 +8331,14 @@
+ ast_log(LOG_NOTICE, "Marking Incoming Call on port[%d]\n", port);
+ return misdn_in_calls[port] - max_in_calls;
+ }
+-
++
+ return 0;
+ }
+
+ int add_out_calls(int port)
+ {
+ int max_out_calls;
+-
++
+ misdn_cfg_get(port, MISDN_CFG_MAX_OUT, &max_out_calls, sizeof(max_out_calls));
+
+ if (max_out_calls >= 0 && max_out_calls <= misdn_out_calls[port]) {
+@@ -4235,11 +8347,12 @@
+ }
+
+ misdn_out_calls[port]++;
+-
++
+ return 0;
+ }
+
+-static void start_pbx(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan) {
++static void start_pbx(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan)
++{
+ if (pbx_start_chan(ch) < 0) {
+ hangup_chan(ch);
+ chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
+@@ -4252,36 +8365,967 @@
+ }
+ }
+
+-static void wait_for_digits(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan) {
++static void wait_for_digits(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan)
++{
+ ch->state = MISDN_WAITING4DIGS;
+- misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
+- if (bc->nt && !bc->dad[0]) {
++ misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
++ if (bc->nt && !bc->dialed.number[0]) {
+ dialtone_indicate(ch);
+ }
+ }
+
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Handle the FACILITY CCBSStatusRequest message.
++ *
++ * \param port Logical port number.
++ * \param facility Facility ie contents.
++ *
++ * \return Nothing
++ */
++static void misdn_cc_handle_ccbs_status_request(int port, const struct FacParm *facility)
++{
++ struct misdn_cc_record *cc_record;
++ struct misdn_bchannel dummy;
+
++ switch (facility->u.CCBSStatusRequest.ComponentType) {
++ case FacComponent_Invoke:
++ /* Build message */
++ misdn_make_dummy(&dummy, port, 0, misdn_lib_port_is_nt(port), 0);
++ dummy.fac_out.Function = Fac_CCBSStatusRequest;
++ dummy.fac_out.u.CCBSStatusRequest.InvokeID = facility->u.CCBSStatusRequest.InvokeID;
++ dummy.fac_out.u.CCBSStatusRequest.ComponentType = FacComponent_Result;
++
++ /* Answer User-A free question */
++ AST_LIST_LOCK(&misdn_cc_records_db);
++ cc_record = misdn_cc_find_by_reference(port, facility->u.CCBSStatusRequest.Component.Invoke.CCBSReference);
++ if (cc_record) {
++ dummy.fac_out.u.CCBSStatusRequest.Component.Result.Free = cc_record->party_a_free;
++ } else {
++ /* No record so say User-A is free */
++ dummy.fac_out.u.CCBSStatusRequest.Component.Result.Free = 1;
++ }
++ AST_LIST_UNLOCK(&misdn_cc_records_db);
++
++ /* Send message */
++ print_facility(&dummy.fac_out, &dummy);
++ misdn_lib_send_event(&dummy, EVENT_FACILITY);
++ break;
++
++ default:
++ chan_misdn_log(0, port, " --> not yet handled: facility type:0x%04X\n", facility->Function);
++ break;
++ }
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Start a PBX to notify that User-B is available.
++ *
++ * \param record_id Call completion record ID
++ * \param notify Dialplan location to start processing.
++ *
++ * \return Nothing
++ */
++static void misdn_cc_pbx_notify(long record_id, const struct misdn_cc_notify *notify)
++{
++ struct ast_channel *chan;
++ char id_str[32];
++
++ static unsigned short sequence = 0;
++
++ /* Create a channel to notify with */
++ snprintf(id_str, sizeof(id_str), "%ld", record_id);
++ chan = ast_channel_alloc(0, AST_STATE_DOWN, id_str, NULL, NULL,
++ notify->exten, notify->context, 0,
++ "mISDN-CC/%ld-%X", record_id, (unsigned) ++sequence);
++ if (!chan) {
++ ast_log(LOG_ERROR, "Unable to allocate channel!\n");
++ return;
++ }
++ chan->priority = notify->priority;
++ if (chan->cid.cid_dnid) {
++ ast_free(chan->cid.cid_dnid);
++ }
++ chan->cid.cid_dnid = ast_strdup(notify->exten);
++
++ if (ast_pbx_start(chan)) {
++ ast_log(LOG_WARNING, "Unable to start pbx channel %s!\n", chan->name);
++ ast_channel_release(chan);
++ } else {
++ ast_verb(1, "Started pbx for call completion notify channel %s\n", chan->name);
++ }
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Handle the FACILITY CCBS_T_RemoteUserFree message.
++ *
++ * \param bc B channel control structure message came in on
++ *
++ * \return Nothing
++ */
++static void misdn_cc_handle_T_remote_user_free(struct misdn_bchannel *bc)
++{
++ struct misdn_cc_record *cc_record;
++ struct misdn_cc_notify notify;
++ long record_id;
++
++ AST_LIST_LOCK(&misdn_cc_records_db);
++ cc_record = misdn_cc_find_by_bc(bc);
++ if (cc_record) {
++ if (cc_record->party_a_free) {
++ notify = cc_record->remote_user_free;
++ } else {
++ /* Send CCBS_T_Suspend message */
++ bc->fac_out.Function = Fac_CCBS_T_Suspend;
++ bc->fac_out.u.CCBS_T_Suspend.InvokeID = ++misdn_invoke_id;
++ print_facility(&bc->fac_out, bc);
++ misdn_lib_send_event(bc, EVENT_FACILITY);
++
++ notify = cc_record->b_free;
++ }
++ record_id = cc_record->record_id;
++ AST_LIST_UNLOCK(&misdn_cc_records_db);
++ if (notify.context[0]) {
++ /* Party A is free or B-Free notify has been setup. */
++ misdn_cc_pbx_notify(record_id, &notify);
++ }
++ } else {
++ AST_LIST_UNLOCK(&misdn_cc_records_db);
++ }
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Handle the FACILITY CCBSRemoteUserFree message.
++ *
++ * \param port Logical port number.
++ * \param facility Facility ie contents.
++ *
++ * \return Nothing
++ */
++static void misdn_cc_handle_remote_user_free(int port, const struct FacParm *facility)
++{
++ struct misdn_cc_record *cc_record;
++ struct misdn_cc_notify notify;
++ long record_id;
++
++ AST_LIST_LOCK(&misdn_cc_records_db);
++ cc_record = misdn_cc_find_by_reference(port, facility->u.CCBSRemoteUserFree.CCBSReference);
++ if (cc_record) {
++ notify = cc_record->remote_user_free;
++ record_id = cc_record->record_id;
++ AST_LIST_UNLOCK(&misdn_cc_records_db);
++ misdn_cc_pbx_notify(record_id, &notify);
++ } else {
++ AST_LIST_UNLOCK(&misdn_cc_records_db);
++ }
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Handle the FACILITY CCBSBFree message.
++ *
++ * \param port Logical port number.
++ * \param facility Facility ie contents.
++ *
++ * \return Nothing
++ */
++static void misdn_cc_handle_b_free(int port, const struct FacParm *facility)
++{
++ struct misdn_cc_record *cc_record;
++ struct misdn_cc_notify notify;
++ long record_id;
++
++ AST_LIST_LOCK(&misdn_cc_records_db);
++ cc_record = misdn_cc_find_by_reference(port, facility->u.CCBSBFree.CCBSReference);
++ if (cc_record && cc_record->b_free.context[0]) {
++ /* B-Free notify has been setup. */
++ notify = cc_record->b_free;
++ record_id = cc_record->record_id;
++ AST_LIST_UNLOCK(&misdn_cc_records_db);
++ misdn_cc_pbx_notify(record_id, &notify);
++ } else {
++ AST_LIST_UNLOCK(&misdn_cc_records_db);
++ }
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++/*!
++ * \internal
++ * \brief Handle the incoming facility ie contents
++ *
++ * \param event Message type facility ie came in on
++ * \param bc B channel control structure message came in on
++ * \param ch Associated channel call record
++ *
++ * \return Nothing
++ */
++static void misdn_facility_ie_handler(enum event_e event, struct misdn_bchannel *bc, struct chan_list *ch)
++{
++#if defined(AST_MISDN_ENHANCEMENTS)
++ const char *diagnostic_msg;
++ struct misdn_cc_record *cc_record;
++ char buf[32];
++ struct misdn_party_id party_id;
++ long new_record_id;
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++ print_facility(&bc->fac_in, bc);
++ switch (bc->fac_in.Function) {
++#if defined(AST_MISDN_ENHANCEMENTS)
++ case Fac_ActivationDiversion:
++ switch (bc->fac_in.u.ActivationDiversion.ComponentType) {
++ case FacComponent_Result:
++ /* Positive ACK to activation */
++ /* We don't handle this yet */
++ break;
++ default:
++ chan_misdn_log(0, bc->port," --> not yet handled: facility type:0x%04X\n",
++ bc->fac_in.Function);
++ break;
++ }
++ break;
++ case Fac_DeactivationDiversion:
++ switch (bc->fac_in.u.DeactivationDiversion.ComponentType) {
++ case FacComponent_Result:
++ /* Positive ACK to deactivation */
++ /* We don't handle this yet */
++ break;
++ default:
++ chan_misdn_log(0, bc->port," --> not yet handled: facility type:0x%04X\n",
++ bc->fac_in.Function);
++ break;
++ }
++ break;
++ case Fac_ActivationStatusNotificationDiv:
++ /* Sent to other MSN numbers on the line when a user activates call forwarding. */
++ /* Sent in the first call control message of an outgoing call from the served user. */
++ /* We do not have anything to do for this message. */
++ break;
++ case Fac_DeactivationStatusNotificationDiv:
++ /* Sent to other MSN numbers on the line when a user deactivates call forwarding. */
++ /* We do not have anything to do for this message. */
++ break;
++#if 0 /* We don't handle this yet */
++ case Fac_InterrogationDiversion:
++ /* We don't handle this yet */
++ break;
++ case Fac_InterrogateServedUserNumbers:
++ /* We don't handle this yet */
++ break;
++#endif /* We don't handle this yet */
++ case Fac_DiversionInformation:
++ /* Sent to the served user when a call is forwarded. */
++ /* We do not have anything to do for this message. */
++ break;
++ case Fac_CallDeflection:
++ if (ch && ch->ast) {
++ switch (bc->fac_in.u.CallDeflection.ComponentType) {
++ case FacComponent_Invoke:
++ ast_copy_string(bc->redirecting.from.number, bc->dialed.number,
++ sizeof(bc->redirecting.from.number));
++ bc->redirecting.from.name[0] = 0;
++ bc->redirecting.from.number_plan = bc->dialed.number_plan;
++ bc->redirecting.from.number_type = bc->dialed.number_type;
++ bc->redirecting.from.screening = 0;/* Unscreened */
++ if (bc->fac_in.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent) {
++ bc->redirecting.from.presentation =
++ bc->fac_in.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser
++ ? 0 /* Allowed */ : 1 /* Restricted */;
++ } else {
++ bc->redirecting.from.presentation = 0;/* Allowed */
++ }
++
++ /* Add configured prefix to the call deflection number */
++ memset(&party_id, 0, sizeof(party_id));
++ misdn_PartyNumber_extract(&party_id,
++ &bc->fac_in.u.CallDeflection.Component.Invoke.Deflection.Party);
++ misdn_add_number_prefix(bc->port, party_id.number_type,
++ party_id.number, sizeof(party_id.number));
++ //party_id.presentation = 0;/* Allowed */
++ //party_id.screening = 0;/* Unscreened */
++ bc->redirecting.to = party_id;
++
++ ++bc->redirecting.count;
++ bc->redirecting.reason = mISDN_REDIRECTING_REASON_DEFLECTION;
++
++ misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting);
++ ast_string_field_set(ch->ast, call_forward, bc->redirecting.to.number);
++
++ /* Send back positive ACK */
++ bc->fac_out.Function = Fac_CallDeflection;
++ bc->fac_out.u.CallDeflection.InvokeID = bc->fac_in.u.CallDeflection.InvokeID;
++ bc->fac_out.u.CallDeflection.ComponentType = FacComponent_Result;
++ print_facility(&bc->fac_out, bc);
++ misdn_lib_send_event(bc, EVENT_DISCONNECT);
++
++ /* This line is BUSY to further attempts by this dialing attempt. */
++ ast_queue_control(ch->ast, AST_CONTROL_BUSY);
++ break;
++
++ case FacComponent_Result:
++ /* Positive ACK to call deflection */
++ /*
++ * Sent in DISCONNECT or FACILITY message depending upon network option.
++ * It is in the FACILITY message if the call is still offered to the user
++ * while trying to alert the deflected to party.
++ */
++ /* Ignore the ACK */
++ break;
++
++ default:
++ break;
++ }
++ }
++ break;
++#if 0 /* We don't handle this yet */
++ case Fac_CallRerouteing:
++ /* Private-Public ISDN interworking message */
++ /* We don't handle this yet */
++ break;
++#endif /* We don't handle this yet */
++ case Fac_DivertingLegInformation1:
++ /* Private-Public ISDN interworking message */
++ bc->div_leg_3_rx_wanted = 0;
++ if (ch && ch->ast) {
++ bc->redirecting.reason =
++ diversion_reason_to_misdn(bc->fac_in.u.DivertingLegInformation1.DiversionReason);
++ if (bc->fac_in.u.DivertingLegInformation1.DivertedToPresent) {
++ misdn_PresentedNumberUnscreened_extract(&bc->redirecting.to,
++ &bc->fac_in.u.DivertingLegInformation1.DivertedTo);
++
++ /* Add configured prefix to redirecting.to.number */
++ misdn_add_number_prefix(bc->port, bc->redirecting.to.number_type,
++ bc->redirecting.to.number, sizeof(bc->redirecting.to.number));
++ } else {
++ bc->redirecting.to.number[0] = '\0';
++ bc->redirecting.to.number_plan = NUMPLAN_ISDN;
++ bc->redirecting.to.number_type = NUMTYPE_UNKNOWN;
++ bc->redirecting.to.presentation = 1;/* restricted */
++ bc->redirecting.to.screening = 0;/* unscreened */
++ }
++ misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting);
++ bc->div_leg_3_rx_wanted = 1;
++ }
++ break;
++ case Fac_DivertingLegInformation2:
++ /* Private-Public ISDN interworking message */
++ switch (event) {
++ case EVENT_SETUP:
++ /* Comes in on a SETUP with redirecting.from information */
++ bc->div_leg_3_tx_pending = 1;
++ if (ch && ch->ast) {
++ /*
++ * Setup the redirecting.to informtion so we can identify
++ * if the user wants to manually supply the COLR for this
++ * redirected to number if further redirects could happen.
++ *
++ * All the user needs to do is set the REDIRECTING(to-pres)
++ * to the COLR and REDIRECTING(to-num) = ${EXTEN} to be safe
++ * after determining that the incoming call was redirected by
++ * checking if there is a REDIRECTING(from-num).
++ */
++ ast_copy_string(bc->redirecting.to.number, bc->dialed.number,
++ sizeof(bc->redirecting.to.number));
++ bc->redirecting.to.number_plan = bc->dialed.number_plan;
++ bc->redirecting.to.number_type = bc->dialed.number_type;
++ bc->redirecting.to.presentation = 1;/* restricted */
++ bc->redirecting.to.screening = 0;/* unscreened */
++
++ bc->redirecting.reason =
++ diversion_reason_to_misdn(bc->fac_in.u.DivertingLegInformation2.DiversionReason);
++ bc->redirecting.count = bc->fac_in.u.DivertingLegInformation2.DiversionCounter;
++ if (bc->fac_in.u.DivertingLegInformation2.DivertingPresent) {
++ /* This information is redundant if there was a redirecting ie in the SETUP. */
++ misdn_PresentedNumberUnscreened_extract(&bc->redirecting.from,
++ &bc->fac_in.u.DivertingLegInformation2.Diverting);
++
++ /* Add configured prefix to redirecting.from.number */
++ misdn_add_number_prefix(bc->port, bc->redirecting.from.number_type,
++ bc->redirecting.from.number, sizeof(bc->redirecting.from.number));
++ }
++#if 0
++ if (bc->fac_in.u.DivertingLegInformation2.OriginalCalledPresent) {
++ /* We have no place to put the OriginalCalled number */
++ }
++#endif
++ misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting);
++ }
++ break;
++ default:
++ chan_misdn_log(0, bc->port," --> Expected in a SETUP message: facility type:0x%04X\n",
++ bc->fac_in.Function);
++ break;
++ }
++ break;
++ case Fac_DivertingLegInformation3:
++ /* Private-Public ISDN interworking message */
++ if (bc->div_leg_3_rx_wanted) {
++ bc->div_leg_3_rx_wanted = 0;
++
++ if (ch && ch->ast) {
++ ch->ast->redirecting.to.number_presentation =
++ bc->fac_in.u.DivertingLegInformation3.PresentationAllowedIndicator
++ ? AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_UNSCREENED
++ : AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_UNSCREENED;
++ ast_channel_queue_redirecting_update(ch->ast, &ch->ast->redirecting);
++ }
++ }
++ break;
++
++#else /* !defined(AST_MISDN_ENHANCEMENTS) */
++
++ case Fac_CD:
++ if (ch && ch->ast) {
++ ast_copy_string(bc->redirecting.from.number, bc->dialed.number,
++ sizeof(bc->redirecting.from.number));
++ bc->redirecting.from.name[0] = 0;
++ bc->redirecting.from.number_plan = bc->dialed.number_plan;
++ bc->redirecting.from.number_type = bc->dialed.number_type;
++ bc->redirecting.from.screening = 0;/* Unscreened */
++ bc->redirecting.from.presentation =
++ bc->fac_in.u.CDeflection.PresentationAllowed
++ ? 0 /* Allowed */ : 1 /* Restricted */;
++
++ ast_copy_string(bc->redirecting.to.number,
++ (char *) bc->fac_in.u.CDeflection.DeflectedToNumber,
++ sizeof(bc->redirecting.to.number));
++ bc->redirecting.to.name[0] = 0;
++ bc->redirecting.to.number_plan = NUMPLAN_UNKNOWN;
++ bc->redirecting.to.number_type = NUMTYPE_UNKNOWN;
++ bc->redirecting.to.presentation = 0;/* Allowed */
++ bc->redirecting.to.screening = 0;/* Unscreened */
++
++ ++bc->redirecting.count;
++ bc->redirecting.reason = mISDN_REDIRECTING_REASON_DEFLECTION;
++
++ misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting);
++ ast_string_field_set(ch->ast, call_forward, bc->redirecting.to.number);
++
++ misdn_lib_send_event(bc, EVENT_DISCONNECT);
++
++ /* This line is BUSY to further attempts by this dialing attempt. */
++ ast_queue_control(ch->ast, AST_CONTROL_BUSY);
++ }
++ break;
++#endif /* !defined(AST_MISDN_ENHANCEMENTS) */
++ case Fac_AOCDCurrency:
++ if (ch && ch->ast) {
++ bc->AOCDtype = Fac_AOCDCurrency;
++ memcpy(&bc->AOCD.currency, &bc->fac_in.u.AOCDcur, sizeof(bc->AOCD.currency));
++ bc->AOCD_need_export = 1;
++ export_aoc_vars(ch->originator, ch->ast, bc);
++ }
++ break;
++ case Fac_AOCDChargingUnit:
++ if (ch && ch->ast) {
++ bc->AOCDtype = Fac_AOCDChargingUnit;
++ memcpy(&bc->AOCD.chargingUnit, &bc->fac_in.u.AOCDchu, sizeof(bc->AOCD.chargingUnit));
++ bc->AOCD_need_export = 1;
++ export_aoc_vars(ch->originator, ch->ast, bc);
++ }
++ break;
++#if defined(AST_MISDN_ENHANCEMENTS)
++ case Fac_ERROR:
++ diagnostic_msg = misdn_to_str_error_code(bc->fac_in.u.ERROR.errorValue);
++ chan_misdn_log(1, bc->port, " --> Facility error code: %s\n", diagnostic_msg);
++ switch (event) {
++ case EVENT_DISCONNECT:
++ case EVENT_RELEASE:
++ case EVENT_RELEASE_COMPLETE:
++ /* Possible call failure as a result of Fac_CCBSCall/Fac_CCBS_T_Call */
++ if (ch && ch->peer) {
++ misdn_cc_set_peer_var(ch->peer, MISDN_ERROR_MSG, diagnostic_msg);
++ }
++ break;
++ default:
++ break;
++ }
++ AST_LIST_LOCK(&misdn_cc_records_db);
++ cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.ERROR.invokeId);
++ if (cc_record) {
++ cc_record->outstanding_message = 0;
++ cc_record->error_code = bc->fac_in.u.ERROR.errorValue;
++ }
++ AST_LIST_UNLOCK(&misdn_cc_records_db);
++ break;
++ case Fac_REJECT:
++ diagnostic_msg = misdn_to_str_reject_code(bc->fac_in.u.REJECT.Code);
++ chan_misdn_log(1, bc->port, " --> Facility reject code: %s\n", diagnostic_msg);
++ switch (event) {
++ case EVENT_DISCONNECT:
++ case EVENT_RELEASE:
++ case EVENT_RELEASE_COMPLETE:
++ /* Possible call failure as a result of Fac_CCBSCall/Fac_CCBS_T_Call */
++ if (ch && ch->peer) {
++ misdn_cc_set_peer_var(ch->peer, MISDN_ERROR_MSG, diagnostic_msg);
++ }
++ break;
++ default:
++ break;
++ }
++ if (bc->fac_in.u.REJECT.InvokeIDPresent) {
++ AST_LIST_LOCK(&misdn_cc_records_db);
++ cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.REJECT.InvokeID);
++ if (cc_record) {
++ cc_record->outstanding_message = 0;
++ cc_record->reject_code = bc->fac_in.u.REJECT.Code;
++ }
++ AST_LIST_UNLOCK(&misdn_cc_records_db);
++ }
++ break;
++ case Fac_RESULT:
++ AST_LIST_LOCK(&misdn_cc_records_db);
++ cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.RESULT.InvokeID);
++ if (cc_record) {
++ cc_record->outstanding_message = 0;
++ }
++ AST_LIST_UNLOCK(&misdn_cc_records_db);
++ break;
++#if 0 /* We don't handle this yet */
++ case Fac_EctExecute:
++ /* We don't handle this yet */
++ break;
++ case Fac_ExplicitEctExecute:
++ /* We don't handle this yet */
++ break;
++ case Fac_EctLinkIdRequest:
++ /* We don't handle this yet */
++ break;
++#endif /* We don't handle this yet */
++ case Fac_SubaddressTransfer:
++ /* We do not have anything to do for this message since we do not handle subaddreses. */
++ break;
++ case Fac_RequestSubaddress:
++ /* We do not have anything to do for this message since we do not handle subaddreses. */
++ break;
++ case Fac_EctInform:
++ /* Private-Public ISDN interworking message */
++ if (ch && ch->ast && bc->fac_in.u.EctInform.RedirectionPresent) {
++ /* Add configured prefix to the redirection number */
++ memset(&party_id, 0, sizeof(party_id));
++ misdn_PresentedNumberUnscreened_extract(&party_id,
++ &bc->fac_in.u.EctInform.Redirection);
++ misdn_add_number_prefix(bc->port, party_id.number_type,
++ party_id.number, sizeof(party_id.number));
++
++ /*
++ * It would be preferable to update the connected line information
++ * only when the message callStatus is active. However, the
++ * optional redirection number may not be present in the active
++ * message if an alerting message were received earlier.
++ *
++ * The consequences if we wind up sending two updates is benign.
++ * The other end will think that it got transferred twice.
++ */
++ misdn_queue_connected_line_update(ch->ast, &party_id,
++ (bc->fac_in.u.EctInform.Status == 0 /* alerting */)
++ ? AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING
++ : AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER);
++ }
++ break;
++#if 0 /* We don't handle this yet */
++ case Fac_EctLoopTest:
++ /* The use of this message is unclear on how it works to detect loops. */
++ /* We don't handle this yet */
++ break;
++#endif /* We don't handle this yet */
++ case Fac_CallInfoRetain:
++ switch (event) {
++ case EVENT_ALERTING:
++ case EVENT_DISCONNECT:
++ /* CCBS/CCNR is available */
++ if (ch && ch->peer) {
++ AST_LIST_LOCK(&misdn_cc_records_db);
++ if (ch->record_id == -1) {
++ cc_record = misdn_cc_new();
++ } else {
++ /*
++ * We are doing a call-completion attempt
++ * or the switch is sending us extra call-completion
++ * availability indications (erroneously?).
++ *
++ * Assume that the network request retention option
++ * is not on and that the current call-completion
++ * request is disabled.
++ */
++ cc_record = misdn_cc_find_by_id(ch->record_id);
++ if (cc_record) {
++ if (cc_record->ptp && cc_record->mode.ptp.bc) {
++ /*
++ * What? We are getting mixed messages from the
++ * switch. We are currently setup for
++ * point-to-point. Now we are switching to
++ * point-to-multipoint.
++ *
++ * Close the call-completion signaling link
++ */
++ cc_record->mode.ptp.bc->fac_out.Function = Fac_None;
++ cc_record->mode.ptp.bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
++ misdn_lib_send_event(cc_record->mode.ptp.bc, EVENT_RELEASE_COMPLETE);
++ }
++
++ /*
++ * Resetup the existing record for a possible new
++ * call-completion request.
++ */
++ new_record_id = misdn_cc_record_id_new();
++ if (new_record_id < 0) {
++ /* Looks like we must keep the old id anyway. */
++ } else {
++ cc_record->record_id = new_record_id;
++ ch->record_id = new_record_id;
++ }
++ cc_record->ptp = 0;
++ cc_record->port = bc->port;
++ memset(&cc_record->mode, 0, sizeof(cc_record->mode));
++ cc_record->mode.ptmp.linkage_id = bc->fac_in.u.CallInfoRetain.CallLinkageID;
++ cc_record->invoke_id = ++misdn_invoke_id;
++ cc_record->activated = 0;
++ cc_record->outstanding_message = 0;
++ cc_record->activation_requested = 0;
++ cc_record->error_code = FacError_None;
++ cc_record->reject_code = FacReject_None;
++ memset(&cc_record->remote_user_free, 0, sizeof(cc_record->remote_user_free));
++ memset(&cc_record->b_free, 0, sizeof(cc_record->b_free));
++ cc_record->time_created = time(NULL);
++
++ cc_record = NULL;
++ } else {
++ /*
++ * Where did the record go? We will have to recapture
++ * the call setup information. Unfortunately, some
++ * setup information may have been changed.
++ */
++ ch->record_id = -1;
++ cc_record = misdn_cc_new();
++ }
++ }
++ if (cc_record) {
++ ch->record_id = cc_record->record_id;
++ cc_record->ptp = 0;
++ cc_record->port = bc->port;
++ cc_record->mode.ptmp.linkage_id = bc->fac_in.u.CallInfoRetain.CallLinkageID;
++
++ /* Record call information for possible call-completion attempt. */
++ cc_record->redial.caller = bc->caller;
++ cc_record->redial.dialed = bc->dialed;
++ cc_record->redial.setup_bc_hlc_llc = bc->setup_bc_hlc_llc;
++ cc_record->redial.capability = bc->capability;
++ cc_record->redial.hdlc = bc->hdlc;
++ }
++ AST_LIST_UNLOCK(&misdn_cc_records_db);
++
++ /* Set MISDN_CC_RECORD_ID in original channel */
++ if (ch->record_id != -1) {
++ snprintf(buf, sizeof(buf), "%ld", ch->record_id);
++ } else {
++ buf[0] = 0;
++ }
++ misdn_cc_set_peer_var(ch->peer, MISDN_CC_RECORD_ID, buf);
++ }
++ break;
++ default:
++ chan_misdn_log(0, bc->port,
++ " --> Expected in a DISCONNECT or ALERTING message: facility type:0x%04X\n",
++ bc->fac_in.Function);
++ break;
++ }
++ break;
++ case Fac_CCBS_T_Call:
++ case Fac_CCBSCall:
++ switch (event) {
++ case EVENT_SETUP:
++ /*
++ * This is a call completion retry call.
++ * If we had anything to do we would do it here.
++ */
++ break;
++ default:
++ chan_misdn_log(0, bc->port, " --> Expected in a SETUP message: facility type:0x%04X\n",
++ bc->fac_in.Function);
++ break;
++ }
++ break;
++ case Fac_CCBSDeactivate:
++ switch (bc->fac_in.u.CCBSDeactivate.ComponentType) {
++ case FacComponent_Result:
++ AST_LIST_LOCK(&misdn_cc_records_db);
++ cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.CCBSDeactivate.InvokeID);
++ if (cc_record) {
++ cc_record->outstanding_message = 0;
++ }
++ AST_LIST_UNLOCK(&misdn_cc_records_db);
++ break;
++
++ default:
++ chan_misdn_log(0, bc->port, " --> not yet handled: facility type:0x%04X\n",
++ bc->fac_in.Function);
++ break;
++ }
++ break;
++ case Fac_CCBSErase:
++ AST_LIST_LOCK(&misdn_cc_records_db);
++ cc_record = misdn_cc_find_by_reference(bc->port, bc->fac_in.u.CCBSErase.CCBSReference);
++ if (cc_record) {
++ misdn_cc_delete(cc_record);
++ }
++ AST_LIST_UNLOCK(&misdn_cc_records_db);
++ break;
++ case Fac_CCBSRemoteUserFree:
++ misdn_cc_handle_remote_user_free(bc->port, &bc->fac_in);
++ break;
++ case Fac_CCBSBFree:
++ misdn_cc_handle_b_free(bc->port, &bc->fac_in);
++ break;
++ case Fac_CCBSStatusRequest:
++ misdn_cc_handle_ccbs_status_request(bc->port, &bc->fac_in);
++ break;
++ case Fac_EraseCallLinkageID:
++ AST_LIST_LOCK(&misdn_cc_records_db);
++ cc_record = misdn_cc_find_by_linkage(bc->port,
++ bc->fac_in.u.EraseCallLinkageID.CallLinkageID);
++ if (cc_record && !cc_record->activation_requested) {
++ /*
++ * The T-RETENTION timer expired before we requested
++ * call completion activation. Call completion is no
++ * longer available.
++ */
++ misdn_cc_delete(cc_record);
++ }
++ AST_LIST_UNLOCK(&misdn_cc_records_db);
++ break;
++ case Fac_CCBSStopAlerting:
++ /* We do not have anything to do for this message. */
++ break;
++ case Fac_CCBSRequest:
++ case Fac_CCNRRequest:
++ switch (bc->fac_in.u.CCBSRequest.ComponentType) {
++ case FacComponent_Result:
++ AST_LIST_LOCK(&misdn_cc_records_db);
++ cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.CCBSRequest.InvokeID);
++ if (cc_record && !cc_record->ptp) {
++ cc_record->outstanding_message = 0;
++ cc_record->activated = 1;
++ cc_record->mode.ptmp.recall_mode = bc->fac_in.u.CCBSRequest.Component.Result.RecallMode;
++ cc_record->mode.ptmp.reference_id = bc->fac_in.u.CCBSRequest.Component.Result.CCBSReference;
++ }
++ AST_LIST_UNLOCK(&misdn_cc_records_db);
++ break;
++
++ default:
++ chan_misdn_log(0, bc->port, " --> not yet handled: facility type:0x%04X\n",
++ bc->fac_in.Function);
++ break;
++ }
++ break;
++#if 0 /* We don't handle this yet */
++ case Fac_CCBSInterrogate:
++ case Fac_CCNRInterrogate:
++ /* We don't handle this yet */
++ break;
++ case Fac_StatusRequest:
++ /* We don't handle this yet */
++ break;
++#endif /* We don't handle this yet */
++#if 0 /* We don't handle this yet */
++ case Fac_CCBS_T_Suspend:
++ case Fac_CCBS_T_Resume:
++ /* We don't handle this yet */
++ break;
++#endif /* We don't handle this yet */
++ case Fac_CCBS_T_RemoteUserFree:
++ misdn_cc_handle_T_remote_user_free(bc);
++ break;
++ case Fac_CCBS_T_Available:
++ switch (event) {
++ case EVENT_ALERTING:
++ case EVENT_DISCONNECT:
++ /* CCBS-T/CCNR-T is available */
++ if (ch && ch->peer) {
++ int set_id = 1;
++
++ AST_LIST_LOCK(&misdn_cc_records_db);
++ if (ch->record_id == -1) {
++ cc_record = misdn_cc_new();
++ } else {
++ /*
++ * We are doing a call-completion attempt
++ * or the switch is sending us extra call-completion
++ * availability indications (erroneously?).
++ */
++ cc_record = misdn_cc_find_by_id(ch->record_id);
++ if (cc_record) {
++ if (cc_record->ptp && cc_record->mode.ptp.retention_enabled) {
++ /*
++ * Call-completion is still activated.
++ * The user does not have to request it again.
++ */
++ chan_misdn_log(1, bc->port, " --> Call-completion request retention option is enabled\n");
++
++ set_id = 0;
++ } else {
++ if (cc_record->ptp && cc_record->mode.ptp.bc) {
++ /*
++ * The network request retention option
++ * is not on and the current call-completion
++ * request is to be disabled.
++ *
++ * We should get here only if EVENT_DISCONNECT
++ *
++ * Close the call-completion signaling link
++ */
++ cc_record->mode.ptp.bc->fac_out.Function = Fac_None;
++ cc_record->mode.ptp.bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
++ misdn_lib_send_event(cc_record->mode.ptp.bc, EVENT_RELEASE_COMPLETE);
++ }
++
++ /*
++ * Resetup the existing record for a possible new
++ * call-completion request.
++ */
++ new_record_id = misdn_cc_record_id_new();
++ if (new_record_id < 0) {
++ /* Looks like we must keep the old id anyway. */
++ } else {
++ cc_record->record_id = new_record_id;
++ ch->record_id = new_record_id;
++ }
++ cc_record->ptp = 1;
++ cc_record->port = bc->port;
++ memset(&cc_record->mode, 0, sizeof(cc_record->mode));
++ cc_record->invoke_id = ++misdn_invoke_id;
++ cc_record->activated = 0;
++ cc_record->outstanding_message = 0;
++ cc_record->activation_requested = 0;
++ cc_record->error_code = FacError_None;
++ cc_record->reject_code = FacReject_None;
++ memset(&cc_record->remote_user_free, 0, sizeof(cc_record->remote_user_free));
++ memset(&cc_record->b_free, 0, sizeof(cc_record->b_free));
++ cc_record->time_created = time(NULL);
++ }
++ cc_record = NULL;
++ } else {
++ /*
++ * Where did the record go? We will have to recapture
++ * the call setup information. Unfortunately, some
++ * setup information may have been changed.
++ */
++ ch->record_id = -1;
++ cc_record = misdn_cc_new();
++ }
++ }
++ if (cc_record) {
++ ch->record_id = cc_record->record_id;
++ cc_record->ptp = 1;
++ cc_record->port = bc->port;
++
++ /* Record call information for possible call-completion attempt. */
++ cc_record->redial.caller = bc->caller;
++ cc_record->redial.dialed = bc->dialed;
++ cc_record->redial.setup_bc_hlc_llc = bc->setup_bc_hlc_llc;
++ cc_record->redial.capability = bc->capability;
++ cc_record->redial.hdlc = bc->hdlc;
++ }
++ AST_LIST_UNLOCK(&misdn_cc_records_db);
++
++ /* Set MISDN_CC_RECORD_ID in original channel */
++ if (ch->record_id != -1 && set_id) {
++ snprintf(buf, sizeof(buf), "%ld", ch->record_id);
++ } else {
++ buf[0] = 0;
++ }
++ misdn_cc_set_peer_var(ch->peer, MISDN_CC_RECORD_ID, buf);
++ }
++ break;
++ default:
++ chan_misdn_log(0, bc->port,
++ " --> Expected in a DISCONNECT or ALERTING message: facility type:0x%04X\n",
++ bc->fac_in.Function);
++ break;
++ }
++ break;
++ case Fac_CCBS_T_Request:
++ case Fac_CCNR_T_Request:
++ switch (bc->fac_in.u.CCBS_T_Request.ComponentType) {
++ case FacComponent_Result:
++ AST_LIST_LOCK(&misdn_cc_records_db);
++ cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.CCBS_T_Request.InvokeID);
++ if (cc_record && cc_record->ptp) {
++ cc_record->outstanding_message = 0;
++ cc_record->activated = 1;
++ cc_record->mode.ptp.retention_enabled =
++ cc_record->mode.ptp.requested_retention
++ ? bc->fac_in.u.CCBS_T_Request.Component.Result.RetentionSupported
++ ? 1 : 0
++ : 0;
++ }
++ AST_LIST_UNLOCK(&misdn_cc_records_db);
++ break;
++
++ case FacComponent_Invoke:
++ /* We cannot be User-B in ptp mode. */
++ default:
++ chan_misdn_log(0, bc->port, " --> not yet handled: facility type:0x%04X\n",
++ bc->fac_in.Function);
++ break;
++ }
++ break;
++
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++ case Fac_None:
++ break;
++ default:
++ chan_misdn_log(0, bc->port, " --> not yet handled: facility type:0x%04X\n",
++ bc->fac_in.Function);
++ break;
++ }
++}
++
+ /************************************************************/
+ /* Receive Events from isdn_lib here */
+ /************************************************************/
+ static enum event_response_e
+ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
+ {
++#if defined(AST_MISDN_ENHANCEMENTS)
++ struct misdn_cc_record *cc_record;
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
+ struct chan_list *ch = find_chan_by_bc(cl_te, bc);
+-
+- if (event != EVENT_BCHAN_DATA && event != EVENT_TONE_GENERATE) { /* Debug Only Non-Bchan */
++
++ if (event != EVENT_BCHAN_DATA && event != EVENT_TONE_GENERATE) {
+ int debuglevel = 1;
+- if ( event == EVENT_CLEANUP && !user_data) {
++
++ /* Debug Only Non-Bchan */
++ if (event == EVENT_CLEANUP && !user_data) {
+ debuglevel = 5;
+ }
+
+- chan_misdn_log(debuglevel, bc->port, "I IND :%s oad:%s dad:%s pid:%d state:%s\n", manager_isdn_get_info(event), bc->oad, bc->dad, bc->pid, ch ? misdn_get_ch_state(ch) : "none");
++ chan_misdn_log(debuglevel, bc->port,
++ "I IND :%s caller:\"%s\" <%s> dialed:%s pid:%d state:%s\n",
++ manager_isdn_get_info(event),
++ bc->caller.name,
++ bc->caller.number,
++ bc->dialed.number,
++ bc->pid,
++ ch ? misdn_get_ch_state(ch) : "none");
+ if (debuglevel == 1) {
+ misdn_lib_log_ies(bc);
+ chan_misdn_log(4, bc->port, " --> bc_state:%s\n", bc_state2str(bc->bc_state));
+ }
+ }
+-
++
+ if (!ch) {
+ switch(event) {
+ case EVENT_SETUP:
+@@ -4290,6 +9334,7 @@
+ case EVENT_RETRIEVE:
+ case EVENT_NEW_BC:
+ case EVENT_FACILITY:
++ case EVENT_REGISTER:
+ break;
+ case EVENT_RELEASE_COMPLETE:
+ chan_misdn_log(1, bc->port, " --> no Ch, so we've already released.\n");
+@@ -4303,7 +9348,7 @@
+ return -1;
+ }
+ }
+-
++
+ if (ch) {
+ switch (event) {
+ case EVENT_TONE_GENERATE:
+@@ -4318,16 +9363,17 @@
+ }
+ break;
+ default:
+- if (!ch->ast || !MISDN_ASTERISK_PVT(ch->ast) || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
++ if (!ch->ast || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
+ if (event != EVENT_BCHAN_DATA) {
+ ast_log(LOG_NOTICE, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
+ }
+ return -1;
+ }
++ break;
+ }
+ }
+-
+-
++
++
+ switch (event) {
+ case EVENT_PORT_ALARM:
+ {
+@@ -4335,17 +9381,17 @@
+ misdn_cfg_get(bc->port, MISDN_CFG_ALARM_BLOCK, &boa, sizeof(boa));
+ if (boa) {
+ cb_log(1, bc->port, " --> blocking\n");
+- misdn_lib_port_block(bc->port);
++ misdn_lib_port_block(bc->port);
+ }
+ }
+ break;
+ case EVENT_BCHAN_ACTIVATED:
+ break;
+-
++
+ case EVENT_NEW_CHANNEL:
+ update_name(ch->ast,bc->port,bc->channel);
+ break;
+-
++
+ case EVENT_NEW_L3ID:
+ ch->l3id=bc->l3_id;
+ ch->addr=bc->addr;
+@@ -4355,17 +9401,17 @@
+ if (!ch) {
+ ch = find_holded(cl_te,bc);
+ }
+-
++
+ if (!ch) {
+ ast_log(LOG_WARNING, "NEW_BC without chan_list?\n");
+ break;
+ }
+
+ if (bc) {
+- ch->bc = (struct misdn_bchannel *)user_data;
++ ch->bc = (struct misdn_bchannel *) user_data;
+ }
+ break;
+-
++
+ case EVENT_DTMF_TONE:
+ {
+ /* sending INFOS as DTMF-Frames :) */
+@@ -4381,56 +9427,54 @@
+ fr.mallocd = 0;
+ fr.offset = 0;
+ fr.delivery = ast_tv(0,0);
+-
++
+ if (!ch->ignore_dtmf) {
+ chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
+ ast_queue_frame(ch->ast, &fr);
+ } else {
+ chan_misdn_log(2, bc->port, " --> Ignoring DTMF:%c due to bridge flags\n", bc->dtmf);
+ }
++ break;
+ }
+- break;
+ case EVENT_STATUS:
+ break;
+-
++
+ case EVENT_INFORMATION:
+ if (ch->state != MISDN_CONNECTED) {
+ stop_indicate(ch);
+ }
+-
++
+ if (!ch->ast) {
+ break;
+ }
+
+- if (ch->state == MISDN_WAITING4DIGS ) {
++ if (ch->state == MISDN_WAITING4DIGS) {
+ /* Ok, incomplete Setup, waiting till extension exists */
+ if (ast_strlen_zero(bc->info_dad) && ! ast_strlen_zero(bc->keypad)) {
+ chan_misdn_log(1, bc->port, " --> using keypad as info\n");
+ ast_copy_string(bc->info_dad, bc->keypad, sizeof(bc->info_dad));
+ }
+
+- strncat(bc->dad, bc->info_dad, sizeof(bc->dad) - strlen(bc->dad) - 1);
+- ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
++ strncat(bc->dialed.number, bc->info_dad, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
++ ast_copy_string(ch->ast->exten, bc->dialed.number, sizeof(ch->ast->exten));
+
+ /* Check for Pickup Request first */
+ if (!strcmp(ch->ast->exten, ast_pickup_ext())) {
+ if (ast_pickup_call(ch->ast)) {
+ hangup_chan(ch);
+ } else {
+- struct ast_channel *chan = ch->ast;
+ ch->state = MISDN_CALLING_ACKNOWLEDGE;
+- ast_setstate(chan, AST_STATE_DOWN);
+ hangup_chan(ch);
+ ch->ast = NULL;
+ break;
+ }
+ }
+-
+- if (!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
+- if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) {
++
++ if (!ast_canmatch_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
++ if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->caller.number)) {
+ ast_log(LOG_WARNING,
+ "Extension '%s@%s' can never match. Jumping to 'i' extension. port:%d\n",
+- bc->dad, ch->context, bc->port);
++ bc->dialed.number, ch->context, bc->port);
+ strcpy(ch->ast->exten, "i");
+
+ ch->state = MISDN_DIALING;
+@@ -4441,7 +9485,7 @@
+ ast_log(LOG_WARNING,
+ "Extension '%s@%s' can never match. Disconnecting. port:%d\n"
+ "\tMaybe you want to add an 'i' extension to catch this case.\n",
+- bc->dad, ch->context, bc->port);
++ bc->dialed.number, ch->context, bc->port);
+
+ if (bc->nt) {
+ hanguptone_indicate(ch);
+@@ -4458,13 +9502,13 @@
+ ch->overlap_tv = ast_tvnow();
+ ast_mutex_unlock(&ch->overlap_tv_lock);
+ if (ch->overlap_dial_task == -1) {
+- ch->overlap_dial_task =
++ ch->overlap_dial_task =
+ misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
+ }
+ break;
+ }
+
+- if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
++ if (ast_exists_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
+ ch->state = MISDN_DIALING;
+ start_pbx(ch, bc, ch->ast);
+ }
+@@ -4485,13 +9529,13 @@
+ fr.delivery = ast_tv(0,0);
+
+ misdn_cfg_get(0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(digits));
+- if (ch->state != MISDN_CONNECTED ) {
++ if (ch->state != MISDN_CONNECTED) {
+ if (digits) {
+- strncat(bc->dad, bc->info_dad, sizeof(bc->dad) - strlen(bc->dad) - 1);
+- ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
++ strncat(bc->dialed.number, bc->info_dad, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
++ ast_copy_string(ch->ast->exten, bc->dialed.number, sizeof(ch->ast->exten));
+ ast_cdr_update(ch->ast);
+ }
+-
++
+ ast_queue_frame(ch->ast, &fr);
+ }
+ }
+@@ -4499,10 +9543,9 @@
+ case EVENT_SETUP:
+ {
+ struct chan_list *ch = find_chan_by_bc(cl_te, bc);
+- int msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dad);
++ int msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dialed.number);
+ struct ast_channel *chan;
+ int exceed;
+- int pres, screen;
+ int ai;
+ int im;
+
+@@ -4533,7 +9576,6 @@
+ print_bearer(bc);
+
+ ch = init_chan_list(ORG_MISDN);
+-
+ if (!ch) {
+ chan_misdn_log(-1, bc->port, "cb_events: malloc for chan_list failed!\n");
+ return 0;
+@@ -4542,13 +9584,11 @@
+ ch->bc = bc;
+ ch->l3id = bc->l3_id;
+ ch->addr = bc->addr;
+- ch->originator = ORG_MISDN;
+
+- chan = misdn_new(ch, AST_STATE_RESERVED, bc->dad, bc->oad, AST_FORMAT_ALAW, bc->port, bc->channel);
+-
++ chan = misdn_new(ch, AST_STATE_RESERVED, bc->dialed.number, bc->caller.number, AST_FORMAT_ALAW, bc->port, bc->channel);
+ if (!chan) {
+ misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
+- ast_log(LOG_ERROR, "cb_events: misdn_new failed !\n");
++ ast_log(LOG_ERROR, "cb_events: misdn_new failed !\n");
+ return 0;
+ }
+
+@@ -4560,50 +9600,34 @@
+ pbx_builtin_setvar_helper(chan, "MAX_OVERFLOW", tmp);
+ }
+
+- read_config(ch, ORG_MISDN);
++ read_config(ch);
+
+ export_ch(chan, bc, ch);
+
+ ch->ast->rings = 1;
+ ast_setstate(ch->ast, AST_STATE_RINGING);
+
+- switch (bc->pres) {
+- case 1:
+- pres = AST_PRES_RESTRICTED;
+- chan_misdn_log(2, bc->port, " --> PRES: Restricted (1)\n");
+- break;
+- case 2:
+- pres = AST_PRES_UNAVAILABLE;
+- chan_misdn_log(2, bc->port, " --> PRES: Unavailable (2)\n");
+- break;
+- default:
+- pres = AST_PRES_ALLOWED;
+- chan_misdn_log(2, bc->port, " --> PRES: Allowed (%d)\n", bc->pres);
+- break;
+- }
++ /* Update asterisk channel caller information */
++ chan_misdn_log(2, bc->port, " --> TON: %s(%d)\n", misdn_to_str_ton(bc->caller.number_type), bc->caller.number_type);
++ chan_misdn_log(2, bc->port, " --> PLAN: %s(%d)\n", misdn_to_str_plan(bc->caller.number_plan), bc->caller.number_plan);
++ chan->cid.cid_ton = misdn_to_ast_ton(bc->caller.number_type)
++ | misdn_to_ast_plan(bc->caller.number_plan);
+
+- switch (bc->screen) {
+- default:
+- case 0:
+- screen = AST_PRES_USER_NUMBER_UNSCREENED;
+- chan_misdn_log(2, bc->port, " --> SCREEN: Unscreened (%d)\n", bc->screen);
+- break;
+- case 1:
+- screen = AST_PRES_USER_NUMBER_PASSED_SCREEN;
+- chan_misdn_log(2, bc->port, " --> SCREEN: Passed screen (1)\n");
+- break;
+- case 2:
+- screen = AST_PRES_USER_NUMBER_FAILED_SCREEN;
+- chan_misdn_log(2, bc->port, " --> SCREEN: failed screen (2)\n");
+- break;
+- case 3:
+- screen = AST_PRES_NETWORK_NUMBER;
+- chan_misdn_log(2, bc->port, " --> SCREEN: Network Number (3)\n");
+- break;
++ chan_misdn_log(2, bc->port, " --> PRES: %s(%d)\n", misdn_to_str_pres(bc->caller.presentation), bc->caller.presentation);
++ chan_misdn_log(2, bc->port, " --> SCREEN: %s(%d)\n", misdn_to_str_screen(bc->caller.screening), bc->caller.screening);
++ chan->cid.cid_pres = misdn_to_ast_pres(bc->caller.presentation)
++ | misdn_to_ast_screen(bc->caller.screening);
++
++ ast_set_callerid(chan, bc->caller.number, NULL, bc->caller.number);
++
++ if (!ast_strlen_zero(bc->redirecting.from.number)) {
++ /* Add configured prefix to redirecting.from.number */
++ misdn_add_number_prefix(bc->port, bc->redirecting.from.number_type, bc->redirecting.from.number, sizeof(bc->redirecting.from.number));
++
++ /* Update asterisk channel redirecting information */
++ misdn_copy_redirecting_to_ast(chan, &bc->redirecting);
+ }
+
+- chan->cid.cid_pres = pres | screen;
+-
+ pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
+ chan->transfercapability = bc->capability;
+
+@@ -4613,6 +9637,7 @@
+ break;
+ default:
+ pbx_builtin_setvar_helper(chan, "CALLTYPE", "SPEECH");
++ break;
+ }
+
+ /** queue new chan **/
+@@ -4632,7 +9657,7 @@
+ break;
+ }
+ }
+- } /* end for */
++ }
+ if (i == ARRAY_LEN(allowed_bearers_array)) {
+ /* We did not find the bearer capability */
+ chan_misdn_log(0, bc->port, "Bearer capability not allowed: %s(%d)\n",
+@@ -4645,11 +9670,15 @@
+ }
+ }
+
++ if (bc->fac_in.Function != Fac_None) {
++ misdn_facility_ie_handler(event, bc, ch);
++ }
++
+ /* Check for Pickup Request first */
+ if (!strcmp(chan->exten, ast_pickup_ext())) {
+ if (!ch->noautorespond_on_setup) {
+- int ret;/** Sending SETUP_ACK**/
+- ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
++ /* Sending SETUP_ACK */
++ misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
+ } else {
+ ch->state = MISDN_INCOMING_SETUP;
+ }
+@@ -4657,7 +9686,6 @@
+ hangup_chan(ch);
+ } else {
+ ch->state = MISDN_CALLING_ACKNOWLEDGE;
+- ast_setstate(chan, AST_STATE_DOWN);
+ hangup_chan(ch);
+ ch->ast = NULL;
+ break;
+@@ -4674,19 +9702,19 @@
+ break;
+ }
+
+- /* check if we should jump into s when we have no dad */
++ /* check if we should jump into s when we have no dialed.number */
+ misdn_cfg_get(bc->port, MISDN_CFG_IMMEDIATE, &im, sizeof(im));
+- if (im && ast_strlen_zero(bc->dad)) {
++ if (im && ast_strlen_zero(bc->dialed.number)) {
+ do_immediate_setup(bc, ch, chan);
+ break;
+ }
+
+ chan_misdn_log(5, bc->port, "CONTEXT:%s\n", ch->context);
+- if (!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
+- if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) {
++ if (!ast_canmatch_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
++ if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->caller.number)) {
+ ast_log(LOG_WARNING,
+ "Extension '%s@%s' can never match. Jumping to 'i' extension. port:%d\n",
+- bc->dad, ch->context, bc->port);
++ bc->dialed.number, ch->context, bc->port);
+ strcpy(ch->ast->exten, "i");
+ misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
+ ch->state = MISDN_DIALING;
+@@ -4697,7 +9725,7 @@
+ ast_log(LOG_WARNING,
+ "Extension '%s@%s' can never match. Disconnecting. port:%d\n"
+ "\tMaybe you want to add an 'i' extension to catch this case.\n",
+- bc->dad, ch->context, bc->port);
++ bc->dialed.number, ch->context, bc->port);
+ if (bc->nt) {
+ hanguptone_indicate(ch);
+ }
+@@ -4706,17 +9734,16 @@
+ bc->out_cause = AST_CAUSE_UNALLOCATED;
+
+ misdn_lib_send_event(bc, bc->nt ? EVENT_RELEASE_COMPLETE : EVENT_RELEASE);
+-
+ break;
+ }
+
+- /* Whatever happens, when sending_complete is set or we are PTMP TE, we will definitely
+- * jump into the dialplan, when the dialed extension does not exist, the 's' extension
++ /* Whatever happens, when sending_complete is set or we are PTMP TE, we will definitely
++ * jump into the dialplan, when the dialed extension does not exist, the 's' extension
+ * will be used by Asterisk automatically. */
+ if (bc->sending_complete || (!bc->nt && !misdn_lib_is_ptp(bc->port))) {
+ if (!ch->noautorespond_on_setup) {
+ ch->state=MISDN_DIALING;
+- misdn_lib_send_event(bc, EVENT_PROCEEDING );
++ misdn_lib_send_event(bc, EVENT_PROCEEDING);
+ } else {
+ ch->state = MISDN_INCOMING_SETUP;
+ }
+@@ -4726,17 +9753,17 @@
+
+
+ /*
+- * When we are NT and overlapdial is set and if
++ * When we are NT and overlapdial is set and if
+ * the number is empty, we wait for the ISDN timeout
+ * instead of our own timer.
+ */
+- if (ch->overlap_dial && bc->nt && !bc->dad[0] ) {
++ if (ch->overlap_dial && bc->nt && !bc->dialed.number[0]) {
+ wait_for_digits(ch, bc, chan);
+ break;
+ }
+
+- /*
+- * If overlapdial we will definitely send a SETUP_ACKNOWLEDGE and wait for more
++ /*
++ * If overlapdial we will definitely send a SETUP_ACKNOWLEDGE and wait for more
+ * Infos with a Interdigit Timeout.
+ * */
+ if (ch->overlap_dial) {
+@@ -4746,16 +9773,16 @@
+
+ wait_for_digits(ch, bc, chan);
+ if (ch->overlap_dial_task == -1) {
+- ch->overlap_dial_task =
++ ch->overlap_dial_task =
+ misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
+ }
+ break;
+ }
+
+- /* If the extension does not exist and we're not TE_PTMP we wait for more digits
++ /* If the extension does not exist and we're not TE_PTMP we wait for more digits
+ * without interdigit timeout.
+ * */
+- if (!ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
++ if (!ast_exists_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
+ wait_for_digits(ch, bc, chan);
+ break;
+ }
+@@ -4763,29 +9790,50 @@
+ /*
+ * If the extension exists let's just jump into it.
+ * */
+- if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
++ if (ast_exists_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
+ misdn_lib_send_event(bc, bc->need_more_infos ? EVENT_SETUP_ACKNOWLEDGE : EVENT_PROCEEDING);
+ ch->state = MISDN_DIALING;
+ start_pbx(ch, bc, chan);
+ break;
+ }
++ break;
+ }
++#if defined(AST_MISDN_ENHANCEMENTS)
++ case EVENT_REGISTER:
++ if (bc->fac_in.Function != Fac_None) {
++ misdn_facility_ie_handler(event, bc, ch);
++ }
++ /*
++ * Shut down this connection immediately.
++ * The current design of chan_misdn data structures
++ * does not allow the proper handling of inbound call records
++ * without an assigned B channel. Therefore, we cannot
++ * be the CCBS User-B party in a point-to-point setup.
++ */
++ bc->fac_out.Function = Fac_None;
++ bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
++ misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
+ break;
+-
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
+ case EVENT_SETUP_ACKNOWLEDGE:
+ ch->state = MISDN_CALLING_ACKNOWLEDGE;
+
+- if (bc->channel)
++ if (bc->channel) {
+ update_name(ch->ast,bc->port,bc->channel);
+-
++ }
++
++ if (bc->fac_in.Function != Fac_None) {
++ misdn_facility_ie_handler(event, bc, ch);
++ }
++
+ if (!ast_strlen_zero(bc->infos_pending)) {
+ /* TX Pending Infos */
+- strncat(bc->dad, bc->infos_pending, sizeof(bc->dad) - strlen(bc->dad) - 1);
++ strncat(bc->dialed.number, bc->infos_pending, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
+
+ if (!ch->ast) {
+ break;
+ }
+- ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
++ ast_copy_string(ch->ast->exten, bc->dialed.number, sizeof(ch->ast->exten));
+ ast_copy_string(bc->info_dad, bc->infos_pending, sizeof(bc->info_dad));
+ ast_copy_string(bc->infos_pending, "", sizeof(bc->infos_pending));
+
+@@ -4794,12 +9842,16 @@
+ break;
+ case EVENT_PROCEEDING:
+ if (misdn_cap_is_speech(bc->capability) &&
+- misdn_inband_avail(bc) ) {
++ misdn_inband_avail(bc)) {
+ start_bc_tones(ch);
+ }
+
+ ch->state = MISDN_PROCEEDING;
+-
++
++ if (bc->fac_in.Function != Fac_None) {
++ misdn_facility_ie_handler(event, bc, ch);
++ }
++
+ if (!ch->ast) {
+ break;
+ }
+@@ -4811,12 +9863,16 @@
+ update_name(ch->ast, bc->port, bc->channel);
+ }
+
+- if (!bc->nt ) {
++ if (bc->fac_in.Function != Fac_None) {
++ misdn_facility_ie_handler(event, bc, ch);
++ }
++
++ if (!bc->nt) {
+ if (misdn_cap_is_speech(bc->capability) &&
+ misdn_inband_avail(bc)) {
+ start_bc_tones(ch);
+ }
+-
++
+ ch->state = MISDN_PROGRESS;
+
+ if (!ch->ast) {
+@@ -4827,16 +9883,20 @@
+ break;
+ case EVENT_ALERTING:
+ ch->state = MISDN_ALERTING;
+-
++
+ if (!ch->ast) {
+ break;
+ }
+
++ if (bc->fac_in.Function != Fac_None) {
++ misdn_facility_ie_handler(event, bc, ch);
++ }
++
+ ast_queue_control(ch->ast, AST_CONTROL_RINGING);
+ ast_setstate(ch->ast, AST_STATE_RINGING);
+-
++
+ cb_log(7, bc->port, " --> Set State Ringing\n");
+-
++
+ if (misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
+ cb_log(1, bc->port, "Starting Tones, we have inband Data\n");
+ start_bc_tones(ch);
+@@ -4850,36 +9910,73 @@
+ }
+ break;
+ case EVENT_CONNECT:
+- {
+- struct ast_channel *bridged;
++ if (bc->fac_in.Function != Fac_None) {
++ misdn_facility_ie_handler(event, bc, ch);
++ }
++#if defined(AST_MISDN_ENHANCEMENTS)
++ if (bc->div_leg_3_rx_wanted) {
++ bc->div_leg_3_rx_wanted = 0;
+
+- /*we answer when we've got our very new L3 ID from the NT stack */
+- misdn_lib_send_event(bc, EVENT_CONNECT_ACKNOWLEDGE);
+-
+- if (!ch->ast) {
+- break;
++ if (ch->ast) {
++ ch->ast->redirecting.to.number_presentation =
++ AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_UNSCREENED;
++ ast_channel_queue_redirecting_update(ch->ast, &ch->ast->redirecting);
+ }
++ }
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
+
+- bridged = ast_bridged_channel(ch->ast);
+- stop_indicate(ch);
++ /* we answer when we've got our very new L3 ID from the NT stack */
++ misdn_lib_send_event(bc, EVENT_CONNECT_ACKNOWLEDGE);
+
+- if (bridged && !strcasecmp(bridged->tech->type, "mISDN")) {
+- struct chan_list *bridged_ch = MISDN_ASTERISK_TECH_PVT(bridged);
++ if (!ch->ast) {
++ break;
++ }
+
+- chan_misdn_log(1, bc->port, " --> copying cpndialplan:%d and cad:%s to the A-Channel\n", bc->cpnnumplan, bc->cad);
+- if (bridged_ch) {
+- bridged_ch->bc->cpnnumplan = bc->cpnnumplan;
+- ast_copy_string(bridged_ch->bc->cad, bc->cad, sizeof(bridged_ch->bc->cad));
++ stop_indicate(ch);
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++ if (ch->record_id != -1) {
++ /*
++ * We will delete the associated call completion
++ * record since we now have a completed call.
++ * We will not wait/depend on the network to tell
++ * us to delete it.
++ */
++ AST_LIST_LOCK(&misdn_cc_records_db);
++ cc_record = misdn_cc_find_by_id(ch->record_id);
++ if (cc_record) {
++ if (cc_record->ptp && cc_record->mode.ptp.bc) {
++ /* Close the call-completion signaling link */
++ cc_record->mode.ptp.bc->fac_out.Function = Fac_None;
++ cc_record->mode.ptp.bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
++ misdn_lib_send_event(cc_record->mode.ptp.bc, EVENT_RELEASE_COMPLETE);
+ }
++ misdn_cc_delete(cc_record);
+ }
++ AST_LIST_UNLOCK(&misdn_cc_records_db);
++ ch->record_id = -1;
++ if (ch->peer) {
++ misdn_cc_set_peer_var(ch->peer, MISDN_CC_RECORD_ID, "");
++
++ ao2_ref(ch->peer, -1);
++ ch->peer = NULL;
++ }
+ }
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++ /* Add configured prefix to connected.number */
++ misdn_add_number_prefix(bc->port, bc->connected.number_type, bc->connected.number, sizeof(bc->connected.number));
++
++ /* Update the connected line information on the other channel */
++ misdn_queue_connected_line_update(ch->ast, &bc->connected, AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER);
++
+ ch->l3id = bc->l3_id;
+ ch->addr = bc->addr;
+
+ start_bc_tones(ch);
+-
++
+ ch->state = MISDN_CONNECTED;
+-
++
+ ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
+ break;
+ case EVENT_CONNECT_ACKNOWLEDGE:
+@@ -4895,6 +9992,10 @@
+ if (ch) {
+ struct chan_list *holded_ch = find_holded(cl_te, bc);
+
++ if (bc->fac_in.Function != Fac_None) {
++ misdn_facility_ie_handler(event, bc, ch);
++ }
++
+ chan_misdn_log(3, bc->port, " --> org:%d nt:%d, inbandavail:%d state:%d\n", ch->originator, bc->nt, misdn_inband_avail(bc), ch->state);
+ if (ch->originator == ORG_AST && !bc->nt && misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
+ /* If there's inband information available (e.g. a
+@@ -4903,7 +10004,7 @@
+ alternative number, then play it instead of
+ immediately releasing the call */
+ chan_misdn_log(1, bc->port, " --> Inband Info Avail, not sending RELEASE\n");
+-
++
+ ch->state = MISDN_DISCONNECTED;
+ start_bc_tones(ch);
+
+@@ -4941,6 +10042,10 @@
+ }
+ break;
+ case EVENT_RELEASE:
++ if (bc->fac_in.Function != Fac_None) {
++ misdn_facility_ie_handler(event, bc, ch);
++ }
++
+ bc->need_disconnect = 0;
+ bc->need_release = 0;
+
+@@ -4948,22 +10053,41 @@
+ release_chan(bc);
+ break;
+ case EVENT_RELEASE_COMPLETE:
++ if (bc->fac_in.Function != Fac_None) {
++ misdn_facility_ie_handler(event, bc, ch);
++ }
++
+ bc->need_disconnect = 0;
+ bc->need_release = 0;
+ bc->need_release_complete = 0;
+
+- stop_bc_tones(ch);
+- hangup_chan(ch);
+-
+- if (ch)
++ if (ch) {
++ stop_bc_tones(ch);
++ hangup_chan(ch);
+ ch->state = MISDN_CLEANING;
++#if defined(AST_MISDN_ENHANCEMENTS)
++ } else {
++ /*
++ * A call-completion signaling link established with
++ * REGISTER does not have a struct chan_list record
++ * associated with it.
++ */
++ AST_LIST_LOCK(&misdn_cc_records_db);
++ cc_record = misdn_cc_find_by_bc(bc);
++ if (cc_record) {
++ /* The call-completion signaling link is closed. */
++ misdn_cc_delete(cc_record);
++ }
++ AST_LIST_UNLOCK(&misdn_cc_records_db);
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++ }
+
+ release_chan(bc);
+ break;
+ case EVENT_BCHAN_ERROR:
+ case EVENT_CLEANUP:
+ stop_bc_tones(ch);
+-
++
+ switch (ch->state) {
+ case MISDN_CALLING:
+ bc->cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
+@@ -4971,7 +10095,7 @@
+ default:
+ break;
+ }
+-
++
+ hangup_chan(ch);
+ release_chan(bc);
+ break;
+@@ -4997,30 +10121,30 @@
+ ast->generatordata = NULL;
+ generate = ast->generator->generate;
+
+- if (tone_len < 0 || tone_len > 512 ) {
++ if (tone_len < 0 || tone_len > 512) {
+ ast_log(LOG_NOTICE, "TONE_GEN: len was %d, set to 128\n", tone_len);
+ tone_len = 128;
+ }
+
+ res = generate(ast, tmp, tone_len, tone_len);
+ ast->generatordata = tmp;
+-
++
+ if (res) {
+ ast_log(LOG_WARNING, "Auto-deactivating generator\n");
+ ast_deactivate_generator(ast);
+ } else {
+ bc->tone_cnt = 0;
+ }
++ break;
+ }
+- break;
+-
+ case EVENT_BCHAN_DATA:
+ if (ch->bc->AOCD_need_export) {
+ export_aoc_vars(ch->originator, ch->ast, ch->bc);
+ }
+ if (!misdn_cap_is_speech(ch->bc->capability)) {
+ struct ast_frame frame;
+- /*In Data Modes we queue frames*/
++
++ /* In Data Modes we queue frames */
+ frame.frametype = AST_FRAME_VOICE; /* we have no data frames yet */
+ frame.subclass = AST_FORMAT_ALAW;
+ frame.datalen = bc->bframe_len;
+@@ -5031,8 +10155,9 @@
+ frame.src = NULL;
+ frame.data.ptr = bc->bframe;
+
+- if (ch->ast)
++ if (ch->ast) {
+ ast_queue_frame(ch->ast, &frame);
++ }
+ } else {
+ fd_set wrfs;
+ struct timeval tv = { 0, 0 };
+@@ -5042,17 +10167,16 @@
+ FD_SET(ch->pipe[1], &wrfs);
+
+ t = select(FD_SETSIZE, NULL, &wrfs, NULL, &tv);
+-
+ if (!t) {
+ chan_misdn_log(9, bc->port, "Select Timed out\n");
+ break;
+ }
+-
++
+ if (t < 0) {
+ chan_misdn_log(-1, bc->port, "Select Error (err=%s)\n", strerror(errno));
+ break;
+ }
+-
++
+ if (FD_ISSET(ch->pipe[1], &wrfs)) {
+ chan_misdn_log(9, bc->port, "writing %d bytes to asterisk\n", bc->bframe_len);
+ if (write(ch->pipe[1], bc->bframe, bc->bframe_len) <= 0) {
+@@ -5102,11 +10226,12 @@
+ misdn_lib_send_event(bc, EVENT_RELEASE);
+ }
+ break;
+- case MISDN_CLEANING:
++ case MISDN_CLEANING:
+ chan_misdn_log(1, bc->port, " --> in state cleaning .. so ignoring, the stack should clean it for us\n");
+ break;
+ default:
+ misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
++ break;
+ }
+ break;
+
+@@ -5140,13 +10265,13 @@
+ if (hold_ast) {
+ ast_moh_stop(hold_ast);
+ }
+-
++
+ if (misdn_lib_send_event(bc, EVENT_RETRIEVE_ACKNOWLEDGE) < 0) {
+ chan_misdn_log(4, bc->port, " --> RETRIEVE_ACK failed\n");
+ misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
+ }
++ break;
+ }
+- break;
+ case EVENT_HOLD:
+ {
+ int hold_allowed;
+@@ -5164,7 +10289,7 @@
+ chan_misdn_log(2, bc->port, "Bridge Partner is of type: %s\n", bridged->tech->type);
+ ch->state = MISDN_HOLDED;
+ ch->l3id = bc->l3_id;
+-
++
+ misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE);
+
+ /* XXX This should queue an AST_CONTROL_HOLD frame on this channel
+@@ -5179,61 +10304,80 @@
+ misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
+ chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
+ }
+- }
+ break;
+- case EVENT_FACILITY:
+- print_facility(&(bc->fac_in), bc);
+-
+- switch (bc->fac_in.Function) {
+-#ifdef HAVE_MISDN_FAC_RESULT
+- case Fac_RESULT:
++ }
++ case EVENT_NOTIFY:
++ if (bc->redirecting.to_changed) {
++ /* Add configured prefix to redirecting.to.number */
++ misdn_add_number_prefix(bc->port, bc->redirecting.to.number_type,
++ bc->redirecting.to.number, sizeof(bc->redirecting.to.number));
++ }
++ switch (bc->notify_description_code) {
++ case mISDN_NOTIFY_CODE_DIVERSION_ACTIVATED:
++ /* Ignore for now. */
++ bc->redirecting.to_changed = 0;
+ break;
+-#endif
+- case Fac_CD:
+- if (ch) {
+- struct ast_channel *bridged = ast_bridged_channel(ch->ast);
+- struct chan_list *ch_br;
+- if (bridged && MISDN_ASTERISK_TECH_PVT(bridged)) {
+- ch_br = MISDN_ASTERISK_TECH_PVT(bridged);
+- /*ch->state = MISDN_FACILITY_DEFLECTED;*/
+- if (ch_br->bc) {
+- if (ast_exists_extension(bridged, ch->context, (char *)bc->fac_in.u.CDeflection.DeflectedToNumber, 1, bc->oad)) {
+- ch_br->state = MISDN_DIALING;
+- if (pbx_start_chan(ch_br) < 0) {
+- chan_misdn_log(-1, ch_br->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
+- }
+- }
++ case mISDN_NOTIFY_CODE_CALL_IS_DIVERTING:
++ if (bc->redirecting.to_changed) {
++ bc->redirecting.to_changed = 0;
++ if (ch && ch->ast) {
++ switch (ch->state) {
++ case MISDN_ALERTING:
++ /* Call is deflecting after we have seen an ALERTING message */
++ bc->redirecting.reason = mISDN_REDIRECTING_REASON_NO_REPLY;
++ break;
++ default:
++ /* Call is deflecting for call forwarding unconditional or busy reason. */
++ bc->redirecting.reason = mISDN_REDIRECTING_REASON_UNKNOWN;
++ break;
+ }
++ misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting);
++ ast_channel_queue_redirecting_update(ch->ast, &ch->ast->redirecting);
+ }
+- misdn_lib_send_event(bc, EVENT_DISCONNECT);
+- }
++ }
+ break;
+- case Fac_AOCDCurrency:
+- if (ch) {
+- bc->AOCDtype = Fac_AOCDCurrency;
+- memcpy(&(bc->AOCD.currency), &(bc->fac_in.u.AOCDcur), sizeof(bc->AOCD.currency));
+- bc->AOCD_need_export = 1;
+- export_aoc_vars(ch->originator, ch->ast, bc);
++ case mISDN_NOTIFY_CODE_CALL_TRANSFER_ALERTING:
++ /*
++ * It would be preferable to update the connected line information
++ * only when the message callStatus is active. However, the
++ * optional redirection number may not be present in the active
++ * message if an alerting message were received earlier.
++ *
++ * The consequences if we wind up sending two updates is benign.
++ * The other end will think that it got transferred twice.
++ */
++ if (bc->redirecting.to_changed) {
++ bc->redirecting.to_changed = 0;
++ if (ch && ch->ast) {
++ misdn_queue_connected_line_update(ch->ast, &bc->redirecting.to,
++ AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING);
++ }
+ }
+ break;
+- case Fac_AOCDChargingUnit:
+- if (ch) {
+- bc->AOCDtype = Fac_AOCDChargingUnit;
+- memcpy(&(bc->AOCD.chargingUnit), &(bc->fac_in.u.AOCDchu), sizeof(bc->AOCD.chargingUnit));
+- bc->AOCD_need_export = 1;
+- export_aoc_vars(ch->originator, ch->ast, bc);
++ case mISDN_NOTIFY_CODE_CALL_TRANSFER_ACTIVE:
++ if (bc->redirecting.to_changed) {
++ bc->redirecting.to_changed = 0;
++ if (ch && ch->ast) {
++ misdn_queue_connected_line_update(ch->ast, &bc->redirecting.to,
++ AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER);
++ }
+ }
+ break;
+- case Fac_None:
+-#ifdef HAVE_MISDN_FAC_ERROR
+- case Fac_ERROR:
+-#endif
++ default:
++ bc->redirecting.to_changed = 0;
++ chan_misdn_log(0, bc->port," --> not yet handled: notify code:0x%02X\n",
++ bc->notify_description_code);
+ break;
+- default:
+- chan_misdn_log(0, bc->port," --> not yet handled: facility type:%d\n", bc->fac_in.Function);
+ }
+-
+ break;
++ case EVENT_FACILITY:
++ if (bc->fac_in.Function == Fac_None) {
++ /* This is a FACILITY message so we MUST have a facility ie */
++ chan_misdn_log(0, bc->port," --> Missing facility ie or unknown facility ie contents.\n");
++ } else {
++ misdn_facility_ie_handler(event, bc, ch);
++ }
++ break;
+ case EVENT_RESTART:
+ if (!bc->dummy) {
+ stop_bc_tones(ch);
+@@ -5244,12 +10388,140 @@
+ chan_misdn_log(1, 0, "Got Unknown Event\n");
+ break;
+ }
+-
++
+ return RESPONSE_OK;
+ }
+
+ /** TE STUFF END **/
+
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Get call completion record information.
++ *
++ * \param chan Asterisk channel to operate upon. (Not used)
++ * \param function_name Name of the function that called us.
++ * \param function_args Argument string passed to function (Could be NULL)
++ * \param buf Buffer to put returned string.
++ * \param size Size of the supplied buffer including the null terminator.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++static int misdn_cc_read(struct ast_channel *chan, const char *function_name,
++ char *function_args, char *buf, size_t size)
++{
++ char *parse;
++ struct misdn_cc_record *cc_record;
++
++ AST_DECLARE_APP_ARGS(args,
++ AST_APP_ARG(cc_id); /* Call completion record ID value. */
++ AST_APP_ARG(get_name); /* Name of what to get */
++ AST_APP_ARG(other); /* Any extraneous garbage arguments */
++ );
++
++ /* Ensure that the buffer is empty */
++ *buf = 0;
++
++ if (ast_strlen_zero(function_args)) {
++ ast_log(LOG_ERROR, "Function '%s' requires arguments.\n", function_name);
++ return -1;
++ }
++
++ parse = ast_strdupa(function_args);
++ AST_STANDARD_APP_ARGS(args, parse);
++
++ if (!args.argc || ast_strlen_zero(args.cc_id)) {
++ ast_log(LOG_ERROR, "Function '%s' missing call completion record ID.\n",
++ function_name);
++ return -1;
++ }
++ if (!isdigit(*args.cc_id)) {
++ ast_log(LOG_ERROR, "Function '%s' call completion record ID must be numeric.\n",
++ function_name);
++ return -1;
++ }
++
++ if (ast_strlen_zero(args.get_name)) {
++ ast_log(LOG_ERROR, "Function '%s' missing what-to-get parameter.\n",
++ function_name);
++ return -1;
++ }
++
++ AST_LIST_LOCK(&misdn_cc_records_db);
++ cc_record = misdn_cc_find_by_id(atoi(args.cc_id));
++ if (cc_record) {
++ if (!strcasecmp("a-all", args.get_name)) {
++ snprintf(buf, size, "\"%s\" <%s>", cc_record->redial.caller.name,
++ cc_record->redial.caller.number);
++ } else if (!strcasecmp("a-name", args.get_name)) {
++ ast_copy_string(buf, cc_record->redial.caller.name, size);
++ } else if (!strncasecmp("a-num", args.get_name, 5)) {
++ ast_copy_string(buf, cc_record->redial.caller.number, size);
++ } else if (!strcasecmp("a-ton", args.get_name)) {
++ snprintf(buf, size, "%d",
++ misdn_to_ast_plan(cc_record->redial.caller.number_plan)
++ | misdn_to_ast_ton(cc_record->redial.caller.number_type));
++ } else if (!strncasecmp("a-pres", args.get_name, 6)) {
++ ast_copy_string(buf, ast_named_caller_presentation(
++ misdn_to_ast_pres(cc_record->redial.caller.presentation)
++ | misdn_to_ast_screen(cc_record->redial.caller.screening)), size);
++ } else if (!strcasecmp("a-busy", args.get_name)) {
++ ast_copy_string(buf, cc_record->party_a_free ? "no" : "yes", size);
++ } else if (!strncasecmp("b-num", args.get_name, 5)) {
++ ast_copy_string(buf, cc_record->redial.dialed.number, size);
++ } else if (!strcasecmp("b-ton", args.get_name)) {
++ snprintf(buf, size, "%d",
++ misdn_to_ast_plan(cc_record->redial.dialed.number_plan)
++ | misdn_to_ast_ton(cc_record->redial.dialed.number_type));
++ } else if (!strcasecmp("port", args.get_name)) {
++ snprintf(buf, size, "%d", cc_record->port);
++ } else if (!strcasecmp("available-notify-priority", args.get_name)) {
++ snprintf(buf, size, "%d", cc_record->remote_user_free.priority);
++ } else if (!strcasecmp("available-notify-exten", args.get_name)) {
++ ast_copy_string(buf, cc_record->remote_user_free.exten, size);
++ } else if (!strcasecmp("available-notify-context", args.get_name)) {
++ ast_copy_string(buf, cc_record->remote_user_free.context, size);
++ } else if (!strcasecmp("busy-notify-priority", args.get_name)) {
++ snprintf(buf, size, "%d", cc_record->b_free.priority);
++ } else if (!strcasecmp("busy-notify-exten", args.get_name)) {
++ ast_copy_string(buf, cc_record->b_free.exten, size);
++ } else if (!strcasecmp("busy-notify-context", args.get_name)) {
++ ast_copy_string(buf, cc_record->b_free.context, size);
++ } else {
++ AST_LIST_UNLOCK(&misdn_cc_records_db);
++ ast_log(LOG_ERROR, "Function '%s': Unknown what-to-get '%s'.\n", function_name, args.get_name);
++ return -1;
++ }
++ }
++ AST_LIST_UNLOCK(&misdn_cc_records_db);
++
++ return 0;
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++static struct ast_custom_function misdn_cc_function = {
++ .name = "mISDN_CC",
++ .synopsis = "Get call completion record information.",
++ .syntax = "mISDN_CC(${MISDN_CC_RECORD_ID},<what-to-get>)",
++ .desc =
++ "mISDN_CC(${MISDN_CC_RECORD_ID},<what-to-get>)\n"
++ "The following can be retrieved:\n"
++ "\"a-num\", \"a-name\", \"a-all\", \"a-ton\", \"a-pres\", \"a-busy\",\n"
++ "\"b-num\", \"b-ton\", \"port\",\n"
++ " User-A is available for call completion:\n"
++ " \"available-notify-priority\",\n"
++ " \"available-notify-exten\",\n"
++ " \"available-notify-context\",\n"
++ " User-A is busy:\n"
++ " \"busy-notify-priority\",\n"
++ " \"busy-notify-exten\",\n"
++ " \"busy-notify-context\"\n",
++ .read = misdn_cc_read,
++};
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
+ /******************************************
+ *
+ * Asterisk Channel Endpoint END
+@@ -5265,24 +10537,28 @@
+ ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
+
+ misdn_tasks_destroy();
+-
++
+ if (!g_config_initialized) {
+ return 0;
+ }
+-
++
+ ast_cli_unregister_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
+
+ /* ast_unregister_application("misdn_crypt"); */
+ ast_unregister_application("misdn_set_opt");
+ ast_unregister_application("misdn_facility");
+ ast_unregister_application("misdn_check_l2l1");
++#if defined(AST_MISDN_ENHANCEMENTS)
++ ast_unregister_application(misdn_command_name);
++ ast_custom_function_unregister(&misdn_cc_function);
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
+
+ ast_channel_unregister(&misdn_tech);
+
+ free_robin_list();
+ misdn_cfg_destroy();
+ misdn_lib_destroy();
+-
++
+ if (misdn_debug) {
+ ast_free(misdn_debug);
+ }
+@@ -5290,7 +10566,11 @@
+ ast_free(misdn_debug_only);
+ }
+ ast_free(misdn_ports);
+-
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++ misdn_cc_destroy();
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
+ return 0;
+ }
+
+@@ -5308,18 +10588,22 @@
+ };
+
+ max_ports = misdn_lib_maxports_get();
+-
++
+ if (max_ports <= 0) {
+ ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
+ return AST_MODULE_LOAD_DECLINE;
+ }
+-
++
+ if (misdn_cfg_init(max_ports, 0)) {
+ ast_log(LOG_ERROR, "Unable to initialize misdn_config.\n");
+ return AST_MODULE_LOAD_DECLINE;
+ }
+ g_config_initialized = 1;
+-
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++ misdn_cc_init();
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
+ misdn_debug = ast_malloc(sizeof(int) * (max_ports + 1));
+ if (!misdn_debug) {
+ ast_log(LOG_ERROR, "Out of memory for misdn_debug\n");
+@@ -5366,7 +10650,7 @@
+
+ misdn_cfg_get(0, MISDN_GEN_NTDEBUGFLAGS, &ntflags, sizeof(ntflags));
+ misdn_cfg_get(0, MISDN_GEN_NTDEBUGFILE, &ntfile, sizeof(ntfile));
+- misdn_cfg_get( 0, MISDN_GEN_NTKEEPCALLS, &ntkc, sizeof(ntkc));
++ misdn_cfg_get(0, MISDN_GEN_NTKEEPCALLS, &ntkc, sizeof(ntkc));
+
+ misdn_lib_nt_keepcalls(ntkc);
+ misdn_lib_nt_debug_init(ntflags, ntfile);
+@@ -5376,7 +10660,7 @@
+ unload_module();
+ return AST_MODULE_LOAD_DECLINE;
+ }
+-
++
+ ast_cli_register_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
+
+ ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
+@@ -5407,45 +10691,71 @@
+ " vt - Tx gain control, optarg is gain\n"
+ );
+
+-
++
+ ast_register_application("misdn_facility", misdn_facility_exec, "misdn_facility",
+- "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
+- "Sends the Facility Message FACILITY_TYPE with \n"
+- "the given Arguments to the current ISDN Channel\n"
+- "Supported Facilities are:\n"
+- "\n"
+- "type=calldeflect args=Nr where to deflect\n"
++ "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
++ "Sends the Facility Message FACILITY_TYPE with \n"
++ "the given Arguments to the current ISDN Channel\n"
++ "Supported Facilities are:\n"
++ "\n"
++ "type=calldeflect args=Nr where to deflect\n"
+ );
+
+
+ ast_register_application("misdn_check_l2l1", misdn_check_l2l1, "misdn_check_l2l1",
+- "misdn_check_l2l1(<port>||g:<groupname>,timeout)"
+- "Checks if the L2 and L1 are up on either the given <port> or\n"
+- "on the ports in the group with <groupname>\n"
+- "If the L1/L2 are down, check_l2l1 gets up the L1/L2 and waits\n"
+- "for <timeout> seconds that this happens. Otherwise, nothing happens\n"
+- "\n"
+- "This application, ensures the L1/L2 state of the Ports in a group\n"
+- "it is intended to make the pmp_l1_check option redundant and to\n"
+- "fix a buggy switch config from your provider\n"
+- "\n"
+- "a sample dialplan would look like:\n\n"
+- "exten => _X.,1,misdn_check_l2l1(g:out|2)\n"
+- "exten => _X.,n,dial(mISDN/g:out/${EXTEN})\n"
+- "\n"
++ "misdn_check_l2l1(<port>||g:<groupname>,timeout)\n"
++ "Checks if the L2 and L1 are up on either the given <port> or\n"
++ "on the ports in the group with <groupname>\n"
++ "If the L1/L2 are down, check_l2l1 gets up the L1/L2 and waits\n"
++ "for <timeout> seconds that this happens. Otherwise, nothing happens\n"
++ "\n"
++ "This application, ensures the L1/L2 state of the Ports in a group\n"
++ "it is intended to make the pmp_l1_check option redundant and to\n"
++ "fix a buggy switch config from your provider\n"
++ "\n"
++ "a sample dialplan would look like:\n\n"
++ "exten => _X.,1,misdn_check_l2l1(g:out|2)\n"
++ "exten => _X.,n,dial(mISDN/g:out/${EXTEN})\n"
+ );
+
++#if defined(AST_MISDN_ENHANCEMENTS)
++ ast_register_application(misdn_command_name, misdn_command_exec, misdn_command_name,
++ "misdn_command(<command>[,<options>])\n"
++ "The following commands are defined:\n"
++ "cc-initialize\n"
++ " Setup mISDN support for call completion\n"
++ " Must call before doing any Dial() involving call completion.\n"
++ "ccnr-request,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>\n"
++ " Request Call Completion No Reply activation\n"
++ "ccbs-request,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>\n"
++ " Request Call Completion Busy Subscriber activation\n"
++ "cc-b-free,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>\n"
++ " Set the dialplan location to notify when User-B is available but User-A is busy.\n"
++ " Setting this dialplan location is optional.\n"
++ "cc-a-busy,${MISDN_CC_RECORD_ID},<yes/no>\n"
++ " Set the busy status of call completion User-A\n"
++ "cc-deactivate,${MISDN_CC_RECORD_ID}\n"
++ " Deactivate the identified call completion request\n"
++ "\n"
++ "MISDN_CC_RECORD_ID is set when Dial() returns and call completion is possible\n"
++ "MISDN_CC_STATUS is set to ACTIVATED or ERROR after the call completion\n"
++ "activation request.\n"
++ "MISDN_ERROR_MSG is set to a descriptive message on error.\n"
++ );
+
++ ast_custom_function_register(&misdn_cc_function);
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
+ misdn_cfg_get(0, MISDN_GEN_TRACEFILE, global_tracefile, sizeof(global_tracefile));
+
+ /* start the l1 watchers */
+-
++
+ for (port = misdn_cfg_get_next_port(0); port >= 0; port = misdn_cfg_get_next_port(port)) {
+ int l1timeout;
+ misdn_cfg_get(port, MISDN_CFG_L1_TIMEOUT, &l1timeout, sizeof(l1timeout));
+ if (l1timeout) {
+ chan_misdn_log(4, 0, "Adding L1watcher task: port:%d timeout:%ds\n", port, l1timeout);
+- misdn_tasks_add(l1timeout * 1000, misdn_l1_task, &misdn_ports[port]);
++ misdn_tasks_add(l1timeout * 1000, misdn_l1_task, &misdn_ports[port]);
+ }
+ }
+
+@@ -5465,23 +10775,646 @@
+
+ /*** SOME APPS ;)***/
+
+-static int misdn_facility_exec(struct ast_channel *chan, void *data)
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++* \brief misdn_command arguments container.
++*/
++AST_DEFINE_APP_ARGS_TYPE(misdn_command_args,
++ AST_APP_ARG(name); /* Subcommand name */
++ AST_APP_ARG(arg)[10 + 1]; /* Subcommand arguments */
++);
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++static void misdn_cc_caller_destroy(void *obj)
+ {
++ /* oh snap! */
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++static struct misdn_cc_caller *misdn_cc_caller_alloc(struct ast_channel *chan)
++{
++ struct misdn_cc_caller *cc_caller;
++
++ if (!(cc_caller = ao2_alloc(sizeof(*cc_caller), misdn_cc_caller_destroy))) {
++ return NULL;
++ }
++
++ cc_caller->chan = chan;
++
++ return cc_caller;
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief misdn_command(cc-initialize) subcommand handler
++ *
++ * \param chan Asterisk channel to operate upon.
++ * \param subcommand Arguments for the subcommand
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++static int misdn_command_cc_initialize(struct ast_channel *chan, struct misdn_command_args *subcommand)
++{
++ struct misdn_cc_caller *cc_caller;
++ struct ast_datastore *datastore;
++
++ if (!(cc_caller = misdn_cc_caller_alloc(chan))) {
++ return -1;
++ }
++
++ if (!(datastore = ast_datastore_alloc(&misdn_cc_ds_info, NULL))) {
++ ao2_ref(cc_caller, -1);
++ return -1;
++ }
++
++ ast_channel_lock(chan);
++
++ /* Inherit reference */
++ datastore->data = cc_caller;
++ cc_caller = NULL;
++
++ datastore->inheritance = DATASTORE_INHERIT_FOREVER;
++
++ ast_channel_datastore_add(chan, datastore);
++
++ ast_channel_unlock(chan);
++
++ return 0;
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief misdn_command(cc-deactivate) subcommand handler
++ *
++ * \details
++ * misdn_command(cc-deactivate,${MISDN_CC_RECORD_ID})
++ * Deactivate a call completion service instance.
++ *
++ * \param chan Asterisk channel to operate upon.
++ * \param subcommand Arguments for the subcommand
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++static int misdn_command_cc_deactivate(struct ast_channel *chan, struct misdn_command_args *subcommand)
++{
++ long record_id;
++ const char *error_str;
++ struct misdn_cc_record *cc_record;
++ struct misdn_bchannel *bc;
++ struct misdn_bchannel dummy;
++
++ static const char cmd_help[] = "%s(%s,${MISDN_CC_RECORD_ID})\n";
++
++ if (ast_strlen_zero(subcommand->arg[0]) || !isdigit(*subcommand->arg[0])) {
++ ast_log(LOG_WARNING, cmd_help, misdn_command_name, subcommand->name);
++ return -1;
++ }
++ record_id = atol(subcommand->arg[0]);
++
++ AST_LIST_LOCK(&misdn_cc_records_db);
++ cc_record = misdn_cc_find_by_id(record_id);
++ if (cc_record && 0 <= cc_record->port) {
++ if (cc_record->ptp) {
++ if (cc_record->mode.ptp.bc) {
++ /* Close the call-completion signaling link */
++ bc = cc_record->mode.ptp.bc;
++ bc->fac_out.Function = Fac_None;
++ bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
++ misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
++ }
++ misdn_cc_delete(cc_record);
++ } else if (cc_record->activated) {
++ cc_record->error_code = FacError_None;
++ cc_record->reject_code = FacReject_None;
++ cc_record->invoke_id = ++misdn_invoke_id;
++ cc_record->outstanding_message = 1;
++
++ /* Build message */
++ misdn_make_dummy(&dummy, cc_record->port, 0, misdn_lib_port_is_nt(cc_record->port), 0);
++ dummy.fac_out.Function = Fac_CCBSDeactivate;
++ dummy.fac_out.u.CCBSDeactivate.InvokeID = cc_record->invoke_id;
++ dummy.fac_out.u.CCBSDeactivate.ComponentType = FacComponent_Invoke;
++ dummy.fac_out.u.CCBSDeactivate.Component.Invoke.CCBSReference = cc_record->mode.ptmp.reference_id;
++
++ /* Send message */
++ print_facility(&dummy.fac_out, &dummy);
++ misdn_lib_send_event(&dummy, EVENT_FACILITY);
++ }
++ }
++ AST_LIST_UNLOCK(&misdn_cc_records_db);
++
++ /* Wait for the response to the call completion deactivation request. */
++ misdn_cc_response_wait(chan, MISDN_CC_REQUEST_WAIT_MAX, record_id);
++
++ AST_LIST_LOCK(&misdn_cc_records_db);
++ cc_record = misdn_cc_find_by_id(record_id);
++ if (cc_record) {
++ if (cc_record->port < 0) {
++ /* The network did not tell us that call completion was available. */
++ error_str = NULL;
++ } else if (cc_record->outstanding_message) {
++ cc_record->outstanding_message = 0;
++ error_str = misdn_no_response_from_network;
++ } else if (cc_record->reject_code != FacReject_None) {
++ error_str = misdn_to_str_reject_code(cc_record->reject_code);
++ } else if (cc_record->reject_code != FacError_None) {
++ error_str = misdn_to_str_error_code(cc_record->error_code);
++ } else {
++ error_str = NULL;
++ }
++
++ misdn_cc_delete(cc_record);
++ } else {
++ error_str = NULL;
++ }
++ AST_LIST_UNLOCK(&misdn_cc_records_db);
++ if (error_str) {
++ ast_verb(1, "%s(%s) diagnostic '%s' on channel %s\n",
++ misdn_command_name, subcommand->name, error_str, chan->name);
++ pbx_builtin_setvar_helper(chan, MISDN_ERROR_MSG, error_str);
++ }
++
++ return 0;
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief misdn_command(cc-a-busy) subcommand handler
++ *
++ * \details
++ * misdn_command(cc-a-busy,${MISDN_CC_RECORD_ID},<yes/no>)
++ * Set the status of User-A for a call completion service instance.
++ *
++ * \param chan Asterisk channel to operate upon.
++ * \param subcommand Arguments for the subcommand
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++static int misdn_command_cc_a_busy(struct ast_channel *chan, struct misdn_command_args *subcommand)
++{
++ long record_id;
++ int party_a_free;
++ struct misdn_cc_record *cc_record;
++ struct misdn_bchannel *bc;
++
++ static const char cmd_help[] = "%s(%s,${MISDN_CC_RECORD_ID},<yes/no>)\n";
++
++ if (ast_strlen_zero(subcommand->arg[0]) || !isdigit(*subcommand->arg[0])) {
++ ast_log(LOG_WARNING, cmd_help, misdn_command_name, subcommand->name);
++ return -1;
++ }
++ record_id = atol(subcommand->arg[0]);
++
++ if (ast_true(subcommand->arg[1])) {
++ party_a_free = 0;
++ } else if (ast_false(subcommand->arg[1])) {
++ party_a_free = 1;
++ } else {
++ ast_log(LOG_WARNING, cmd_help, misdn_command_name, subcommand->name);
++ return -1;
++ }
++
++ AST_LIST_LOCK(&misdn_cc_records_db);
++ cc_record = misdn_cc_find_by_id(record_id);
++ if (cc_record && cc_record->party_a_free != party_a_free) {
++ /* User-A's status has changed */
++ cc_record->party_a_free = party_a_free;
++
++ if (cc_record->ptp && cc_record->mode.ptp.bc) {
++ cc_record->error_code = FacError_None;
++ cc_record->reject_code = FacReject_None;
++
++ /* Build message */
++ bc = cc_record->mode.ptp.bc;
++ if (cc_record->party_a_free) {
++ bc->fac_out.Function = Fac_CCBS_T_Resume;
++ bc->fac_out.u.CCBS_T_Resume.InvokeID = ++misdn_invoke_id;
++ } else {
++ bc->fac_out.Function = Fac_CCBS_T_Suspend;
++ bc->fac_out.u.CCBS_T_Suspend.InvokeID = ++misdn_invoke_id;
++ }
++
++ /* Send message */
++ print_facility(&bc->fac_out, bc);
++ misdn_lib_send_event(bc, EVENT_FACILITY);
++ }
++ }
++ AST_LIST_UNLOCK(&misdn_cc_records_db);
++
++ return 0;
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief misdn_command(cc-b-free) subcommand handler
++ *
++ * \details
++ * misdn_command(cc-b-free,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>)
++ * Set the dialplan location to notify when User-B is free and User-A is busy.
++ *
++ * \param chan Asterisk channel to operate upon.
++ * \param subcommand Arguments for the subcommand
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++static int misdn_command_cc_b_free(struct ast_channel *chan, struct misdn_command_args *subcommand)
++{
++ unsigned index;
++ long record_id;
++ int priority;
++ char *context;
++ char *exten;
++ struct misdn_cc_record *cc_record;
++
++ static const char cmd_help[] = "%s(%s,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>)\n";
++
++ /* Check that all arguments are present */
++ for (index = 0; index < 4; ++index) {
++ if (ast_strlen_zero(subcommand->arg[index])) {
++ ast_log(LOG_WARNING, cmd_help, misdn_command_name, subcommand->name);
++ return -1;
++ }
++ }
++
++ /* These must be numeric */
++ if (!isdigit(*subcommand->arg[0]) || !isdigit(*subcommand->arg[3])) {
++ ast_log(LOG_WARNING, cmd_help, misdn_command_name, subcommand->name);
++ return -1;
++ }
++
++ record_id = atol(subcommand->arg[0]);
++ context = subcommand->arg[1];
++ exten = subcommand->arg[2];
++ priority = atoi(subcommand->arg[3]);
++
++ AST_LIST_LOCK(&misdn_cc_records_db);
++ cc_record = misdn_cc_find_by_id(record_id);
++ if (cc_record) {
++ /* Save User-B free information */
++ ast_copy_string(cc_record->b_free.context, context, sizeof(cc_record->b_free.context));
++ ast_copy_string(cc_record->b_free.exten, exten, sizeof(cc_record->b_free.exten));
++ cc_record->b_free.priority = priority;
++ }
++ AST_LIST_UNLOCK(&misdn_cc_records_db);
++
++ return 0;
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++struct misdn_cc_request {
++ enum FacFunction ptmp;
++ enum FacFunction ptp;
++};
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief misdn_command(ccbs-request/ccnr-request) subcommand handler helper
++ *
++ * \details
++ * misdn_command(ccbs-request,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>)
++ * misdn_command(ccnr-request,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>)
++ * Set the dialplan location to notify when User-B is free and User-A is free.
++ *
++ * \param chan Asterisk channel to operate upon.
++ * \param subcommand Arguments for the subcommand
++ * \param request Which call-completion request message to generate.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++static int misdn_command_cc_request(struct ast_channel *chan, struct misdn_command_args *subcommand, const struct misdn_cc_request *request)
++{
++ unsigned index;
++ int request_retention;
++ long record_id;
++ int priority;
++ char *context;
++ char *exten;
++ const char *error_str;
++ struct misdn_cc_record *cc_record;
++ struct misdn_bchannel *bc;
++ struct misdn_bchannel dummy;
++ struct misdn_party_id id;
++
++ static const char cmd_help[] = "%s(%s,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>)\n";
++
++ /* Check that all arguments are present */
++ for (index = 0; index < 4; ++index) {
++ if (ast_strlen_zero(subcommand->arg[index])) {
++ ast_log(LOG_WARNING, cmd_help, misdn_command_name, subcommand->name);
++ return -1;
++ }
++ }
++
++ /* These must be numeric */
++ if (!isdigit(*subcommand->arg[0]) || !isdigit(*subcommand->arg[3])) {
++ ast_log(LOG_WARNING, cmd_help, misdn_command_name, subcommand->name);
++ return -1;
++ }
++
++ record_id = atol(subcommand->arg[0]);
++ context = subcommand->arg[1];
++ exten = subcommand->arg[2];
++ priority = atoi(subcommand->arg[3]);
++
++ AST_LIST_LOCK(&misdn_cc_records_db);
++ cc_record = misdn_cc_find_by_id(record_id);
++ if (cc_record) {
++ /* Save User-B free information */
++ ast_copy_string(cc_record->remote_user_free.context, context,
++ sizeof(cc_record->remote_user_free.context));
++ ast_copy_string(cc_record->remote_user_free.exten, exten,
++ sizeof(cc_record->remote_user_free.exten));
++ cc_record->remote_user_free.priority = priority;
++
++ if (0 <= cc_record->port) {
++ if (cc_record->ptp) {
++ if (!cc_record->mode.ptp.bc) {
++ bc = misdn_lib_get_register_bc(cc_record->port);
++ if (bc) {
++ cc_record->mode.ptp.bc = bc;
++ cc_record->error_code = FacError_None;
++ cc_record->reject_code = FacReject_None;
++ cc_record->invoke_id = ++misdn_invoke_id;
++ cc_record->outstanding_message = 1;
++ cc_record->activation_requested = 1;
++
++ misdn_cfg_get(bc->port, MISDN_CFG_CC_REQUEST_RETENTION,
++ &request_retention, sizeof(request_retention));
++ cc_record->mode.ptp.requested_retention = request_retention ? 1 : 0;
++
++ /* Build message */
++ bc->fac_out.Function = request->ptp;
++ bc->fac_out.u.CCBS_T_Request.InvokeID = cc_record->invoke_id;
++ bc->fac_out.u.CCBS_T_Request.ComponentType = FacComponent_Invoke;
++ bc->fac_out.u.CCBS_T_Request.Component.Invoke.Q931ie =
++ cc_record->redial.setup_bc_hlc_llc;
++ memset(&id, 0, sizeof(id));
++ id.number_plan = cc_record->redial.dialed.number_plan;
++ id.number_type = cc_record->redial.dialed.number_type;
++ ast_copy_string(id.number, cc_record->redial.dialed.number,
++ sizeof(id.number));
++ misdn_Address_fill(
++ &bc->fac_out.u.CCBS_T_Request.Component.Invoke.Destination,
++ &id);
++ misdn_Address_fill(
++ &bc->fac_out.u.CCBS_T_Request.Component.Invoke.Originating,
++ &cc_record->redial.caller);
++ bc->fac_out.u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicatorPresent = 1;
++ bc->fac_out.u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicator =
++ (cc_record->redial.caller.presentation != 0) ? 0 : 1;
++ bc->fac_out.u.CCBS_T_Request.Component.Invoke.RetentionSupported =
++ request_retention ? 1 : 0;
++
++ /* Send message */
++ print_facility(&bc->fac_out, bc);
++ misdn_lib_send_event(bc, EVENT_REGISTER);
++ }
++ }
++ } else {
++ cc_record->error_code = FacError_None;
++ cc_record->reject_code = FacReject_None;
++ cc_record->invoke_id = ++misdn_invoke_id;
++ cc_record->outstanding_message = 1;
++ cc_record->activation_requested = 1;
++
++ /* Build message */
++ misdn_make_dummy(&dummy, cc_record->port, 0,
++ misdn_lib_port_is_nt(cc_record->port), 0);
++ dummy.fac_out.Function = request->ptmp;
++ dummy.fac_out.u.CCBSRequest.InvokeID = cc_record->invoke_id;
++ dummy.fac_out.u.CCBSRequest.ComponentType = FacComponent_Invoke;
++ dummy.fac_out.u.CCBSRequest.Component.Invoke.CallLinkageID =
++ cc_record->mode.ptmp.linkage_id;
++
++ /* Send message */
++ print_facility(&dummy.fac_out, &dummy);
++ misdn_lib_send_event(&dummy, EVENT_FACILITY);
++ }
++ }
++ }
++ AST_LIST_UNLOCK(&misdn_cc_records_db);
++
++ /* Wait for the response to the call completion request. */
++ misdn_cc_response_wait(chan, MISDN_CC_REQUEST_WAIT_MAX, record_id);
++
++ AST_LIST_LOCK(&misdn_cc_records_db);
++ cc_record = misdn_cc_find_by_id(record_id);
++ if (cc_record) {
++ if (!cc_record->activated) {
++ if (cc_record->port < 0) {
++ /* The network did not tell us that call completion was available. */
++ error_str = "No port number";
++ } else if (cc_record->outstanding_message) {
++ cc_record->outstanding_message = 0;
++ error_str = misdn_no_response_from_network;
++ } else if (cc_record->reject_code != FacReject_None) {
++ error_str = misdn_to_str_reject_code(cc_record->reject_code);
++ } else if (cc_record->error_code != FacError_None) {
++ error_str = misdn_to_str_error_code(cc_record->error_code);
++ } else if (cc_record->ptp) {
++ if (cc_record->mode.ptp.bc) {
++ error_str = "Call-completion already requested";
++ } else {
++ error_str = "Could not allocate call-completion signaling link";
++ }
++ } else {
++ /* Should never happen. */
++ error_str = "Unexpected error";
++ }
++
++ /* No need to keep the call completion record. */
++ if (cc_record->ptp && cc_record->mode.ptp.bc) {
++ /* Close the call-completion signaling link */
++ bc = cc_record->mode.ptp.bc;
++ bc->fac_out.Function = Fac_None;
++ bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
++ misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
++ }
++ misdn_cc_delete(cc_record);
++ } else {
++ error_str = NULL;
++ }
++ } else {
++ error_str = misdn_cc_record_not_found;
++ }
++ AST_LIST_UNLOCK(&misdn_cc_records_db);
++ if (error_str) {
++ ast_verb(1, "%s(%s) diagnostic '%s' on channel %s\n",
++ misdn_command_name, subcommand->name, error_str, chan->name);
++ pbx_builtin_setvar_helper(chan, MISDN_ERROR_MSG, error_str);
++ pbx_builtin_setvar_helper(chan, MISDN_CC_STATUS, "ERROR");
++ } else {
++ pbx_builtin_setvar_helper(chan, MISDN_CC_STATUS, "ACTIVATED");
++ }
++
++ return 0;
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief misdn_command(ccbs-request) subcommand handler
++ *
++ * \details
++ * misdn_command(ccbs-request,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>)
++ * Set the dialplan location to notify when User-B is free and User-A is free.
++ *
++ * \param chan Asterisk channel to operate upon.
++ * \param subcommand Arguments for the subcommand
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++static int misdn_command_ccbs_request(struct ast_channel *chan, struct misdn_command_args *subcommand)
++{
++ static const struct misdn_cc_request request = {
++ .ptmp = Fac_CCBSRequest,
++ .ptp = Fac_CCBS_T_Request
++ };
++
++ return misdn_command_cc_request(chan, subcommand, &request);
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief misdn_command(ccnr-request) subcommand handler
++ *
++ * \details
++ * misdn_command(ccnr-request,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>)
++ * Set the dialplan location to notify when User-B is free and User-A is free.
++ *
++ * \param chan Asterisk channel to operate upon.
++ * \param subcommand Arguments for the subcommand
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++static int misdn_command_ccnr_request(struct ast_channel *chan, struct misdn_command_args *subcommand)
++{
++ static const struct misdn_cc_request request = {
++ .ptmp = Fac_CCNRRequest,
++ .ptp = Fac_CCNR_T_Request
++ };
++
++ return misdn_command_cc_request(chan, subcommand, &request);
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++struct misdn_command_table {
++ /*! \brief subcommand name */
++ const char *name;
++
++ /*! \brief subcommand handler */
++ int (*func)(struct ast_channel *chan, struct misdn_command_args *subcommand);
++
++ /*! \brief TRUE if the subcommand can only be executed on mISDN channels */
++ int misdn_only;
++};
++static const struct misdn_command_table misdn_commands[] = {
++/* *INDENT-OFF* */
++ /* subcommand-name subcommand-handler mISDN only */
++ { "cc-initialize", misdn_command_cc_initialize, 0 },
++ { "cc-deactivate", misdn_command_cc_deactivate, 0 },
++ { "cc-a-busy", misdn_command_cc_a_busy, 0 },
++ { "cc-b-free", misdn_command_cc_b_free, 0 },
++ { "ccbs-request", misdn_command_ccbs_request, 0 },
++ { "ccnr-request", misdn_command_ccnr_request, 0 },
++/* *INDENT-ON* */
++};
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief misdn_command() dialplan application.
++ *
++ * \param chan Asterisk channel to operate upon.
++ * \param data Application options string.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++static int misdn_command_exec(struct ast_channel *chan, const char *data)
++{
++ char *parse;
++ unsigned index;
++ struct misdn_command_args subcommand;
++
++ if (ast_strlen_zero((char *) data)) {
++ ast_log(LOG_ERROR, "%s requires arguments\n", misdn_command_name);
++ return -1;
++ }
++
++ ast_log(LOG_DEBUG, "%s(%s)\n", misdn_command_name, (char *) data);
++
++ parse = ast_strdupa(data);
++ AST_STANDARD_APP_ARGS(subcommand, parse);
++ if (!subcommand.argc || ast_strlen_zero(subcommand.name)) {
++ ast_log(LOG_ERROR, "%s requires a subcommand\n", misdn_command_name);
++ return -1;
++ }
++
++ for (index = 0; index < ARRAY_LEN(misdn_commands); ++index) {
++ if (strcasecmp(misdn_commands[index].name, subcommand.name) == 0) {
++ strcpy(subcommand.name, misdn_commands[index].name);
++ if (misdn_commands[index].misdn_only
++ && strcasecmp(chan->tech->type, misdn_type) != 0) {
++ ast_log(LOG_WARNING,
++ "%s(%s) only makes sense with %s channels!\n",
++ misdn_command_name, subcommand.name, misdn_type);
++ return -1;
++ }
++ return misdn_commands[index].func(chan, &subcommand);
++ }
++ }
++
++ ast_log(LOG_WARNING, "%s(%s) subcommand is unknown\n", misdn_command_name,
++ subcommand.name);
++ return -1;
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++static int misdn_facility_exec(struct ast_channel *chan, const char *data)
++{
+ struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
+ char *parse;
++ unsigned max_len;
++
+ AST_DECLARE_APP_ARGS(args,
+ AST_APP_ARG(facility_type);
+ AST_APP_ARG(arg)[99];
+ );
+
+ chan_misdn_log(0, 0, "TYPE: %s\n", chan->tech->type);
+-
+- if (strcasecmp(chan->tech->type, "mISDN")) {
+- ast_log(LOG_WARNING, "misdn_facility makes only sense with chan_misdn channels!\n");
++
++ if (strcasecmp(chan->tech->type, misdn_type)) {
++ ast_log(LOG_WARNING, "misdn_facility only makes sense with %s channels!\n", misdn_type);
+ return -1;
+ }
+-
+- if (ast_strlen_zero((char *)data)) {
++
++ if (ast_strlen_zero((char *) data)) {
+ ast_log(LOG_WARNING, "misdn_facility requires arguments: facility_type[,<args>]\n");
+ return -1;
+ }
+@@ -5499,12 +11432,41 @@
+ ast_log(LOG_WARNING, "Facility: Call Deflection requires an argument: Number\n");
+ }
+
+- if (strlen(args.arg[0]) >= sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber)) {
+- ast_log(LOG_WARNING, "Facility: Number argument too long (up to %d digits are allowed). Ignoring.\n", (int)sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber));
++#if defined(AST_MISDN_ENHANCEMENTS)
++ max_len = sizeof(ch->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Number) - 1;
++ if (max_len < strlen(args.arg[0])) {
++ ast_log(LOG_WARNING,
++ "Facility: Number argument too long (up to %u digits are allowed). Ignoring.\n",
++ max_len);
+ return 0;
+ }
++ ch->bc->fac_out.Function = Fac_CallDeflection;
++ ch->bc->fac_out.u.CallDeflection.InvokeID = ++misdn_invoke_id;
++ ch->bc->fac_out.u.CallDeflection.ComponentType = FacComponent_Invoke;
++ ch->bc->fac_out.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent = 1;
++ ch->bc->fac_out.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser = 0;
++ ch->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Type = 0;/* unknown */
++ ch->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.LengthOfNumber = strlen(args.arg[0]);
++ strcpy((char *) ch->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Number, args.arg[0]);
++ ch->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Subaddress.Length = 0;
++
++#else /* !defined(AST_MISDN_ENHANCEMENTS) */
++
++ max_len = sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber) - 1;
++ if (max_len < strlen(args.arg[0])) {
++ ast_log(LOG_WARNING,
++ "Facility: Number argument too long (up to %u digits are allowed). Ignoring.\n",
++ max_len);
++ return 0;
++ }
+ ch->bc->fac_out.Function = Fac_CD;
+- ast_copy_string((char *)ch->bc->fac_out.u.CDeflection.DeflectedToNumber, args.arg[0], sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber));
++ ch->bc->fac_out.u.CDeflection.PresentationAllowed = 0;
++ //ch->bc->fac_out.u.CDeflection.DeflectedToSubaddress[0] = 0;
++ strcpy((char *) ch->bc->fac_out.u.CDeflection.DeflectedToNumber, args.arg[0]);
++#endif /* !defined(AST_MISDN_ENHANCEMENTS) */
++
++ /* Send message */
++ print_facility(&ch->bc->fac_out, ch->bc);
+ misdn_lib_send_event(ch->bc, EVENT_FACILITY);
+ } else {
+ chan_misdn_log(1, ch->bc->port, "Unknown Facility: %s\n", args.facility_type);
+@@ -5513,7 +11475,7 @@
+ return 0;
+ }
+
+-static int misdn_check_l2l1(struct ast_channel *chan, void *data)
++static int misdn_check_l2l1(struct ast_channel *chan, const char *data)
+ {
+ char *parse;
+ char group[BUFFERSIZE + 1];
+@@ -5524,11 +11486,11 @@
+ int port_up;
+
+ AST_DECLARE_APP_ARGS(args,
+- AST_APP_ARG(grouppar);
+- AST_APP_ARG(timeout);
++ AST_APP_ARG(grouppar);
++ AST_APP_ARG(timeout);
+ );
+
+- if (ast_strlen_zero((char *)data)) {
++ if (ast_strlen_zero((char *) data)) {
+ ast_log(LOG_WARNING, "misdn_check_l2l1 Requires arguments\n");
+ return -1;
+ }
+@@ -5545,13 +11507,13 @@
+ timeout = atoi(args.timeout);
+ port_str = args.grouppar;
+
+- if (port_str[0] == 'g' && port_str[1] == ':' ) {
++ if (port_str[0] == 'g' && port_str[1] == ':') {
+ /* We make a group call lets checkout which ports are in my group */
+ port_str += 2;
+ ast_copy_string(group, port_str, sizeof(group));
+ chan_misdn_log(2, 0, "Checking Ports in group: %s\n", group);
+
+- for ( port = misdn_cfg_get_next_port(port);
++ for (port = misdn_cfg_get_next_port(port);
+ port > 0;
+ port = misdn_cfg_get_next_port(port)) {
+ char cfg_group[BUFFERSIZE + 1];
+@@ -5562,7 +11524,6 @@
+
+ if (!strcasecmp(cfg_group, group)) {
+ port_up = misdn_lib_port_up(port, 1);
+-
+ if (!port_up) {
+ chan_misdn_log(2, 0, " --> port '%d'\n", port);
+ misdn_lib_get_port_up(port);
+@@ -5570,10 +11531,9 @@
+ }
+ }
+ }
+-
+ } else {
+ port = atoi(port_str);
+- chan_misdn_log(2, 0, "Checking Port: %d\n",port);
++ chan_misdn_log(2, 0, "Checking Port: %d\n", port);
+ port_up = misdn_lib_port_up(port, 1);
+ if (!port_up) {
+ misdn_lib_get_port_up(port);
+@@ -5589,54 +11549,53 @@
+ return 0;
+ }
+
+-static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
++static int misdn_set_opt_exec(struct ast_channel *chan, const char *data)
+ {
+ struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
+- char *tok, *tokb, *parse;
+- int keyidx = 0;
++ char *tok;
++ char *tokb;
++ char *parse;
++ int keyidx = 0;
+ int rxgain = 0;
+ int txgain = 0;
+ int change_jitter = 0;
+
+- if (strcasecmp(chan->tech->type, "mISDN")) {
+- ast_log(LOG_WARNING, "misdn_set_opt makes only sense with chan_misdn channels!\n");
++ if (strcasecmp(chan->tech->type, misdn_type)) {
++ ast_log(LOG_WARNING, "misdn_set_opt makes sense only with %s channels!\n", misdn_type);
+ return -1;
+ }
+-
+- if (ast_strlen_zero((char *)data)) {
++
++ if (ast_strlen_zero((char *) data)) {
+ ast_log(LOG_WARNING, "misdn_set_opt Requires arguments\n");
+ return -1;
+ }
+
+ parse = ast_strdupa(data);
+ for (tok = strtok_r(parse, ":", &tokb);
+- tok;
+- tok = strtok_r(NULL, ":", &tokb) ) {
++ tok;
++ tok = strtok_r(NULL, ":", &tokb)) {
+ int neglect = 0;
+
+- if (tok[0] == '!' ) {
++ if (tok[0] == '!') {
+ neglect = 1;
+ tok++;
+ }
+-
++
+ switch(tok[0]) {
+-
+ case 'd' :
+ ast_copy_string(ch->bc->display, ++tok, sizeof(ch->bc->display));
+ chan_misdn_log(1, ch->bc->port, "SETOPT: Display:%s\n", ch->bc->display);
+ break;
+-
+ case 'n':
+ chan_misdn_log(1, ch->bc->port, "SETOPT: No DSP\n");
+ ch->bc->nodsp = 1;
+ break;
+-
+ case 'j':
+ chan_misdn_log(1, ch->bc->port, "SETOPT: jitter\n");
+ tok++;
+ change_jitter = 1;
+
+- switch ( tok[0] ) {
++ switch (tok[0]) {
+ case 'b':
+ ch->jb_len = atoi(++tok);
+ chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d\n", ch->jb_len);
+@@ -5654,6 +11613,7 @@
+ ch->jb_upper_threshold = 0;
+ chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d (default)\n", ch->jb_len);
+ chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d (default)\n", ch->jb_upper_threshold);
++ break;
+ }
+ break;
+ case 'v':
+@@ -5684,13 +11644,14 @@
+ break;
+ }
+ break;
+-
+ case 'c':
+ keyidx = atoi(++tok);
+ {
+ char keys[4096];
+- char *key = NULL, *tmp = keys;
++ char *key = NULL;
++ char *tmp = keys;
+ int i;
++
+ misdn_cfg_get(0, MISDN_GEN_CRYPT_KEYS, keys, sizeof(keys));
+
+ for (i = 0; i < keyidx; i++) {
+@@ -5706,7 +11667,7 @@
+ }
+ case 'e':
+ chan_misdn_log(1, ch->bc->port, "SETOPT: EchoCancel\n");
+-
++
+ if (neglect) {
+ chan_misdn_log(1, ch->bc->port, " --> disabled\n");
+ #ifdef MISDN_1_2
+@@ -5726,11 +11687,10 @@
+ }
+ #endif
+ }
+-
+ break;
+ case 'h':
+ chan_misdn_log(1, ch->bc->port, "SETOPT: Digital\n");
+-
++
+ if (strlen(tok) > 1 && tok[1] == '1') {
+ chan_misdn_log(1, ch->bc->port, "SETOPT: HDLC \n");
+ if (!ch->bc->hdlc) {
+@@ -5739,38 +11699,37 @@
+ }
+ ch->bc->capability = INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
+ break;
+-
+ case 's':
+ chan_misdn_log(1, ch->bc->port, "SETOPT: Send DTMF\n");
+ ch->bc->send_dtmf = 1;
+ break;
+-
+ case 'f':
+ chan_misdn_log(1, ch->bc->port, "SETOPT: Faxdetect\n");
+ ch->faxdetect = 1;
+ misdn_cfg_get(ch->bc->port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
+ break;
+-
+ case 'a':
+ chan_misdn_log(1, ch->bc->port, "SETOPT: AST_DSP (for DTMF)\n");
+ ch->ast_dsp = 1;
+ break;
+-
+ case 'p':
+ chan_misdn_log(1, ch->bc->port, "SETOPT: callerpres: %s\n", &tok[1]);
+ /* CRICH: callingpres!!! */
+ if (strstr(tok, "allowed")) {
+- ch->bc->pres = 0;
++ ch->bc->presentation = 0;
++ ch->bc->set_presentation = 1;
+ } else if (strstr(tok, "restricted")) {
+- ch->bc->pres = 1;
++ ch->bc->presentation = 1;
++ ch->bc->set_presentation = 1;
+ } else if (strstr(tok, "not_screened")) {
+ chan_misdn_log(0, ch->bc->port, "SETOPT: callerpres: not_screened is deprecated\n");
+- ch->bc->pres = 1;
++ ch->bc->presentation = 1;
++ ch->bc->set_presentation = 1;
+ }
+ break;
+ case 'i' :
+ chan_misdn_log(1, ch->bc->port, "Ignoring dtmf tones, just use them inband\n");
+- ch->ignore_dtmf=1;
++ ch->ignore_dtmf = 1;
+ break;
+ default:
+ break;
+@@ -5797,19 +11756,19 @@
+ chan_misdn_log(1, ch->bc->port, "SETOPT: with AST_DSP we deactivate mISDN_dsp\n");
+ ch->bc->nodsp = 1;
+ }
+-
++
+ return 0;
+ }
+
+
+-int chan_misdn_jb_empty ( struct misdn_bchannel *bc, char *buf, int len)
++int chan_misdn_jb_empty(struct misdn_bchannel *bc, char *buf, int len)
+ {
+ struct chan_list *ch = find_chan_by_bc(cl_te, bc);
+-
++
+ if (ch && ch->jb) {
+ return misdn_jb_empty(ch->jb, buf, len);
+ }
+-
++
+ return -1;
+ }
+
+@@ -5866,7 +11825,7 @@
+ void misdn_jb_destroy(struct misdn_jb *jb)
+ {
+ ast_mutex_destroy(&jb->mutexjb);
+-
++
+ ast_free(jb->ok);
+ ast_free(jb->samples);
+ ast_free(jb);
+@@ -5876,17 +11835,20 @@
+ error (buffer overflow). */
+ int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len)
+ {
+- int i, j, rp, wp;
++ int i;
++ int j;
++ int rp;
++ int wp;
+
+ if (!jb || ! data) {
+ return 0;
+ }
+
+ ast_mutex_lock(&jb->mutexjb);
+-
++
+ wp = jb->wp;
+ rp = jb->rp;
+-
++
+ for (i = 0; i < len; i++) {
+ jb->samples[wp] = data[i];
+ jb->ok[wp] = 1;
+@@ -5930,7 +11892,7 @@
+ jb->wp = wp;
+
+ ast_mutex_unlock(&jb->mutexjb);
+-
++
+ return 0;
+ }
+
+@@ -5939,14 +11901,17 @@
+ of data. */
+ int misdn_jb_empty(struct misdn_jb *jb, char *data, int len)
+ {
+- int i, wp, rp, read = 0;
++ int i;
++ int wp;
++ int rp;
++ int read = 0;
+
+ ast_mutex_lock(&jb->mutexjb);
+
+ rp = jb->rp;
+ wp = jb->wp;
+
+- if (jb->state_empty) {
++ if (jb->state_empty) {
+ for (i = 0; i < len; i++) {
+ if (wp == rp) {
+ jb->rp = rp;
+@@ -5982,66 +11947,70 @@
+ return read;
+ }
+
+-
+-
+-
+ /*******************************************************/
+ /*************** JITTERBUFFER END *********************/
+ /*******************************************************/
+
+-
+-
+-
+ static void chan_misdn_log(int level, int port, char *tmpl, ...)
+ {
+ va_list ap;
+ char buf[1024];
+ char port_buf[8];
+
+- if (! ((0 <= port) && (port <= max_ports))) {
++ if (!(0 <= port && port <= max_ports)) {
+ ast_log(LOG_WARNING, "cb_log called with out-of-range port number! (%d)\n", port);
+ port = 0;
+ level = -1;
++ } else if (!(level == -1
++ || (misdn_debug_only[port]
++ ? (level == 1 && misdn_debug[port]) || level == misdn_debug[port]
++ : level <= misdn_debug[port])
++ || (level <= misdn_debug[0] && !ast_strlen_zero(global_tracefile)))) {
++ /*
++ * We are not going to print anything so lets not
++ * go to all the work of generating a string.
++ */
++ return;
+ }
+
+ snprintf(port_buf, sizeof(port_buf), "P[%2d] ", port);
+-
+ va_start(ap, tmpl);
+ vsnprintf(buf, sizeof(buf), tmpl, ap);
+ va_end(ap);
+
+ if (level == -1) {
+ ast_log(LOG_WARNING, "%s", buf);
+-
+- } else if (misdn_debug_only[port] ?
+- (level == 1 && misdn_debug[port]) || (level == misdn_debug[port])
+- : level <= misdn_debug[port]) {
+-
++ } else if (misdn_debug_only[port]
++ ? (level == 1 && misdn_debug[port]) || level == misdn_debug[port]
++ : level <= misdn_debug[port]) {
+ ast_console_puts(port_buf);
+ ast_console_puts(buf);
+ }
+-
+- if ((level <= misdn_debug[0]) && !ast_strlen_zero(global_tracefile) ) {
++
++ if (level <= misdn_debug[0] && !ast_strlen_zero(global_tracefile)) {
+ char ctimebuf[30];
+- time_t tm = time(NULL);
+- char *tmp = ctime_r(&tm, ctimebuf), *p;
++ time_t tm;
++ char *tmp;
++ char *p;
++ FILE *fp;
+
+- FILE *fp = fopen(global_tracefile, "a+");
+-
+- if ((p = strchr(tmp, '\n'))) {
+- *p = ':';
+- }
+-
++ fp = fopen(global_tracefile, "a+");
+ if (!fp) {
+ ast_console_puts("Error opening Tracefile: [ ");
+ ast_console_puts(global_tracefile);
+ ast_console_puts(" ] ");
+-
++
+ ast_console_puts(strerror(errno));
+ ast_console_puts("\n");
+- return ;
++ return;
+ }
+-
++
++ tm = time(NULL);
++ tmp = ctime_r(&tm, ctimebuf);
++ p = strchr(tmp, '\n');
++ if (p) {
++ *p = ':';
++ }
+ fputs(tmp, fp);
+ fputs(" ", fp);
+ fputs(port_buf, fp);
+Index: channels/chan_skinny.c
+===================================================================
+--- a/channels/chan_skinny.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/channels/chan_skinny.c (.../trunk) (revision 202568)
+@@ -49,7 +49,7 @@
+ #include "asterisk/pbx.h"
+ #include "asterisk/sched.h"
+ #include "asterisk/io.h"
+-#include "asterisk/rtp.h"
++#include "asterisk/rtp_engine.h"
+ #include "asterisk/netsock.h"
+ #include "asterisk/acl.h"
+ #include "asterisk/callerid.h"
+@@ -71,6 +71,63 @@
+ #include "asterisk/indications.h"
+ #include "asterisk/linkedlists.h"
+
++/*** DOCUMENTATION
++ <manager name="SKINNYdevices" language="en_US">
++ <synopsis>
++ List SKINNY devices (text format).
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ </syntax>
++ <description>
++ <para>Lists Skinny devices in text format with details on current status.
++ Devicelist will follow as separate events, followed by a final event called
++ DevicelistComplete.</para>
++ </description>
++ </manager>
++ <manager name="SKINNYshowdevice" language="en_US">
++ <synopsis>
++ Show SKINNY device (text format).
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Device" required="true">
++ <para>The device name you want to check.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Show one SKINNY device with details on current status.</para>
++ </description>
++ </manager>
++ <manager name="SKINNYlines" language="en_US">
++ <synopsis>
++ List SKINNY lines (text format).
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ </syntax>
++ <description>
++ <para>Lists Skinny lines in text format with details on current status.
++ Linelist will follow as separate events, followed by a final event called
++ LinelistComplete.</para>
++ </description>
++ </manager>
++ <manager name="SKINNYshowline" language="en_US">
++ <synopsis>
++ Show SKINNY line (text format).
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Line" required="true">
++ <para>The line name you want to check.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Show one SKINNY line with details on current status.</para>
++ </description>
++ </manager>
++ ***/
++
+ #ifdef SKINNY_DEVMODE
+ #define SKINNY_DEVONLY(code) \
+ code
+@@ -585,7 +642,7 @@
+ #define SOFTKEY_DND 0x13
+ #define SOFTKEY_IDIVERT 0x14
+
+-struct soft_key_template_definition soft_key_template_default[] = {
++static struct soft_key_template_definition soft_key_template_default[] = {
+ { "\200\001", SOFTKEY_REDIAL },
+ { "\200\002", SOFTKEY_NEWCALL },
+ { "\200\003", SOFTKEY_HOLD },
+@@ -963,7 +1020,7 @@
+ /* XXX This is the combined size of the variables above. (len, res, e)
+ If more are added, this MUST change.
+ (sizeof(skinny_req) - sizeof(skinny_data)) DOES NOT WORK on all systems (amd64?). */
+-int skinny_header_size = 12;
++static int skinny_header_size = 12;
+
+ /*****************************
+ * Asterisk specific globals *
+@@ -977,8 +1034,8 @@
+ static char ourhost[256];
+ static int ourport;
+ static struct in_addr __ourip;
+-struct ast_hostent ahp;
+-struct hostent *hp;
++static struct ast_hostent ahp;
++static struct hostent *hp;
+ static int skinnysock = -1;
+ static pthread_t accept_t;
+ static int callnums = 1;
+@@ -1076,7 +1133,7 @@
+ #define SKINNY_CX_INACTIVE 4
+
+ #if 0
+-static char *skinny_cxmodes[] = {
++static const char * const skinny_cxmodes[] = {
+ "sendonly",
+ "recvonly",
+ "sendrecv",
+@@ -1111,8 +1168,8 @@
+ struct skinny_subchannel {
+ ast_mutex_t lock;
+ struct ast_channel *owner;
+- struct ast_rtp *rtp;
+- struct ast_rtp *vrtp;
++ struct ast_rtp_instance *rtp;
++ struct ast_rtp_instance *vrtp;
+ unsigned int callid;
+ /* time_t lastouttime; */ /* Unused */
+ int progress;
+@@ -1198,7 +1255,7 @@
+ int newmsgs;
+ };
+
+-struct skinny_line_options{
++static struct skinny_line_options{
+ SKINNY_LINE_OPTIONS
+ } default_line_struct = {
+ .callwaiting = 1,
+@@ -1217,7 +1274,7 @@
+ .prune = 0,
+ .hookstate = SKINNY_ONHOOK,
+ };
+-struct skinny_line_options *default_line = &default_line_struct;
++static struct skinny_line_options *default_line = &default_line_struct;
+
+ static AST_LIST_HEAD_STATIC(lines, skinny_line);
+
+@@ -1278,7 +1335,7 @@
+ AST_LIST_ENTRY(skinny_device) list;
+ };
+
+-struct skinny_device_options{
++static struct skinny_device_options {
+ SKINNY_DEVICE_OPTIONS
+ } default_device_struct = {
+ .transfer = 1,
+@@ -1290,7 +1347,7 @@
+ .capability = 0,
+ .prune = 0,
+ };
+-struct skinny_device_options *default_device = &default_device_struct;
++static struct skinny_device_options *default_device = &default_device_struct;
+
+ static AST_LIST_HEAD_STATIC(devices, skinny_device);
+
+@@ -1347,7 +1404,7 @@
+ .fixup = skinny_fixup,
+ .send_digit_begin = skinny_senddigit_begin,
+ .send_digit_end = skinny_senddigit_end,
+- .bridge = ast_rtp_bridge,
++ .bridge = ast_rtp_instance_bridge,
+ };
+
+ static int skinny_extensionstate_cb(char *context, char* exten, int state, void *data);
+@@ -2516,6 +2573,43 @@
+ return 0;
+ }
+
++static void update_connectedline(struct skinny_subchannel *sub, const void *data, size_t datalen)
++{
++ struct ast_channel *c = sub->owner;
++ struct skinny_line *l = sub->parent;
++ struct skinny_device *d = l->device;
++
++ if (ast_strlen_zero(c->cid.cid_num) || ast_strlen_zero(c->connected.id.number))
++ return;
++
++ if (sub->owner->_state == AST_STATE_UP) {
++ transmit_callstate(d, l->instance, SKINNY_CONNECTED, sub->callid);
++ transmit_displaypromptstatus(d, "Connected", 0, l->instance, sub->callid);
++ if (sub->outgoing)
++ transmit_callinfo(d, c->connected.id.name, c->connected.id.number, l->cid_name, l->cid_num, l->instance, sub->callid, 1);
++ else
++ transmit_callinfo(d, l->cid_name, l->cid_num, c->connected.id.name, c->connected.id.number, l->instance, sub->callid, 2);
++ } else {
++ if (sub->outgoing) {
++ transmit_callstate(d, l->instance, SKINNY_RINGIN, sub->callid);
++ transmit_displaypromptstatus(d, "Ring-In", 0, l->instance, sub->callid);
++ transmit_callinfo(d, c->connected.id.name, c->connected.id.number, l->cid_name, l->cid_num, l->instance, sub->callid, 1);
++ } else {
++ if (!sub->ringing) {
++ transmit_callstate(d, l->instance, SKINNY_RINGOUT, sub->callid);
++ transmit_displaypromptstatus(d, "Ring-Out", 0, l->instance, sub->callid);
++ sub->ringing = 1;
++ } else {
++ transmit_callstate(d, l->instance, SKINNY_PROGRESS, sub->callid);
++ transmit_displaypromptstatus(d, "Call Progress", 0, l->instance, sub->callid);
++ sub->progress = 1;
++ }
++
++ transmit_callinfo(d, l->cid_name, l->cid_num, c->connected.id.name, c->connected.id.number, l->instance, sub->callid, 2);
++ }
++ }
++}
++
+ static void mwi_event_cb(const struct ast_event *event, void *userdata)
+ {
+ struct skinny_line *l = userdata;
+@@ -2557,46 +2651,48 @@
+ /* I do not believe skinny can deal with video.
+ Anyone know differently? */
+ /* Yes, it can. Currently 7985 and Cisco VT Advantage do video. */
+-static enum ast_rtp_get_result skinny_get_vrtp_peer(struct ast_channel *c, struct ast_rtp **rtp)
++static enum ast_rtp_glue_result skinny_get_vrtp_peer(struct ast_channel *c, struct ast_rtp_instance **instance)
+ {
+ struct skinny_subchannel *sub = NULL;
+
+ if (!(sub = c->tech_pvt) || !(sub->vrtp))
+- return AST_RTP_GET_FAILED;
++ return AST_RTP_GLUE_RESULT_FORBID;
+
+- *rtp = sub->vrtp;
++ ao2_ref(sub->vrtp, +1);
++ *instance = sub->vrtp;
+
+- return AST_RTP_TRY_NATIVE;
++ return AST_RTP_GLUE_RESULT_REMOTE;
+ }
+
+-static enum ast_rtp_get_result skinny_get_rtp_peer(struct ast_channel *c, struct ast_rtp **rtp)
++static enum ast_rtp_glue_result skinny_get_rtp_peer(struct ast_channel *c, struct ast_rtp_instance **instance)
+ {
+ struct skinny_subchannel *sub = NULL;
+ struct skinny_line *l;
+- enum ast_rtp_get_result res = AST_RTP_TRY_NATIVE;
++ enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_REMOTE;
+
+ if (skinnydebug)
+ ast_verb(1, "skinny_get_rtp_peer() Channel = %s\n", c->name);
+
+
+ if (!(sub = c->tech_pvt))
+- return AST_RTP_GET_FAILED;
++ return AST_RTP_GLUE_RESULT_FORBID;
+
+ ast_mutex_lock(&sub->lock);
+
+ if (!(sub->rtp)){
+ ast_mutex_unlock(&sub->lock);
+- return AST_RTP_GET_FAILED;
++ return AST_RTP_GLUE_RESULT_FORBID;
+ }
+-
+- *rtp = sub->rtp;
+
++ ao2_ref(sub->rtp, +1);
++ *instance = sub->rtp;
++
+ l = sub->parent;
+
+ if (!l->canreinvite || l->nat){
+- res = AST_RTP_TRY_PARTIAL;
++ res = AST_RTP_GLUE_RESULT_LOCAL;
+ if (skinnydebug)
+- ast_verb(1, "skinny_get_rtp_peer() Using AST_RTP_TRY_PARTIAL \n");
++ ast_verb(1, "skinny_get_rtp_peer() Using AST_RTP_GLUE_RESULT_LOCAL \n");
+ }
+
+ ast_mutex_unlock(&sub->lock);
+@@ -2605,15 +2701,15 @@
+
+ }
+
+-static int skinny_set_rtp_peer(struct ast_channel *c, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active)
++static int skinny_set_rtp_peer(struct ast_channel *c, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, int codecs, int nat_active)
+ {
+ struct skinny_subchannel *sub;
+ struct skinny_line *l;
+ struct skinny_device *d;
+ struct skinnysession *s;
+ struct ast_format_list fmt;
+- struct sockaddr_in us;
+- struct sockaddr_in them;
++ struct sockaddr_in us = { 0, };
++ struct sockaddr_in them = { 0, };
+ struct skinny_req *req;
+
+ sub = c->tech_pvt;
+@@ -2630,7 +2726,7 @@
+ s = d->session;
+
+ if (rtp){
+- ast_rtp_get_peer(rtp, &them);
++ ast_rtp_instance_get_remote_address(rtp, &them);
+
+ /* Shutdown any early-media or previous media on re-invite */
+ if (!(req = req_alloc(sizeof(struct stop_media_transmission_message), STOP_MEDIA_TRANSMISSION_MESSAGE)))
+@@ -2654,7 +2750,7 @@
+ req->data.startmedia.conferenceId = htolel(sub->callid);
+ req->data.startmedia.passThruPartyId = htolel(sub->callid);
+ if (!(l->canreinvite) || (l->nat)){
+- ast_rtp_get_us(rtp, &us);
++ ast_rtp_instance_get_local_address(rtp, &us);
+ req->data.startmedia.remoteIp = htolel(d->ourip.s_addr);
+ req->data.startmedia.remotePort = htolel(ntohs(us.sin_port));
+ } else {
+@@ -2675,11 +2771,11 @@
+ return 0;
+ }
+
+-static struct ast_rtp_protocol skinny_rtp = {
++static struct ast_rtp_glue skinny_rtp_glue = {
+ .type = "Skinny",
+ .get_rtp_info = skinny_get_rtp_peer,
+ .get_vrtp_info = skinny_get_vrtp_peer,
+- .set_rtp_peer = skinny_set_rtp_peer,
++ .update_peer = skinny_set_rtp_peer,
+ };
+
+ static char *handle_skinny_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+@@ -3010,13 +3106,6 @@
+ return CLI_SUCCESS;
+ }
+
+-static char mandescr_show_devices[] =
+-"Description: Lists Skinny devices in text format with details on current status.\n"
+-"Devicelist will follow as separate events, followed by a final event called\n"
+-"DevicelistComplete.\n"
+-"Variables: \n"
+-" ActionID: <id> Action ID for this transaction. Will be returned.\n";
+-
+ /*! \brief Show SKINNY devices in the manager API */
+ /* Inspired from chan_sip */
+ static int manager_skinny_show_devices(struct mansession *s, const struct message *m)
+@@ -3155,12 +3244,6 @@
+ return CLI_SUCCESS;
+ }
+
+-static char mandescr_show_device[] =
+-"Description: Show one SKINNY device with details on current status.\n"
+-"Variables: \n"
+-" Device: <name> The device name you want to check.\n"
+-" ActionID: <id> Optional action ID for this AMI transaction.\n";
+-
+ static int manager_skinny_show_device(struct mansession *s, const struct message *m)
+ {
+ const char *a[4];
+@@ -3271,13 +3354,6 @@
+ return CLI_SUCCESS;
+ }
+
+-static char mandescr_show_lines[] =
+-"Description: Lists Skinny lines in text format with details on current status.\n"
+-"Linelist will follow as separate events, followed by a final event called\n"
+-"LinelistComplete.\n"
+-"Variables: \n"
+-" ActionID: <id> Action ID for this transaction. Will be returned.\n";
+-
+ /*! \brief Show Skinny lines in the manager API */
+ /* Inspired from chan_sip */
+ static int manager_skinny_show_lines(struct mansession *s, const struct message *m)
+@@ -3463,12 +3539,6 @@
+ return CLI_SUCCESS;
+ }
+
+-static char mandescr_show_line[] =
+-"Description: Show one SKINNY line with details on current status.\n"
+-"Variables: \n"
+-" Line: <name> The line name you want to check.\n"
+-" ActionID: <id> Optional action ID for this AMI transaction.\n";
+-
+ static int manager_skinny_show_line(struct mansession *s, const struct message *m)
+ {
+ const char *a[4];
+@@ -3559,29 +3629,36 @@
+
+ ast_mutex_lock(&sub->lock);
+ /* Allocate the RTP */
+- sub->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
++ sub->rtp = ast_rtp_instance_new(NULL, sched, &bindaddr, NULL);
+ if (hasvideo)
+- sub->vrtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
+-
++ sub->vrtp = ast_rtp_instance_new(NULL, sched, &bindaddr, NULL);
++
++ if (sub->rtp) {
++ ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_RTCP, 1);
++ }
++ if (sub->vrtp) {
++ ast_rtp_instance_set_prop(sub->vrtp, AST_RTP_PROPERTY_RTCP, 1);
++ }
++
+ if (sub->rtp && sub->owner) {
+- ast_channel_set_fd(sub->owner, 0, ast_rtp_fd(sub->rtp));
+- ast_channel_set_fd(sub->owner, 1, ast_rtcp_fd(sub->rtp));
++ ast_channel_set_fd(sub->owner, 0, ast_rtp_instance_fd(sub->rtp, 0));
++ ast_channel_set_fd(sub->owner, 1, ast_rtp_instance_fd(sub->rtp, 1));
+ }
+ if (hasvideo && sub->vrtp && sub->owner) {
+- ast_channel_set_fd(sub->owner, 2, ast_rtp_fd(sub->vrtp));
+- ast_channel_set_fd(sub->owner, 3, ast_rtcp_fd(sub->vrtp));
++ ast_channel_set_fd(sub->owner, 2, ast_rtp_instance_fd(sub->vrtp, 0));
++ ast_channel_set_fd(sub->owner, 3, ast_rtp_instance_fd(sub->vrtp, 1));
+ }
+ if (sub->rtp) {
+- ast_rtp_setqos(sub->rtp, qos.tos_audio, qos.cos_audio, "Skinny RTP");
+- ast_rtp_setnat(sub->rtp, l->nat);
++ ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "Skinny RTP");
++ ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, l->nat);
+ }
+ if (sub->vrtp) {
+- ast_rtp_setqos(sub->vrtp, qos.tos_video, qos.cos_video, "Skinny VRTP");
+- ast_rtp_setnat(sub->vrtp, l->nat);
++ ast_rtp_instance_set_qos(sub->vrtp, qos.tos_video, qos.cos_video, "Skinny VRTP");
++ ast_rtp_instance_set_prop(sub->vrtp, AST_RTP_PROPERTY_NAT, l->nat);
+ }
+ /* Set Frame packetization */
+ if (sub->rtp)
+- ast_rtp_codec_setpref(sub->rtp, &l->prefs);
++ ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp, &l->prefs);
+
+ /* Create the RTP connection */
+ transmit_connect(d, sub);
+@@ -3601,6 +3678,8 @@
+ l->hidecallerid ? "" : l->cid_num,
+ l->hidecallerid ? "" : l->cid_name,
+ c->cid.cid_ani ? NULL : l->cid_num);
++ c->connected.id.number = ast_strdup(c->exten);
++ c->connected.id.name = NULL;
+ ast_setstate(c, AST_STATE_RING);
+ if (!sub->rtp) {
+ start_rtp(sub);
+@@ -3764,7 +3843,7 @@
+ transmit_callstateonly(d, sub, SKINNY_RINGIN);
+ transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGIN);
+ transmit_displaypromptstatus(d, "Ring-In", 0, l->instance, sub->callid);
+- transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, l->cid_name, l->cid_num, l->instance, sub->callid, 1);
++ transmit_callinfo(d, ast->connected.id.name, ast->connected.id.number, l->cid_name, l->cid_num, l->instance, sub->callid, 1);
+ transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK);
+ transmit_ringer_mode(d, SKINNY_RING_INSIDE);
+
+@@ -3852,7 +3931,7 @@
+ sub->alreadygone = 0;
+ sub->outgoing = 0;
+ if (sub->rtp) {
+- ast_rtp_destroy(sub->rtp);
++ ast_rtp_instance_destroy(sub->rtp);
+ sub->rtp = NULL;
+ }
+ ast_mutex_unlock(&sub->lock);
+@@ -3891,7 +3970,7 @@
+ /* order matters here...
+ for some reason, transmit_callinfo must be before transmit_callstate,
+ or you won't get keypad messages in some situations. */
+- transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, l->lastnumberdialed, l->lastnumberdialed, l->instance, sub->callid, 2);
++ transmit_callinfo(d, ast->connected.id.name, ast->connected.id.number, l->lastnumberdialed, l->lastnumberdialed, l->instance, sub->callid, 2);
+ transmit_callstateonly(d, sub, SKINNY_CONNECTED);
+ transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_CONNECTED);
+ transmit_dialednumber(d, l->lastnumberdialed, l->instance, sub->callid);
+@@ -3913,16 +3992,16 @@
+
+ switch(ast->fdno) {
+ case 0:
+- f = ast_rtp_read(sub->rtp); /* RTP Audio */
++ f = ast_rtp_instance_read(sub->rtp, 0); /* RTP Audio */
+ break;
+ case 1:
+- f = ast_rtcp_read(sub->rtp); /* RTCP Control Channel */
++ f = ast_rtp_instance_read(sub->rtp, 1); /* RTCP Control Channel */
+ break;
+ case 2:
+- f = ast_rtp_read(sub->vrtp); /* RTP Video */
++ f = ast_rtp_instance_read(sub->vrtp, 0); /* RTP Video */
+ break;
+ case 3:
+- f = ast_rtcp_read(sub->vrtp); /* RTCP Control Channel for video */
++ f = ast_rtp_instance_read(sub->vrtp, 1); /* RTCP Control Channel for video */
+ break;
+ #if 0
+ case 5:
+@@ -3979,7 +4058,7 @@
+ if (sub) {
+ ast_mutex_lock(&sub->lock);
+ if (sub->rtp) {
+- res = ast_rtp_write(sub->rtp, frame);
++ res = ast_rtp_instance_write(sub->rtp, frame);
+ }
+ ast_mutex_unlock(&sub->lock);
+ }
+@@ -4086,6 +4165,10 @@
+ return "Unhold";
+ case AST_CONTROL_SRCUPDATE:
+ return "Media Source Update";
++ case AST_CONTROL_CONNECTED_LINE:
++ return "Connected Line";
++ case AST_CONTROL_REDIRECTING:
++ return "Redirecting";
+ case -1:
+ return "Stop tone";
+ default:
+@@ -4193,7 +4276,7 @@
+ transmit_callstateonly(d, sub, SKINNY_RINGOUT);
+ transmit_dialednumber(d, l->lastnumberdialed, l->instance, sub->callid);
+ transmit_displaypromptstatus(d, "Ring Out", 0, l->instance, sub->callid);
+- transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, l->lastnumberdialed, l->lastnumberdialed, l->instance, sub->callid, 2); /* 2 = outgoing from phone */
++ transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, S_OR(ast->connected.id.name, l->lastnumberdialed), S_OR(ast->connected.id.number, l->lastnumberdialed), l->instance, sub->callid, 2); /* 2 = outgoing from phone */
+ sub->ringing = 1;
+ if (!d->earlyrtp) {
+ break;
+@@ -4234,7 +4317,7 @@
+ }
+ transmit_callstateonly(d, sub, SKINNY_PROGRESS);
+ transmit_displaypromptstatus(d, "Call Progress", 0, l->instance, sub->callid);
+- transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, l->lastnumberdialed, l->lastnumberdialed, l->instance, sub->callid, 2); /* 2 = outgoing from phone */
++ transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, S_OR(ast->connected.id.name, l->lastnumberdialed), S_OR(ast->connected.id.number, l->lastnumberdialed), l->instance, sub->callid, 2); /* 2 = outgoing from phone */
+ sub->progress = 1;
+ if (!d->earlyrtp) {
+ break;
+@@ -4253,8 +4336,11 @@
+ case AST_CONTROL_PROCEEDING:
+ break;
+ case AST_CONTROL_SRCUPDATE:
+- ast_rtp_new_source(sub->rtp);
++ ast_rtp_instance_new_source(sub->rtp);
+ break;
++ case AST_CONTROL_CONNECTED_LINE:
++ update_connectedline(sub, data, datalen);
++ break;
+ default:
+ ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
+ return -1; /* Tell asterisk to provide inband signalling */
+@@ -4312,7 +4398,7 @@
+ if (skinnydebug)
+ ast_verb(1, "skinny_new: tmp->nativeformats=%d fmt=%d\n", tmp->nativeformats, fmt);
+ if (sub->rtp) {
+- ast_channel_set_fd(tmp, 0, ast_rtp_fd(sub->rtp));
++ ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(sub->rtp, 0));
+ }
+ if (state == AST_STATE_RING) {
+ tmp->rings = 1;
+@@ -5509,8 +5595,8 @@
+ struct skinny_line *l;
+ struct skinny_subchannel *sub;
+ struct ast_format_list fmt;
+- struct sockaddr_in sin;
+- struct sockaddr_in us;
++ struct sockaddr_in sin = { 0, };
++ struct sockaddr_in us = { 0, };
+ uint32_t addr;
+ int port;
+ int status;
+@@ -5537,8 +5623,8 @@
+ l = sub->parent;
+
+ if (sub->rtp) {
+- ast_rtp_set_peer(sub->rtp, &sin);
+- ast_rtp_get_us(sub->rtp, &us);
++ ast_rtp_instance_set_remote_address(sub->rtp, &sin);
++ ast_rtp_instance_get_local_address(sub->rtp, &us);
+ } else {
+ ast_log(LOG_ERROR, "No RTP structure, this is very bad\n");
+ return 0;
+@@ -7289,17 +7375,13 @@
+ return -1;
+ }
+
+- ast_rtp_proto_register(&skinny_rtp);
++ ast_rtp_glue_register(&skinny_rtp_glue);
+ ast_cli_register_multiple(cli_skinny, ARRAY_LEN(cli_skinny));
+
+- ast_manager_register2("SKINNYdevices", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_devices,
+- "List SKINNY devices (text format)", mandescr_show_devices);
+- ast_manager_register2("SKINNYshowdevice", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_device,
+- "Show SKINNY device (text format)", mandescr_show_device);
+- ast_manager_register2("SKINNYlines", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_lines,
+- "List SKINNY lines (text format)", mandescr_show_lines);
+- ast_manager_register2("SKINNYshowline", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_line,
+- "Show SKINNY line (text format)", mandescr_show_line);
++ ast_manager_register_xml("SKINNYdevices", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_devices);
++ ast_manager_register_xml("SKINNYshowdevice", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_device);
++ ast_manager_register_xml("SKINNYlines", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_lines);
++ ast_manager_register_xml("SKINNYshowline", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_line);
+
+ sched = sched_context_create();
+ if (!sched) {
+@@ -7323,7 +7405,7 @@
+ struct skinny_subchannel *sub;
+ struct ast_context *con;
+
+- ast_rtp_proto_unregister(&skinny_rtp);
++ ast_rtp_glue_unregister(&skinny_rtp_glue);
+ ast_channel_unregister(&skinny_tech);
+ ast_cli_unregister_multiple(cli_skinny, ARRAY_LEN(cli_skinny));
+
+Index: channels/xpmr/xpmr.c
+===================================================================
+--- a/channels/xpmr/xpmr.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/channels/xpmr/xpmr.c (.../trunk) (revision 202568)
+@@ -157,7 +157,7 @@
+ TRACEJ(2,(" source len = %i\n",slen));
+
+ pd=*dest;
+- if(pd) free(pd);
++ free(pd);
+ pd=calloc(slen+1,1);
+ memcpy(pd,src,slen);
+ *dest=pd;
+Index: channels/console_gui.c
+===================================================================
+--- a/channels/console_gui.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/channels/console_gui.c (.../trunk) (revision 202568)
+@@ -832,7 +832,7 @@
+ * use a translation table, below - one line per entry,
+ * plain, shift, ctrl, ... using the first char as key.
+ */
+-static const char *us_kbd_map[] = {
++static const char * const us_kbd_map[] = {
+ "`~", "1!", "2@", "3#", "4$", "5%", "6^",
+ "7&", "8*", "9(", "0)", "-_", "=+", "[{",
+ "]}", "\\|", ";:", "'\"", ",<", ".>", "/?",
+@@ -1505,7 +1505,7 @@
+ }
+
+ struct _s_k { const char *s; int k; };
+-static struct _s_k gui_key_map[] = {
++static const struct _s_k gui_key_map[] = {
+ {"FREEZE", KEY_FREEZE},
+ {"PIP", KEY_PIP},
+ {"PICK_UP", KEY_PICK_UP },
+Index: channels/chan_alsa.c
+===================================================================
+--- a/channels/chan_alsa.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/channels/chan_alsa.c (.../trunk) (revision 202568)
+@@ -782,7 +782,7 @@
+ {
+ char tmp[256], *tmp2;
+ char *mye, *myc;
+- char *d;
++ const char *d;
+ char *res = CLI_SUCCESS;
+
+ switch (cmd) {
+Index: channels/chan_nbs.c
+===================================================================
+--- a/channels/chan_nbs.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/channels/chan_nbs.c (.../trunk) (revision 202568)
+@@ -53,7 +53,7 @@
+ static int prefformat = AST_FORMAT_SLINEAR;
+
+ static char context[AST_MAX_EXTENSION] = "default";
+-static char type[] = "NBS";
++static const char type[] = "NBS";
+
+ /* NBS creates private structures on demand */
+
+Index: channels/chan_mgcp.c
+===================================================================
+--- a/channels/chan_mgcp.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/channels/chan_mgcp.c (.../trunk) (revision 202568)
+@@ -52,7 +52,7 @@
+ #include "asterisk/pbx.h"
+ #include "asterisk/sched.h"
+ #include "asterisk/io.h"
+-#include "asterisk/rtp.h"
++#include "asterisk/rtp_engine.h"
+ #include "asterisk/acl.h"
+ #include "asterisk/callerid.h"
+ #include "asterisk/cli.h"
+@@ -119,7 +119,7 @@
+ #define MGCP_CX_INACTIVE 4
+ /*! } */
+
+-static char *mgcp_cxmodes[] = {
++static const char * const mgcp_cxmodes[] = {
+ "sendonly",
+ "recvonly",
+ "sendrecv",
+@@ -282,7 +282,7 @@
+ int id;
+ struct ast_channel *owner;
+ struct mgcp_endpoint *parent;
+- struct ast_rtp *rtp;
++ struct ast_rtp_instance *rtp;
+ struct sockaddr_in tmpdest;
+ char txident[80]; /*! \todo FIXME txident is replaced by rqnt_ident in endpoint.
+ This should be obsoleted */
+@@ -408,7 +408,7 @@
+ static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone);
+ static int transmit_modify_request(struct mgcp_subchannel *sub);
+ static int transmit_notify_request_with_callerid(struct mgcp_subchannel *sub, char *tone, char *callernum, char *callername);
+-static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp *rtp, int codecs);
++static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp, int codecs);
+ static int transmit_connection_del(struct mgcp_subchannel *sub);
+ static int transmit_audit_endpoint(struct mgcp_endpoint *p);
+ static void start_rtp(struct mgcp_subchannel *sub);
+@@ -447,7 +447,7 @@
+ .fixup = mgcp_fixup,
+ .send_digit_begin = mgcp_senddigit_begin,
+ .send_digit_end = mgcp_senddigit_end,
+- .bridge = ast_rtp_bridge,
++ .bridge = ast_rtp_instance_bridge,
+ };
+
+ static void mwi_event_cb(const struct ast_event *event, void *userdata)
+@@ -503,7 +503,7 @@
+ sub->alreadygone = 0;
+ memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
+ if (sub->rtp) {
+- ast_rtp_destroy(sub->rtp);
++ ast_rtp_instance_destroy(sub->rtp);
+ sub->rtp = NULL;
+ }
+ dump_cmd_queues(NULL, sub); /* SC */
+@@ -915,7 +915,7 @@
+ transmit_modify_request(sub->next);
+ }
+
+- transmit_notify_request_with_callerid(sub, tone, ast->cid.cid_num, ast->cid.cid_name);
++ transmit_notify_request_with_callerid(sub, tone, ast->connected.id.number, ast->connected.id.name);
+ ast_setstate(ast, AST_STATE_RINGING);
+
+ if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) {
+@@ -1003,7 +1003,7 @@
+ /* Reset temporary destination */
+ memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
+ if (sub->rtp) {
+- ast_rtp_destroy(sub->rtp);
++ ast_rtp_instance_destroy(sub->rtp);
+ sub->rtp = NULL;
+ }
+
+@@ -1098,7 +1098,7 @@
+ if (a->argc != 4)
+ return CLI_SHOWUSAGE;
+ /* split the name into parts by null */
+- ename = a->argv[3];
++ ename = ast_strdupa(a->argv[3]);
+ gname = ename;
+ while (*gname) {
+ if (*gname == '@') {
+@@ -1203,7 +1203,7 @@
+ /* Retrieve audio/etc from channel. Assumes sub->lock is already held. */
+ struct ast_frame *f;
+
+- f = ast_rtp_read(sub->rtp);
++ f = ast_rtp_instance_read(sub->rtp, 0);
+ /* Don't send RFC2833 if we're not supposed to */
+ if (f && (f->frametype == AST_FRAME_DTMF) && !(sub->parent->dtmfmode & MGCP_DTMF_RFC2833))
+ return &ast_null_frame;
+@@ -1261,7 +1261,7 @@
+ ast_mutex_lock(&sub->lock);
+ if ((sub->parent->sub == sub) || !sub->parent->singlepath) {
+ if (sub->rtp) {
+- res = ast_rtp_write(sub->rtp, frame);
++ res = ast_rtp_instance_write(sub->rtp, frame);
+ }
+ }
+ ast_mutex_unlock(&sub->lock);
+@@ -1297,7 +1297,7 @@
+ res = -1; /* Let asterisk play inband indications */
+ } else if (p->dtmfmode & MGCP_DTMF_RFC2833) {
+ ast_log(LOG_DEBUG, "Sending DTMF using RFC2833");
+- ast_rtp_senddigit_begin(sub->rtp, digit);
++ ast_rtp_instance_dtmf_begin(sub->rtp, digit);
+ } else {
+ ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode);
+ }
+@@ -1324,7 +1324,7 @@
+ tmp[2] = digit;
+ tmp[3] = '\0';
+ transmit_notify_request(sub, tmp);
+- ast_rtp_senddigit_end(sub->rtp, digit);
++ ast_rtp_instance_dtmf_end(sub->rtp, digit);
+ } else {
+ ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode);
+ }
+@@ -1453,7 +1453,7 @@
+ ast_moh_stop(ast);
+ break;
+ case AST_CONTROL_SRCUPDATE:
+- ast_rtp_new_source(sub->rtp);
++ ast_rtp_instance_new_source(sub->rtp);
+ break;
+ case -1:
+ transmit_notify_request(sub, "");
+@@ -1479,9 +1479,8 @@
+ if (!tmp->nativeformats)
+ tmp->nativeformats = capability;
+ fmt = ast_best_codec(tmp->nativeformats);
+- ast_string_field_build(tmp, name, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id);
+ if (sub->rtp)
+- ast_channel_set_fd(tmp, 0, ast_rtp_fd(sub->rtp));
++ ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(sub->rtp, 0));
+ if (i->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)) {
+ i->dsp = ast_dsp_new();
+ ast_dsp_set_features(i->dsp, DSP_FEATURE_DIGIT_DETECT);
+@@ -1874,12 +1873,12 @@
+ sin.sin_family = AF_INET;
+ memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
+ sin.sin_port = htons(portno);
+- ast_rtp_set_peer(sub->rtp, &sin);
++ ast_rtp_instance_set_remote_address(sub->rtp, &sin);
+ #if 0
+ printf("Peer RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
+ #endif
+ /* Scan through the RTP payload types specified in a "m=" line: */
+- ast_rtp_pt_clear(sub->rtp);
++ ast_rtp_codecs_payloads_clear(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp);
+ codecs = ast_strdupa(m + len);
+ while (!ast_strlen_zero(codecs)) {
+ if (sscanf(codecs, "%d%n", &codec, &len) != 1) {
+@@ -1888,7 +1887,7 @@
+ ast_log(LOG_WARNING, "Error in codec string '%s' at '%s'\n", m, codecs);
+ return -1;
+ }
+- ast_rtp_set_m_type(sub->rtp, codec);
++ ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp, codec);
+ codec_count++;
+ codecs += len;
+ }
+@@ -1901,11 +1900,11 @@
+ if (sscanf(a, "rtpmap: %u %[^/]/", &codec, mimeSubtype) != 2)
+ continue;
+ /* Note: should really look at the 'freq' and '#chans' params too */
+- ast_rtp_set_rtpmap_type(sub->rtp, codec, "audio", mimeSubtype, 0);
++ ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp, codec, "audio", mimeSubtype, 0);
+ }
+
+ /* Now gather all of the codecs that were asked for: */
+- ast_rtp_get_current_formats(sub->rtp, &peercapability, &peerNonCodecCapability);
++ ast_rtp_codecs_payload_formats(ast_rtp_instance_get_codecs(sub->rtp), &peercapability, &peerNonCodecCapability);
+ p->capability = capability & peercapability;
+ if (mgcpdebug) {
+ ast_verbose("Capabilities: us - %d, them - %d, combined - %d\n",
+@@ -1920,7 +1919,7 @@
+ return 0;
+ }
+
+-static int add_header(struct mgcp_request *req, char *var, char *value)
++static int add_header(struct mgcp_request *req, const char *var, const char *value)
+ {
+ if (req->len >= sizeof(req->data) - 4) {
+ ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
+@@ -2043,7 +2042,7 @@
+ }
+
+
+-static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struct ast_rtp *rtp)
++static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp)
+ {
+ int len;
+ int codec;
+@@ -2057,7 +2056,7 @@
+ char m[256] = "";
+ char a[1024] = "";
+ int x;
+- struct sockaddr_in dest;
++ struct sockaddr_in dest = { 0, };
+ struct mgcp_endpoint *p = sub->parent;
+ /* XXX We break with the "recommendation" and send our IP, in order that our
+ peer doesn't have to ast_gethostbyname() us XXX */
+@@ -2066,9 +2065,9 @@
+ ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n");
+ return -1;
+ }
+- ast_rtp_get_us(sub->rtp, &sin);
++ ast_rtp_instance_get_local_address(sub->rtp, &sin);
+ if (rtp) {
+- ast_rtp_get_peer(rtp, &dest);
++ ast_rtp_instance_get_remote_address(sub->rtp, &dest);
+ } else {
+ if (sub->tmpdest.sin_addr.s_addr) {
+ dest.sin_addr = sub->tmpdest.sin_addr;
+@@ -2094,11 +2093,11 @@
+ if (mgcpdebug) {
+ ast_verbose("Answering with capability %d\n", x);
+ }
+- codec = ast_rtp_lookup_code(sub->rtp, 1, x);
++ codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, x);
+ if (codec > -1) {
+ snprintf(costr, sizeof(costr), " %d", codec);
+ strncat(m, costr, sizeof(m) - strlen(m) - 1);
+- snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(1, x, 0));
++ snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype2(1, x, 0));
+ strncat(a, costr, sizeof(a) - strlen(a) - 1);
+ }
+ }
+@@ -2108,11 +2107,11 @@
+ if (mgcpdebug) {
+ ast_verbose("Answering with non-codec capability %d\n", x);
+ }
+- codec = ast_rtp_lookup_code(sub->rtp, 0, x);
++ codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 0, x);
+ if (codec > -1) {
+ snprintf(costr, sizeof(costr), " %d", codec);
+ strncat(m, costr, sizeof(m) - strlen(m) - 1);
+- snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(0, x, 0));
++ snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype2(0, x, 0));
+ strncat(a, costr, sizeof(a) - strlen(a) - 1);
+ if (x == AST_RTP_DTMF) {
+ /* Indicate we support DTMF... Not sure about 16,
+@@ -2136,7 +2135,7 @@
+ return 0;
+ }
+
+-static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp *rtp, int codecs)
++static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp, int codecs)
+ {
+ struct mgcp_request resp;
+ char local[256];
+@@ -2147,13 +2146,13 @@
+ if (ast_strlen_zero(sub->cxident) && rtp) {
+ /* We don't have a CXident yet, store the destination and
+ wait a bit */
+- ast_rtp_get_peer(rtp, &sub->tmpdest);
++ ast_rtp_instance_get_remote_address(rtp, &sub->tmpdest);
+ return 0;
+ }
+ ast_copy_string(local, "p:20", sizeof(local));
+ for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) {
+ if (p->capability & x) {
+- snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x, 0));
++ snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, x, 0));
+ strncat(local, tmp, sizeof(local) - strlen(local) - 1);
+ }
+ }
+@@ -2172,7 +2171,7 @@
+ return send_request(p, sub, &resp, oseq); /* SC */
+ }
+
+-static int transmit_connect_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp *rtp)
++static int transmit_connect_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp)
+ {
+ struct mgcp_request resp;
+ char local[256];
+@@ -2183,7 +2182,7 @@
+ ast_copy_string(local, "p:20", sizeof(local));
+ for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) {
+ if (p->capability & x) {
+- snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x, 0));
++ snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, x, 0));
+ strncat(local, tmp, sizeof(local) - strlen(local) - 1);
+ }
+ }
+@@ -2611,21 +2610,17 @@
+ ast_mutex_lock(&sub->lock);
+ /* check again to be on the safe side */
+ if (sub->rtp) {
+- ast_rtp_destroy(sub->rtp);
++ ast_rtp_instance_destroy(sub->rtp);
+ sub->rtp = NULL;
+ }
+ /* Allocate the RTP now */
+- sub->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
++ sub->rtp = ast_rtp_instance_new(NULL, sched, &bindaddr, NULL);
+ if (sub->rtp && sub->owner)
+- ast_channel_set_fd(sub->owner, 0, ast_rtp_fd(sub->rtp));
++ ast_channel_set_fd(sub->owner, 0, ast_rtp_instance_fd(sub->rtp, 0));
+ if (sub->rtp) {
+- ast_rtp_setqos(sub->rtp, qos.tos_audio, qos.cos_audio, "MGCP RTP");
+- ast_rtp_setnat(sub->rtp, sub->nat);
++ ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "MGCP RTP");
++ ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, sub->nat);
+ }
+-#if 0
+- ast_rtp_set_callback(p->rtp, rtpready);
+- ast_rtp_set_data(p->rtp, p);
+-#endif
+ /* Make a call*ID */
+ snprintf(sub->callid, sizeof(sub->callid), "%08lx%s", ast_random(), sub->txident);
+ /* Transmit the connection create */
+@@ -3940,22 +3935,22 @@
+ return (gw_reload ? NULL : gw);
+ }
+
+-static enum ast_rtp_get_result mgcp_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
++static enum ast_rtp_glue_result mgcp_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
+ {
+ struct mgcp_subchannel *sub = NULL;
+
+ if (!(sub = chan->tech_pvt) || !(sub->rtp))
+- return AST_RTP_GET_FAILED;
++ return AST_RTP_GLUE_RESULT_FORBID;
+
+- *rtp = sub->rtp;
++ *instance = sub->rtp ? ao2_ref(sub->rtp, +1), sub->rtp : NULL;
+
+ if (sub->parent->canreinvite)
+- return AST_RTP_TRY_NATIVE;
++ return AST_RTP_GLUE_RESULT_REMOTE;
+ else
+- return AST_RTP_TRY_PARTIAL;
++ return AST_RTP_GLUE_RESULT_LOCAL;
+ }
+
+-static int mgcp_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active)
++static int mgcp_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, int codecs, int nat_active)
+ {
+ /* XXX Is there such thing as video support with MGCP? XXX */
+ struct mgcp_subchannel *sub;
+@@ -3967,10 +3962,10 @@
+ return -1;
+ }
+
+-static struct ast_rtp_protocol mgcp_rtp = {
++static struct ast_rtp_glue mgcp_rtp_glue = {
+ .type = "MGCP",
+ .get_rtp_info = mgcp_get_rtp_peer,
+- .set_rtp_peer = mgcp_set_rtp_peer,
++ .update_peer = mgcp_set_rtp_peer,
+ };
+
+ static void destroy_endpoint(struct mgcp_endpoint *e)
+@@ -3984,7 +3979,7 @@
+ transmit_connection_del(sub);
+ }
+ if (sub->rtp) {
+- ast_rtp_destroy(sub->rtp);
++ ast_rtp_instance_destroy(sub->rtp);
+ sub->rtp = NULL;
+ }
+ memset(sub->magic, 0, sizeof(sub->magic));
+@@ -4276,7 +4271,7 @@
+ return AST_MODULE_LOAD_FAILURE;
+ }
+
+- ast_rtp_proto_register(&mgcp_rtp);
++ ast_rtp_glue_register(&mgcp_rtp_glue);
+ ast_cli_register_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry));
+
+ /* And start the monitor for the first time */
+@@ -4379,7 +4374,7 @@
+ }
+
+ close(mgcpsock);
+- ast_rtp_proto_unregister(&mgcp_rtp);
++ ast_rtp_glue_unregister(&mgcp_rtp_glue);
+ ast_cli_unregister_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry));
+ sched_context_destroy(sched);
+
+Index: channels/chan_unistim.c
+===================================================================
+--- a/channels/chan_unistim.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/channels/chan_unistim.c (.../trunk) (revision 202568)
+@@ -60,7 +60,7 @@
+ #include "asterisk/module.h"
+ #include "asterisk/pbx.h"
+ #include "asterisk/event.h"
+-#include "asterisk/rtp.h"
++#include "asterisk/rtp_engine.h"
+ #include "asterisk/netsock.h"
+ #include "asterisk/acl.h"
+ #include "asterisk/callerid.h"
+@@ -365,7 +365,7 @@
+ /*! Unistim line */
+ struct unistim_line *parent;
+ /*! RTP handle */
+- struct ast_rtp *rtp;
++ struct ast_rtp_instance *rtp;
+ int alreadygone;
+ char ringvolume;
+ char ringstyle;
+@@ -502,7 +502,7 @@
+
+ static const unsigned char packet_rcv_discovery[] =
+ { 0xff, 0xff, 0xff, 0xff, 0x02, 0x02, 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
+-static unsigned char packet_send_discovery_ack[] =
++static const unsigned char packet_send_discovery_ack[] =
+ { 0x00, 0x00, /*Initial Seq (2 bytes) */ 0x00, 0x00, 0x00, 0x01 };
+
+ static const unsigned char packet_recv_firm_version[] =
+@@ -711,7 +711,7 @@
+ .send_digit_begin = unistim_senddigit_begin,
+ .send_digit_end = unistim_senddigit_end,
+ .send_text = unistim_sendtext,
+-/* .bridge = ast_rtp_bridge, */
++ .bridge = ast_rtp_instance_bridge,
+ };
+
+ static void display_last_error(const char *sz_msg)
+@@ -733,8 +733,8 @@
+ }
+
+ /* Send data to a phone without retransmit nor buffering */
+-static void send_raw_client(int size, unsigned char *data, struct sockaddr_in *addr_to,
+- const struct sockaddr_in *addr_ourip)
++static void send_raw_client(int size, const unsigned char *data, struct sockaddr_in *addr_to,
++ const struct sockaddr_in *addr_ourip)
+ {
+ #ifdef HAVE_PKTINFO
+ struct iovec msg_iov;
+@@ -743,7 +743,12 @@
+ struct cmsghdr *ip_msg = (struct cmsghdr *) buffer;
+ struct in_pktinfo *pki = (struct in_pktinfo *) CMSG_DATA(ip_msg);
+
+- msg_iov.iov_base = data;
++ /* cast this to a non-const pointer, since the sendmsg() API
++ * does not provide read-only and write-only flavors of the
++ * structures used for its arguments, but in this case we know
++ * the data will not be modified
++ */
++ msg_iov.iov_base = (char *) data;
+ msg_iov.iov_len = size;
+
+ msg.msg_name = addr_to; /* optional address */
+@@ -1854,7 +1859,7 @@
+ static void swap_subs(struct unistim_line *p, int a, int b)
+ {
+ /* struct ast_channel *towner; */
+- struct ast_rtp *rtp;
++ struct ast_rtp_instance *rtp;
+ int fds;
+
+ if (unistimdebug)
+@@ -2027,11 +2032,11 @@
+ static void start_rtp(struct unistim_subchannel *sub)
+ {
+ BUFFSEND;
+- struct sockaddr_in us;
+- struct sockaddr_in public;
+- struct sockaddr_in sin;
++ struct sockaddr_in us = { 0, };
++ struct sockaddr_in public = { 0, };
++ struct sockaddr_in sin = { 0, };
+ int codec;
+- struct sockaddr_in sout;
++ struct sockaddr_in sout = { 0, };
+
+ /* Sanity checks */
+ if (!sub) {
+@@ -2056,30 +2061,29 @@
+ /* Allocate the RTP */
+ if (unistimdebug)
+ ast_verb(0, "Starting RTP. Bind on %s\n", ast_inet_ntoa(sout.sin_addr));
+- sub->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, sout.sin_addr);
++ sub->rtp = ast_rtp_instance_new(NULL, sched, &sout, NULL);
+ if (!sub->rtp) {
+ ast_log(LOG_WARNING, "Unable to create RTP session: %s binaddr=%s\n",
+ strerror(errno), ast_inet_ntoa(sout.sin_addr));
+ ast_mutex_unlock(&sub->lock);
+ return;
+ }
+- if (sub->rtp && sub->owner) {
+- sub->owner->fds[0] = ast_rtp_fd(sub->rtp);
+- sub->owner->fds[1] = ast_rtcp_fd(sub->rtp);
++ ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_RTCP, 1);
++ if (sub->owner) {
++ sub->owner->fds[0] = ast_rtp_instance_fd(sub->rtp, 0);
++ sub->owner->fds[1] = ast_rtp_instance_fd(sub->rtp, 1);
+ }
+- if (sub->rtp) {
+- ast_rtp_setqos(sub->rtp, qos.tos_audio, qos.cos_audio, "UNISTIM RTP");
+- ast_rtp_setnat(sub->rtp, sub->parent->parent->nat);
+- }
++ ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "UNISTIM RTP");
++ ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, sub->parent->parent->nat);
+
+ /* Create the RTP connection */
+- ast_rtp_get_us(sub->rtp, &us);
++ ast_rtp_instance_get_local_address(sub->rtp, &us);
+ sin.sin_family = AF_INET;
+ /* Setting up RTP for our side */
+ memcpy(&sin.sin_addr, &sub->parent->parent->session->sin.sin_addr,
+ sizeof(sin.sin_addr));
+ sin.sin_port = htons(sub->parent->parent->rtp_port);
+- ast_rtp_set_peer(sub->rtp, &sin);
++ ast_rtp_instance_set_remote_address(sub->rtp, &sin);
+ if (!(sub->owner->nativeformats & sub->owner->readformat)) {
+ int fmt;
+ fmt = ast_best_codec(sub->owner->nativeformats);
+@@ -2091,7 +2095,7 @@
+ sub->owner->readformat = fmt;
+ sub->owner->writeformat = fmt;
+ }
+- codec = ast_rtp_lookup_code(sub->rtp, 1, sub->owner->readformat);
++ codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, sub->owner->readformat);
+ /* Setting up RTP of the phone */
+ if (public_ip.sin_family == 0) /* NAT IP override ? */
+ memcpy(&public, &us, sizeof(public)); /* No defined, using IP from recvmsg */
+@@ -3671,16 +3675,16 @@
+ Sendicon(TEXT_LINE0, FAV_ICON_NONE, session);
+
+ if (sub->owner) {
+- if (sub->owner->cid.cid_num) {
+- send_text(TEXT_LINE1, TEXT_NORMAL, session, sub->owner->cid.cid_num);
+- change_callerid(session, 0, sub->owner->cid.cid_num);
++ if (sub->owner->connected.id.number) {
++ send_text(TEXT_LINE1, TEXT_NORMAL, session, sub->owner->connected.id.number);
++ change_callerid(session, 0, sub->owner->connected.id.number);
+ } else {
+ send_text(TEXT_LINE1, TEXT_NORMAL, session, DEFAULTCALLERID);
+ change_callerid(session, 0, DEFAULTCALLERID);
+ }
+- if (sub->owner->cid.cid_name) {
+- send_text(TEXT_LINE0, TEXT_NORMAL, session, sub->owner->cid.cid_name);
+- change_callerid(session, 1, sub->owner->cid.cid_name);
++ if (sub->owner->connected.id.name) {
++ send_text(TEXT_LINE0, TEXT_NORMAL, session, sub->owner->connected.id.name);
++ change_callerid(session, 1, sub->owner->connected.id.name);
+ } else {
+ send_text(TEXT_LINE0, TEXT_NORMAL, session, DEFAULTCALLERNAME);
+ change_callerid(session, 1, DEFAULTCALLERNAME);
+@@ -3723,7 +3727,7 @@
+ if (sub->rtp) {
+ if (unistimdebug)
+ ast_verb(0, "Destroying RTP session\n");
+- ast_rtp_destroy(sub->rtp);
++ ast_rtp_instance_destroy(sub->rtp);
+ sub->rtp = NULL;
+ }
+ return 0;
+@@ -3768,7 +3772,7 @@
+ if (sub->rtp) {
+ if (unistimdebug)
+ ast_verb(0, "Destroying RTP session\n");
+- ast_rtp_destroy(sub->rtp);
++ ast_rtp_instance_destroy(sub->rtp);
+ sub->rtp = NULL;
+ }
+ return 0;
+@@ -3793,7 +3797,7 @@
+ if (sub->rtp) {
+ if (unistimdebug)
+ ast_verb(0, "Destroying RTP session\n");
+- ast_rtp_destroy(sub->rtp);
++ ast_rtp_instance_destroy(sub->rtp);
+ sub->rtp = NULL;
+ } else if (unistimdebug)
+ ast_verb(0, "No RTP session to destroy\n");
+@@ -3920,10 +3924,10 @@
+
+ switch (ast->fdno) {
+ case 0:
+- f = ast_rtp_read(sub->rtp); /* RTP Audio */
++ f = ast_rtp_instance_read(sub->rtp, 0); /* RTP Audio */
+ break;
+ case 1:
+- f = ast_rtcp_read(sub->rtp); /* RTCP Control Channel */
++ f = ast_rtp_instance_read(sub->rtp, 1); /* RTCP Control Channel */
+ break;
+ default:
+ f = &ast_null_frame;
+@@ -3989,7 +3993,7 @@
+ if (sub) {
+ ast_mutex_lock(&sub->lock);
+ if (sub->rtp) {
+- res = ast_rtp_write(sub->rtp, frame);
++ res = ast_rtp_instance_write(sub->rtp, frame);
+ }
+ ast_mutex_unlock(&sub->lock);
+ }
+@@ -4433,8 +4437,8 @@
+ return NULL;
+ }
+ l = sub->parent;
+- tmp = ast_channel_alloc(1, state, l->cid_num, NULL, l->accountcode, l->exten,
+- l->context, l->amaflags, "%s-%08x", l->fullname, (int) (long) sub);
++ tmp = ast_channel_alloc(1, state, l->cid_num, NULL, l->accountcode, l->exten,
++ l->context, l->amaflags, "%s@%s-%d", l->name, l->parent->name, sub->subtype);
+ if (unistimdebug)
+ ast_verb(0, "unistim_new sub=%d (%p) chan=%p\n", sub->subtype, sub, tmp);
+ if (!tmp) {
+@@ -4449,13 +4453,11 @@
+ if (unistimdebug)
+ ast_verb(0, "Best codec = %d from nativeformats %d (line cap=%d global=%d)\n", fmt,
+ tmp->nativeformats, l->capability, CAPABILITY);
+- ast_string_field_build(tmp, name, "USTM/%s@%s-%d", l->name, l->parent->name,
+- sub->subtype);
+ if ((sub->rtp) && (sub->subtype == 0)) {
+ if (unistimdebug)
+ ast_verb(0, "New unistim channel with a previous rtp handle ?\n");
+- tmp->fds[0] = ast_rtp_fd(sub->rtp);
+- tmp->fds[1] = ast_rtcp_fd(sub->rtp);
++ tmp->fds[0] = ast_rtp_instance_fd(sub->rtp, 0);
++ tmp->fds[1] = ast_rtp_instance_fd(sub->rtp, 1);
+ }
+ if (sub->rtp)
+ ast_jb_configure(tmp, &global_jbconf);
+@@ -5525,51 +5527,19 @@
+ return 0;
+ }
+
+-static enum ast_rtp_get_result unistim_get_vrtp_peer(struct ast_channel *chan,
+- struct ast_rtp **rtp)
++static enum ast_rtp_glue_result unistim_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
+ {
+- return AST_RTP_TRY_NATIVE;
+-}
++ struct unistim_subchannel *sub = chan->tech_pvt;
+
+-static enum ast_rtp_get_result unistim_get_rtp_peer(struct ast_channel *chan,
+- struct ast_rtp **rtp)
+-{
+- struct unistim_subchannel *sub;
+- enum ast_rtp_get_result res = AST_RTP_GET_FAILED;
++ ao2_ref(sub->rtp, +1);
++ *instance = sub->rtp;
+
+- if (unistimdebug)
+- ast_verb(0, "unistim_get_rtp_peer called\n");
+-
+- sub = chan->tech_pvt;
+- if (sub && sub->rtp) {
+- *rtp = sub->rtp;
+- res = AST_RTP_TRY_NATIVE;
+- }
+-
+- return res;
++ return AST_RTP_GLUE_RESULT_LOCAL;
+ }
+
+-static int unistim_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp,
+- struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active)
+-{
+- struct unistim_subchannel *sub;
+-
+- if (unistimdebug)
+- ast_verb(0, "unistim_set_rtp_peer called\n");
+-
+- sub = chan->tech_pvt;
+-
+- if (sub)
+- return 0;
+-
+- return -1;
+-}
+-
+-static struct ast_rtp_protocol unistim_rtp = {
++static struct ast_rtp_glue unistim_rtp_glue = {
+ .type = channel_type,
+ .get_rtp_info = unistim_get_rtp_peer,
+- .get_vrtp_info = unistim_get_vrtp_peer,
+- .set_rtp_peer = unistim_set_rtp_peer,
+ };
+
+ /*--- load_module: PBX load module - initialization ---*/
+@@ -5602,7 +5572,7 @@
+ goto chanreg_failed;
+ }
+
+- ast_rtp_proto_register(&unistim_rtp);
++ ast_rtp_glue_register(&unistim_rtp_glue);
+
+ ast_cli_register_multiple(unistim_cli, ARRAY_LEN(unistim_cli));
+
+@@ -5633,7 +5603,7 @@
+ ast_cli_unregister_multiple(unistim_cli, ARRAY_LEN(unistim_cli));
+
+ ast_channel_unregister(&unistim_tech);
+- ast_rtp_proto_unregister(&unistim_rtp);
++ ast_rtp_glue_unregister(&unistim_rtp_glue);
+
+ ast_mutex_lock(&monlock);
+ if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
+Index: channels/chan_local.c
+===================================================================
+--- a/channels/chan_local.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/channels/chan_local.c (.../trunk) (revision 202568)
+@@ -39,7 +39,6 @@
+ #include "asterisk/pbx.h"
+ #include "asterisk/sched.h"
+ #include "asterisk/io.h"
+-#include "asterisk/rtp.h"
+ #include "asterisk/acl.h"
+ #include "asterisk/callerid.h"
+ #include "asterisk/file.h"
+@@ -407,6 +406,40 @@
+ ast_moh_start(ast, data, NULL);
+ } else if (condition == AST_CONTROL_UNHOLD) {
+ ast_moh_stop(ast);
++ } else if (condition == AST_CONTROL_CONNECTED_LINE || condition == AST_CONTROL_REDIRECTING) {
++ struct ast_channel *this_channel;
++ struct ast_channel *the_other_channel;
++ /* A connected line update frame may only contain a partial amount of data, such
++ * as just a source, or just a ton, and not the full amount of information. However,
++ * the collected information is all stored in the outgoing channel's connectedline
++ * structure, so when receiving a connected line update on an outgoing local channel,
++ * we need to transmit the collected connected line information instead of whatever
++ * happens to be in this control frame. The same applies for redirecting information, which
++ * is why it is handled here as well.*/
++ ast_mutex_lock(&p->lock);
++ isoutbound = IS_OUTBOUND(ast, p);
++ if (isoutbound) {
++ this_channel = p->chan;
++ the_other_channel = p->owner;
++ } else {
++ this_channel = p->owner;
++ the_other_channel = p->chan;
++ }
++ if (the_other_channel) {
++ unsigned char frame_data[1024];
++ if (condition == AST_CONTROL_CONNECTED_LINE) {
++ f.datalen = ast_connected_line_build_data(frame_data, sizeof(frame_data), &this_channel->connected);
++ } else {
++ f.datalen = ast_redirecting_build_data(frame_data, sizeof(frame_data), &this_channel->redirecting);
++ }
++ f.subclass = condition;
++ f.data.ptr = frame_data;
++ if (!(res = local_queue_frame(p, isoutbound, &f, ast, 1))) {
++ ast_mutex_unlock(&p->lock);
++ }
++ } else {
++ ast_mutex_unlock(&p->lock);
++ }
+ } else {
+ /* Queue up a frame representing the indication as a control frame */
+ ast_mutex_lock(&p->lock);
+@@ -510,22 +543,53 @@
+
+ if (!p)
+ return -1;
+-
+- ast_mutex_lock(&p->lock);
+
++ /* If you value your sanity, please don't look at this code */
++start_over:
++ while (ast_channel_trylock(p->chan)) {
++ ast_channel_unlock(p->owner);
++ usleep(1);
++ ast_channel_lock(p->owner);
++ }
++
++ /* p->owner and p->chan are locked now. Let's get p locked */
++ if (ast_mutex_trylock(&p->lock)) {
++ /* @#$&$@ */
++ ast_channel_unlock(p->chan);
++ ast_channel_unlock(p->owner);
++ usleep(1);
++ ast_channel_lock(p->owner);
++ goto start_over;
++ }
++
+ /*
+ * Note that cid_num and cid_name aren't passed in the ast_channel_alloc
+ * call, so it's done here instead.
++ *
++ * All these failure points just return -1. The individual strings will
++ * be cleared when we destroy the channel.
+ */
+- p->chan->cid.cid_dnid = ast_strdup(p->owner->cid.cid_dnid);
+- p->chan->cid.cid_num = ast_strdup(p->owner->cid.cid_num);
+- p->chan->cid.cid_name = ast_strdup(p->owner->cid.cid_name);
+- p->chan->cid.cid_rdnis = ast_strdup(p->owner->cid.cid_rdnis);
+- p->chan->cid.cid_ani = ast_strdup(p->owner->cid.cid_ani);
+- p->chan->cid.cid_pres = p->owner->cid.cid_pres;
+- p->chan->cid.cid_ani2 = p->owner->cid.cid_ani2;
+- p->chan->cid.cid_ton = p->owner->cid.cid_ton;
++ if (p->owner->cid.cid_rdnis) {
++ if (!(p->chan->cid.cid_rdnis = ast_strdup(p->owner->cid.cid_rdnis))) {
++ ast_mutex_unlock(&p->lock);
++ ast_channel_unlock(p->chan);
++ return -1;
++ }
++ }
++ ast_party_redirecting_copy(&p->chan->redirecting, &p->owner->redirecting);
++
++ if (p->owner->cid.cid_dnid) {
++ if (!(p->chan->cid.cid_dnid = ast_strdup(p->owner->cid.cid_dnid))) {
++ ast_mutex_unlock(&p->lock);
++ ast_channel_unlock(p->chan);
++ return -1;
++ }
++ }
+ p->chan->cid.cid_tns = p->owner->cid.cid_tns;
++
++ ast_connected_line_copy_to_caller(&p->chan->cid, &p->owner->connected);
++ ast_connected_line_copy_from_caller(&p->chan->connected, &p->owner->cid);
++
+ ast_string_field_set(p->chan, language, p->owner->language);
+ ast_string_field_set(p->chan, accountcode, p->owner->accountcode);
+ ast_string_field_set(p->chan, musicclass, p->owner->musicclass);
+@@ -535,6 +599,7 @@
+ if (!ast_exists_extension(NULL, p->chan->context, p->chan->exten, 1, p->owner->cid.cid_num)) {
+ ast_log(LOG_NOTICE, "No such extension/context %s@%s while calling Local channel\n", p->chan->exten, p->chan->context);
+ ast_mutex_unlock(&p->lock);
++ ast_channel_unlock(p->chan);
+ return -1;
+ }
+
+@@ -561,6 +626,7 @@
+ ast_set_flag(p, LOCAL_LAUNCHED_PBX);
+
+ ast_mutex_unlock(&p->lock);
++ ast_channel_unlock(p->chan);
+ return res;
+ }
+
+@@ -734,13 +800,12 @@
+ ama = 0;
+ if (!(tmp = ast_channel_alloc(1, state, 0, 0, t, p->exten, p->context, ama, "Local/%s@%s-%04x;1", p->exten, p->context, randnum))
+ || !(tmp2 = ast_channel_alloc(1, AST_STATE_RING, 0, 0, t, p->exten, p->context, ama, "Local/%s@%s-%04x;2", p->exten, p->context, randnum))) {
+- if (tmp)
+- ast_channel_free(tmp);
+- if (tmp2)
+- ast_channel_free(tmp2);
++ if (tmp) {
++ tmp = ast_channel_release(tmp);
++ }
+ ast_log(LOG_WARNING, "Unable to allocate channel structure(s)\n");
+ return NULL;
+- }
++ }
+
+ tmp2->tech = tmp->tech = &local_tech;
+
+Index: channels/chan_bridge.c
+===================================================================
+--- a/channels/chan_bridge.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/channels/chan_bridge.c (.../trunk) (revision 202568)
+@@ -39,7 +39,6 @@
+ #include "asterisk/pbx.h"
+ #include "asterisk/sched.h"
+ #include "asterisk/io.h"
+-#include "asterisk/rtp.h"
+ #include "asterisk/acl.h"
+ #include "asterisk/callerid.h"
+ #include "asterisk/file.h"
+@@ -205,7 +204,7 @@
+ return NULL;
+ }
+ if (!(p->output = ast_channel_alloc(1, AST_STATE_UP, 0, 0, "", "", "", 0, "Bridge/%p-output", p))) {
+- ast_channel_free(p->input);
++ p->input = ast_channel_release(p->input);
+ ast_free(p);
+ return NULL;
+ }
+Index: channels/vcodecs.c
+===================================================================
+--- a/channels/vcodecs.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/channels/vcodecs.c (.../trunk) (revision 202568)
+@@ -1113,7 +1113,7 @@
+ //struct video_codec_desc *codec_desc;
+ };
+
+-static struct _cm video_formats[] = {
++static const struct _cm video_formats[] = {
+ { AST_FORMAT_H263_PLUS, CODEC_ID_H263, CM_RD }, /* incoming H263P ? */
+ { AST_FORMAT_H263_PLUS, CODEC_ID_H263P, CM_WR },
+ { AST_FORMAT_H263, CODEC_ID_H263, CM_RD },
+@@ -1137,7 +1137,7 @@
+ }
+
+ /* pointers to supported codecs. We assume the first one to be non null. */
+-static struct video_codec_desc *supported_codecs[] = {
++static const struct video_codec_desc *supported_codecs[] = {
+ &h263p_codec,
+ &h264_codec,
+ &h263_codec,
+Index: channels/misdn/isdn_msg_parser.c
+===================================================================
+--- a/channels/misdn/isdn_msg_parser.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/channels/misdn/isdn_msg_parser.c (.../trunk) (revision 202568)
+@@ -11,7 +11,7 @@
+ * the GNU General Public License
+ */
+
+-/*! \file
++/*! \file
+ * \brief Interface to mISDN - message parser
+ * \author Christian Richter <crich@beronet.com>
+ */
+@@ -25,21 +25,131 @@
+
+ #include "ie.c"
+
++/*!
++ * \internal
++ * \brief Build the name, number, name/number display message string
++ *
++ * \param display Display buffer to fill in
++ * \param display_length Length of the display buffer to fill in
++ * \param display_format Display format enumeration
++ * \param name Name string to use
++ * \param number Number string to use
++ *
++ * \return Nothing
++ */
++static void build_display_str(char *display, size_t display_length, int display_format, const char *name, const char *number)
++{
++ display[0] = 0;
++ switch (display_format) {
++ default:
++ case 0: /* none */
++ break;
+
++ case 1: /* name */
++ snprintf(display, display_length, "%s", name);
++ break;
++
++ case 2: /* number */
++ snprintf(display, display_length, "%s", number);
++ break;
++
++ case 3: /* both */
++ if (name[0] || number[0]) {
++ snprintf(display, display_length, "\"%s\" <%s>", name, number);
++ }
++ break;
++ }
++}
++
++/*!
++ * \internal
++ * \brief Encode the Facility IE and put it into the message structure.
++ *
++ * \param ntmode Where the encoded facility was put when in NT mode.
++ * \param msg General message structure
++ * \param fac Data to encode into the facility ie.
++ * \param nt TRUE if in NT mode.
++ *
++ * \return Nothing
++ */
++static void enc_ie_facility(unsigned char **ntmode, msg_t *msg, struct FacParm *fac, int nt)
++{
++ int len;
++ Q931_info_t *qi;
++ unsigned char *p;
++ unsigned char buf[256];
++
++ len = encodeFac(buf, fac);
++ if (len <= 0) {
++ /*
++ * mISDN does not know how to build the requested facility structure
++ * Clear facility information
++ */
++ fac->Function = Fac_None;
++ return;
++ }
++
++ p = msg_put(msg, len);
++ if (nt) {
++ *ntmode = p + 1;
++ } else {
++ qi = (Q931_info_t *) (msg->data + mISDN_HEADER_LEN);
++ qi->QI_ELEMENT(facility) = p - (unsigned char *) qi - sizeof(Q931_info_t);
++ }
++
++ memcpy(p, buf, len);
++
++ /* Clear facility information */
++ fac->Function = Fac_None;
++}
++
++/*!
++ * \internal
++ * \brief Decode the Facility IE.
++ *
++ * \param p Encoded facility ie data to decode. (NT mode)
++ * \param qi Encoded facility ie data to decode. (TE mode)
++ * \param fac Where to put the decoded facility ie data if it is available.
++ * \param nt TRUE if in NT mode.
++ * \param bc Associated B channel
++ *
++ * \return Nothing
++ */
++static void dec_ie_facility(unsigned char *p, Q931_info_t *qi, struct FacParm *fac, int nt, struct misdn_bchannel *bc)
++{
++ fac->Function = Fac_None;
++
++ if (!nt) {
++ p = NULL;
++ if (qi->QI_ELEMENT(facility)) {
++ p = (unsigned char *) qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(facility) + 1;
++ }
++ }
++ if (!p) {
++ return;
++ }
++
++ if (decodeFac(p, fac)) {
++ cb_log(3, bc->port, "Decoding facility ie failed! Unrecognized facility message?\n");
++ }
++}
++
++
++
+ static void set_channel(struct misdn_bchannel *bc, int channel)
+ {
+
+ cb_log(3,bc->port,"set_channel: bc->channel:%d channel:%d\n", bc->channel, channel);
+-
+-
++
++
+ if (channel==0xff) {
+ /* any channel */
+ channel=-1;
+ }
+-
++
+ /* ALERT: is that everytime true ? */
+ if (channel > 0 && bc->nt ) {
+-
++
+ if (bc->channel && ( bc->channel != 0xff) ) {
+ cb_log(0,bc->port,"We already have a channel (%d)\n", bc->channel);
+ } else {
+@@ -47,179 +157,289 @@
+ cb_event(EVENT_NEW_CHANNEL,bc,NULL);
+ }
+ }
+-
++
+ if (channel > 0 && !bc->nt ) {
+ bc->channel = channel;
+ cb_event(EVENT_NEW_CHANNEL,bc,NULL);
+ }
+ }
+
+-static void parse_proceeding (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
++static void parse_proceeding (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+- CALL_PROCEEDING_t *proceeding=(CALL_PROCEEDING_t*)((unsigned long)msg->data+ HEADER_LEN);
++ CALL_PROCEEDING_t *proceeding = (CALL_PROCEEDING_t *) (msg->data + HEADER_LEN);
+ //struct misdn_stack *stack=get_stack_by_bc(bc);
+-
++
+ {
+ int exclusive, channel;
+ dec_ie_channel_id(proceeding->CHANNEL_ID, (Q931_info_t *)proceeding, &exclusive, &channel, nt,bc);
+
+ set_channel(bc,channel);
+-
++
+ }
+-
++
+ dec_ie_progress(proceeding->PROGRESS, (Q931_info_t *)proceeding, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
+-
+-
+-#ifdef DEBUG
+- printf("Parsing PROCEEDING Msg\n");
++
++ dec_ie_facility(proceeding->FACILITY, (Q931_info_t *) proceeding, &bc->fac_in, nt, bc);
++
++ /* dec_ie_redir_dn */
++
++#ifdef DEBUG
++ printf("Parsing PROCEEDING Msg\n");
+ #endif
+ }
+ static msg_t *build_proceeding (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+ CALL_PROCEEDING_t *proceeding;
+- msg_t *msg =(msg_t*)create_l3msg(CC_PROCEEDING | REQUEST, MT_CALL_PROCEEDING, bc?bc->l3_id:-1, sizeof(CALL_PROCEEDING_t) ,nt);
+-
++ msg_t *msg =(msg_t*)create_l3msg(CC_PROCEEDING | REQUEST, MT_CALL_PROCEEDING, bc?bc->l3_id:-1, sizeof(CALL_PROCEEDING_t) ,nt);
++
+ proceeding=(CALL_PROCEEDING_t*)((msg->data+HEADER_LEN));
+
+ enc_ie_channel_id(&proceeding->CHANNEL_ID, msg, 1,bc->channel, nt,bc);
+-
+- if (nt)
++
++ if (nt)
+ enc_ie_progress(&proceeding->PROGRESS, msg, 0, nt?1:5, 8, nt,bc);
+-
+
+-#ifdef DEBUG
+- printf("Building PROCEEDING Msg\n");
++ if (bc->fac_out.Function != Fac_None) {
++ enc_ie_facility(&proceeding->FACILITY, msg, &bc->fac_out, nt);
++ }
++
++ /* enc_ie_redir_dn */
++
++#ifdef DEBUG
++ printf("Building PROCEEDING Msg\n");
+ #endif
+- return msg;
++ return msg;
+ }
+
+-static void parse_alerting (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
++static void parse_alerting (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
+ {
+- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+- ALERTING_t *alerting=(ALERTING_t*)((unsigned long)(msg->data+HEADER_LEN));
++ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
++ ALERTING_t *alerting = (ALERTING_t *) (msg->data + HEADER_LEN);
+ //Q931_info_t *qi=(Q931_info_t*)(msg->data+HEADER_LEN);
+-
++
++ dec_ie_facility(alerting->FACILITY, (Q931_info_t *) alerting, &bc->fac_in, nt, bc);
++
++ /* dec_ie_redir_dn */
++
+ dec_ie_progress(alerting->PROGRESS, (Q931_info_t *)alerting, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
+-
+-#ifdef DEBUG
+- printf("Parsing ALERTING Msg\n");
++
++#ifdef DEBUG
++ printf("Parsing ALERTING Msg\n");
+ #endif
+
+-
++
+ }
+
+-static msg_t *build_alerting (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
++static msg_t *build_alerting (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+ ALERTING_t *alerting;
+- msg_t *msg =(msg_t*)create_l3msg(CC_ALERTING | REQUEST, MT_ALERTING, bc?bc->l3_id:-1, sizeof(ALERTING_t) ,nt);
+-
+- alerting=(ALERTING_t*)((msg->data+HEADER_LEN));
+-
++ msg_t *msg =(msg_t*)create_l3msg(CC_ALERTING | REQUEST, MT_ALERTING, bc?bc->l3_id:-1, sizeof(ALERTING_t) ,nt);
++
++ alerting=(ALERTING_t*)((msg->data+HEADER_LEN));
++
+ enc_ie_channel_id(&alerting->CHANNEL_ID, msg, 1,bc->channel, nt,bc);
+-
+- if (nt)
++
++ if (nt)
+ enc_ie_progress(&alerting->PROGRESS, msg, 0, nt?1:5, 8, nt,bc);
+-#ifdef DEBUG
+- printf("Building ALERTING Msg\n");
++
++ if (bc->fac_out.Function != Fac_None) {
++ enc_ie_facility(&alerting->FACILITY, msg, &bc->fac_out, nt);
++ }
++
++ /* enc_ie_redir_dn */
++
++#ifdef DEBUG
++ printf("Building ALERTING Msg\n");
+ #endif
+- return msg;
++ return msg;
+ }
+
+
+-static void parse_progress (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
++static void parse_progress (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+- PROGRESS_t *progress=(PROGRESS_t*)((unsigned long)(msg->data+HEADER_LEN));
+- //Q931_info_t *qi=(Q931_info_t*)(msg->data+HEADER_LEN);
+-
++ PROGRESS_t *progress = (PROGRESS_t *) (msg->data + HEADER_LEN);
++ //Q931_info_t *qi=(Q931_info_t*)(msg->data+HEADER_LEN);
++
+ dec_ie_progress(progress->PROGRESS, (Q931_info_t *)progress, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
+-
+-#ifdef DEBUG
+- printf("Parsing PROGRESS Msg\n");
++
++ dec_ie_facility(progress->FACILITY, (Q931_info_t *) progress, &bc->fac_in, nt, bc);
++
++#ifdef DEBUG
++ printf("Parsing PROGRESS Msg\n");
+ #endif
+ }
+
+-static msg_t *build_progress (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
++static msg_t *build_progress (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+ PROGRESS_t *progress;
+- msg_t *msg =(msg_t*)create_l3msg(CC_PROGRESS | REQUEST, MT_PROGRESS, bc?bc->l3_id:-1, sizeof(PROGRESS_t) ,nt);
+-
+- progress=(PROGRESS_t*)((msg->data+HEADER_LEN));
++ msg_t *msg =(msg_t*)create_l3msg(CC_PROGRESS | REQUEST, MT_PROGRESS, bc?bc->l3_id:-1, sizeof(PROGRESS_t) ,nt);
+
+-#ifdef DEBUG
+- printf("Building PROGRESS Msg\n");
++ progress=(PROGRESS_t*)((msg->data+HEADER_LEN));
++
++ if (bc->fac_out.Function != Fac_None) {
++ enc_ie_facility(&progress->FACILITY, msg, &bc->fac_out, nt);
++ }
++
++#ifdef DEBUG
++ printf("Building PROGRESS Msg\n");
+ #endif
+- return msg;
++ return msg;
+ }
+
+-static void parse_setup (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
+-{
+- int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+- SETUP_t *setup= (SETUP_t*)((unsigned long)msg->data+HEADER_LEN);
+- Q931_info_t *qi=(Q931_info_t*)((unsigned long)msg->data+HEADER_LEN);
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Extract the SETUP message's BC, HLC, and LLC encoded ie contents.
++ *
++ * \param setup Indexed setup message contents
++ * \param nt TRUE if in NT mode.
++ * \param bc Associated B channel
++ *
++ * \return Nothing
++ */
++static void extract_setup_Bc_Hlc_Llc(SETUP_t *setup, int nt, struct misdn_bchannel *bc)
++{
++ __u8 *p;
++ Q931_info_t *qi;
+
+-#ifdef DEBUG
+- printf("Parsing SETUP Msg\n");
+-#endif
+- {
+- int type,plan,present, screen;
+- char id[32];
+- dec_ie_calling_pn(setup->CALLING_PN, qi, &type, &plan, &present, &screen, id, sizeof(id)-1, nt,bc);
++ qi = (Q931_info_t *) setup;
+
+- bc->onumplan=type;
+- strcpy(bc->oad, id);
+- switch (present) {
+- case 0:
+- bc->pres=0; /* screened */
+- break;
+- case 1:
+- bc->pres=1; /* not screened */
+- break;
+- default:
+- bc->pres=0;
++ /* Extract Bearer Capability */
++ if (nt) {
++ p = (__u8 *) setup->BEARER;
++ } else {
++ if (qi->QI_ELEMENT(bearer_capability)) {
++ p = (__u8 *) qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(bearer_capability) + 1;
++ } else {
++ p = NULL;
+ }
+- switch (screen) {
+- case 0:
+- break;
+- default:
+- ;
+- }
+ }
+- {
+- int type, plan;
+- char number[32];
+- dec_ie_called_pn(setup->CALLED_PN, (Q931_info_t *)setup, &type, &plan, number, sizeof(number)-1, nt,bc);
+- strcpy(bc->dad, number);
+- bc->dnumplan=type;
++ if (!p || *p == 0 || sizeof(bc->setup_bc_hlc_llc.Bc.Contents) < *p) {
++ bc->setup_bc_hlc_llc.Bc.Length = 0;
++ } else {
++ bc->setup_bc_hlc_llc.Bc.Length = *p;
++ memcpy(bc->setup_bc_hlc_llc.Bc.Contents, p + 1, *p);
+ }
+- {
+- char keypad[32];
+- dec_ie_keypad(setup->KEYPAD, (Q931_info_t *)setup, keypad, sizeof(keypad)-1, nt,bc);
+- strcpy(bc->keypad, keypad);
++
++ /* Extract Low Layer Compatibility */
++ if (nt) {
++ p = (__u8 *) setup->LLC;
++ } else {
++ if (qi->QI_ELEMENT(llc)) {
++ p = (__u8 *) qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(llc) + 1;
++ } else {
++ p = NULL;
++ }
+ }
++ if (!p || *p == 0 || sizeof(bc->setup_bc_hlc_llc.Llc.Contents) < *p) {
++ bc->setup_bc_hlc_llc.Llc.Length = 0;
++ } else {
++ bc->setup_bc_hlc_llc.Llc.Length = *p;
++ memcpy(bc->setup_bc_hlc_llc.Llc.Contents, p + 1, *p);
++ }
+
+- {
+- dec_ie_complete(setup->COMPLETE, (Q931_info_t *)setup, &bc->sending_complete, nt,bc);
+-
++ /* Extract High Layer Compatibility */
++ if (nt) {
++ p = (__u8 *) setup->HLC;
++ } else {
++ if (qi->QI_ELEMENT(hlc)) {
++ p = (__u8 *) qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(hlc) + 1;
++ } else {
++ p = NULL;
++ }
+ }
+-
+- {
+- int type, plan, present, screen, reason;
+- char id[32];
+- dec_ie_redir_nr(setup->REDIR_NR, (Q931_info_t *)setup, &type, &plan, &present, &screen, &reason, id, sizeof(id)-1, nt,bc);
+-
+- strcpy(bc->rad, id);
+- bc->rnumplan=type;
++ if (!p || *p == 0 || sizeof(bc->setup_bc_hlc_llc.Hlc.Contents) < *p) {
++ bc->setup_bc_hlc_llc.Hlc.Length = 0;
++ } else {
++ bc->setup_bc_hlc_llc.Hlc.Length = *p;
++ memcpy(bc->setup_bc_hlc_llc.Hlc.Contents, p + 1, *p);
+ }
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++static void parse_setup (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
++{
++ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
++ SETUP_t *setup = (SETUP_t *) (msg->data + HEADER_LEN);
++ Q931_info_t *qi = (Q931_info_t *) (msg->data + HEADER_LEN);
++ int type;
++ int plan;
++ int present;
++ int screen;
++ int reason;
++
++#ifdef DEBUG
++ printf("Parsing SETUP Msg\n");
++#endif
++
++ dec_ie_calling_pn(setup->CALLING_PN, qi, &type, &plan, &present, &screen, bc->caller.number, sizeof(bc->caller.number), nt, bc);
++ bc->caller.number_type = type;
++ bc->caller.number_plan = plan;
++ switch (present) {
++ default:
++ case 0:
++ bc->caller.presentation = 0; /* presentation allowed */
++ break;
++ case 1:
++ bc->caller.presentation = 1; /* presentation restricted */
++ break;
++ case 2:
++ bc->caller.presentation = 2; /* Number not available */
++ break;
++ }
++ if (0 <= screen) {
++ bc->caller.screening = screen;
++ } else {
++ bc->caller.screening = 0; /* Unscreened */
++ }
++
++ dec_ie_facility(setup->FACILITY, (Q931_info_t *) setup, &bc->fac_in, nt, bc);
++
++ dec_ie_called_pn(setup->CALLED_PN, (Q931_info_t *) setup, &type, &plan, bc->dialed.number, sizeof(bc->dialed.number), nt, bc);
++ bc->dialed.number_type = type;
++ bc->dialed.number_plan = plan;
++
++ dec_ie_keypad(setup->KEYPAD, (Q931_info_t *) setup, bc->keypad, sizeof(bc->keypad), nt, bc);
++
++ dec_ie_complete(setup->COMPLETE, (Q931_info_t *) setup, &bc->sending_complete, nt, bc);
++
++ dec_ie_redir_nr(setup->REDIR_NR, (Q931_info_t *) setup, &type, &plan, &present, &screen, &reason, bc->redirecting.from.number, sizeof(bc->redirecting.from.number), nt, bc);
++ bc->redirecting.from.number_type = type;
++ bc->redirecting.from.number_plan = plan;
++ switch (present) {
++ default:
++ case 0:
++ bc->redirecting.from.presentation = 0; /* presentation allowed */
++ break;
++ case 1:
++ bc->redirecting.from.presentation = 1; /* presentation restricted */
++ break;
++ case 2:
++ bc->redirecting.from.presentation = 2; /* Number not available */
++ break;
++ }
++ if (0 <= screen) {
++ bc->redirecting.from.screening = screen;
++ } else {
++ bc->redirecting.from.screening = 0; /* Unscreened */
++ }
++ if (0 <= reason) {
++ bc->redirecting.reason = reason;
++ } else {
++ bc->redirecting.reason = mISDN_REDIRECTING_REASON_UNKNOWN;
++ }
++
+ {
+ int coding, capability, mode, rate, multi, user, async, urate, stopbits, dbits, parity;
++
+ dec_ie_bearer(setup->BEARER, (Q931_info_t *)setup, &coding, &capability, &mode, &rate, &multi, &user, &async, &urate, &stopbits, &dbits, &parity, nt,bc);
+ switch (capability) {
+- case -1: bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
++ case -1: bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
+ break;
+ case 0: bc->capability=INFO_CAPABILITY_SPEECH;
+ break;
+@@ -228,7 +448,7 @@
+ case 8: bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
+ bc->user1 = user;
+ bc->urate = urate;
+-
++
+ bc->rate = rate;
+ bc->mode = mode;
+ break;
+@@ -237,7 +457,7 @@
+ default:
+ break;
+ }
+-
++
+ switch(user) {
+ case 2:
+ bc->law=INFO_CODEC_ULAW;
+@@ -247,15 +467,15 @@
+ break;
+ default:
+ bc->law=INFO_CODEC_ALAW;
+-
++
+ }
+-
+- bc->capability=capability;
++
++ bc->capability=capability;
+ }
+ {
+ int exclusive, channel;
+ dec_ie_channel_id(setup->CHANNEL_ID, (Q931_info_t *)setup, &exclusive, &channel, nt,bc);
+-
++
+ set_channel(bc,channel);
+ }
+
+@@ -266,55 +486,85 @@
+ else
+ cb_log(1,bc->port,"NO USERUESRINFO\n");
+ }
+-
++
+ dec_ie_progress(setup->PROGRESS, (Q931_info_t *)setup, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
+-
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++ extract_setup_Bc_Hlc_Llc(setup, nt, bc);
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
+ }
+
+-#define ANY_CHANNEL 0xff /* IE attribut for 'any channel' */
+-static msg_t *build_setup (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
++#define ANY_CHANNEL 0xff /* IE attribute for 'any channel' */
++static msg_t *build_setup (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+ SETUP_t *setup;
+- msg_t *msg =(msg_t*)create_l3msg(CC_SETUP | REQUEST, MT_SETUP, bc?bc->l3_id:-1, sizeof(SETUP_t) ,nt);
+-
+- setup=(SETUP_t*)((msg->data+HEADER_LEN));
+-
++ msg_t *msg =(msg_t*)create_l3msg(CC_SETUP | REQUEST, MT_SETUP, bc?bc->l3_id:-1, sizeof(SETUP_t) ,nt);
++
++ setup=(SETUP_t*)((msg->data+HEADER_LEN));
++
+ if (bc->channel == 0 || bc->channel == ANY_CHANNEL || bc->channel==-1)
+ enc_ie_channel_id(&setup->CHANNEL_ID, msg, 0, bc->channel, nt,bc);
+- else
++ else
+ enc_ie_channel_id(&setup->CHANNEL_ID, msg, 1, bc->channel, nt,bc);
+-
+-
+- {
+- int type=bc->onumplan,plan=1,present=bc->pres,screen=bc->screen;
+- enc_ie_calling_pn(&setup->CALLING_PN, msg, type, plan, present,
+- screen, bc->oad, nt, bc);
++
++ if (bc->fac_out.Function != Fac_None) {
++ enc_ie_facility(&setup->FACILITY, msg, &bc->fac_out, nt);
+ }
+-
+- {
+- if (bc->dad[0])
+- enc_ie_called_pn(&setup->CALLED_PN, msg, bc->dnumplan, 1, bc->dad, nt,bc);
++
++ enc_ie_calling_pn(&setup->CALLING_PN, msg, bc->caller.number_type, bc->caller.number_plan,
++ bc->caller.presentation, bc->caller.screening, bc->caller.number, nt, bc);
++
++ if (bc->dialed.number[0]) {
++ enc_ie_called_pn(&setup->CALLED_PN, msg, bc->dialed.number_type, bc->dialed.number_plan, bc->dialed.number, nt, bc);
+ }
+
+- {
+- if (bc->rad[0])
+- enc_ie_redir_nr(&setup->REDIR_NR, msg, 1, 1, bc->pres, bc->screen, 0, bc->rad, nt,bc);
++ switch (bc->outgoing_colp) {
++ case 0:/* pass */
++ case 1:/* restricted */
++ if (bc->redirecting.from.number[0]) {
++#if 1
++ /* ETSI and Q.952 do not define the screening field */
++ enc_ie_redir_nr(&setup->REDIR_NR, msg, bc->redirecting.from.number_type,
++ bc->redirecting.from.number_plan, bc->redirecting.from.presentation, 0,
++ bc->redirecting.reason, bc->redirecting.from.number, nt, bc);
++#else
++ /* Q.931 defines the screening field */
++ enc_ie_redir_nr(&setup->REDIR_NR, msg, bc->redirecting.from.number_type,
++ bc->redirecting.from.number_plan, bc->redirecting.from.presentation,
++ bc->redirecting.from.screening, bc->redirecting.reason,
++ bc->redirecting.from.number, nt, bc);
++#endif
++ }
++ break;
++ default:
++ break;
+ }
+
+- {
+- if (bc->keypad[0])
+- enc_ie_keypad(&setup->KEYPAD, msg, bc->keypad, nt,bc);
++ if (bc->keypad[0]) {
++ enc_ie_keypad(&setup->KEYPAD, msg, bc->keypad, nt,bc);
+ }
+-
+-
++
++
++
+ if (*bc->display) {
+- enc_ie_display(&setup->DISPLAY, msg, bc->display, nt,bc);
++ enc_ie_display(&setup->DISPLAY, msg, bc->display, nt, bc);
++ } else if (nt && bc->caller.presentation == 0) {
++ char display[sizeof(bc->display)];
++
++ /* Presentation is allowed */
++ build_display_str(display, sizeof(display), bc->display_setup, bc->caller.name, bc->caller.number);
++ if (display[0]) {
++ enc_ie_display(&setup->DISPLAY, msg, display, nt, bc);
++ }
+ }
+-
++
+ {
+- int coding=0, capability, mode=0 /* 2 for packet ! */
+- ,user, rate=0x10;
++ int coding = 0;
++ int capability;
++ int mode = 0; /* 2 for packet! */
++ int user;
++ int rate = 0x10;
+
+ switch (bc->law) {
+ case INFO_CODEC_ULAW: user=2;
+@@ -324,7 +574,7 @@
+ default:
+ user=3;
+ }
+-
++
+ switch (bc->capability) {
+ case INFO_CAPABILITY_SPEECH: capability = 0;
+ break;
+@@ -337,84 +587,129 @@
+ user=-1;
+ break;
+ default:
+- capability=bc->capability;
++ capability=bc->capability;
+ }
+-
+-
+-
++
+ enc_ie_bearer(&setup->BEARER, msg, coding, capability, mode, rate, -1, user, nt,bc);
+ }
+
+ if (bc->sending_complete) {
+ enc_ie_complete(&setup->COMPLETE,msg, bc->sending_complete, nt, bc);
+ }
+-
++
+ if (bc->uulen) {
+ int protocol=4;
+ enc_ie_useruser(&setup->USER_USER, msg, protocol, bc->uu, bc->uulen, nt,bc);
+ cb_log(1,bc->port,"ENCODING USERUESRINFO:%s\n",bc->uu);
+ }
+
+-#ifdef DEBUG
+- printf("Building SETUP Msg\n");
++#if defined(AST_MISDN_ENHANCEMENTS)
++ extract_setup_Bc_Hlc_Llc(setup, nt, bc);
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#ifdef DEBUG
++ printf("Building SETUP Msg\n");
+ #endif
+- return msg;
++ return msg;
+ }
+
+-static void parse_connect (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
++static void parse_connect (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+- CONNECT_t *connect=(CONNECT_t*)((unsigned long)(msg->data+HEADER_LEN));
+-
+- int plan,pres,screen;
+-
++ CONNECT_t *connect = (CONNECT_t *) (msg->data + HEADER_LEN);
++ int type;
++ int plan;
++ int pres;
++ int screen;
++
+ bc->ces = connect->ces;
+- bc->ces = connect->ces;
+
+ dec_ie_progress(connect->PROGRESS, (Q931_info_t *)connect, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
+
+- dec_ie_connected_pn(connect->CONNECT_PN,(Q931_info_t *)connect, &bc->cpnnumplan, &plan, &pres, &screen, bc->cad, 31, nt, bc);
++ dec_ie_connected_pn(connect->CONNECT_PN, (Q931_info_t *) connect, &type, &plan,
++ &pres, &screen, bc->connected.number, sizeof(bc->connected.number), nt, bc);
++ bc->connected.number_type = type;
++ bc->connected.number_plan = plan;
++ switch (pres) {
++ default:
++ case 0:
++ bc->connected.presentation = 0; /* presentation allowed */
++ break;
++ case 1:
++ bc->connected.presentation = 1; /* presentation restricted */
++ break;
++ case 2:
++ bc->connected.presentation = 2; /* Number not available */
++ break;
++ }
++ if (0 <= screen) {
++ bc->connected.screening = screen;
++ } else {
++ bc->connected.screening = 0; /* Unscreened */
++ }
+
++ dec_ie_facility(connect->FACILITY, (Q931_info_t *) connect, &bc->fac_in, nt, bc);
++
+ /*
+ cb_log(1,bc->port,"CONNETED PN: %s cpn_dialplan:%d\n", connected_pn, type);
+ */
+-
+-#ifdef DEBUG
+- printf("Parsing CONNECT Msg\n");
++
++#ifdef DEBUG
++ printf("Parsing CONNECT Msg\n");
+ #endif
+ }
+
+-static msg_t *build_connect (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
++static msg_t *build_connect (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+ CONNECT_t *connect;
+- msg_t *msg =(msg_t*)create_l3msg(CC_CONNECT | REQUEST, MT_CONNECT, bc?bc->l3_id:-1, sizeof(CONNECT_t) ,nt);
+-
++ msg_t *msg =(msg_t*)create_l3msg(CC_CONNECT | REQUEST, MT_CONNECT, bc?bc->l3_id:-1, sizeof(CONNECT_t) ,nt);
++
+ cb_log(6,bc->port,"BUILD_CONNECT: bc:%p bc->l3id:%d, nt:%d\n",bc,bc->l3_id,nt);
+
+- connect=(CONNECT_t*)((msg->data+HEADER_LEN));
++ connect=(CONNECT_t*)((msg->data+HEADER_LEN));
+
+ if (nt) {
+ time_t now;
+ time(&now);
+ enc_ie_date(&connect->DATE, msg, now, nt,bc);
+ }
+-
+- {
+- int type=bc->cpnnumplan, plan=1, present=2, screen=0;
+- enc_ie_connected_pn(&connect->CONNECT_PN, msg, type,plan, present, screen, bc->cad, nt , bc);
++
++ switch (bc->outgoing_colp) {
++ case 0:/* pass */
++ case 1:/* restricted */
++ enc_ie_connected_pn(&connect->CONNECT_PN, msg, bc->connected.number_type,
++ bc->connected.number_plan, bc->connected.presentation,
++ bc->connected.screening, bc->connected.number, nt, bc);
++ break;
++ default:
++ break;
+ }
+
+-#ifdef DEBUG
+- printf("Building CONNECT Msg\n");
++ if (nt && bc->connected.presentation == 0) {
++ char display[sizeof(bc->display)];
++
++ /* Presentation is allowed */
++ build_display_str(display, sizeof(display), bc->display_connected, bc->connected.name, bc->connected.number);
++ if (display[0]) {
++ enc_ie_display(&connect->DISPLAY, msg, display, nt, bc);
++ }
++ }
++
++ if (bc->fac_out.Function != Fac_None) {
++ enc_ie_facility(&connect->FACILITY, msg, &bc->fac_out, nt);
++ }
++
++#ifdef DEBUG
++ printf("Building CONNECT Msg\n");
+ #endif
+- return msg;
++ return msg;
+ }
+
+-static void parse_setup_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
++static void parse_setup_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+- SETUP_ACKNOWLEDGE_t *setup_acknowledge=(SETUP_ACKNOWLEDGE_t*)((unsigned long)(msg->data+HEADER_LEN));
++ SETUP_ACKNOWLEDGE_t *setup_acknowledge = (SETUP_ACKNOWLEDGE_t *) (msg->data + HEADER_LEN);
+
+ {
+ int exclusive, channel;
+@@ -423,428 +718,443 @@
+
+ set_channel(bc, channel);
+ }
+-
++
+ dec_ie_progress(setup_acknowledge->PROGRESS, (Q931_info_t *)setup_acknowledge, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
+-#ifdef DEBUG
+- printf("Parsing SETUP_ACKNOWLEDGE Msg\n");
++
++ dec_ie_facility(setup_acknowledge->FACILITY, (Q931_info_t *) setup_acknowledge, &bc->fac_in, nt, bc);
++
++#ifdef DEBUG
++ printf("Parsing SETUP_ACKNOWLEDGE Msg\n");
+ #endif
+
+-
++
+ }
+
+-static msg_t *build_setup_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
++static msg_t *build_setup_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+ SETUP_ACKNOWLEDGE_t *setup_acknowledge;
+- msg_t *msg =(msg_t*)create_l3msg(CC_SETUP_ACKNOWLEDGE | REQUEST, MT_SETUP_ACKNOWLEDGE, bc?bc->l3_id:-1, sizeof(SETUP_ACKNOWLEDGE_t) ,nt);
+-
+- setup_acknowledge=(SETUP_ACKNOWLEDGE_t*)((msg->data+HEADER_LEN));
+-
++ msg_t *msg =(msg_t*)create_l3msg(CC_SETUP_ACKNOWLEDGE | REQUEST, MT_SETUP_ACKNOWLEDGE, bc?bc->l3_id:-1, sizeof(SETUP_ACKNOWLEDGE_t) ,nt);
++
++ setup_acknowledge=(SETUP_ACKNOWLEDGE_t*)((msg->data+HEADER_LEN));
++
+ enc_ie_channel_id(&setup_acknowledge->CHANNEL_ID, msg, 1,bc->channel, nt,bc);
+-
+- if (nt)
++
++ if (nt)
+ enc_ie_progress(&setup_acknowledge->PROGRESS, msg, 0, nt?1:5, 8, nt,bc);
+-
+-#ifdef DEBUG
+- printf("Building SETUP_ACKNOWLEDGE Msg\n");
++
++ if (bc->fac_out.Function != Fac_None) {
++ enc_ie_facility(&setup_acknowledge->FACILITY, msg, &bc->fac_out, nt);
++ }
++
++#ifdef DEBUG
++ printf("Building SETUP_ACKNOWLEDGE Msg\n");
+ #endif
+- return msg;
++ return msg;
+ }
+
+-static void parse_connect_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
++static void parse_connect_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
+ {
+-#ifdef DEBUG
+- printf("Parsing CONNECT_ACKNOWLEDGE Msg\n");
++#ifdef DEBUG
++ printf("Parsing CONNECT_ACKNOWLEDGE Msg\n");
+ #endif
+
+-
++
+ }
+
+-static msg_t *build_connect_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
++static msg_t *build_connect_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+ CONNECT_ACKNOWLEDGE_t *connect_acknowledge;
+- msg_t *msg =(msg_t*)create_l3msg(CC_CONNECT | RESPONSE, MT_CONNECT, bc?bc->l3_id:-1, sizeof(CONNECT_ACKNOWLEDGE_t) ,nt);
+-
+- connect_acknowledge=(CONNECT_ACKNOWLEDGE_t*)((msg->data+HEADER_LEN));
+-
++ msg_t *msg =(msg_t*)create_l3msg(CC_CONNECT | RESPONSE, MT_CONNECT, bc?bc->l3_id:-1, sizeof(CONNECT_ACKNOWLEDGE_t) ,nt);
++
++ connect_acknowledge=(CONNECT_ACKNOWLEDGE_t*)((msg->data+HEADER_LEN));
++
+ enc_ie_channel_id(&connect_acknowledge->CHANNEL_ID, msg, 1, bc->channel, nt,bc);
+-
+-#ifdef DEBUG
+- printf("Building CONNECT_ACKNOWLEDGE Msg\n");
++
++#ifdef DEBUG
++ printf("Building CONNECT_ACKNOWLEDGE Msg\n");
+ #endif
+- return msg;
++ return msg;
+ }
+
+-static void parse_user_information (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
++static void parse_user_information (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
+ {
+-#ifdef DEBUG
+- printf("Parsing USER_INFORMATION Msg\n");
++#ifdef DEBUG
++ printf("Parsing USER_INFORMATION Msg\n");
+ #endif
+
+-
++
+ }
+
+-static msg_t *build_user_information (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
++static msg_t *build_user_information (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+ USER_INFORMATION_t *user_information;
+- msg_t *msg =(msg_t*)create_l3msg(CC_USER_INFORMATION | REQUEST, MT_USER_INFORMATION, bc?bc->l3_id:-1, sizeof(USER_INFORMATION_t) ,nt);
+-
+- user_information=(USER_INFORMATION_t*)((msg->data+HEADER_LEN));
++ msg_t *msg =(msg_t*)create_l3msg(CC_USER_INFORMATION | REQUEST, MT_USER_INFORMATION, bc?bc->l3_id:-1, sizeof(USER_INFORMATION_t) ,nt);
+
+-#ifdef DEBUG
+- printf("Building USER_INFORMATION Msg\n");
++ user_information=(USER_INFORMATION_t*)((msg->data+HEADER_LEN));
++
++#ifdef DEBUG
++ printf("Building USER_INFORMATION Msg\n");
+ #endif
+- return msg;
++ return msg;
+ }
+
+-static void parse_suspend_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
++static void parse_suspend_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
+ {
+-#ifdef DEBUG
+- printf("Parsing SUSPEND_REJECT Msg\n");
++#ifdef DEBUG
++ printf("Parsing SUSPEND_REJECT Msg\n");
+ #endif
+
+-
++
+ }
+
+-static msg_t *build_suspend_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
++static msg_t *build_suspend_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+ SUSPEND_REJECT_t *suspend_reject;
+- msg_t *msg =(msg_t*)create_l3msg(CC_SUSPEND_REJECT | REQUEST, MT_SUSPEND_REJECT, bc?bc->l3_id:-1, sizeof(SUSPEND_REJECT_t) ,nt);
+-
+- suspend_reject=(SUSPEND_REJECT_t*)((msg->data+HEADER_LEN));
++ msg_t *msg =(msg_t*)create_l3msg(CC_SUSPEND_REJECT | REQUEST, MT_SUSPEND_REJECT, bc?bc->l3_id:-1, sizeof(SUSPEND_REJECT_t) ,nt);
+
+-#ifdef DEBUG
+- printf("Building SUSPEND_REJECT Msg\n");
++ suspend_reject=(SUSPEND_REJECT_t*)((msg->data+HEADER_LEN));
++
++#ifdef DEBUG
++ printf("Building SUSPEND_REJECT Msg\n");
+ #endif
+- return msg;
++ return msg;
+ }
+
+-static void parse_resume_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
++static void parse_resume_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
+ {
+-#ifdef DEBUG
+- printf("Parsing RESUME_REJECT Msg\n");
++#ifdef DEBUG
++ printf("Parsing RESUME_REJECT Msg\n");
+ #endif
+
+-
++
+ }
+
+-static msg_t *build_resume_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
++static msg_t *build_resume_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+ RESUME_REJECT_t *resume_reject;
+- msg_t *msg =(msg_t*)create_l3msg(CC_RESUME_REJECT | REQUEST, MT_RESUME_REJECT, bc?bc->l3_id:-1, sizeof(RESUME_REJECT_t) ,nt);
+-
+- resume_reject=(RESUME_REJECT_t*)((msg->data+HEADER_LEN));
++ msg_t *msg =(msg_t*)create_l3msg(CC_RESUME_REJECT | REQUEST, MT_RESUME_REJECT, bc?bc->l3_id:-1, sizeof(RESUME_REJECT_t) ,nt);
+
+-#ifdef DEBUG
+- printf("Building RESUME_REJECT Msg\n");
++ resume_reject=(RESUME_REJECT_t*)((msg->data+HEADER_LEN));
++
++#ifdef DEBUG
++ printf("Building RESUME_REJECT Msg\n");
+ #endif
+- return msg;
++ return msg;
+ }
+
+-static void parse_hold (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
++static void parse_hold (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
+ {
+-#ifdef DEBUG
+- printf("Parsing HOLD Msg\n");
++#ifdef DEBUG
++ printf("Parsing HOLD Msg\n");
+ #endif
+
+-
++
+ }
+
+-static msg_t *build_hold (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
++static msg_t *build_hold (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+ HOLD_t *hold;
+- msg_t *msg =(msg_t*)create_l3msg(CC_HOLD | REQUEST, MT_HOLD, bc?bc->l3_id:-1, sizeof(HOLD_t) ,nt);
+-
+- hold=(HOLD_t*)((msg->data+HEADER_LEN));
++ msg_t *msg =(msg_t*)create_l3msg(CC_HOLD | REQUEST, MT_HOLD, bc?bc->l3_id:-1, sizeof(HOLD_t) ,nt);
+
+-#ifdef DEBUG
+- printf("Building HOLD Msg\n");
++ hold=(HOLD_t*)((msg->data+HEADER_LEN));
++
++#ifdef DEBUG
++ printf("Building HOLD Msg\n");
+ #endif
+- return msg;
++ return msg;
+ }
+
+-static void parse_suspend (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
++static void parse_suspend (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
+ {
+-#ifdef DEBUG
+- printf("Parsing SUSPEND Msg\n");
++#ifdef DEBUG
++ printf("Parsing SUSPEND Msg\n");
+ #endif
+
+-
++
+ }
+
+-static msg_t *build_suspend (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
++static msg_t *build_suspend (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+ SUSPEND_t *suspend;
+- msg_t *msg =(msg_t*)create_l3msg(CC_SUSPEND | REQUEST, MT_SUSPEND, bc?bc->l3_id:-1, sizeof(SUSPEND_t) ,nt);
+-
+- suspend=(SUSPEND_t*)((msg->data+HEADER_LEN));
++ msg_t *msg =(msg_t*)create_l3msg(CC_SUSPEND | REQUEST, MT_SUSPEND, bc?bc->l3_id:-1, sizeof(SUSPEND_t) ,nt);
+
+-#ifdef DEBUG
+- printf("Building SUSPEND Msg\n");
++ suspend=(SUSPEND_t*)((msg->data+HEADER_LEN));
++
++#ifdef DEBUG
++ printf("Building SUSPEND Msg\n");
+ #endif
+- return msg;
++ return msg;
+ }
+
+-static void parse_resume (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
++static void parse_resume (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
+ {
+-#ifdef DEBUG
+- printf("Parsing RESUME Msg\n");
++#ifdef DEBUG
++ printf("Parsing RESUME Msg\n");
+ #endif
+
+-
++
+ }
+
+-static msg_t *build_resume (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
++static msg_t *build_resume (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+ RESUME_t *resume;
+- msg_t *msg =(msg_t*)create_l3msg(CC_RESUME | REQUEST, MT_RESUME, bc?bc->l3_id:-1, sizeof(RESUME_t) ,nt);
+-
+- resume=(RESUME_t*)((msg->data+HEADER_LEN));
++ msg_t *msg =(msg_t*)create_l3msg(CC_RESUME | REQUEST, MT_RESUME, bc?bc->l3_id:-1, sizeof(RESUME_t) ,nt);
+
+-#ifdef DEBUG
+- printf("Building RESUME Msg\n");
++ resume=(RESUME_t*)((msg->data+HEADER_LEN));
++
++#ifdef DEBUG
++ printf("Building RESUME Msg\n");
+ #endif
+- return msg;
++ return msg;
+ }
+
+-static void parse_hold_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
++static void parse_hold_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
+ {
+-#ifdef DEBUG
+- printf("Parsing HOLD_ACKNOWLEDGE Msg\n");
++#ifdef DEBUG
++ printf("Parsing HOLD_ACKNOWLEDGE Msg\n");
+ #endif
+
+-
++
+ }
+
+-static msg_t *build_hold_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
++static msg_t *build_hold_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+ HOLD_ACKNOWLEDGE_t *hold_acknowledge;
+- msg_t *msg =(msg_t*)create_l3msg(CC_HOLD_ACKNOWLEDGE | REQUEST, MT_HOLD_ACKNOWLEDGE, bc?bc->l3_id:-1, sizeof(HOLD_ACKNOWLEDGE_t) ,nt);
+-
+- hold_acknowledge=(HOLD_ACKNOWLEDGE_t*)((msg->data+HEADER_LEN));
++ msg_t *msg =(msg_t*)create_l3msg(CC_HOLD_ACKNOWLEDGE | REQUEST, MT_HOLD_ACKNOWLEDGE, bc?bc->l3_id:-1, sizeof(HOLD_ACKNOWLEDGE_t) ,nt);
+
+-#ifdef DEBUG
+- printf("Building HOLD_ACKNOWLEDGE Msg\n");
++ hold_acknowledge=(HOLD_ACKNOWLEDGE_t*)((msg->data+HEADER_LEN));
++
++#ifdef DEBUG
++ printf("Building HOLD_ACKNOWLEDGE Msg\n");
+ #endif
+- return msg;
++ return msg;
+ }
+
+-static void parse_suspend_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
++static void parse_suspend_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
+ {
+-#ifdef DEBUG
+- printf("Parsing SUSPEND_ACKNOWLEDGE Msg\n");
++#ifdef DEBUG
++ printf("Parsing SUSPEND_ACKNOWLEDGE Msg\n");
+ #endif
+
+-
++
+ }
+
+-static msg_t *build_suspend_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
++static msg_t *build_suspend_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+ SUSPEND_ACKNOWLEDGE_t *suspend_acknowledge;
+- msg_t *msg =(msg_t*)create_l3msg(CC_SUSPEND_ACKNOWLEDGE | REQUEST, MT_SUSPEND_ACKNOWLEDGE, bc?bc->l3_id:-1, sizeof(SUSPEND_ACKNOWLEDGE_t) ,nt);
+-
+- suspend_acknowledge=(SUSPEND_ACKNOWLEDGE_t*)((msg->data+HEADER_LEN));
++ msg_t *msg =(msg_t*)create_l3msg(CC_SUSPEND_ACKNOWLEDGE | REQUEST, MT_SUSPEND_ACKNOWLEDGE, bc?bc->l3_id:-1, sizeof(SUSPEND_ACKNOWLEDGE_t) ,nt);
+
+-#ifdef DEBUG
+- printf("Building SUSPEND_ACKNOWLEDGE Msg\n");
++ suspend_acknowledge=(SUSPEND_ACKNOWLEDGE_t*)((msg->data+HEADER_LEN));
++
++#ifdef DEBUG
++ printf("Building SUSPEND_ACKNOWLEDGE Msg\n");
+ #endif
+- return msg;
++ return msg;
+ }
+
+-static void parse_resume_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
++static void parse_resume_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
+ {
+-#ifdef DEBUG
+- printf("Parsing RESUME_ACKNOWLEDGE Msg\n");
++#ifdef DEBUG
++ printf("Parsing RESUME_ACKNOWLEDGE Msg\n");
+ #endif
+
+-
++
+ }
+
+-static msg_t *build_resume_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
++static msg_t *build_resume_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+ RESUME_ACKNOWLEDGE_t *resume_acknowledge;
+- msg_t *msg =(msg_t*)create_l3msg(CC_RESUME_ACKNOWLEDGE | REQUEST, MT_RESUME_ACKNOWLEDGE, bc?bc->l3_id:-1, sizeof(RESUME_ACKNOWLEDGE_t) ,nt);
+-
+- resume_acknowledge=(RESUME_ACKNOWLEDGE_t*)((msg->data+HEADER_LEN));
++ msg_t *msg =(msg_t*)create_l3msg(CC_RESUME_ACKNOWLEDGE | REQUEST, MT_RESUME_ACKNOWLEDGE, bc?bc->l3_id:-1, sizeof(RESUME_ACKNOWLEDGE_t) ,nt);
+
+-#ifdef DEBUG
+- printf("Building RESUME_ACKNOWLEDGE Msg\n");
++ resume_acknowledge=(RESUME_ACKNOWLEDGE_t*)((msg->data+HEADER_LEN));
++
++#ifdef DEBUG
++ printf("Building RESUME_ACKNOWLEDGE Msg\n");
+ #endif
+- return msg;
++ return msg;
+ }
+
+-static void parse_hold_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
++static void parse_hold_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
+ {
+-#ifdef DEBUG
+- printf("Parsing HOLD_REJECT Msg\n");
++#ifdef DEBUG
++ printf("Parsing HOLD_REJECT Msg\n");
+ #endif
+
+-
++
+ }
+
+-static msg_t *build_hold_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
++static msg_t *build_hold_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+ HOLD_REJECT_t *hold_reject;
+- msg_t *msg =(msg_t*)create_l3msg(CC_HOLD_REJECT | REQUEST, MT_HOLD_REJECT, bc?bc->l3_id:-1, sizeof(HOLD_REJECT_t) ,nt);
+-
+- hold_reject=(HOLD_REJECT_t*)((msg->data+HEADER_LEN));
++ msg_t *msg =(msg_t*)create_l3msg(CC_HOLD_REJECT | REQUEST, MT_HOLD_REJECT, bc?bc->l3_id:-1, sizeof(HOLD_REJECT_t) ,nt);
+
+-#ifdef DEBUG
+- printf("Building HOLD_REJECT Msg\n");
++ hold_reject=(HOLD_REJECT_t*)((msg->data+HEADER_LEN));
++
++#ifdef DEBUG
++ printf("Building HOLD_REJECT Msg\n");
+ #endif
+- return msg;
++ return msg;
+ }
+
+-static void parse_retrieve (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
++static void parse_retrieve (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
+ {
+-#ifdef DEBUG
+- printf("Parsing RETRIEVE Msg\n");
++#ifdef DEBUG
++ printf("Parsing RETRIEVE Msg\n");
+ #endif
+
+-
++
+ }
+
+-static msg_t *build_retrieve (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
++static msg_t *build_retrieve (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+ RETRIEVE_t *retrieve;
+- msg_t *msg =(msg_t*)create_l3msg(CC_RETRIEVE | REQUEST, MT_RETRIEVE, bc?bc->l3_id:-1, sizeof(RETRIEVE_t) ,nt);
+-
+- retrieve=(RETRIEVE_t*)((msg->data+HEADER_LEN));
++ msg_t *msg =(msg_t*)create_l3msg(CC_RETRIEVE | REQUEST, MT_RETRIEVE, bc?bc->l3_id:-1, sizeof(RETRIEVE_t) ,nt);
+
+-#ifdef DEBUG
+- printf("Building RETRIEVE Msg\n");
++ retrieve=(RETRIEVE_t*)((msg->data+HEADER_LEN));
++
++#ifdef DEBUG
++ printf("Building RETRIEVE Msg\n");
+ #endif
+- return msg;
++ return msg;
+ }
+
+-static void parse_retrieve_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
++static void parse_retrieve_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
+ {
+-#ifdef DEBUG
+- printf("Parsing RETRIEVE_ACKNOWLEDGE Msg\n");
++#ifdef DEBUG
++ printf("Parsing RETRIEVE_ACKNOWLEDGE Msg\n");
+ #endif
+
+-
++
+ }
+
+-static msg_t *build_retrieve_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
++static msg_t *build_retrieve_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+ RETRIEVE_ACKNOWLEDGE_t *retrieve_acknowledge;
+- msg_t *msg =(msg_t*)create_l3msg(CC_RETRIEVE_ACKNOWLEDGE | REQUEST, MT_RETRIEVE_ACKNOWLEDGE, bc?bc->l3_id:-1, sizeof(RETRIEVE_ACKNOWLEDGE_t) ,nt);
+-
+- retrieve_acknowledge=(RETRIEVE_ACKNOWLEDGE_t*)((msg->data+HEADER_LEN));
++ msg_t *msg =(msg_t*)create_l3msg(CC_RETRIEVE_ACKNOWLEDGE | REQUEST, MT_RETRIEVE_ACKNOWLEDGE, bc?bc->l3_id:-1, sizeof(RETRIEVE_ACKNOWLEDGE_t) ,nt);
+
++ retrieve_acknowledge=(RETRIEVE_ACKNOWLEDGE_t*)((msg->data+HEADER_LEN));
++
+ enc_ie_channel_id(&retrieve_acknowledge->CHANNEL_ID, msg, 1, bc->channel, nt,bc);
+-#ifdef DEBUG
+- printf("Building RETRIEVE_ACKNOWLEDGE Msg\n");
++#ifdef DEBUG
++ printf("Building RETRIEVE_ACKNOWLEDGE Msg\n");
+ #endif
+- return msg;
++ return msg;
+ }
+
+-static void parse_retrieve_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
++static void parse_retrieve_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
+ {
+-#ifdef DEBUG
+- printf("Parsing RETRIEVE_REJECT Msg\n");
++#ifdef DEBUG
++ printf("Parsing RETRIEVE_REJECT Msg\n");
+ #endif
+
+-
++
+ }
+
+-static msg_t *build_retrieve_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
++static msg_t *build_retrieve_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+ RETRIEVE_REJECT_t *retrieve_reject;
+- msg_t *msg =(msg_t*)create_l3msg(CC_RETRIEVE_REJECT | REQUEST, MT_RETRIEVE_REJECT, bc?bc->l3_id:-1, sizeof(RETRIEVE_REJECT_t) ,nt);
+-
+- retrieve_reject=(RETRIEVE_REJECT_t*)((msg->data+HEADER_LEN));
++ msg_t *msg =(msg_t*)create_l3msg(CC_RETRIEVE_REJECT | REQUEST, MT_RETRIEVE_REJECT, bc?bc->l3_id:-1, sizeof(RETRIEVE_REJECT_t) ,nt);
+
+-#ifdef DEBUG
+- printf("Building RETRIEVE_REJECT Msg\n");
++ retrieve_reject=(RETRIEVE_REJECT_t*)((msg->data+HEADER_LEN));
++
++#ifdef DEBUG
++ printf("Building RETRIEVE_REJECT Msg\n");
+ #endif
+- return msg;
++ return msg;
+ }
+
+-static void parse_disconnect (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
++static void parse_disconnect (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+- DISCONNECT_t *disconnect=(DISCONNECT_t*)((unsigned long)(msg->data+HEADER_LEN));
++ DISCONNECT_t *disconnect = (DISCONNECT_t *) (msg->data + HEADER_LEN);
+ int location;
+- int cause;
++ int cause;
+ dec_ie_cause(disconnect->CAUSE, (Q931_info_t *)(disconnect), &location, &cause, nt,bc);
+ if (cause>0) bc->cause=cause;
+
++ dec_ie_facility(disconnect->FACILITY, (Q931_info_t *) disconnect, &bc->fac_in, nt, bc);
++
+ dec_ie_progress(disconnect->PROGRESS, (Q931_info_t *)disconnect, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
+-#ifdef DEBUG
+- printf("Parsing DISCONNECT Msg\n");
++#ifdef DEBUG
++ printf("Parsing DISCONNECT Msg\n");
+ #endif
+
+-
++
+ }
+
+-static msg_t *build_disconnect (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
++static msg_t *build_disconnect (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+ DISCONNECT_t *disconnect;
+- msg_t *msg =(msg_t*)create_l3msg(CC_DISCONNECT | REQUEST, MT_DISCONNECT, bc?bc->l3_id:-1, sizeof(DISCONNECT_t) ,nt);
+-
+- disconnect=(DISCONNECT_t*)((msg->data+HEADER_LEN));
+-
++ msg_t *msg =(msg_t*)create_l3msg(CC_DISCONNECT | REQUEST, MT_DISCONNECT, bc?bc->l3_id:-1, sizeof(DISCONNECT_t) ,nt);
++
++ disconnect=(DISCONNECT_t*)((msg->data+HEADER_LEN));
++
+ enc_ie_cause(&disconnect->CAUSE, msg, (nt)?1:0, bc->out_cause,nt,bc);
+- if (nt) enc_ie_progress(&disconnect->PROGRESS, msg, 0, nt?1:5, 8 ,nt,bc);
++ if (nt) {
++ enc_ie_progress(&disconnect->PROGRESS, msg, 0, nt ? 1 : 5, 8, nt, bc);
++ }
+
++ if (bc->fac_out.Function != Fac_None) {
++ enc_ie_facility(&disconnect->FACILITY, msg, &bc->fac_out, nt);
++ }
++
+ if (bc->uulen) {
+ int protocol=4;
+ enc_ie_useruser(&disconnect->USER_USER, msg, protocol, bc->uu, bc->uulen, nt,bc);
+ cb_log(1,bc->port,"ENCODING USERUESRINFO:%s\n",bc->uu);
+ }
+-
+-#ifdef DEBUG
+- printf("Building DISCONNECT Msg\n");
++
++#ifdef DEBUG
++ printf("Building DISCONNECT Msg\n");
+ #endif
+- return msg;
++ return msg;
+ }
+
+-static void parse_restart (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
++static void parse_restart (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+- RESTART_t *restart=(RESTART_t*)((unsigned long)(msg->data+HEADER_LEN));
++ RESTART_t *restart = (RESTART_t *) (msg->data + HEADER_LEN);
+
+ struct misdn_stack *stack=get_stack_by_bc(bc);
+-
+-#ifdef DEBUG
++
++#ifdef DEBUG
+ printf("Parsing RESTART Msg\n");
+ #endif
+-
++
+ {
+ int exclusive;
+ dec_ie_channel_id(restart->CHANNEL_ID, (Q931_info_t *)restart, &exclusive, &bc->restart_channel, nt,bc);
+ cb_log(3, stack->port, "CC_RESTART Request on channel:%d on this port.\n", bc->restart_channel);
+ }
+-
++
+ }
+
+-static msg_t *build_restart (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
++static msg_t *build_restart (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+ RESTART_t *restart;
+- msg_t *msg =(msg_t*)create_l3msg(CC_RESTART | REQUEST, MT_RESTART, bc?bc->l3_id:-1, sizeof(RESTART_t) ,nt);
+-
+- restart=(RESTART_t*)((msg->data+HEADER_LEN));
++ msg_t *msg =(msg_t*)create_l3msg(CC_RESTART | REQUEST, MT_RESTART, bc?bc->l3_id:-1, sizeof(RESTART_t) ,nt);
+
+-#ifdef DEBUG
+- printf("Building RESTART Msg\n");
++ restart=(RESTART_t*)((msg->data+HEADER_LEN));
++
++#ifdef DEBUG
++ printf("Building RESTART Msg\n");
+ #endif
+
+ if (bc->channel > 0) {
+@@ -855,52 +1165,59 @@
+ }
+
+ cb_log(0,bc->port, "Restarting channel %d\n", bc->channel);
+- return msg;
++ return msg;
+ }
+
+-static void parse_release (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
++static void parse_release (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+- RELEASE_t *release=(RELEASE_t*)((unsigned long)(msg->data+HEADER_LEN));
++ RELEASE_t *release = (RELEASE_t *) (msg->data + HEADER_LEN);
+ int location;
+ int cause;
+-
++
+ dec_ie_cause(release->CAUSE, (Q931_info_t *)(release), &location, &cause, nt,bc);
+ if (cause>0) bc->cause=cause;
+-#ifdef DEBUG
+- printf("Parsing RELEASE Msg\n");
++
++ dec_ie_facility(release->FACILITY, (Q931_info_t *) release, &bc->fac_in, nt, bc);
++
++#ifdef DEBUG
++ printf("Parsing RELEASE Msg\n");
+ #endif
+
+-
++
+ }
+
+-static msg_t *build_release (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
++static msg_t *build_release (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+ RELEASE_t *release;
+- msg_t *msg =(msg_t*)create_l3msg(CC_RELEASE | REQUEST, MT_RELEASE, bc?bc->l3_id:-1, sizeof(RELEASE_t) ,nt);
+-
+- release=(RELEASE_t*)((msg->data+HEADER_LEN));
+-
++ msg_t *msg =(msg_t*)create_l3msg(CC_RELEASE | REQUEST, MT_RELEASE, bc?bc->l3_id:-1, sizeof(RELEASE_t) ,nt);
++
++ release=(RELEASE_t*)((msg->data+HEADER_LEN));
++
+ if (bc->out_cause>= 0)
+ enc_ie_cause(&release->CAUSE, msg, nt?1:0, bc->out_cause, nt,bc);
+
++ if (bc->fac_out.Function != Fac_None) {
++ enc_ie_facility(&release->FACILITY, msg, &bc->fac_out, nt);
++ }
++
+ if (bc->uulen) {
+ int protocol=4;
+ enc_ie_useruser(&release->USER_USER, msg, protocol, bc->uu, bc->uulen, nt,bc);
+ cb_log(1,bc->port,"ENCODING USERUESRINFO:%s\n",bc->uu);
+ }
+-
+-#ifdef DEBUG
+- printf("Building RELEASE Msg\n");
++
++#ifdef DEBUG
++ printf("Building RELEASE Msg\n");
+ #endif
+- return msg;
++ return msg;
+ }
+
+-static void parse_release_complete (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
++static void parse_release_complete (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+- RELEASE_COMPLETE_t *release_complete=(RELEASE_COMPLETE_t*)((unsigned long)(msg->data+HEADER_LEN));
++ RELEASE_COMPLETE_t *release_complete = (RELEASE_COMPLETE_t *) (msg->data + HEADER_LEN);
+ int location;
+ int cause;
+ iframe_t *frm = (iframe_t*) msg->data;
+@@ -926,45 +1243,52 @@
+ dec_ie_cause(release_complete->CAUSE, (Q931_info_t *)(release_complete), &location, &cause, nt,bc);
+ if (cause>0) bc->cause=cause;
+
+-#ifdef DEBUG
+- printf("Parsing RELEASE_COMPLETE Msg\n");
++ dec_ie_facility(release_complete->FACILITY, (Q931_info_t *) release_complete, &bc->fac_in, nt, bc);
++
++#ifdef DEBUG
++ printf("Parsing RELEASE_COMPLETE Msg\n");
+ #endif
+ }
+
+-static msg_t *build_release_complete (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
++static msg_t *build_release_complete (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+ RELEASE_COMPLETE_t *release_complete;
+- msg_t *msg =(msg_t*)create_l3msg(CC_RELEASE_COMPLETE | REQUEST, MT_RELEASE_COMPLETE, bc?bc->l3_id:-1, sizeof(RELEASE_COMPLETE_t) ,nt);
+-
+- release_complete=(RELEASE_COMPLETE_t*)((msg->data+HEADER_LEN));
+-
++ msg_t *msg =(msg_t*)create_l3msg(CC_RELEASE_COMPLETE | REQUEST, MT_RELEASE_COMPLETE, bc?bc->l3_id:-1, sizeof(RELEASE_COMPLETE_t) ,nt);
++
++ release_complete=(RELEASE_COMPLETE_t*)((msg->data+HEADER_LEN));
++
+ enc_ie_cause(&release_complete->CAUSE, msg, nt?1:0, bc->out_cause, nt,bc);
+
++ if (bc->fac_out.Function != Fac_None) {
++ enc_ie_facility(&release_complete->FACILITY, msg, &bc->fac_out, nt);
++ }
++
+ if (bc->uulen) {
+ int protocol=4;
+ enc_ie_useruser(&release_complete->USER_USER, msg, protocol, bc->uu, bc->uulen, nt,bc);
+ cb_log(1,bc->port,"ENCODING USERUESRINFO:%s\n",bc->uu);
+ }
+-
+-#ifdef DEBUG
+- printf("Building RELEASE_COMPLETE Msg\n");
++
++#ifdef DEBUG
++ printf("Building RELEASE_COMPLETE Msg\n");
+ #endif
+- return msg;
++ return msg;
+ }
+
+-static void parse_facility (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
++static void parse_facility (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt ? mISDNUSER_HEAD_SIZE : mISDN_HEADER_LEN;
+- FACILITY_t *facility = (FACILITY_t*)(msg->data+HEADER_LEN);
+- Q931_info_t *qi = (Q931_info_t*)(msg->data+HEADER_LEN);
++ FACILITY_t *facility = (FACILITY_t*)(msg->data+HEADER_LEN);
++ Q931_info_t *qi = (Q931_info_t*)(msg->data+HEADER_LEN);
+ unsigned char *p = NULL;
+- int err;
+
+-#ifdef DEBUG
+- printf("Parsing FACILITY Msg\n");
++#ifdef DEBUG
++ printf("Parsing FACILITY Msg\n");
+ #endif
+
++ bc->fac_in.Function = Fac_None;
++
+ if (!bc->nt) {
+ if (qi->QI_ELEMENT(facility))
+ p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(facility) + 1;
+@@ -973,31 +1297,40 @@
+ }
+ if (!p)
+ return;
+-
+- err = decodeFac(p, &(bc->fac_in));
+- if (err) {
+- cb_log(5, bc->port, "Decoding FACILITY failed! (%d)\n", err);
++
++ if (decodeFac(p, &bc->fac_in)) {
++ cb_log(3, bc->port, "Decoding facility ie failed! Unrecognized facility message?\n");
+ }
+ }
+
+-static msg_t *build_facility (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
++static msg_t *build_facility (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
+ {
+- int len,
+- HEADER_LEN = nt ? mISDNUSER_HEAD_SIZE : mISDN_HEADER_LEN;
+- unsigned char *ie_fac,
+- fac_tmp[256];
+- msg_t *msg =(msg_t*)create_l3msg(CC_FACILITY | REQUEST, MT_FACILITY, bc?bc->l3_id:-1, sizeof(FACILITY_t) ,nt);
+- FACILITY_t *facility = (FACILITY_t*)(msg->data+HEADER_LEN);
++ int len;
++ int HEADER_LEN;
++ unsigned char *ie_fac;
++ unsigned char fac_tmp[256];
++ msg_t *msg;
++ FACILITY_t *facility;
+ Q931_info_t *qi;
+
+-#ifdef DEBUG
+- printf("Building FACILITY Msg\n");
++#ifdef DEBUG
++ printf("Building FACILITY Msg\n");
+ #endif
+-
++
+ len = encodeFac(fac_tmp, &(bc->fac_out));
+- if (len <= 0)
++ if (len <= 0) {
++ /*
++ * mISDN does not know how to build the requested facility structure
++ * Clear facility information
++ */
++ bc->fac_out.Function = Fac_None;
+ return NULL;
++ }
+
++ msg = (msg_t *) create_l3msg(CC_FACILITY | REQUEST, MT_FACILITY, bc ? bc->l3_id : -1, sizeof(FACILITY_t), nt);
++ HEADER_LEN = nt ? mISDNUSER_HEAD_SIZE : mISDN_HEADER_LEN;
++ facility = (FACILITY_t *) (msg->data + HEADER_LEN);
++
+ ie_fac = msg_put(msg, len);
+ if (bc->nt) {
+ facility->FACILITY = ie_fac + 1;
+@@ -1008,148 +1341,259 @@
+
+ memcpy(ie_fac, fac_tmp, len);
+
++ /* Clear facility information */
++ bc->fac_out.Function = Fac_None;
++
+ if (*bc->display) {
++#ifdef DEBUG
+ printf("Sending %s as Display\n", bc->display);
++#endif
+ enc_ie_display(&facility->DISPLAY, msg, bc->display, nt,bc);
+ }
+
+- return msg;
++ return msg;
+ }
+
+-static void parse_notify (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Parse a received REGISTER message
++ *
++ * \param msgs Search table entry that called us.
++ * \param msg Received message contents
++ * \param bc Associated B channel
++ * \param nt TRUE if in NT mode.
++ *
++ * \return Nothing
++ */
++static void parse_register(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
+ {
+-#ifdef DEBUG
+- printf("Parsing NOTIFY Msg\n");
++ int HEADER_LEN;
++ REGISTER_t *reg;
++
++ HEADER_LEN = nt ? mISDNUSER_HEAD_SIZE : mISDN_HEADER_LEN;
++ reg = (REGISTER_t *) (msg->data + HEADER_LEN);
++
++ /*
++ * A facility ie is optional.
++ * The peer may just be establishing a connection to send
++ * messages later.
++ */
++ dec_ie_facility(reg->FACILITY, (Q931_info_t *) reg, &bc->fac_in, nt, bc);
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \internal
++ * \brief Construct a REGISTER message
++ *
++ * \param msgs Search table entry that called us.
++ * \param bc Associated B channel
++ * \param nt TRUE if in NT mode.
++ *
++ * \return Allocated built message
++ */
++static msg_t *build_register(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
++{
++ int HEADER_LEN;
++ REGISTER_t *reg;
++ msg_t *msg;
++
++ msg = (msg_t *) create_l3msg(CC_REGISTER | REQUEST, MT_REGISTER, bc ? bc->l3_id : -1, sizeof(REGISTER_t), nt);
++ HEADER_LEN = nt ? mISDNUSER_HEAD_SIZE : mISDN_HEADER_LEN;
++ reg = (REGISTER_t *) (msg->data + HEADER_LEN);
++
++ if (bc->fac_out.Function != Fac_None) {
++ enc_ie_facility(&reg->FACILITY, msg, &bc->fac_out, nt);
++ }
++
++ return msg;
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++static void parse_notify (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
++{
++ int HEADER_LEN = nt ? mISDNUSER_HEAD_SIZE : mISDN_HEADER_LEN;
++ NOTIFY_t *notify = (NOTIFY_t *) (msg->data + HEADER_LEN);
++ int description_code;
++ int type;
++ int plan;
++ int present;
++ char number[sizeof(bc->redirecting.to.number)];
++
++#ifdef DEBUG
++ printf("Parsing NOTIFY Msg\n");
+ #endif
++
++ dec_ie_notify(notify->NOTIFY, (Q931_info_t *) notify, &description_code, nt, bc);
++ if (description_code < 0) {
++ bc->notify_description_code = mISDN_NOTIFY_CODE_INVALID;
++ } else {
++ bc->notify_description_code = description_code;
++ }
++
++ dec_ie_redir_dn(notify->REDIR_DN, (Q931_info_t *) notify, &type, &plan, &present, number, sizeof(number), nt, bc);
++ if (0 <= type) {
++ bc->redirecting.to_changed = 1;
++
++ bc->redirecting.to.number_type = type;
++ bc->redirecting.to.number_plan = plan;
++ switch (present) {
++ default:
++ case 0:
++ bc->redirecting.to.presentation = 0; /* presentation allowed */
++ break;
++ case 1:
++ bc->redirecting.to.presentation = 1; /* presentation restricted */
++ break;
++ case 2:
++ bc->redirecting.to.presentation = 2; /* Number not available */
++ break;
++ }
++ bc->redirecting.to.screening = 0; /* Unscreened */
++ strcpy(bc->redirecting.to.number, number);
++ }
+ }
+
+-static msg_t *build_notify (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
++static msg_t *build_notify (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+ NOTIFY_t *notify;
+- msg_t *msg =(msg_t*)create_l3msg(CC_NOTIFY | REQUEST, MT_NOTIFY, bc?bc->l3_id:-1, sizeof(NOTIFY_t) ,nt);
+-
+- notify=(NOTIFY_t*)((msg->data+HEADER_LEN));
++ msg_t *msg =(msg_t*)create_l3msg(CC_NOTIFY | REQUEST, MT_NOTIFY, bc?bc->l3_id:-1, sizeof(NOTIFY_t) ,nt);
+
+-#ifdef DEBUG
+- printf("Building NOTIFY Msg\n");
++#ifdef DEBUG
++ printf("Building NOTIFY Msg\n");
+ #endif
+- return msg;
++
++ notify = (NOTIFY_t *) (msg->data + HEADER_LEN);
++
++ enc_ie_notify(&notify->NOTIFY, msg, bc->notify_description_code, nt, bc);
++
++ if (bc->redirecting.to_changed) {
++ bc->redirecting.to_changed = 0;
++ switch (bc->outgoing_colp) {
++ case 0:/* pass */
++ case 1:/* restricted */
++ enc_ie_redir_dn(&notify->REDIR_DN, msg, bc->redirecting.to.number_type,
++ bc->redirecting.to.number_plan, bc->redirecting.to.presentation,
++ bc->redirecting.to.number, nt, bc);
++ break;
++ default:
++ break;
++ }
++ }
++ return msg;
+ }
+
+-static void parse_status_enquiry (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
++static void parse_status_enquiry (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
+ {
+-#ifdef DEBUG
+- printf("Parsing STATUS_ENQUIRY Msg\n");
++#ifdef DEBUG
++ printf("Parsing STATUS_ENQUIRY Msg\n");
+ #endif
+ }
+
+-static msg_t *build_status_enquiry (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
++static msg_t *build_status_enquiry (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+ STATUS_ENQUIRY_t *status_enquiry;
+- msg_t *msg =(msg_t*)create_l3msg(CC_STATUS_ENQUIRY | REQUEST, MT_STATUS_ENQUIRY, bc?bc->l3_id:-1, sizeof(STATUS_ENQUIRY_t) ,nt);
+-
+- status_enquiry=(STATUS_ENQUIRY_t*)((msg->data+HEADER_LEN));
++ msg_t *msg =(msg_t*)create_l3msg(CC_STATUS_ENQUIRY | REQUEST, MT_STATUS_ENQUIRY, bc?bc->l3_id:-1, sizeof(STATUS_ENQUIRY_t) ,nt);
+
+-#ifdef DEBUG
+- printf("Building STATUS_ENQUIRY Msg\n");
++ status_enquiry=(STATUS_ENQUIRY_t*)((msg->data+HEADER_LEN));
++
++#ifdef DEBUG
++ printf("Building STATUS_ENQUIRY Msg\n");
+ #endif
+- return msg;
++ return msg;
+ }
+
+-static void parse_information (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
++static void parse_information (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+- INFORMATION_t *information=(INFORMATION_t*)((unsigned long)(msg->data+HEADER_LEN));
+- {
+- int type, plan;
+- char number[32];
+- char keypad[32];
+- dec_ie_called_pn(information->CALLED_PN, (Q931_info_t *)information, &type, &plan, number, sizeof(number)-1, nt, bc);
+- dec_ie_keypad(information->KEYPAD, (Q931_info_t *)information, keypad, sizeof(keypad)-1, nt, bc);
+- strcpy(bc->info_dad, number);
+- strcpy(bc->keypad,keypad);
+- }
+-#ifdef DEBUG
+- printf("Parsing INFORMATION Msg\n");
++ INFORMATION_t *information = (INFORMATION_t *) (msg->data + HEADER_LEN);
++ int type, plan;
++
++ dec_ie_called_pn(information->CALLED_PN, (Q931_info_t *) information, &type, &plan, bc->info_dad, sizeof(bc->info_dad), nt, bc);
++ dec_ie_keypad(information->KEYPAD, (Q931_info_t *) information, bc->keypad, sizeof(bc->keypad), nt, bc);
++
++#ifdef DEBUG
++ printf("Parsing INFORMATION Msg\n");
+ #endif
+ }
+
+-static msg_t *build_information (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
++static msg_t *build_information (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+ INFORMATION_t *information;
+- msg_t *msg =(msg_t*)create_l3msg(CC_INFORMATION | REQUEST, MT_INFORMATION, bc?bc->l3_id:-1, sizeof(INFORMATION_t) ,nt);
+-
+- information=(INFORMATION_t*)((msg->data+HEADER_LEN));
+-
+- {
+- enc_ie_called_pn(&information->CALLED_PN, msg, 0, 1, bc->info_dad, nt,bc);
+- }
++ msg_t *msg =(msg_t*)create_l3msg(CC_INFORMATION | REQUEST, MT_INFORMATION, bc?bc->l3_id:-1, sizeof(INFORMATION_t) ,nt);
+
++ information=(INFORMATION_t*)((msg->data+HEADER_LEN));
++
++ enc_ie_called_pn(&information->CALLED_PN, msg, 0, 1, bc->info_dad, nt,bc);
++
+ {
+ if (*bc->display) {
++#ifdef DEBUG
+ printf("Sending %s as Display\n", bc->display);
++#endif
+ enc_ie_display(&information->DISPLAY, msg, bc->display, nt,bc);
+ }
+ }
+-
+-#ifdef DEBUG
+- printf("Building INFORMATION Msg\n");
++
++#ifdef DEBUG
++ printf("Building INFORMATION Msg\n");
+ #endif
+- return msg;
++ return msg;
+ }
+
+-static void parse_status (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
++static void parse_status (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+- STATUS_t *status=(STATUS_t*)((unsigned long)(msg->data+HEADER_LEN));
++ STATUS_t *status = (STATUS_t *) (msg->data + HEADER_LEN);
+ int location;
+ int cause;
+-
++
+ dec_ie_cause(status->CAUSE, (Q931_info_t *)(status), &location, &cause, nt,bc);
+ if (cause>0) bc->cause=cause;
+- ;
+
+-#ifdef DEBUG
+- printf("Parsing STATUS Msg\n");
++#ifdef DEBUG
++ printf("Parsing STATUS Msg\n");
+ #endif
+ }
+
+-static msg_t *build_status (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
++static msg_t *build_status (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+ STATUS_t *status;
+- msg_t *msg =(msg_t*)create_l3msg(CC_STATUS | REQUEST, MT_STATUS, bc?bc->l3_id:-1, sizeof(STATUS_t) ,nt);
+-
+- status=(STATUS_t*)((msg->data+HEADER_LEN));
++ msg_t *msg =(msg_t*)create_l3msg(CC_STATUS | REQUEST, MT_STATUS, bc?bc->l3_id:-1, sizeof(STATUS_t) ,nt);
+
+-#ifdef DEBUG
+- printf("Building STATUS Msg\n");
++ status=(STATUS_t*)((msg->data+HEADER_LEN));
++
++#ifdef DEBUG
++ printf("Building STATUS Msg\n");
+ #endif
+- return msg;
++ return msg;
+ }
+
+-static void parse_timeout (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
++static void parse_timeout (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
+ {
+-#ifdef DEBUG
+- printf("Parsing STATUS Msg\n");
+-#endif
++#ifdef DEBUG
++ printf("Parsing STATUS Msg\n");
++#endif
+ }
+
+-static msg_t *build_timeout (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
++static msg_t *build_timeout (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
+ {
+ int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
+ STATUS_t *status;
+- msg_t *msg =(msg_t*)create_l3msg(CC_STATUS | REQUEST, MT_STATUS, bc?bc->l3_id:-1, sizeof(STATUS_t) ,nt);
+-
+- status=(STATUS_t*)((msg->data+HEADER_LEN));
++ msg_t *msg =(msg_t*)create_l3msg(CC_STATUS | REQUEST, MT_STATUS, bc?bc->l3_id:-1, sizeof(STATUS_t) ,nt);
+
+-#ifdef DEBUG
+- printf("Building STATUS Msg\n");
++ status=(STATUS_t*)((msg->data+HEADER_LEN));
++
++#ifdef DEBUG
++ printf("Building STATUS Msg\n");
+ #endif
+- return msg;
++ return msg;
+ }
+
+
+@@ -1161,97 +1605,43 @@
+ /** Msg Array **/
+
+ struct isdn_msg msgs_g[] = {
+- {CC_PROCEEDING,L3,EVENT_PROCEEDING,
+- parse_proceeding,build_proceeding,
+- "PROCEEDING"},
+- {CC_ALERTING,L3,EVENT_ALERTING,
+- parse_alerting,build_alerting,
+- "ALERTING"},
+- {CC_PROGRESS,L3,EVENT_PROGRESS,
+- parse_progress,build_progress,
+- "PROGRESS"},
+- {CC_SETUP,L3,EVENT_SETUP,
+- parse_setup,build_setup,
+- "SETUP"},
+- {CC_CONNECT,L3,EVENT_CONNECT,
+- parse_connect,build_connect,
+- "CONNECT"},
+- {CC_SETUP_ACKNOWLEDGE,L3,EVENT_SETUP_ACKNOWLEDGE,
+- parse_setup_acknowledge,build_setup_acknowledge,
+- "SETUP_ACKNOWLEDGE"},
+- {CC_CONNECT_ACKNOWLEDGE ,L3,EVENT_CONNECT_ACKNOWLEDGE ,
+- parse_connect_acknowledge ,build_connect_acknowledge,
+- "CONNECT_ACKNOWLEDGE "},
+- {CC_USER_INFORMATION,L3,EVENT_USER_INFORMATION,
+- parse_user_information,build_user_information,
+- "USER_INFORMATION"},
+- {CC_SUSPEND_REJECT,L3,EVENT_SUSPEND_REJECT,
+- parse_suspend_reject,build_suspend_reject,
+- "SUSPEND_REJECT"},
+- {CC_RESUME_REJECT,L3,EVENT_RESUME_REJECT,
+- parse_resume_reject,build_resume_reject,
+- "RESUME_REJECT"},
+- {CC_HOLD,L3,EVENT_HOLD,
+- parse_hold,build_hold,
+- "HOLD"},
+- {CC_SUSPEND,L3,EVENT_SUSPEND,
+- parse_suspend,build_suspend,
+- "SUSPEND"},
+- {CC_RESUME,L3,EVENT_RESUME,
+- parse_resume,build_resume,
+- "RESUME"},
+- {CC_HOLD_ACKNOWLEDGE,L3,EVENT_HOLD_ACKNOWLEDGE,
+- parse_hold_acknowledge,build_hold_acknowledge,
+- "HOLD_ACKNOWLEDGE"},
+- {CC_SUSPEND_ACKNOWLEDGE,L3,EVENT_SUSPEND_ACKNOWLEDGE,
+- parse_suspend_acknowledge,build_suspend_acknowledge,
+- "SUSPEND_ACKNOWLEDGE"},
+- {CC_RESUME_ACKNOWLEDGE,L3,EVENT_RESUME_ACKNOWLEDGE,
+- parse_resume_acknowledge,build_resume_acknowledge,
+- "RESUME_ACKNOWLEDGE"},
+- {CC_HOLD_REJECT,L3,EVENT_HOLD_REJECT,
+- parse_hold_reject,build_hold_reject,
+- "HOLD_REJECT"},
+- {CC_RETRIEVE,L3,EVENT_RETRIEVE,
+- parse_retrieve,build_retrieve,
+- "RETRIEVE"},
+- {CC_RETRIEVE_ACKNOWLEDGE,L3,EVENT_RETRIEVE_ACKNOWLEDGE,
+- parse_retrieve_acknowledge,build_retrieve_acknowledge,
+- "RETRIEVE_ACKNOWLEDGE"},
+- {CC_RETRIEVE_REJECT,L3,EVENT_RETRIEVE_REJECT,
+- parse_retrieve_reject,build_retrieve_reject,
+- "RETRIEVE_REJECT"},
+- {CC_DISCONNECT,L3,EVENT_DISCONNECT,
+- parse_disconnect,build_disconnect,
+- "DISCONNECT"},
+- {CC_RESTART,L3,EVENT_RESTART,
+- parse_restart,build_restart,
+- "RESTART"},
+- {CC_RELEASE,L3,EVENT_RELEASE,
+- parse_release,build_release,
+- "RELEASE"},
+- {CC_RELEASE_COMPLETE,L3,EVENT_RELEASE_COMPLETE,
+- parse_release_complete,build_release_complete,
+- "RELEASE_COMPLETE"},
+- {CC_FACILITY,L3,EVENT_FACILITY,
+- parse_facility,build_facility,
+- "FACILITY"},
+- {CC_NOTIFY,L3,EVENT_NOTIFY,
+- parse_notify,build_notify,
+- "NOTIFY"},
+- {CC_STATUS_ENQUIRY,L3,EVENT_STATUS_ENQUIRY,
+- parse_status_enquiry,build_status_enquiry,
+- "STATUS_ENQUIRY"},
+- {CC_INFORMATION,L3,EVENT_INFORMATION,
+- parse_information,build_information,
+- "INFORMATION"},
+- {CC_STATUS,L3,EVENT_STATUS,
+- parse_status,build_status,
+- "STATUS"},
+- {CC_TIMEOUT,L3,EVENT_TIMEOUT,
+- parse_timeout,build_timeout,
+- "TIMEOUT"},
+- {0,0,0,NULL,NULL,NULL}
++/* *INDENT-OFF* */
++ /* misdn_msg, event, msg_parser, msg_builder, info */
++ { CC_PROCEEDING, EVENT_PROCEEDING, parse_proceeding, build_proceeding, "PROCEEDING" },
++ { CC_ALERTING, EVENT_ALERTING, parse_alerting, build_alerting, "ALERTING" },
++ { CC_PROGRESS, EVENT_PROGRESS, parse_progress, build_progress, "PROGRESS" },
++ { CC_SETUP, EVENT_SETUP, parse_setup, build_setup, "SETUP" },
++#if defined(AST_MISDN_ENHANCEMENTS)
++ { CC_REGISTER, EVENT_REGISTER, parse_register, build_register, "REGISTER" },
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++ { CC_CONNECT, EVENT_CONNECT, parse_connect, build_connect, "CONNECT" },
++ { CC_SETUP_ACKNOWLEDGE, EVENT_SETUP_ACKNOWLEDGE, parse_setup_acknowledge, build_setup_acknowledge, "SETUP_ACKNOWLEDGE" },
++ { CC_CONNECT_ACKNOWLEDGE, EVENT_CONNECT_ACKNOWLEDGE, parse_connect_acknowledge, build_connect_acknowledge, "CONNECT_ACKNOWLEDGE " },
++ { CC_USER_INFORMATION, EVENT_USER_INFORMATION, parse_user_information, build_user_information, "USER_INFORMATION" },
++ { CC_SUSPEND_REJECT, EVENT_SUSPEND_REJECT, parse_suspend_reject, build_suspend_reject, "SUSPEND_REJECT" },
++ { CC_RESUME_REJECT, EVENT_RESUME_REJECT, parse_resume_reject, build_resume_reject, "RESUME_REJECT" },
++ { CC_HOLD, EVENT_HOLD, parse_hold, build_hold, "HOLD" },
++ { CC_SUSPEND, EVENT_SUSPEND, parse_suspend, build_suspend, "SUSPEND" },
++ { CC_RESUME, EVENT_RESUME, parse_resume, build_resume, "RESUME" },
++ { CC_HOLD_ACKNOWLEDGE, EVENT_HOLD_ACKNOWLEDGE, parse_hold_acknowledge, build_hold_acknowledge, "HOLD_ACKNOWLEDGE" },
++ { CC_SUSPEND_ACKNOWLEDGE, EVENT_SUSPEND_ACKNOWLEDGE, parse_suspend_acknowledge, build_suspend_acknowledge, "SUSPEND_ACKNOWLEDGE" },
++ { CC_RESUME_ACKNOWLEDGE, EVENT_RESUME_ACKNOWLEDGE, parse_resume_acknowledge, build_resume_acknowledge, "RESUME_ACKNOWLEDGE" },
++ { CC_HOLD_REJECT, EVENT_HOLD_REJECT, parse_hold_reject, build_hold_reject, "HOLD_REJECT" },
++ { CC_RETRIEVE, EVENT_RETRIEVE, parse_retrieve, build_retrieve, "RETRIEVE" },
++ { CC_RETRIEVE_ACKNOWLEDGE, EVENT_RETRIEVE_ACKNOWLEDGE, parse_retrieve_acknowledge, build_retrieve_acknowledge, "RETRIEVE_ACKNOWLEDGE" },
++ { CC_RETRIEVE_REJECT, EVENT_RETRIEVE_REJECT, parse_retrieve_reject, build_retrieve_reject, "RETRIEVE_REJECT" },
++ { CC_DISCONNECT, EVENT_DISCONNECT, parse_disconnect, build_disconnect, "DISCONNECT" },
++ { CC_RESTART, EVENT_RESTART, parse_restart, build_restart, "RESTART" },
++ { CC_RELEASE, EVENT_RELEASE, parse_release, build_release, "RELEASE" },
++ { CC_RELEASE_COMPLETE, EVENT_RELEASE_COMPLETE, parse_release_complete, build_release_complete, "RELEASE_COMPLETE" },
++ { CC_FACILITY, EVENT_FACILITY, parse_facility, build_facility, "FACILITY" },
++ { CC_NOTIFY, EVENT_NOTIFY, parse_notify, build_notify, "NOTIFY" },
++ { CC_STATUS_ENQUIRY, EVENT_STATUS_ENQUIRY, parse_status_enquiry, build_status_enquiry, "STATUS_ENQUIRY" },
++ { CC_INFORMATION, EVENT_INFORMATION, parse_information, build_information, "INFORMATION" },
++ { CC_STATUS, EVENT_STATUS, parse_status, build_status, "STATUS" },
++ { CC_TIMEOUT, EVENT_TIMEOUT, parse_timeout, build_timeout, "TIMEOUT" },
++ { 0, 0, NULL, NULL, NULL }
++/* *INDENT-ON* */
+ };
+
+ #define msgs_max (sizeof(msgs_g)/sizeof(struct isdn_msg))
+@@ -1263,15 +1653,15 @@
+
+ if (nt){
+ mISDNuser_head_t *hh = (mISDNuser_head_t*)msg->data;
+-
++
+ for (i=0; i< msgs_max -1; i++) {
+ if ( (hh->prim&COMMAND_MASK)==(msgs[i].misdn_msg&COMMAND_MASK)) return i;
+ }
+-
++
+ } else {
+ iframe_t *frm = (iframe_t*)msg->data;
+-
+- for (i=0; i< msgs_max -1; i++)
++
++ for (i=0; i< msgs_max -1; i++)
+ if ( (frm->prim&COMMAND_MASK)==(msgs[i].misdn_msg&COMMAND_MASK)) return i;
+ }
+
+@@ -1281,11 +1671,11 @@
+ int isdn_msg_get_index_by_event(struct isdn_msg msgs[], enum event_e event, int nt)
+ {
+ int i;
+- for (i=0; i< msgs_max; i++)
++ for (i=0; i< msgs_max; i++)
+ if ( event == msgs[i].event) return i;
+
+ cb_log(10,0, "get_index: event not found!\n");
+-
++
+ return -1;
+ }
+
+@@ -1318,9 +1708,9 @@
+ char * isdn_get_info(struct isdn_msg msgs[], enum event_e event, int nt)
+ {
+ int i=isdn_msg_get_index_by_event(msgs, event, nt);
+-
++
+ if(i>=0) return msgs[i].info;
+-
++
+ if (event == EVENT_CLEANUP) return EVENT_CLEAN_INFO;
+ if (event == EVENT_DTMF_TONE) return EVENT_DTMF_TONE_INFO;
+ if (event == EVENT_NEW_L3ID) return EVENT_NEW_L3ID_INFO;
+@@ -1331,7 +1721,7 @@
+ if (event == EVENT_TONE_GENERATE) return EVENT_TONE_GENERATE_INFO;
+ if (event == EVENT_PORT_ALARM) return EVENT_PORT_ALARM_INFO;
+ if (event == EVENT_BCHAN_ERROR) return EVENT_BCHAN_ERROR_INFO;
+-
++
+ return NULL;
+ }
+
+@@ -1348,6 +1738,6 @@
+ {
+ int i=isdn_msg_get_index_by_event(msgs, event, nt);
+ if(i<0) return NULL;
+-
++
+ return msgs[i].msg_builder(msgs, bc, nt);
+ }
+Index: channels/misdn/portinfo.c
+===================================================================
+--- a/channels/misdn/portinfo.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/channels/misdn/portinfo.c (.../trunk) (revision 202568)
+@@ -1,4 +1,4 @@
+-/*! \file
++/*! \file
+ * \brief Interface to mISDN - port info
+ * \author Christian Richter <crich@beronet.com>
+ */
+Index: channels/misdn/isdn_lib.c
+===================================================================
+--- a/channels/misdn/isdn_lib.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/channels/misdn/isdn_lib.c (.../trunk) (revision 202568)
+@@ -11,7 +11,7 @@
+ * the GNU General Public License
+ */
+
+-/*! \file
++/*! \file
+ * \brief Interface to mISDN
+ * \author Christian Richter <crich@beronet.com>
+ */
+@@ -25,15 +25,15 @@
+ #include "isdn_lib_intern.h"
+ #include "isdn_lib.h"
+
+-enum event_response_e (*cb_event) (enum event_e event, struct misdn_bchannel *bc, void *user_data);
++enum event_response_e (*cb_event)(enum event_e event, struct misdn_bchannel *bc, void *user_data);
+
+-void (*cb_log) (int level, int port, char *tmpl, ...)
++void (*cb_log)(int level, int port, char *tmpl, ...)
+ __attribute__ ((format (printf, 3, 4)));
+
+ int (*cb_jb_empty)(struct misdn_bchannel *bc, char *buffer, int len);
+
+
+-/*
++/*
+ * Define ARRAY_LEN() because I cannot
+ * #include "asterisk/utils.h"
+ */
+@@ -48,12 +48,8 @@
+
+ int misdn_lib_get_l2_up(struct misdn_stack *stack);
+
+-struct misdn_stack* get_misdn_stack( void );
++struct misdn_stack *get_misdn_stack(void);
+
+-static int set_chan_in_stack(struct misdn_stack *stack, int channel);
+-
+-int release_cr(struct misdn_stack *stack, mISDNuser_head_t *hh);
+-
+ int misdn_lib_port_is_pri(int port)
+ {
+ struct misdn_stack *stack=get_misdn_stack();
+@@ -62,7 +58,7 @@
+ return stack->pri;
+ }
+ }
+-
++
+ return -1;
+ }
+
+@@ -74,15 +70,15 @@
+ return stack->nt;
+ }
+ }
+-
++
+ return -1;
+ }
+
+-void misdn_make_dummy(struct misdn_bchannel *dummybc, int port, int l3id, int nt, int channel)
++void misdn_make_dummy(struct misdn_bchannel *dummybc, int port, int l3id, int nt, int channel)
+ {
+ memset (dummybc,0,sizeof(struct misdn_bchannel));
+ dummybc->port=port;
+- if (l3id==0)
++ if (l3id==0)
+ dummybc->l3_id = MISDN_ID_DUMMY;
+ else
+ dummybc->l3_id=l3id;
+@@ -119,7 +115,7 @@
+ }
+
+ int misdn_lib_is_port_blocked(int port)
+-{
++{
+ struct misdn_stack *stack=get_misdn_stack();
+ for ( ; stack; stack=stack->next) {
+ if (stack->port == port) {
+@@ -138,12 +134,12 @@
+ return -1;
+ }
+
+-int misdn_lib_get_maxchans(int port)
++int misdn_lib_get_maxchans(int port)
+ {
+ struct misdn_stack *stack=get_misdn_stack();
+ for ( ; stack; stack=stack->next) {
+ if (stack->port == port) {
+- if (stack->pri)
++ if (stack->pri)
+ return 30;
+ else
+ return 2;
+@@ -159,7 +155,7 @@
+
+ if (!bc)
+ return NULL;
+-
++
+ for ( ; stack; stack = stack->next) {
+ if (bc->port == stack->port)
+ return stack;
+@@ -171,19 +167,24 @@
+
+ void get_show_stack_details(int port, char *buf)
+ {
+- struct misdn_stack *stack=get_misdn_stack();
+-
+- for ( ; stack; stack=stack->next) {
+- if (stack->port == port) break;
++ struct misdn_stack *stack = get_misdn_stack();
++
++ for (; stack; stack = stack->next) {
++ if (stack->port == port) {
++ break;
++ }
+ }
+-
++
+ if (stack) {
+- sprintf(buf, "* Port %d Type %s Prot. %s L2Link %s L1Link:%s Blocked:%d",
+- stack->port, stack->nt ? "NT" : "TE", stack->ptp ? "PTP" : "PMP",
+- stack->l2link ? "UP" : "DOWN", stack->l1link ? "UP" : "DOWN",
++ sprintf(buf, "* Port %2d Type %s Prot. %s L2Link %s L1Link:%s Blocked:%d",
++ stack->port,
++ stack->nt ? "NT" : "TE",
++ stack->ptp ? "PTP" : "PMP",
++ stack->l2link ? "UP " : "DOWN",
++ stack->l1link ? "UP " : "DOWN",
+ stack->blocked);
+ } else {
+- buf[0]=0;
++ buf[0] = 0;
+ }
+ }
+
+@@ -219,10 +220,10 @@
+ void *user_data;
+
+ msg_queue_t upqueue;
+- msg_queue_t activatequeue;
+-
++ msg_queue_t activatequeue;
++
+ sem_t new_msg;
+-
++
+ struct misdn_stack *stack_list;
+ } ;
+
+@@ -248,7 +249,7 @@
+ int misdn_lib_port_restart(int port);
+ int misdn_lib_pid_restart(int pid);
+
+-extern struct isdn_msg msgs_g[];
++extern struct isdn_msg msgs_g[];
+
+ #define ISDN_PID_L3_B_USER 0x430000ff
+ #define ISDN_PID_L4_B_USER 0x440000ff
+@@ -263,7 +264,7 @@
+ #define TONE_BUSY_CNT 20 /* ? */
+ #define TONE_BUSY_SILENCE_CNT 48 /* ? */
+
+-static int entity;
++static int entity;
+
+ static struct misdn_lib *glob_mgr;
+
+@@ -280,7 +281,6 @@
+
+ /* from isdn_lib.h */
+ /* user iface */
+-int te_lib_init( void ) ; /* returns midev */
+ void te_lib_destroy(int midev) ;
+ struct misdn_bchannel *manager_find_bc_by_pid(int pid);
+ struct misdn_bchannel *manager_find_bc_holded(struct misdn_bchannel* bc);
+@@ -304,7 +304,7 @@
+ "Res Digital",
+ "Unknown Bearer"
+ };
+-
++
+ switch (cap) {
+ case INFO_CAPABILITY_SPEECH:
+ return bearers[0];
+@@ -330,7 +330,7 @@
+ static void init_flip_bits(void)
+ {
+ int i,k;
+-
++
+ for (i = 0 ; i < 256 ; i++) {
+ unsigned char sample = 0 ;
+ for (k = 0; k<8; k++) {
+@@ -344,11 +344,11 @@
+ {
+ int i;
+ char * start = buf;
+-
++
+ for (i = 0 ; i < len; i++) {
+ buf[i] = flip_table[(unsigned char)buf[i]];
+ }
+-
++
+ return start;
+ }
+
+@@ -359,13 +359,13 @@
+ {
+ int i = 0;
+ msg_t *dmsg;
+-
++
+ while(i < 10)
+ {
+ dmsg = prep_l3data_msg(prim, dinfo, size, 256, NULL);
+ if (dmsg)
+ return(dmsg);
+-
++
+ if (!i)
+ printf("cannot allocate memory, trying again...\n");
+ i++;
+@@ -383,10 +383,10 @@
+ msg_t *dmsg;
+ Q931_info_t *qi;
+ iframe_t *frm;
+-
++
+ if (!ntmode)
+ size = sizeof(Q931_info_t)+2;
+-
++
+ while(i < 10) {
+ if (ntmode) {
+ dmsg = prep_l3data_msg(prim, dinfo, size, 256, NULL);
+@@ -406,7 +406,7 @@
+ return(dmsg);
+ }
+ }
+-
++
+ if (!i) printf("cannot allocate memory, trying again...\n");
+ i++;
+ usleep(300000);
+@@ -425,11 +425,11 @@
+ cb_log(0,bc->port,"send_msg: IEK!! no stack\n ");
+ return -1;
+ }
+-
++
+ frm->addr = (stack->upper_id | FLG_MSG_DOWN);
+ frm->dinfo = bc->l3_id;
+ frm->len = (dmsg->len) - mISDN_HEADER_LEN;
+-
++
+ cb_log(4,stack->port,"Sending msg, prim:%x addr:%x dinfo:%x\n",frm->prim,frm->addr,frm->dinfo);
+
+ mISDN_write(midev, dmsg->data, dmsg->len, TIMEOUT_1SEC);
+@@ -457,7 +457,7 @@
+ /* We have opted to never receive any available inband recorded messages */
+ return 0;
+ }
+-
++
+ switch (bc->progress_indicator) {
+ case INFO_PI_INBAND_AVAILABLE:
+ case INFO_PI_CALL_NOT_E2E_ISDN:
+@@ -474,9 +474,18 @@
+ {
+ int i;
+
+- for (i=0; i <= stack->b_num; i++) {
+- cb_log(6, stack->port, "Idx:%d stack->cchan:%d in_use:%d Chan:%d\n",i,stack->channels[i], stack->bc[i].in_use, i+1);
++ for (i = 0; i <= stack->b_num; ++i) {
++ cb_log(6, stack->port, "Idx:%d stack->cchan:%d in_use:%d Chan:%d\n",
++ i, stack->channels[i], stack->bc[i].in_use, i + 1);
+ }
++#if defined(AST_MISDN_ENHANCEMENTS)
++ for (i = MAX_BCHANS + 1; i < ARRAY_LEN(stack->bc); ++i) {
++ if (stack->bc[i].in_use) {
++ cb_log(6, stack->port, "Idx:%d stack->cchan:%d REGISTER Chan:%d in_use\n",
++ i, stack->channels[i], i + 1);
++ }
++ }
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
+ }
+
+
+@@ -491,10 +500,9 @@
+
+ static int set_chan_in_stack(struct misdn_stack *stack, int channel)
+ {
+-
+ cb_log(4,stack->port,"set_chan_in_stack: %d\n",channel);
+ dump_chan_list(stack);
+- if (channel >=1 && channel <= MAX_BCHANS) {
++ if (1 <= channel && channel <= ARRAY_LEN(stack->channels)) {
+ if (!stack->channels[channel-1])
+ stack->channels[channel-1] = 1;
+ else {
+@@ -505,7 +513,7 @@
+ cb_log(0,stack->port,"couldn't set channel %d in\n", channel );
+ return -1;
+ }
+-
++
+ return 0;
+ }
+
+@@ -514,78 +522,92 @@
+ static int find_free_chan_in_stack(struct misdn_stack *stack, struct misdn_bchannel *bc, int channel, int dec)
+ {
+ int i;
+- int chan=0;
+- int bnums = stack->pri ? stack->b_num : stack->b_num - 1;
++ int chan = 0;
++ int bnums;
+
+- if (bc->channel_found)
++ if (bc->channel_found) {
+ return 0;
+-
+- bc->channel_found=1;
++ }
+
+- cb_log(5,stack->port,"find_free_chan: req_chan:%d\n",channel);
++ bc->channel_found = 1;
+
+- if (channel < 0 || channel > MAX_BCHANS) {
+- cb_log(0, stack->port, " !! out of bound call to find_free_chan_in_stack! (ch:%d)\n", channel);
+- return 0;
+- }
+-
+- channel--;
++#if defined(AST_MISDN_ENHANCEMENTS)
++ if (bc->is_register_pool) {
++ for (i = MAX_BCHANS + 1; i < ARRAY_LEN(stack->channels); ++i) {
++ if (!stack->channels[i]) {
++ chan = i + 1;
++ cb_log(3, stack->port, " --> found REGISTER chan: %d\n", chan);
++ break;
++ }
++ }
++ } else
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++ {
++ cb_log(5, stack->port, "find_free_chan: req_chan:%d\n", channel);
+
+- if (dec) {
+- for (i = bnums; i >=0; i--) {
+- if (i != 15 && (channel < 0 || i == channel)) { /* skip E1 D channel ;) and work with chan preselection */
+- if (!stack->channels[i]) {
+- cb_log (3, stack->port, " --> found chan%s: %d\n", channel>=0?" (preselected)":"", i+1);
+- chan=i+1;
+- break;
++ if (channel < 0 || channel > MAX_BCHANS) {
++ cb_log(0, stack->port, " !! out of bound call to find_free_chan_in_stack! (ch:%d)\n", channel);
++ return 0;
++ }
++
++ --channel;
++
++ bnums = stack->pri ? stack->b_num : stack->b_num - 1;
++ if (dec) {
++ for (i = bnums; i >= 0; --i) {
++ if (i != 15 && (channel < 0 || i == channel)) { /* skip E1 D channel ;) and work with chan preselection */
++ if (!stack->channels[i]) {
++ chan = i + 1;
++ cb_log(3, stack->port, " --> found chan%s: %d\n", channel >= 0 ? " (preselected)" : "", chan);
++ break;
++ }
+ }
+ }
+- }
+- } else {
+- for (i = 0; i <= bnums; i++) {
+- if (i != 15 && (channel < 0 || i == channel)) { /* skip E1 D channel ;) and work with chan preselection */
+- if (!stack->channels[i]) {
+- cb_log (3, stack->port, " --> found chan%s: %d\n", channel>=0?" (preselected)":"", i+1);
+- chan=i+1;
+- break;
++ } else {
++ for (i = 0; i <= bnums; ++i) {
++ if (i != 15 && (channel < 0 || i == channel)) { /* skip E1 D channel ;) and work with chan preselection */
++ if (!stack->channels[i]) {
++ chan = i + 1;
++ cb_log(3, stack->port, " --> found chan%s: %d\n", channel >= 0 ? " (preselected)" : "", chan);
++ break;
++ }
+ }
+ }
+ }
+ }
+
+ if (!chan) {
+- cb_log (1, stack->port, " !! NO FREE CHAN IN STACK\n");
++ cb_log(1, stack->port, " !! NO FREE CHAN IN STACK\n");
+ dump_chan_list(stack);
+ bc->out_cause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION;
+ return -1;
+- }
++ }
+
+- if (set_chan_in_stack(stack, chan)<0) {
+- cb_log (0, stack->port, "Channel Already in use:%d\n", chan);
++ if (set_chan_in_stack(stack, chan) < 0) {
++ cb_log(0, stack->port, "Channel Already in use:%d\n", chan);
+ bc->out_cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
+ return -1;
+ }
+
+- bc->channel=chan;
++ bc->channel = chan;
+ return 0;
+ }
+
+-static int empty_chan_in_stack(struct misdn_stack *stack, int channel)
++static void empty_chan_in_stack(struct misdn_stack *stack, int channel)
+ {
+- if (channel<=0 || channel>MAX_BCHANS) {
+- cb_log(0,stack?stack->port:0, "empty_chan_in_stack: cannot empty channel %d\n",channel);
+- return -1;
++ if (channel < 1 || ARRAY_LEN(stack->channels) < channel) {
++ cb_log(0, stack->port, "empty_chan_in_stack: cannot empty channel %d\n", channel);
++ return;
+ }
+-
+- cb_log (4, stack?stack->port:0, "empty_chan_in_stack: %d\n",channel);
+- stack->channels[channel-1] = 0;
++
++ cb_log(4, stack->port, "empty_chan_in_stack: %d\n", channel);
++ stack->channels[channel - 1] = 0;
+ dump_chan_list(stack);
+- return 0;
+ }
+
+ char *bc_state2str(enum bchannel_state state) {
+ int i;
+-
++
+ struct bchan_state_s {
+ char *n;
+ enum bchannel_state s;
+@@ -604,7 +626,7 @@
+ {"BCHAN_CLEAN_REQUEST", BCHAN_CLEAN_REQUEST},
+ {"BCHAN_ERROR", BCHAN_ERROR}
+ };
+-
++
+ for (i=0; i< sizeof(states)/sizeof(struct bchan_state_s); i++)
+ if ( states[i].s == state)
+ return states[i].n;
+@@ -618,7 +640,7 @@
+ bc->l3_id,
+ bc_state2str(bc->bc_state),
+ bc_state2str(state) );
+-
++
+ switch (state) {
+ case BCHAN_ACTIVATED:
+ if (bc->next_bc_state == BCHAN_BRIDGED) {
+@@ -644,6 +666,38 @@
+
+ static void empty_bc(struct misdn_bchannel *bc)
+ {
++ bc->caller.presentation = 0; /* allowed */
++ bc->caller.number_plan = NUMPLAN_ISDN;
++ bc->caller.number_type = NUMTYPE_UNKNOWN;
++ bc->caller.name[0] = 0;
++ bc->caller.number[0] = 0;
++ bc->caller.subaddress[0] = 0;
++
++ bc->connected.presentation = 0; /* allowed */
++ bc->connected.number_plan = NUMPLAN_ISDN;
++ bc->connected.number_type = NUMTYPE_UNKNOWN;
++ bc->connected.name[0] = 0;
++ bc->connected.number[0] = 0;
++ bc->connected.subaddress[0] = 0;
++
++ bc->redirecting.from.presentation = 0; /* allowed */
++ bc->redirecting.from.number_plan = NUMPLAN_ISDN;
++ bc->redirecting.from.number_type = NUMTYPE_UNKNOWN;
++ bc->redirecting.from.name[0] = 0;
++ bc->redirecting.from.number[0] = 0;
++ bc->redirecting.from.subaddress[0] = 0;
++
++ bc->redirecting.to.presentation = 0; /* allowed */
++ bc->redirecting.to.number_plan = NUMPLAN_ISDN;
++ bc->redirecting.to.number_type = NUMTYPE_UNKNOWN;
++ bc->redirecting.to.name[0] = 0;
++ bc->redirecting.to.number[0] = 0;
++ bc->redirecting.to.subaddress[0] = 0;
++
++ bc->redirecting.reason = mISDN_REDIRECTING_REASON_UNKNOWN;
++ bc->redirecting.count = 0;
++ bc->redirecting.to_changed = 0;
++
+ bc->dummy=0;
+
+ bc->bframe_len=0;
+@@ -656,38 +710,32 @@
+ bc->sending_complete = 0;
+
+ bc->restart_channel=0;
+-
++
+ bc->conf_id = 0;
+
+ bc->need_more_infos = 0;
+-
++
+ bc->send_dtmf=0;
+ bc->nodsp=0;
+ bc->nojitter=0;
+
+ bc->time_usec=0;
+-
++
+ bc->rxgain=0;
+ bc->txgain=0;
+
+ bc->crypt=0;
+ bc->curptx=0; bc->curprx=0;
+-
++
+ bc->crypt_key[0] = 0;
+-
++
+ bc->generate_tone=0;
+ bc->tone_cnt=0;
+-
+- bc->dnumplan=NUMPLAN_UNKNOWN;
+- bc->onumplan=NUMPLAN_UNKNOWN;
+- bc->rnumplan=NUMPLAN_UNKNOWN;
+- bc->cpnnumplan=NUMPLAN_UNKNOWN;
+-
+
+ bc->active = 0;
+
+ bc->early_bconnect = 1;
+-
++
+ #ifdef MISDN_1_2
+ *bc->pipeline = 0;
+ #else
+@@ -698,17 +746,31 @@
+ bc->AOCD_need_export = 0;
+
+ bc->orig=0;
+-
++
+ bc->cause = AST_CAUSE_NORMAL_CLEARING;
+ bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
+- bc->pres = 0; /* allowed */
+-
++
++ bc->display_connected = 0; /* none */
++ bc->display_setup = 0; /* none */
++
++ bc->outgoing_colp = 0;/* pass */
++
++ bc->presentation = 0; /* allowed */
++ bc->set_presentation = 0;
++
++ bc->notify_description_code = mISDN_NOTIFY_CODE_INVALID;
++
+ bc->evq=EVENT_NOTHING;
+
+ bc->progress_coding=0;
+ bc->progress_location=0;
+ bc->progress_indicator=0;
+-
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++ bc->div_leg_3_rx_wanted = 0;
++ bc->div_leg_3_tx_pending = 0;
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
+ /** Set Default Bearer Caps **/
+ bc->capability=INFO_CAPABILITY_SPEECH;
+ bc->law=INFO_CODEC_ALAW;
+@@ -716,24 +778,23 @@
+ bc->rate=0x10;
+ bc->user1=0;
+ bc->urate=0;
+-
++
+ bc->hdlc=0;
+-
+-
++
++ bc->dialed.number_plan = NUMPLAN_ISDN;
++ bc->dialed.number_type = NUMTYPE_UNKNOWN;
++ bc->dialed.number[0] = 0;
++ bc->dialed.subaddress[0] = 0;
++
+ bc->info_dad[0] = 0;
+ bc->display[0] = 0;
+ bc->infos_pending[0] = 0;
+- bc->cad[0] = 0;
+- bc->oad[0] = 0;
+- bc->dad[0] = 0;
+- bc->rad[0] = 0;
+- bc->orig_dad[0] = 0;
+ bc->uu[0]=0;
+ bc->uulen=0;
+-
++
+ bc->fac_in.Function = Fac_None;
+ bc->fac_out.Function = Fac_None;
+-
++
+ bc->te_choose_channel = 0;
+ bc->channel_found= 0;
+
+@@ -748,32 +809,32 @@
+ struct misdn_stack * stack;
+
+ cb_log(3, bc?bc->port:0, "$$$ CLEANUP CALLED pid:%d\n", bc?bc->pid:-1);
+-
++
+ if (!bc ) return -1;
+ stack=get_stack_by_bc(bc);
+-
++
+ if (!stack) return -1;
+-
++
+ switch (bc->bc_state ) {
+ case BCHAN_CLEANED:
+ cb_log(5, stack->port, "$$$ Already cleaned up bc with stid :%x\n", bc->b_stid);
+ return -1;
+-
++
+ default:
+ break;
+ }
+-
++
+ cb_log(2, stack->port, "$$$ Cleaning up bc with stid :%x pid:%d\n", bc->b_stid, bc->pid);
+-
++
+ manager_ec_disable(bc);
+
+ manager_bchannel_deactivate(bc);
+
+ mISDN_write_frame(stack->midev, buff, bc->layer_id|FLG_MSG_TARGET|FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
+-
++
+ bc->b_stid = 0;
+ bc_state_change(bc, BCHAN_CLEANED);
+-
++
+ return ret;
+ }
+
+@@ -783,27 +844,31 @@
+ {
+ int i;
+
+- for (i=0; i<=stack->b_num; i++) {
+- if (global_state == MISDN_INITIALIZED) {
+- cb_event(EVENT_CLEANUP, &stack->bc[i], NULL);
+- empty_chan_in_stack(stack,i+1);
++ if (global_state == MISDN_INITIALIZED) {
++ for (i = 0; i <= stack->b_num; ++i) {
++ cb_event(EVENT_CLEANUP, &stack->bc[i], NULL);
++ empty_chan_in_stack(stack, i + 1);
+ empty_bc(&stack->bc[i]);
+ clean_up_bc(&stack->bc[i]);
+ stack->bc[i].in_use = 0;
+ }
+-
+- }
++#if defined(AST_MISDN_ENHANCEMENTS)
++ for (i = MAX_BCHANS + 1; i < ARRAY_LEN(stack->bc); ++i) {
++ empty_chan_in_stack(stack, i + 1);
++ empty_bc(&stack->bc[i]);
++ stack->bc[i].in_use = 0;
++ }
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++ }
+ }
+
+ static int new_te_id = 0;
+
+-#define MAXPROCS 0x100
+-
+ static int misdn_lib_get_l1_down(struct misdn_stack *stack)
+ {
+- /* Pull Up L1 */
++ /* Pull Up L1 */
+ iframe_t act;
+- act.prim = PH_DEACTIVATE | REQUEST;
++ act.prim = PH_DEACTIVATE | REQUEST;
+ act.addr = stack->lower_id|FLG_MSG_DOWN;
+ act.dinfo = 0;
+ act.len = 0;
+@@ -815,38 +880,38 @@
+
+ static int misdn_lib_get_l2_down(struct misdn_stack *stack)
+ {
+-
++
+ if (stack->ptp && (stack->nt) ) {
+ msg_t *dmsg;
+ /* L2 */
+ dmsg = create_l2msg(DL_RELEASE| REQUEST, 0, 0);
+-
++
+ if (stack->nst.manager_l3(&stack->nst, dmsg))
+ free_msg(dmsg);
+-
++
+ } else {
+ iframe_t act;
+-
++
+ act.prim = DL_RELEASE| REQUEST;
+ act.addr = (stack->upper_id |FLG_MSG_DOWN) ;
+-
++
+ act.dinfo = 0;
+ act.len = 0;
+ return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
+ }
+-
++
+ return 0;
+ }
+
+
+ static int misdn_lib_get_l1_up(struct misdn_stack *stack)
+ {
+- /* Pull Up L1 */
++ /* Pull Up L1 */
+ iframe_t act;
+- act.prim = PH_ACTIVATE | REQUEST;
++ act.prim = PH_ACTIVATE | REQUEST;
+ act.addr = (stack->upper_id | FLG_MSG_DOWN) ;
+
+-
++
+ act.dinfo = 0;
+ act.len = 0;
+
+@@ -856,26 +921,26 @@
+
+ int misdn_lib_get_l2_up(struct misdn_stack *stack)
+ {
+-
++
+ if (stack->ptp && (stack->nt) ) {
+ msg_t *dmsg;
+ /* L2 */
+ dmsg = create_l2msg(DL_ESTABLISH | REQUEST, 0, 0);
+-
++
+ if (stack->nst.manager_l3(&stack->nst, dmsg))
+ free_msg(dmsg);
+-
++
+ } else {
+ iframe_t act;
+-
++
+ act.prim = DL_ESTABLISH | REQUEST;
+ act.addr = (stack->upper_id |FLG_MSG_DOWN) ;
+-
++
+ act.dinfo = 0;
+ act.len = 0;
+ return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
+ }
+-
++
+ return 0;
+ }
+
+@@ -883,10 +948,10 @@
+ static int misdn_lib_get_l2_te_ptp_up(struct misdn_stack *stack)
+ {
+ iframe_t act;
+-
++
+ act.prim = DL_ESTABLISH | REQUEST;
+ act.addr = (stack->upper_id & ~LAYER_ID_MASK) | 3 | FLG_MSG_DOWN;
+-
++
+ act.dinfo = 0;
+ act.len = 0;
+ return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
+@@ -897,14 +962,14 @@
+ static int misdn_lib_get_short_status(struct misdn_stack *stack)
+ {
+ iframe_t act;
+-
+-
+- act.prim = MGR_SHORTSTATUS | REQUEST;
+-
++
++
++ act.prim = MGR_SHORTSTATUS | REQUEST;
++
+ act.addr = (stack->upper_id | MSG_BROADCAST) ;
+
+ act.dinfo = SSTATUS_BROADCAST_BIT | SSTATUS_ALL;
+-
++
+ act.len = 0;
+ return mISDN_write(stack->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
+ }
+@@ -929,7 +994,7 @@
+ if (stack->procids[proc_id] == 0) {
+ break;
+ }
+- } /* end for */
++ }
+ if (proc_id == MAXPROCS) {
+ cb_log(0, stack->port, "Couldn't Create New ProcId.\n");
+ return -1;
+@@ -996,7 +1061,7 @@
+ cb_log(0, bc->port, "setup_bc: NO STACK FOUND!!\n");
+ return -1;
+ }
+-
++
+ midev = stack->midev;
+ channel = bc->channel - 1 - (bc->channel > 16);
+ b_stid = stack->b_stids[channel >= 0 ? channel : 0];
+@@ -1008,9 +1073,9 @@
+ cb_log(4, stack->port, "$$$ bc already setup stid :%x (state:%s)\n", b_stid, bc_state2str(bc->bc_state) );
+ return -1;
+ }
+-
++
+ cb_log(5, stack->port, "$$$ Setting up bc with stid :%x\n", b_stid);
+-
++
+ /*check if the b_stid is already initialized*/
+ for (i=0; i <= stack->b_num; i++) {
+ if (stack->bc[i].b_stid == b_stid) {
+@@ -1018,10 +1083,10 @@
+ return -1;
+ }
+ }
+-
++
+ if (b_stid <= 0) {
+ cb_log(0, stack->port," -- Stid <=0 at the moment in channel:%d\n",channel);
+-
++
+ bc_state_change(bc,BCHAN_ERROR);
+ return 1;
+ }
+@@ -1031,10 +1096,10 @@
+ {
+ layer_info_t li;
+ memset(&li, 0, sizeof(li));
+-
++
+ li.object_id = -1;
+ li.extentions = 0;
+-
++
+ li.st = bc->b_stid; /* given idx */
+
+
+@@ -1044,18 +1109,18 @@
+ #endif
+ if ( bc->hdlc || bc->nodsp) {
+ cb_log(4, stack->port,"setup_bc: without dsp\n");
+- {
++ {
+ int l = sizeof(li.name);
+ strncpy(li.name, "B L3", l);
+ li.name[l-1] = 0;
+ }
+ li.pid.layermask = ISDN_LAYER((3));
+ li.pid.protocol[3] = ISDN_PID_L3_B_USER;
+-
++
+ bc->layer=3;
+ } else {
+ cb_log(4, stack->port,"setup_bc: with dsp\n");
+- {
++ {
+ int l = sizeof(li.name);
+ strncpy(li.name, "B L4", l);
+ li.name[l-1] = 0;
+@@ -1064,8 +1129,8 @@
+ li.pid.protocol[4] = ISDN_PID_L4_B_USER;
+
+ bc->layer=4;
+- }
+-
++ }
++
+ ret = mISDN_new_layer(midev, &li);
+ if (ret ) {
+ cb_log(0, stack->port,"New Layer Err: %d %s\n",ret,strerror(errno));
+@@ -1073,23 +1138,23 @@
+ bc_state_change(bc,BCHAN_ERROR);
+ return(-EINVAL);
+ }
+-
++
+ bc->layer_id = li.id;
+ }
+-
++
+ memset(&pid, 0, sizeof(pid));
+-
+-
+-
++
++
++
+ cb_log(4, stack->port," --> Channel is %d\n", bc->channel);
+-
++
+ if (bc->nodsp) {
+ cb_log(2, stack->port," --> TRANSPARENT Mode (no DSP, no HDLC)\n");
+ pid.protocol[1] = ISDN_PID_L1_B_64TRANS;
+ pid.protocol[2] = ISDN_PID_L2_B_TRANS;
+ pid.protocol[3] = ISDN_PID_L3_B_USER;
+ pid.layermask = ISDN_LAYER((1)) | ISDN_LAYER((2)) | ISDN_LAYER((3));
+-
++
+ } else if ( bc->hdlc ) {
+ cb_log(2, stack->port," --> HDLC Mode\n");
+ pid.protocol[1] = ISDN_PID_L1_B_64HDLC ;
+@@ -1103,16 +1168,16 @@
+ pid.protocol[3] = ISDN_PID_L3_B_DSP;
+ pid.protocol[4] = ISDN_PID_L4_B_USER;
+ pid.layermask = ISDN_LAYER((1)) | ISDN_LAYER((2)) | ISDN_LAYER((3)) | ISDN_LAYER((4));
+-
+- }
+
++ }
++
+ ret = mISDN_set_stack(midev, bc->b_stid, &pid);
+
+ if (ret){
+ cb_log(0, stack->port,"$$$ Set Stack Err: %d %s\n",ret,strerror(errno));
+-
++
+ mISDN_write_frame(midev, buff, bc->layer_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
+-
++
+ bc_state_change(bc,BCHAN_ERROR);
+ cb_event(EVENT_BCHAN_ERROR, bc, glob_mgr->user_data);
+ return(-EINVAL);
+@@ -1123,7 +1188,7 @@
+ if (ret) {
+ cb_log(0, stack->port,"$$$ Set StackIND Err: %d %s\n",ret,strerror(errno));
+ mISDN_write_frame(midev, buff, bc->layer_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
+-
++
+ bc_state_change(bc,BCHAN_ERROR);
+ cb_event(EVENT_BCHAN_ERROR, bc, glob_mgr->user_data);
+ return(-EINVAL);
+@@ -1136,14 +1201,14 @@
+ if (!bc->addr) {
+ cb_log(0, stack->port,"$$$ Get Layerid Err: %d %s\n",ret,strerror(errno));
+ mISDN_write_frame(midev, buff, bc->layer_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
+-
++
+ bc_state_change(bc,BCHAN_ERROR);
+ cb_event(EVENT_BCHAN_ERROR, bc, glob_mgr->user_data);
+ return (-EINVAL);
+ }
+
+ manager_bchannel_activate(bc);
+-
++
+ bc_state_change(bc,BCHAN_ACTIVATED);
+
+ return 0;
+@@ -1152,70 +1217,65 @@
+
+
+ /** IFACE **/
+-static int init_bc(struct misdn_stack *stack, struct misdn_bchannel *bc, int midev, int port, int bidx, char *msn, int firsttime)
++static int init_bc(struct misdn_stack *stack, struct misdn_bchannel *bc, int midev, int port, int bidx)
+ {
+- unsigned char buff[1025] = "";
+- iframe_t *frm = (iframe_t *)buff;
+- int ret;
+-
+- if (!bc) return -1;
+-
++ if (!bc) {
++ return -1;
++ }
++
+ cb_log(8, port, "Init.BC %d.\n",bidx);
+-
+- memset(bc, 0,sizeof(struct misdn_bchannel));
+
+ bc->send_lock=malloc(sizeof(struct send_lock));
+ if (!bc->send_lock) {
+ return -1;
+ }
+ pthread_mutex_init(&bc->send_lock->lock, NULL);
+-
+- if (msn) {
+- int l = sizeof(bc->msn);
+- strncpy(bc->msn,msn, l);
+- bc->msn[l-1] = 0;
+- }
+-
+-
++
+ empty_bc(bc);
+ bc_state_change(bc, BCHAN_CLEANED);
+-
++
+ bc->port=stack->port;
+ bc->nt=stack->nt?1:0;
+ bc->pri=stack->pri;
+-
++
+ {
+ ibuffer_t* ibuf= init_ibuffer(MISDN_IBUF_SIZE);
+
+ if (!ibuf) return -1;
+-
++
+ clear_ibuffer( ibuf);
+-
++
+ ibuf->rsem=malloc(sizeof(sem_t));
+ if (!ibuf->rsem) {
+ return -1;
+ }
+-
++
+ bc->astbuf=ibuf;
+
+ if (sem_init(ibuf->rsem,1,0)<0)
+ sem_init(ibuf->rsem,0,0);
+-
++
+ }
+-
+- {
++
++#if 0 /* This code does not seem to do anything useful */
++ if (bidx <= stack->b_num) {
++ unsigned char buff[1025];
++ iframe_t *frm = (iframe_t *) buff;
+ stack_info_t *stinf;
++ int ret;
++
+ ret = mISDN_get_stack_info(midev, stack->port, buff, sizeof(buff));
+ if (ret < 0) {
+ cb_log(0, port, "%s: Cannot get stack info for this port. (ret=%d)\n", __FUNCTION__, ret);
+ return -1;
+ }
+-
++
+ stinf = (stack_info_t *)&frm->data.p;
+-
++
+ cb_log(8, port, " --> Child %x\n",stinf->child[bidx]);
+ }
+-
++#endif
++
+ return 0;
+ }
+
+@@ -1227,36 +1287,34 @@
+ unsigned char buff[1025];
+ iframe_t *frm = (iframe_t *)buff;
+ stack_info_t *stinf;
+- int i;
++ struct misdn_stack *stack;
++ int i;
+ layer_info_t li;
+
+- struct misdn_stack *stack = malloc(sizeof(struct misdn_stack));
+- if (!stack ) return NULL;
++ stack = calloc(1, sizeof(struct misdn_stack));
++ if (!stack) {
++ return NULL;
++ }
+
++ cb_log(8, port, "Init. Stack.\n");
+
+- cb_log(8, port, "Init. Stack.\n");
+-
+- memset(stack,0,sizeof(struct misdn_stack));
+-
+- for (i=0; i<MAX_BCHANS + 1; i++ ) stack->channels[i]=0;
+-
+ stack->port=port;
+ stack->midev=midev;
+ stack->ptp=ptp;
+-
++
+ stack->holding=NULL;
+ stack->pri=0;
+-
++
+ msg_queue_init(&stack->downqueue);
+ msg_queue_init(&stack->upqueue);
+-
++
+ /* query port's requirements */
+ ret = mISDN_get_stack_info(midev, port, buff, sizeof(buff));
+ if (ret < 0) {
+ cb_log(0, port, "%s: Cannot get stack info for this port. (ret=%d)\n", __FUNCTION__, ret);
+ return(NULL);
+ }
+-
++
+ stinf = (stack_info_t *)&frm->data.p;
+
+ stack->d_stid = stinf->id;
+@@ -1264,7 +1322,7 @@
+
+ for (i=0; i<=stinf->childcnt; i++)
+ stack->b_stids[i] = stinf->child[i];
+-
++
+ switch(stinf->pid.protocol[0] & ~ISDN_PID_FEATURE_MASK) {
+ case ISDN_PID_L0_TE_S0:
+ stack->nt=0;
+@@ -1283,7 +1341,7 @@
+ cb_log(8, port, "TE S2M Stack\n");
+ stack->nt=1;
+ stack->pri=1;
+-
++
+ break;
+ default:
+ cb_log(0, port, "this is a unknown port type 0x%08x\n", stinf->pid.protocol[0]);
+@@ -1291,19 +1349,19 @@
+ }
+
+ if (!stack->nt) {
+- if (stinf->pid.protocol[2] & ISDN_PID_L2_DF_PTP ) {
++ if (stinf->pid.protocol[2] & ISDN_PID_L2_DF_PTP ) {
+ stack->ptp = 1;
+ } else {
+ stack->ptp = 0;
+ }
+ }
+-
++
+ {
+ int ret;
+ int nt=stack->nt;
+
+ cb_log(8, port, "Init. Stack.\n");
+-
++
+ memset(&li, 0, sizeof(li));
+ {
+ int l = sizeof(li.name);
+@@ -1315,15 +1373,15 @@
+ li.pid.protocol[nt?2:4] = nt?ISDN_PID_L2_LAPD_NET:ISDN_PID_L4_CAPI20;
+ li.pid.layermask = ISDN_LAYER((nt?2:4));
+ li.st = stack->d_stid;
+-
+-
++
++
+ ret = mISDN_new_layer(midev, &li);
+ if (ret) {
+ cb_log(0, port, "%s: Cannot add layer %d to this port.\n", __FUNCTION__, nt?2:4);
+ return(NULL);
+ }
+-
+-
++
++
+ stack->upper_id = li.id;
+ ret = mISDN_register_layer(midev, stack->d_stid, stack->upper_id);
+ if (ret)
+@@ -1331,60 +1389,55 @@
+ cb_log(0,port,"Cannot register layer %d of this port.\n", nt?2:4);
+ return(NULL);
+ }
+-
+- stack->lower_id = mISDN_get_layerid(midev, stack->d_stid, nt?1:3);
++
++ stack->lower_id = mISDN_get_layerid(midev, stack->d_stid, nt?1:3);
+ if (stack->lower_id < 0) {
+ cb_log(0, port, "%s: Cannot get layer(%d) id of this port.\n", __FUNCTION__, nt?1:3);
+ return(NULL);
+ }
+-
++
+ stack->upper_id = mISDN_get_layerid(midev, stack->d_stid, nt?2:4);
+ if (stack->upper_id < 0) {
+ cb_log(0, port, "%s: Cannot get layer(%d) id of this port.\n", __FUNCTION__, 2);
+ return(NULL);
+ }
+-
++
+ cb_log(8, port, "NT Stacks upper_id %x\n",stack->upper_id);
+-
+-
++
++
+ /* create nst (nt-mode only) */
+ if (nt) {
+-
++
+ memset(&stack->nst, 0, sizeof(net_stack_t));
+ memset(&stack->mgr, 0, sizeof(manager_t));
+-
++
+ stack->mgr.nst = &stack->nst;
+ stack->nst.manager = &stack->mgr;
+-
++
+ stack->nst.l3_manager = handle_event_nt;
+ stack->nst.device = midev;
+ stack->nst.cardnr = port;
+ stack->nst.d_stid = stack->d_stid;
+-
++
+ stack->nst.feature = FEATURE_NET_HOLD;
+ if (stack->ptp)
+ stack->nst.feature |= FEATURE_NET_PTP;
+ if (stack->pri)
+ stack->nst.feature |= FEATURE_NET_CRLEN2 | FEATURE_NET_EXTCID;
+-
++
+ stack->nst.l1_id = stack->lower_id;
+ stack->nst.l2_id = stack->upper_id;
+-
++
+ msg_queue_init(&stack->nst.down_queue);
+-
++
+ Isdnl2Init(&stack->nst);
+ Isdnl3Init(&stack->nst);
+-
+- }
+-
+- if (!stack->nt) {
+- /*assume L1 is up, we'll get DEACTIVATES soon, for non
+- * up L1s*/
+- stack->l1link=0;
++
+ }
++
+ stack->l1link=0;
+ stack->l2link=0;
+-#if 0
++#if 0
+ if (!stack->nt) {
+ misdn_lib_get_short_status(stack);
+ } else {
+@@ -1396,12 +1449,12 @@
+
+ misdn_lib_get_short_status(stack);
+ misdn_lib_get_l1_up(stack);
+- misdn_lib_get_l2_up(stack);
+-
++ misdn_lib_get_l2_up(stack);
++
+ }
+
+ cb_log(8,0,"stack_init: port:%d lowerId:%x upperId:%x\n",stack->port,stack->lower_id, stack->upper_id);
+-
++
+ return stack;
+ }
+
+@@ -1415,11 +1468,11 @@
+ cleanup_Isdnl2(&stack->nst);
+ cleanup_Isdnl3(&stack->nst);
+ }
+-
+- if (stack->lower_id)
++
++ if (stack->lower_id)
+ mISDN_write_frame(stack->midev, buf, stack->lower_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
+
+- if (stack->upper_id)
++ if (stack->upper_id)
+ mISDN_write_frame(stack->midev, buf, stack->upper_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
+ }
+
+@@ -1427,59 +1480,85 @@
+ static struct misdn_stack * find_stack_by_addr(int addr)
+ {
+ struct misdn_stack *stack;
+-
+- for (stack=glob_mgr->stack_list;
+- stack;
+- stack=stack->next) {
+- if ( (stack->upper_id&STACK_ID_MASK) == (addr&STACK_ID_MASK)) return stack;
+
++ for (stack = glob_mgr->stack_list; stack; stack = stack->next) {
++ if ((stack->upper_id & STACK_ID_MASK) == (addr & STACK_ID_MASK)) {
++ /* Found the stack */
++ break;
++ }
+ }
+-
+- return NULL;
++
++ return stack;
+ }
+
+
+-static struct misdn_stack * find_stack_by_port(int port)
++static struct misdn_stack *find_stack_by_port(int port)
+ {
+ struct misdn_stack *stack;
+-
+- for (stack=glob_mgr->stack_list;
+- stack;
+- stack=stack->next)
+- if (stack->port == port) return stack;
+-
+- return NULL;
++
++ for (stack = glob_mgr->stack_list; stack; stack = stack->next) {
++ if (stack->port == port) {
++ /* Found the stack */
++ break;
++ }
++ }
++
++ return stack;
+ }
+
+-static struct misdn_stack * find_stack_by_mgr(manager_t* mgr_nt)
++static struct misdn_stack *find_stack_by_mgr(manager_t *mgr_nt)
+ {
+ struct misdn_stack *stack;
+-
+- for (stack=glob_mgr->stack_list;
+- stack;
+- stack=stack->next)
+- if ( &stack->mgr == mgr_nt) return stack;
+-
+- return NULL;
++
++ for (stack = glob_mgr->stack_list; stack; stack = stack->next) {
++ if (&stack->mgr == mgr_nt) {
++ /* Found the stack */
++ break;
++ }
++ }
++
++ return stack;
+ }
+
+ static struct misdn_bchannel *find_bc_by_masked_l3id(struct misdn_stack *stack, unsigned long l3id, unsigned long mask)
+ {
+ int i;
+- for (i=0; i<=stack->b_num; i++) {
+- if ( (stack->bc[i].l3_id & mask) == (l3id & mask)) return &stack->bc[i] ;
++
++ for (i = 0; i <= stack->b_num; ++i) {
++ if ((stack->bc[i].l3_id & mask) == (l3id & mask)) {
++ return &stack->bc[i];
++ }
+ }
+- return stack_holder_find(stack,l3id);
++#if defined(AST_MISDN_ENHANCEMENTS)
++ /* Search the B channel records for a REGISTER signaling link. */
++ for (i = MAX_BCHANS + 1; i < ARRAY_LEN(stack->bc); ++i) {
++ if ((stack->bc[i].l3_id & mask) == (l3id & mask)) {
++ return &stack->bc[i];
++ }
++ }
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++ return stack_holder_find(stack, l3id);
+ }
+
+
+ struct misdn_bchannel *find_bc_by_l3id(struct misdn_stack *stack, unsigned long l3id)
+ {
+ int i;
+- for (i=0; i<=stack->b_num; i++) {
+- if (stack->bc[i].l3_id == l3id) return &stack->bc[i] ;
++
++ for (i = 0; i <= stack->b_num; ++i) {
++ if (stack->bc[i].l3_id == l3id) {
++ return &stack->bc[i];
++ }
+ }
+- return stack_holder_find(stack,l3id);
++#if defined(AST_MISDN_ENHANCEMENTS)
++ /* Search the B channel records for a REGISTER signaling link. */
++ for (i = MAX_BCHANS + 1; i < ARRAY_LEN(stack->bc); ++i) {
++ if (stack->bc[i].l3_id == l3id) {
++ return &stack->bc[i];
++ }
++ }
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++ return stack_holder_find(stack, l3id);
+ }
+
+ static struct misdn_bchannel *find_bc_holded(struct misdn_stack *stack)
+@@ -1506,7 +1585,7 @@
+ }
+ }
+ }
+-
++
+ return NULL;
+ }
+
+@@ -1514,7 +1593,7 @@
+ {
+ struct misdn_stack* stack;
+ int i;
+-
++
+ for (stack=glob_mgr->stack_list;
+ stack;
+ stack=stack->next) {
+@@ -1533,14 +1612,14 @@
+ struct misdn_stack* stack=find_stack_by_port(port);
+ int i;
+
+- if (!stack) return NULL;
+-
++ if (!stack) return NULL;
++
+ for (i=0; i<=stack->b_num; i++) {
+ if ( stack->bc[i].channel== channel ) {
+ return &stack->bc[i];
+ }
+ }
+-
++
+ return NULL;
+ }
+
+@@ -1551,16 +1630,23 @@
+ static int handle_event ( struct misdn_bchannel *bc, enum event_e event, iframe_t *frm)
+ {
+ struct misdn_stack *stack=get_stack_by_bc(bc);
+-
++
+ if (!stack->nt) {
+-
++
+ switch (event) {
+
+ case EVENT_CONNECT_ACKNOWLEDGE:
+ setup_bc(bc);
+
+ if ( *bc->crypt_key ) {
+- cb_log(4, stack->port, "ENABLING BLOWFISH channel:%d oad%d:%s dad%d:%s\n", bc->channel, bc->onumplan,bc->oad, bc->dnumplan,bc->dad);
++ cb_log(4, stack->port,
++ "ENABLING BLOWFISH channel:%d caller%d:\"%s\" <%s> dialed%d:%s\n",
++ bc->channel,
++ bc->caller.number_type,
++ bc->caller.name,
++ bc->caller.number,
++ bc->dialed.number_type,
++ bc->dialed.number);
+ manager_ph_control_block(bc, BF_ENABLE_KEY, bc->crypt_key, strlen(bc->crypt_key) );
+ }
+
+@@ -1582,7 +1668,14 @@
+ case EVENT_CONNECT:
+
+ if ( *bc->crypt_key ) {
+- cb_log(4, stack->port, "ENABLING BLOWFISH channel:%d oad%d:%s dad%d:%s\n", bc->channel, bc->onumplan,bc->oad, bc->dnumplan,bc->dad);
++ cb_log(4, stack->port,
++ "ENABLING BLOWFISH channel:%d caller%d:\"%s\" <%s> dialed%d:%s\n",
++ bc->channel,
++ bc->caller.number_type,
++ bc->caller.name,
++ bc->caller.number,
++ bc->dialed.number_type,
++ bc->dialed.number);
+ manager_ph_control_block(bc, BF_ENABLE_KEY, bc->crypt_key, strlen(bc->crypt_key) );
+ }
+ case EVENT_ALERTING:
+@@ -1600,25 +1693,28 @@
+ break;
+ }
+
+- if (!bc->channel)
++ if (!bc->channel) {
+ cb_log(0, stack->port, "Any Channel Requested, but we have no more!!\n");
+- else
+- cb_log(0, stack->port, "Requested Channel Already in Use releasing this call with cause 34!!!!\n");
++ } else {
++ cb_log(0, stack->port,
++ "Requested Channel Already in Use releasing this call with cause %d!!!!\n",
++ bc->out_cause);
++ }
+
+ /* when the channel is already in use, we can't
+- * simply clear it, we need to make sure that
+- * it will still be marked as in_use in the
++ * simply clear it, we need to make sure that
++ * it will still be marked as in_use in the
+ * available channels list.*/
+ bc->channel=0;
+
+ misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
+ return -1;
+ }
++
++ setup_bc(bc);
++ break;
+ }
+
+- setup_bc(bc);
+- break;
+-
+ case EVENT_RELEASE_COMPLETE:
+ case EVENT_RELEASE:
+ break;
+@@ -1626,17 +1722,19 @@
+ break;
+ }
+ } else { /** NT MODE **/
+-
++
+ }
+ return 0;
+ }
+
+ static int handle_cr ( struct misdn_stack *stack, iframe_t *frm)
+ {
++ struct misdn_bchannel dummybc;
+ struct misdn_bchannel *bc;
++ int channel;
+
+ if (!stack) return -1;
+-
++
+ switch (frm->prim) {
+ case CC_NEW_CR|INDICATION:
+ cb_log(7, stack->port, " --> lib: NEW_CR Ind with l3id:%x on this port.\n",frm->dinfo);
+@@ -1646,7 +1744,7 @@
+ cb_log(0, stack->port, " --> !! lib: No free channel!\n");
+ return -1;
+ }
+-
++
+ cb_log(7, stack->port, " --> new_process: New L3Id: %x\n",frm->dinfo);
+ bc->l3_id=frm->dinfo;
+ return 1;
+@@ -1659,54 +1757,44 @@
+ case CC_RELEASE_CR|CONFIRM:
+ break;
+ case CC_RELEASE_CR|INDICATION:
+- cb_log(4, stack->port, " --> lib: RELEASE_CR Ind with l3id:%x\n",frm->dinfo);
+- {
+- struct misdn_bchannel *bc=find_bc_by_l3id(stack, frm->dinfo);
+- struct misdn_bchannel dummybc;
+-
+- if (!bc) {
+- cb_log(4, stack->port, " --> Didn't find BC so temporarily creating dummy BC (l3id:%x) on this port.\n", frm->dinfo);
+- misdn_make_dummy(&dummybc, stack->port, frm->dinfo, stack->nt, 0);
+-
+- bc=&dummybc;
+- }
+-
+- if (bc) {
+- int channel = bc->channel;
+- cb_log(4, stack->port, " --> lib: CLEANING UP l3id: %x\n",frm->dinfo);
++ cb_log(4, stack->port, " --> lib: RELEASE_CR Ind with l3id:%x\n", frm->dinfo);
++ bc = find_bc_by_l3id(stack, frm->dinfo);
++ if (!bc) {
++ cb_log(4, stack->port, " --> Didn't find BC so temporarily creating dummy BC (l3id:%x) on this port.\n", frm->dinfo);
++ misdn_make_dummy(&dummybc, stack->port, frm->dinfo, stack->nt, 0);
++ bc = &dummybc;
++ }
+
+- /*bc->pid = 0;*/
+- bc->need_disconnect=0;
+- bc->need_release=0;
+- bc->need_release_complete=0;
++ channel = bc->channel;
++ cb_log(4, stack->port, " --> lib: CLEANING UP l3id: %x\n", frm->dinfo);
+
+- cb_event(EVENT_CLEANUP, bc, glob_mgr->user_data);
++ /* bc->pid = 0; */
++ bc->need_disconnect = 0;
++ bc->need_release = 0;
++ bc->need_release_complete = 0;
+
+- empty_bc(bc);
+- clean_up_bc(bc);
++ cb_event(EVENT_CLEANUP, bc, glob_mgr->user_data);
+
+- if (channel>0)
+- empty_chan_in_stack(stack,channel);
+- bc->in_use=0;
++ empty_bc(bc);
++ clean_up_bc(bc);
+
+- dump_chan_list(stack);
++ if (channel > 0)
++ empty_chan_in_stack(stack, channel);
++ bc->in_use = 0;
+
+- if (bc->stack_holder) {
+- cb_log(4,stack->port, "REMOVING Holder\n");
+- stack_holder_remove( stack, bc);
+- free(bc);
+- }
+- }
+- else {
+- if (stack->nt)
+- cb_log(4, stack->port, "BC with dinfo: %x not found.. (prim was %x and addr %x)\n",frm->dinfo, frm->prim, frm->addr);
+- }
+-
+- return 1;
++ dump_chan_list(stack);
++
++ if (bc->stack_holder) {
++ cb_log(4, stack->port, "REMOVING Holder\n");
++ stack_holder_remove(stack, bc);
++ free(bc);
+ }
++
++ return 1;
++ default:
+ break;
+ }
+-
++
+ return 0;
+ }
+
+@@ -1720,10 +1808,10 @@
+ cb_log(1,0,"misdn_release: No Stack found\n");
+ return;
+ }
+-
+- if (bc->channel>0)
++
++ if (bc->channel>0)
+ empty_chan_in_stack(stack,bc->channel);
+-
++
+ empty_bc(bc);
+ clean_up_bc(bc);
+ bc->in_use=0;
+@@ -1732,21 +1820,21 @@
+
+
+
+-int misdn_lib_get_port_up (int port)
+-{ /* Pull Up L1 */
++int misdn_lib_get_port_up (int port)
++{ /* Pull Up L1 */
+ struct misdn_stack *stack;
+-
++
+ for (stack=glob_mgr->stack_list;
+ stack;
+ stack=stack->next) {
+-
++
+ if (stack->port == port) {
+
+ if (!stack->l1link)
+ misdn_lib_get_l1_up(stack);
+ if (!stack->l2link)
+ misdn_lib_get_l2_up(stack);
+-
++
+ return 0;
+ }
+ }
+@@ -1754,8 +1842,8 @@
+ }
+
+
+-int misdn_lib_get_port_down (int port)
+-{ /* Pull Down L1 */
++int misdn_lib_get_port_down (int port)
++{ /* Pull Down L1 */
+ struct misdn_stack *stack;
+ for (stack=glob_mgr->stack_list;
+ stack;
+@@ -1778,7 +1866,7 @@
+ for (stack=glob_mgr->stack_list;
+ stack;
+ stack=stack->next) {
+-
++
+ if (stack->port == port) {
+
+ if (stack->blocked) {
+@@ -1805,36 +1893,33 @@
+ }
+ }
+ }
+-
++
+ return -1;
+ }
+
+
+-int release_cr(struct misdn_stack *stack, mISDNuser_head_t *hh)
++static int release_cr(struct misdn_stack *stack, mISDNuser_head_t *hh)
+ {
+ struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo);
+ struct misdn_bchannel dummybc;
+ iframe_t frm; /* fake te frm to remove callref from global callreflist */
++
+ frm.dinfo = hh->dinfo;
+-
+ frm.addr=stack->upper_id | FLG_MSG_DOWN;
+-
+ frm.prim = CC_RELEASE_CR|INDICATION;
+ cb_log(4, stack->port, " --> CC_RELEASE_CR: Faking Release_cr for %x l3id:%x\n",frm.addr, frm.dinfo);
++
+ /** removing procid **/
+ if (!bc) {
+ cb_log(4, stack->port, " --> Didn't find BC so temporarily creating dummy BC (l3id:%x) on this port.\n", hh->dinfo);
+ misdn_make_dummy(&dummybc, stack->port, hh->dinfo, stack->nt, 0);
+- bc=&dummybc;
++ bc=&dummybc;
+ }
+
+- if (bc) {
+- if ( (bc->l3_id & 0xff00) == 0xff00) {
+- cb_log(4, stack->port, " --> Removing Process Id:%x on this port.\n", bc->l3_id&0xff);
+- stack->procids[bc->l3_id&0xff] = 0 ;
+- }
++ if ((bc->l3_id & 0xff00) == 0xff00) {
++ cb_log(4, stack->port, " --> Removing Process Id:%x on this port.\n", bc->l3_id & 0xff);
++ stack->procids[bc->l3_id & 0xff] = 0;
+ }
+- else cb_log(0, stack->port, "Couldn't find BC so I couldn't remove the Process!!!! this is a bad port.\n");
+
+ if (handle_cr(stack, &frm)<0) {
+ }
+@@ -1842,318 +1927,319 @@
+ return 0 ;
+ }
+
+-static int
+-handle_event_nt(void *dat, void *arg)
++static int handle_event_nt(void *dat, void *arg)
+ {
++ struct misdn_bchannel dummybc;
++ struct misdn_bchannel *bc;
+ manager_t *mgr = (manager_t *)dat;
+ msg_t *msg = (msg_t *)arg;
++ msg_t *dmsg;
+ mISDNuser_head_t *hh;
++ struct misdn_stack *stack;
++ enum event_e event;
+ int reject=0;
+-
+- struct misdn_stack *stack=find_stack_by_mgr(mgr);
+ int port;
++ int l3id;
++ int channel;
++ int tmpcause;
+
+ if (!msg || !mgr)
+ return(-EINVAL);
+
++ stack = find_stack_by_mgr(mgr);
+ hh=(mISDNuser_head_t*)msg->data;
+ port=stack->port;
+-
++
+ cb_log(5, stack->port, " --> lib: prim %x dinfo %x\n",hh->prim, hh->dinfo);
++ switch(hh->prim) {
++ case CC_RETRIEVE|INDICATION:
+ {
+- switch(hh->prim){
+- case CC_RETRIEVE|INDICATION:
+- {
+- struct misdn_bchannel *bc;
+- struct misdn_bchannel *hold_bc;
++ struct misdn_bchannel *hold_bc;
++ iframe_t frm; /* fake te frm to add callref to global callreflist */
+
+- iframe_t frm; /* fake te frm to add callref to global callreflist */
+- frm.dinfo = hh->dinfo;
++ frm.dinfo = hh->dinfo;
++ frm.addr=stack->upper_id | FLG_MSG_DOWN;
++ frm.prim = CC_NEW_CR|INDICATION;
++ if (handle_cr( stack, &frm)< 0) {
++ goto ERR_NO_CHANNEL;
++ }
+
+- frm.addr=stack->upper_id | FLG_MSG_DOWN;
++ bc = find_bc_by_l3id(stack, hh->dinfo);
++ hold_bc = stack_holder_find(stack, bc->l3_id);
++ cb_log(4, stack->port, "bc_l3id:%x holded_bc_l3id:%x\n",bc->l3_id, hold_bc->l3_id);
+
+- frm.prim = CC_NEW_CR|INDICATION;
+-
+- if (handle_cr( stack, &frm)< 0) {
+- msg_t *dmsg;
+- cb_log(4, stack->port, "Patch from MEIDANIS:Sending RELEASE_COMPLETE %x (No free Chan for you..)\n", hh->dinfo);
+- dmsg = create_l3msg(CC_RELEASE_COMPLETE | REQUEST,MT_RELEASE_COMPLETE, hh->dinfo,sizeof(RELEASE_COMPLETE_t), 1);
+- stack->nst.manager_l3(&stack->nst, dmsg);
+- free_msg(msg);
+- return 0;
+- }
+-
+- bc = find_bc_by_l3id(stack, hh->dinfo);
+- hold_bc = stack_holder_find(stack, bc->l3_id);
+- cb_log(4, stack->port, "bc_l3id:%x holded_bc_l3id:%x\n",bc->l3_id, hold_bc->l3_id);
++ if (hold_bc) {
++ cb_log(4, stack->port, "REMOVING Holder\n");
+
+- if (hold_bc) {
+- cb_log(4, stack->port, "REMOVING Holder\n");
++ /* swap the backup to our new channel back */
++ stack_holder_remove(stack, hold_bc);
++ memcpy(bc, hold_bc, sizeof(*bc));
++ free(hold_bc);
+
+- /*swap the backup to our new channel back*/
+- stack_holder_remove(stack, hold_bc);
+- memcpy(bc, hold_bc, sizeof(*bc));
+- free(hold_bc);
++ bc->holded=0;
++ bc->b_stid=0;
++ }
++ break;
++ }
+
+- bc->holded=0;
+- bc->b_stid=0;
+- }
+-
+- }
+-
+- break;
+-
+- case CC_SETUP|CONFIRM:
+- {
+- struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo);
+- int l3id = *((int *)(((u_char *)msg->data)+ mISDNUSER_HEAD_SIZE));
+- cb_log(4, stack->port, " --> lib: Event_ind:SETUP CONFIRM [NT] : new L3ID is %x\n",l3id );
+-
+- if (!bc) { cb_log(4, stack->port, "Bc Not found (after SETUP CONFIRM)\n"); return 0; }
+- cb_log (2,bc->port,"I IND :CC_SETUP|CONFIRM: old l3id:%x new l3id:%x\n", bc->l3_id, l3id);
+- bc->l3_id=l3id;
++ case CC_SETUP | CONFIRM:
++ l3id = *((int *) (msg->data + mISDNUSER_HEAD_SIZE));
++
++ cb_log(4, stack->port, " --> lib: Event_ind:SETUP CONFIRM [NT] : new L3ID is %x\n", l3id);
++
++ bc = find_bc_by_l3id(stack, hh->dinfo);
++ if (bc) {
++ cb_log (2, bc->port, "I IND :CC_SETUP|CONFIRM: old l3id:%x new l3id:%x\n", bc->l3_id, l3id);
++ bc->l3_id = l3id;
+ cb_event(EVENT_NEW_L3ID, bc, glob_mgr->user_data);
++ } else {
++ cb_log(4, stack->port, "Bc Not found (after SETUP CONFIRM)\n");
+ }
+ free_msg(msg);
+ return 0;
+-
+- case CC_SETUP|INDICATION:
+- {
+- struct misdn_bchannel* bc=misdn_lib_get_free_bc(stack->port, 0, 1, 0);
+- if (!bc)
+- ERR_NO_CHANNEL:
+- {
+- msg_t *dmsg;
+- cb_log(4, stack->port, "Patch from MEIDANIS:Sending RELEASE_COMPLETE %x (No free Chan for you..)\n", hh->dinfo);
+- dmsg = create_l3msg(CC_RELEASE_COMPLETE | REQUEST,MT_RELEASE_COMPLETE, hh->dinfo,sizeof(RELEASE_COMPLETE_t), 1);
+- stack->nst.manager_l3(&stack->nst, dmsg);
+- free_msg(msg);
+- return 0;
+- }
+-
+- cb_log(4, stack->port, " --> new_process: New L3Id: %x\n",hh->dinfo);
+- bc->l3_id=hh->dinfo;
++
++ case CC_SETUP | INDICATION:
++ bc = misdn_lib_get_free_bc(stack->port, 0, 1, 0);
++ if (!bc) {
++ goto ERR_NO_CHANNEL;
+ }
++
++ cb_log(4, stack->port, " --> new_process: New L3Id: %x\n",hh->dinfo);
++ bc->l3_id=hh->dinfo;
+ break;
+
+- case CC_CONNECT_ACKNOWLEDGE|INDICATION:
++#if defined(AST_MISDN_ENHANCEMENTS)
++ case CC_REGISTER | CONFIRM:
++ l3id = *((int *) (msg->data + mISDNUSER_HEAD_SIZE));
++
++ cb_log(4, stack->port, " --> lib: Event_ind:REGISTER CONFIRM [NT] : new L3ID is %x\n", l3id);
++
++ bc = find_bc_by_l3id(stack, hh->dinfo);
++ if (bc) {
++ cb_log (2, bc->port, "I IND :CC_REGISTER|CONFIRM: old l3id:%x new l3id:%x\n", bc->l3_id, l3id);
++ bc->l3_id = l3id;
++ } else {
++ cb_log(4, stack->port, "Bc Not found (after REGISTER CONFIRM)\n");
++ }
++ free_msg(msg);
++ return 0;
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++#if defined(AST_MISDN_ENHANCEMENTS)
++ case CC_REGISTER | INDICATION:
++ bc = misdn_lib_get_register_bc(stack->port);
++ if (!bc) {
++ goto ERR_NO_CHANNEL;
++ }
++
++ cb_log(4, stack->port, " --> new_process: New L3Id: %x\n",hh->dinfo);
++ bc->l3_id=hh->dinfo;
+ break;
+-
+- case CC_ALERTING|INDICATION:
+- case CC_PROCEEDING|INDICATION:
+- case CC_SETUP_ACKNOWLEDGE|INDICATION:
+- if(!stack->ptp) break;
+- case CC_CONNECT|INDICATION:
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++ case CC_CONNECT_ACKNOWLEDGE|INDICATION:
+ break;
+- case CC_DISCONNECT|INDICATION:
+- {
+- struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo);
+- if (!bc) {
+- bc=find_bc_by_masked_l3id(stack, hh->dinfo, 0xffff0000);
+- if (bc) {
+- int myprocid=bc->l3_id&0x0000ffff;
+- hh->dinfo=(hh->dinfo&0xffff0000)|myprocid;
+- cb_log(3,stack->port,"Reject dinfo: %x cause:%d\n",hh->dinfo,bc->cause);
+- reject=1;
+- }
++
++ case CC_ALERTING|INDICATION:
++ case CC_PROCEEDING|INDICATION:
++ case CC_SETUP_ACKNOWLEDGE|INDICATION:
++ case CC_CONNECT|INDICATION:
++ break;
++ case CC_DISCONNECT|INDICATION:
++ bc = find_bc_by_l3id(stack, hh->dinfo);
++ if (!bc) {
++ bc=find_bc_by_masked_l3id(stack, hh->dinfo, 0xffff0000);
++ if (bc) {
++ int myprocid=bc->l3_id&0x0000ffff;
++
++ hh->dinfo=(hh->dinfo&0xffff0000)|myprocid;
++ cb_log(3,stack->port,"Reject dinfo: %x cause:%d\n",hh->dinfo,bc->cause);
++ reject=1;
+ }
+ }
+ break;
+-
+- case CC_FACILITY|INDICATION:
+- {
+- struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo);
+- if (!bc) {
+- bc=find_bc_by_masked_l3id(stack, hh->dinfo, 0xffff0000);
+- if (bc) {
+- int myprocid=bc->l3_id&0x0000ffff;
+- hh->dinfo=(hh->dinfo&0xffff0000)|myprocid;
+- cb_log(4,bc->port,"Repaired reject Bug, new dinfo: %x\n",hh->dinfo);
+- }
++
++ case CC_FACILITY|INDICATION:
++ bc = find_bc_by_l3id(stack, hh->dinfo);
++ if (!bc) {
++ bc=find_bc_by_masked_l3id(stack, hh->dinfo, 0xffff0000);
++ if (bc) {
++ int myprocid=bc->l3_id&0x0000ffff;
++
++ hh->dinfo=(hh->dinfo&0xffff0000)|myprocid;
++ cb_log(4,bc->port,"Repaired reject Bug, new dinfo: %x\n",hh->dinfo);
+ }
+ }
+ break;
+-
+- case CC_RELEASE_COMPLETE|INDICATION:
+- break;
+
+- case CC_SUSPEND|INDICATION:
+- {
+- msg_t *dmsg;
+- cb_log(4, stack->port, " --> Got Suspend, sending Reject for now\n");
+- dmsg = create_l3msg(CC_SUSPEND_REJECT | REQUEST,MT_SUSPEND_REJECT, hh->dinfo,sizeof(RELEASE_COMPLETE_t), 1);
+- stack->nst.manager_l3(&stack->nst, dmsg);
+- free_msg(msg);
+- return 0;
++ case CC_RELEASE_COMPLETE|INDICATION:
++ break;
++
++ case CC_SUSPEND|INDICATION:
++ cb_log(4, stack->port, " --> Got Suspend, sending Reject for now\n");
++ dmsg = create_l3msg(CC_SUSPEND_REJECT | REQUEST,MT_SUSPEND_REJECT, hh->dinfo,sizeof(RELEASE_COMPLETE_t), 1);
++ stack->nst.manager_l3(&stack->nst, dmsg);
++ free_msg(msg);
++ return 0;
++
++ case CC_RESUME|INDICATION:
++ break;
++
++ case CC_RELEASE|CONFIRM:
++ bc = find_bc_by_l3id(stack, hh->dinfo);
++ if (bc) {
++ cb_log(1, stack->port, "CC_RELEASE|CONFIRM (l3id:%x), sending RELEASE_COMPLETE\n", hh->dinfo);
++ misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
+ }
+ break;
+- case CC_RESUME|INDICATION:
+- break;
+
+- case CC_RELEASE|CONFIRM:
+- {
+- struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo);
++ case CC_RELEASE|INDICATION:
++ break;
+
+- if (bc) {
+- cb_log(1, stack->port, "CC_RELEASE|CONFIRM (l3id:%x), sending RELEASE_COMPLETE\n", hh->dinfo);
+- misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
+- }
+- }
+- break;
+-
+- case CC_RELEASE|INDICATION:
+- break;
++ case CC_RELEASE_CR|INDICATION:
++ release_cr(stack, hh);
++ free_msg(msg);
++ return 0;
+
+- case CC_RELEASE_CR|INDICATION:
+- release_cr(stack, hh);
+- free_msg(msg);
+- return 0 ;
+- break;
+-
+- case CC_NEW_CR|INDICATION:
+- /* Got New CR for bchan, for now I handle this one in */
+- /* connect_ack, Need to be changed */
+- {
+- struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo);
+- int l3id = *((int *)(((u_char *)msg->data)+ mISDNUSER_HEAD_SIZE));
+- if (!bc) { cb_log(0, stack->port, " --> In NEW_CR: didn't found bc ??\n"); return -1;};
+- if (((l3id&0xff00)!=0xff00) && ((bc->l3_id&0xff00)==0xff00)) {
+- cb_log(4, stack->port, " --> Removing Process Id:%x on this port.\n", 0xff&bc->l3_id);
+- stack->procids[bc->l3_id&0xff] = 0 ;
+- }
+- cb_log(4, stack->port, "lib: Event_ind:CC_NEW_CR : very new L3ID is %x\n",l3id );
+-
+- bc->l3_id =l3id;
++ case CC_NEW_CR|INDICATION:
++ /* Got New CR for bchan, for now I handle this one in */
++ /* connect_ack, Need to be changed */
++ l3id = *((int *) (msg->data + mISDNUSER_HEAD_SIZE));
++
++ bc = find_bc_by_l3id(stack, hh->dinfo);
++ if (!bc) {
++ cb_log(0, stack->port, " --> In NEW_CR: didn't found bc ??\n");
++ return -1;
++ }
++ if (((l3id&0xff00)!=0xff00) && ((bc->l3_id&0xff00)==0xff00)) {
++ cb_log(4, stack->port, " --> Removing Process Id:%x on this port.\n", 0xff&bc->l3_id);
++ stack->procids[bc->l3_id&0xff] = 0 ;
++ }
++ cb_log(4, stack->port, "lib: Event_ind:CC_NEW_CR : very new L3ID is %x\n",l3id );
++
++ bc->l3_id =l3id;
++ if (!bc->is_register_pool) {
+ cb_event(EVENT_NEW_L3ID, bc, glob_mgr->user_data);
+-
+- free_msg(msg);
+- return 0;
+ }
+-
+- case DL_ESTABLISH | INDICATION:
+- case DL_ESTABLISH | CONFIRM:
+- {
+- cb_log(3, stack->port, "%% GOT L2 Activate Info.\n");
+-
+- if (stack->ptp && stack->l2link) {
+- cb_log(0, stack->port, "%% GOT L2 Activate Info. but we're activated already.. this l2 is faulty, blocking port\n");
+- cb_event(EVENT_PORT_ALARM, &stack->bc[0], glob_mgr->user_data);
+- }
+
+- if (stack->ptp && !stack->restart_sent) {
+- /* make sure we restart the interface of the
+- * other side */
+- stack->restart_sent=1;
+- misdn_lib_send_restart(stack->port, -1);
++ free_msg(msg);
++ return 0;
+
+- }
+-
+- /* when we get the L2 UP, the L1 is UP definitely too*/
+- stack->l2link = 1;
+- stack->l2upcnt=0;
+-
+- free_msg(msg);
+- return 0;
++ case DL_ESTABLISH | INDICATION:
++ case DL_ESTABLISH | CONFIRM:
++ cb_log(3, stack->port, "%% GOT L2 Activate Info.\n");
++
++ if (stack->ptp && stack->l2link) {
++ cb_log(0, stack->port, "%% GOT L2 Activate Info. but we're activated already.. this l2 is faulty, blocking port\n");
++ cb_event(EVENT_PORT_ALARM, &stack->bc[0], glob_mgr->user_data);
+ }
+- break;
+
++ if (stack->ptp && !stack->restart_sent) {
++ /* make sure we restart the interface of the
++ * other side */
++ stack->restart_sent=1;
++ misdn_lib_send_restart(stack->port, -1);
+
+- case DL_RELEASE | INDICATION:
+- case DL_RELEASE | CONFIRM:
+- {
+- if (stack->ptp) {
+- cb_log(3 , stack->port, "%% GOT L2 DeActivate Info.\n");
++ }
+
+- if (stack->l2upcnt>3) {
+- cb_log(0 , stack->port, "!!! Could not Get the L2 up after 3 Attempts!!!\n");
+- } else {
++ /* when we get the L2 UP, the L1 is UP definitely too*/
++ stack->l2link = 1;
++ stack->l2upcnt=0;
++
++ free_msg(msg);
++ return 0;
++
++ case DL_RELEASE | INDICATION:
++ case DL_RELEASE | CONFIRM:
++ if (stack->ptp) {
++ cb_log(3 , stack->port, "%% GOT L2 DeActivate Info.\n");
++
++ if (stack->l2upcnt>3) {
++ cb_log(0 , stack->port, "!!! Could not Get the L2 up after 3 Attempts!!!\n");
++ } else {
+ #if 0
+- if (stack->nt) misdn_lib_reinit_nt_stack(stack->port);
++ if (stack->nt)
++ misdn_lib_reinit_nt_stack(stack->port);
+ #endif
+- if (stack->l1link) {
+- misdn_lib_get_l2_up(stack);
+- stack->l2upcnt++;
+- }
++ if (stack->l1link) {
++ misdn_lib_get_l2_up(stack);
++ stack->l2upcnt++;
+ }
+-
+- } else
+- cb_log(3, stack->port, "%% GOT L2 DeActivate Info.\n");
+-
+- stack->l2link = 0;
+- free_msg(msg);
+- return 0;
+- }
++ }
++
++ } else
++ cb_log(3, stack->port, "%% GOT L2 DeActivate Info.\n");
++
++ stack->l2link = 0;
++ free_msg(msg);
++ return 0;
++
++ default:
+ break;
+- }
+ }
+-
+- {
+- /* Parse Events and fire_up to App. */
+- struct misdn_bchannel *bc;
+- struct misdn_bchannel dummybc;
+-
+- enum event_e event = isdn_msg_get_event(msgs_g, msg, 1);
+-
+- bc=find_bc_by_l3id(stack, hh->dinfo);
+-
+- if (!bc) {
+- cb_log(4, stack->port, " --> Didn't find BC so temporarily creating dummy BC (l3id:%x).\n", hh->dinfo);
+- misdn_make_dummy(&dummybc, stack->port, hh->dinfo, stack->nt, 0);
+- bc=&dummybc;
++
++ /* Parse Events and fire_up to App. */
++ event = isdn_msg_get_event(msgs_g, msg, 1);
++
++ bc = find_bc_by_l3id(stack, hh->dinfo);
++ if (!bc) {
++ cb_log(4, stack->port, " --> Didn't find BC so temporarily creating dummy BC (l3id:%x).\n", hh->dinfo);
++ misdn_make_dummy(&dummybc, stack->port, hh->dinfo, stack->nt, 0);
++ bc = &dummybc;
++ }
++
++ isdn_msg_parse_event(msgs_g, msg, bc, 1);
++
++ switch (event) {
++ case EVENT_SETUP:
++ if (bc->channel <= 0 || bc->channel == 0xff) {
++ bc->channel = 0;
+ }
+- if (bc ) {
+- isdn_msg_parse_event(msgs_g,msg,bc, 1);
+
+- switch (event) {
+- case EVENT_SETUP:
+- if (bc->channel<=0 || bc->channel==0xff)
+- bc->channel=0;
+-
+- if (find_free_chan_in_stack(stack,bc, bc->channel,0)<0)
+- goto ERR_NO_CHANNEL;
+- break;
+- case EVENT_RELEASE:
+- case EVENT_RELEASE_COMPLETE:
+- {
+- int channel=bc->channel;
+- int tmpcause=bc->cause;
+- empty_bc(bc);
+- bc->cause=tmpcause;
+- clean_up_bc(bc);
++ if (find_free_chan_in_stack(stack, bc, bc->channel, 0) < 0) {
++ goto ERR_NO_CHANNEL;
++ }
++ break;
++ case EVENT_RELEASE:
++ case EVENT_RELEASE_COMPLETE:
++ channel = bc->channel;
++ tmpcause = bc->cause;
+
+- if (channel>0)
+- empty_chan_in_stack(stack,channel);
+- bc->in_use=0;
+- }
+- break;
++ empty_bc(bc);
++ bc->cause = tmpcause;
++ clean_up_bc(bc);
+
+- default:
++ if (channel > 0)
++ empty_chan_in_stack(stack, channel);
++ bc->in_use = 0;
++ break;
++ default:
++ break;
++ }
++
++ if(!isdn_get_info(msgs_g, event, 1)) {
++ cb_log(4, stack->port, "Unknown Event Ind: prim %x dinfo %x\n", hh->prim, hh->dinfo);
++ } else {
++ if (reject) {
++ switch(bc->cause) {
++ case AST_CAUSE_USER_BUSY:
++ cb_log(1, stack->port, "Siemens Busy reject..\n");
+ break;
++ default:
++ break;
+ }
+-
+- if(!isdn_get_info(msgs_g,event,1)) {
+- cb_log(4, stack->port, "Unknown Event Ind: prim %x dinfo %x\n",hh->prim, hh->dinfo);
+- } else {
+- if (reject) {
+- switch(bc->cause){
+- case AST_CAUSE_USER_BUSY:
+- cb_log(1, stack->port, "Siemens Busy reject..\n");
+-
+- break;
+- default:
+- break;
+- }
+- }
+- cb_event(event, bc, glob_mgr->user_data);
+- }
+- } else {
+- cb_log(4, stack->port, "No BC found with l3id: prim %x dinfo %x\n",hh->prim, hh->dinfo);
+ }
+-
+- free_msg(msg);
++ cb_event(event, bc, glob_mgr->user_data);
+ }
+
++ free_msg(msg);
++ return 0;
+
++ERR_NO_CHANNEL:
++ cb_log(4, stack->port, "Patch from MEIDANIS:Sending RELEASE_COMPLETE %x (No free Chan for you..)\n", hh->dinfo);
++ dmsg = create_l3msg(CC_RELEASE_COMPLETE | REQUEST, MT_RELEASE_COMPLETE, hh->dinfo, sizeof(RELEASE_COMPLETE_t), 1);
++ stack->nst.manager_l3(&stack->nst, dmsg);
++ free_msg(msg);
+ return 0;
+ }
+
+@@ -2161,8 +2247,8 @@
+ static int handle_timers(msg_t* msg)
+ {
+ iframe_t *frm= (iframe_t*)msg->data;
+- struct misdn_stack *stack;
+-
++ struct misdn_stack *stack;
++
+ /* Timer Stuff */
+ switch (frm->prim) {
+ case MGR_INITTIMER | CONFIRM:
+@@ -2172,17 +2258,17 @@
+ free_msg(msg);
+ return(1);
+ }
+-
+-
+-
++
++
++
+ if (frm->prim==(MGR_TIMER | INDICATION) ) {
+ for (stack = glob_mgr->stack_list;
+ stack;
+ stack = stack->next) {
+ itimer_t *it;
+-
++
+ if (!stack->nt) continue;
+-
++
+ it = stack->nst.tlist;
+ /* find timer */
+ for(it=stack->nst.tlist;
+@@ -2201,12 +2287,12 @@
+ return 1;
+ }
+ }
+-
++
+ cb_log(0, 0, "Timer Msg without Timer ??\n");
+ free_msg(msg);
+ return 1;
+ }
+-
++
+ return 0;
+ }
+
+@@ -2226,23 +2312,23 @@
+ static int do_tone(struct misdn_bchannel *bc, int len)
+ {
+ bc->tone_cnt=len;
+-
++
+ if (bc->generate_tone) {
+ cb_event(EVENT_TONE_GENERATE, bc, glob_mgr->user_data);
+-
++
+ if ( !bc->nojitter ) {
+ misdn_tx_jitter(bc,len);
+ }
+-
++
+ return 1;
+ }
+-
++
+ return 0;
+ }
+
+
+ #ifdef MISDN_SAVE_DATA
+-static void misdn_save_data(int id, char *p1, int l1, char *p2, int l2)
++static void misdn_save_data(int id, char *p1, int l1, char *p2, int l2)
+ {
+ char n1[32],n2[32];
+ FILE *rx, *tx;
+@@ -2250,17 +2336,21 @@
+ sprintf(n1,"/tmp/misdn-rx-%d.raw",id);
+ sprintf(n2,"/tmp/misdn-tx-%d.raw",id);
+
+- rx = fopen(n1,"a+");
++ rx = fopen(n1,"a+");
+ tx = fopen(n2,"a+");
+
+ if (!rx || !tx) {
+ cb_log(0,0,"Couldn't open files: %s\n",strerror(errno));
++ if (rx)
++ fclose(rx);
++ if (tx)
++ fclose(tx);
+ return ;
+ }
+-
++
+ fwrite(p1,1,l1,rx);
+ fwrite(p2,1,l2,tx);
+-
++
+ fclose(rx);
+ fclose(tx);
+
+@@ -2273,25 +2363,25 @@
+ char *data=&buf[mISDN_HEADER_LEN];
+ iframe_t *txfrm= (iframe_t*)buf;
+ int jlen, r;
+-
++
+ jlen=cb_jb_empty(bc,data,len);
+-
++
+ if (jlen) {
+ #ifdef MISDN_SAVE_DATA
+ misdn_save_data((bc->port*100+bc->channel), data, jlen, bc->bframe, bc->bframe_len);
+ #endif
+ flip_buf_bits( data, jlen);
+-
++
+ if (jlen < len) {
+ cb_log(1, bc->port, "Jitterbuffer Underrun. Got %d of expected %d\n", jlen, len);
+ }
+-
++
+ txfrm->prim = DL_DATA|REQUEST;
+-
++
+ txfrm->dinfo = 0;
+-
++
+ txfrm->addr = bc->addr|FLG_MSG_DOWN; /* | IF_DOWN; */
+-
++
+ txfrm->len =jlen;
+ cb_log(9, bc->port, "Transmitting %d samples 2 misdn\n", txfrm->len);
+
+@@ -2337,25 +2427,25 @@
+ iframe_t *frm= (iframe_t*)msg->data;
+ struct misdn_bchannel *bc=find_bc_by_addr(frm->addr);
+ struct misdn_stack *stack;
+-
++
+ if (!bc) {
+ cb_log(1,0,"handle_bchan: BC not found for prim:%x with addr:%x dinfo:%x\n", frm->prim, frm->addr, frm->dinfo);
+ return 0 ;
+ }
+-
++
+ stack = get_stack_by_bc(bc);
+-
++
+ if (!stack) {
+ cb_log(0, bc->port,"handle_bchan: STACK not found for prim:%x with addr:%x dinfo:%x\n", frm->prim, frm->addr, frm->dinfo);
+ return 0;
+ }
+-
++
+ switch (frm->prim) {
+
+ case MGR_SETSTACK| CONFIRM:
+ cb_log(3, stack->port, "BCHAN: MGR_SETSTACK|CONFIRM pid:%d\n",bc->pid);
+ break;
+-
++
+ case MGR_SETSTACK| INDICATION:
+ cb_log(3, stack->port, "BCHAN: MGR_SETSTACK|IND pid:%d\n",bc->pid);
+ break;
+@@ -2368,9 +2458,9 @@
+ usleep(1000);
+ goto AGAIN;
+ }
+-
++
+ cb_log(0,stack->port,"$$$ Get Layer (%d) Id Error: %s\n",bc->layer,strerror(errno));
+-
++
+ /* we kill the channel later, when we received some
+ data. */
+ bc->addr= frm->addr;
+@@ -2378,12 +2468,12 @@
+ cb_log(0, stack->port,"$$$ bc->addr <0 Error:%s\n",strerror(errno));
+ bc->addr=0;
+ }
+-
++
+ cb_log(4, stack->port," --> Got Adr %x\n", bc->addr);
+
+ free_msg(msg);
+-
+-
++
++
+ switch(bc->bc_state) {
+ case BCHAN_SETUP:
+ bc_state_change(bc,BCHAN_SETUPED);
+@@ -2400,31 +2490,31 @@
+ case MGR_DELLAYER| INDICATION:
+ cb_log(3, stack->port, "BCHAN: MGR_DELLAYER|IND pid:%d\n",bc->pid);
+ break;
+-
++
+ case MGR_DELLAYER| CONFIRM:
+ cb_log(3, stack->port, "BCHAN: MGR_DELLAYER|CNF pid:%d\n",bc->pid);
+-
++
+ bc->pid=0;
+ bc->addr=0;
+-
++
+ free_msg(msg);
+ return 1;
+-
++
+ case PH_ACTIVATE | INDICATION:
+ case DL_ESTABLISH | INDICATION:
+ cb_log(3, stack->port, "BCHAN: ACT Ind pid:%d\n", bc->pid);
+
+ free_msg(msg);
+- return 1;
++ return 1;
+
+ case PH_ACTIVATE | CONFIRM:
+ case DL_ESTABLISH | CONFIRM:
+-
++
+ cb_log(3, stack->port, "BCHAN: bchan ACT Confirm pid:%d\n",bc->pid);
+ free_msg(msg);
+-
+- return 1;
+
++ return 1;
++
+ case DL_ESTABLISH | REQUEST:
+ {
+ char buf[128];
+@@ -2440,33 +2530,40 @@
+ }
+ free_msg(msg);
+ return 1;
+-
++
+ case PH_DEACTIVATE | INDICATION:
+ case DL_RELEASE | INDICATION:
+ cb_log (3, stack->port, "BCHAN: DeACT Ind pid:%d\n",bc->pid);
+-
++
+ free_msg(msg);
+ return 1;
+-
++
+ case PH_DEACTIVATE | CONFIRM:
+ case DL_RELEASE | CONFIRM:
+ cb_log(3, stack->port, "BCHAN: DeACT Conf pid:%d\n",bc->pid);
+-
++
+ free_msg(msg);
+ return 1;
+-
++
+ case PH_CONTROL|INDICATION:
+ {
+ unsigned int *cont = (unsigned int *) &frm->data.p;
+-
+- cb_log(4, stack->port, "PH_CONTROL: channel:%d oad%d:%s dad%d:%s \n", bc->channel, bc->onumplan,bc->oad, bc->dnumplan,bc->dad);
+
++ cb_log(4, stack->port,
++ "PH_CONTROL: channel:%d caller%d:\"%s\" <%s> dialed%d:%s \n",
++ bc->channel,
++ bc->caller.number_type,
++ bc->caller.name,
++ bc->caller.number,
++ bc->dialed.number_type,
++ bc->dialed.number);
++
+ if ((*cont & ~DTMF_TONE_MASK) == DTMF_TONE_VAL) {
+ int dtmf = *cont & DTMF_TONE_MASK;
+ cb_log(4, stack->port, " --> DTMF TONE: %c\n",dtmf);
+ bc->dtmf=dtmf;
+ cb_event(EVENT_DTMF_TONE, bc, glob_mgr->user_data);
+-
++
+ free_msg(msg);
+ return 1;
+ }
+@@ -2487,11 +2584,11 @@
+ case DL_DATA|REQUEST:
+ cb_log(0, stack->port, "DL_DATA REQUEST \n");
+ do_tone(bc, 64);
+-
++
+ free_msg(msg);
+ return 1;
+-
+-
++
++
+ case PH_DATA|INDICATION:
+ case DL_DATA|INDICATION:
+ {
+@@ -2499,10 +2596,10 @@
+ bc->bframe_len = frm->len;
+
+ /** Anyway flip the bufbits **/
+- if ( misdn_cap_is_speech(bc->capability) )
++ if ( misdn_cap_is_speech(bc->capability) )
+ flip_buf_bits(bc->bframe, bc->bframe_len);
+-
+
++
+ if (!bc->bframe_len) {
+ cb_log(2, stack->port, "DL_DATA INDICATION bc->addr:%x frm->addr:%x\n", bc->addr, frm->addr);
+ free_msg(msg);
+@@ -2514,12 +2611,12 @@
+ free_msg(msg);
+ return 1;
+ }
+-
++
+ #if MISDN_DEBUG
+ cb_log(0, stack->port, "DL_DATA INDICATION Len %d\n", frm->len);
+
+ #endif
+-
++
+ if ( (bc->bc_state == BCHAN_ACTIVATED) && frm->len > 0) {
+ int t;
+
+@@ -2533,7 +2630,7 @@
+ #endif
+ if ( !t ) {
+ int i;
+-
++
+ if ( misdn_cap_is_speech(bc->capability)) {
+ if ( !bc->nojitter ) {
+ #ifdef MISDN_B_DEBUG
+@@ -2546,15 +2643,15 @@
+ }
+ }
+
+-#ifdef MISDN_B_DEBUG
++#ifdef MISDN_B_DEBUG
+ cb_log(0,bc->port,"EVENT_B_DATA START\n");
+ #endif
+-
++
+ i = cb_event(EVENT_BCHAN_DATA, bc, glob_mgr->user_data);
+-#ifdef MISDN_B_DEBUG
++#ifdef MISDN_B_DEBUG
+ cb_log(0,bc->port,"EVENT_B_DATA STOP\n");
+ #endif
+-
++
+ if (i<0) {
+ cb_log(10,stack->port,"cb_event returned <0\n");
+ /*clean_up_bc(bc);*/
+@@ -2587,7 +2684,7 @@
+ #endif
+ break;
+ }
+-
++
+ return 0;
+ }
+
+@@ -2601,187 +2698,173 @@
+
+ stack=find_stack_by_addr( frm->addr );
+
+-
+-
++
++
+ if (!stack || !stack->nt) {
+ return 0;
+ }
+
+-
++
+ if ((err=stack->nst.l1_l2(&stack->nst,msg))) {
+-
++
+ if (nt_err_cnt > 0 ) {
+ if (nt_err_cnt < 100) {
+- nt_err_cnt++;
++ nt_err_cnt++;
+ cb_log(0, stack->port, "NT Stack sends us error: %d \n", err);
+ } else if (nt_err_cnt < 105){
+ cb_log(0, stack->port, "NT Stack sends us error: %d over 100 times, so I'll stop this message\n", err);
+- nt_err_cnt = - 1;
++ nt_err_cnt = - 1;
+ }
+ }
+ free_msg(msg);
+ return 1;
+-
++
+ }
+-
++
+ return 1;
+ }
+
+
+ static int handle_frm(msg_t *msg)
+ {
+- iframe_t *frm = (iframe_t*) msg->data;
+-
+- struct misdn_stack *stack=find_stack_by_addr(frm->addr);
++ struct misdn_bchannel dummybc;
++ struct misdn_bchannel *bc;
++ iframe_t *frm;
++ struct misdn_stack *stack;
++ enum event_e event;
++ enum event_response_e response;
++ int ret;
++ int channel;
++ int tmpcause;
++ int tmp_out_cause;
+
++ frm = (iframe_t*) msg->data;
++ stack = find_stack_by_addr(frm->addr);
+ if (!stack || stack->nt) {
+ return 0;
+ }
+-
+- cb_log(4,stack?stack->port:0,"handle_frm: frm->addr:%x frm->prim:%x\n",frm->addr,frm->prim);
+
+- {
+- struct misdn_bchannel dummybc;
+- struct misdn_bchannel *bc;
+- int ret=handle_cr(stack, frm);
++ cb_log(4, stack ? stack->port : 0, "handle_frm: frm->addr:%x frm->prim:%x\n", frm->addr, frm->prim);
+
+- if (ret<0) {
+- cb_log(3,stack?stack->port:0,"handle_frm: handle_cr <0 prim:%x addr:%x\n", frm->prim, frm->addr);
++ ret = handle_cr(stack, frm);
++ if (ret < 0) {
++ cb_log(3, stack ? stack->port : 0, "handle_frm: handle_cr <0 prim:%x addr:%x\n", frm->prim, frm->addr);
++ }
++ if (ret) {
++ free_msg(msg);
++ return 1;
++ }
+
++ bc = find_bc_by_l3id(stack, frm->dinfo);
++ if (!bc) {
++ misdn_make_dummy(&dummybc, stack->port, 0, stack->nt, 0);
++ switch (frm->prim) {
++ case CC_RESTART | CONFIRM:
++ dummybc.l3_id = MISDN_ID_GLOBAL;
++ bc = &dummybc;
++ break;
++ case CC_SETUP | INDICATION:
++ dummybc.l3_id = frm->dinfo;
++ bc = &dummybc;
+
+- }
++ misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
+
+- if(ret) {
+ free_msg(msg);
+ return 1;
++ default:
++ if (frm->prim == (CC_FACILITY | INDICATION)) {
++ cb_log(5, stack->port, " --> Using Dummy BC for FACILITY\n");
++ } else {
++ cb_log(0, stack->port, " --> Didn't find BC so temporarily creating dummy BC (l3id:%x) on this port.\n", frm->dinfo);
++ dummybc.l3_id = frm->dinfo;
++ }
++ bc = &dummybc;
++ break;
+ }
+-
+- bc=find_bc_by_l3id(stack, frm->dinfo);
++ }
+
+- if (!bc && (frm->prim==(CC_RESTART|CONFIRM)) ) {
+- misdn_make_dummy(&dummybc, stack->port, MISDN_ID_GLOBAL, stack->nt, 0);
+- bc=&dummybc;
+- }
++ event = isdn_msg_get_event(msgs_g, msg, 0);
++ isdn_msg_parse_event(msgs_g, msg, bc, 0);
+
+- if (!bc && (frm->prim==(CC_SETUP|INDICATION)) ) {
+- misdn_make_dummy(&dummybc, stack->port, MISDN_ID_GLOBAL, stack->nt, 0);
+- dummybc.port=stack->port;
+- dummybc.l3_id=frm->dinfo;
+- bc=&dummybc;
++ /* Preprocess some Events */
++ ret = handle_event(bc, event, frm);
++ if (ret < 0) {
++ cb_log(0, stack->port, "couldn't handle event\n");
++ free_msg(msg);
++ return 1;
++ }
+
+- misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
++ /* shoot up event to App: */
++ cb_log(5, stack->port, "lib Got Prim: Addr %x prim %x dinfo %x\n", frm->addr, frm->prim, frm->dinfo);
+
+- free_msg(msg);
+- return 1;
+- }
++ if (!isdn_get_info(msgs_g, event, 0)) {
++ cb_log(0, stack->port, "Unknown Event Ind: Addr:%x prim %x dinfo %x\n", frm->addr, frm->prim, frm->dinfo);
++ response = RESPONSE_OK;
++ } else {
++ response = cb_event(event, bc, glob_mgr->user_data);
++ }
+
+-
+-handle_frm_bc:
+- if (bc ) {
+- enum event_e event = isdn_msg_get_event(msgs_g, msg, 0);
+- enum event_response_e response=RESPONSE_OK;
+- int ret;
+-
+- isdn_msg_parse_event(msgs_g,msg,bc, 0);
+-
+- /** Preprocess some Events **/
+- ret = handle_event(bc, event, frm);
+- if (ret<0) {
+- cb_log(0,stack->port,"couldn't handle event\n");
+- free_msg(msg);
+- return 1;
++ switch (event) {
++ case EVENT_SETUP:
++ switch (response) {
++ case RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE:
++ cb_log(0, stack->port, "TOTALLY IGNORING SETUP\n");
++ break;
++ case RESPONSE_IGNORE_SETUP:
++ /* I think we should send CC_RELEASE_CR, but am not sure*/
++ bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
++ /* fall through */
++ case RESPONSE_RELEASE_SETUP:
++ misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
++ if (bc->channel > 0) {
++ empty_chan_in_stack(stack, bc->channel);
+ }
+- /* shoot up event to App: */
+- cb_log(5, stack->port, "lib Got Prim: Addr %x prim %x dinfo %x\n",frm->addr, frm->prim, frm->dinfo);
+-
+- if(!isdn_get_info(msgs_g,event,0))
+- cb_log(0, stack->port, "Unknown Event Ind: Addr:%x prim %x dinfo %x\n",frm->addr, frm->prim, frm->dinfo);
+- else
+- response=cb_event(event, bc, glob_mgr->user_data);
+-#if 1
+- if (event == EVENT_SETUP) {
+- switch (response) {
+- case RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE:
++ empty_bc(bc);
++ bc_state_change(bc, BCHAN_CLEANED);
++ bc->in_use = 0;
+
+- cb_log(0, stack->port, "TOTALLY IGNORING SETUP\n");
+-
+- break;
+- case RESPONSE_IGNORE_SETUP:
+- /* I think we should send CC_RELEASE_CR, but am not sure*/
+- bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
+-
+- case RESPONSE_RELEASE_SETUP:
+- misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
+- if (bc->channel>0)
+- empty_chan_in_stack(stack, bc->channel);
+- empty_bc(bc);
+- bc_state_change(bc,BCHAN_CLEANED);
+- bc->in_use=0;
++ cb_log(0, stack->port, "GOT IGNORE SETUP\n");
++ break;
++ case RESPONSE_OK:
++ cb_log(4, stack->port, "GOT SETUP OK\n");
++ break;
++ default:
++ break;
++ }
++ break;
++ case EVENT_RELEASE_COMPLETE:
++ /* release bchannel only after we've announced the RELEASE_COMPLETE */
++ channel = bc->channel;
++ tmpcause = bc->cause;
++ tmp_out_cause = bc->out_cause;
+
+- cb_log(0, stack->port, "GOT IGNORE SETUP\n");
+- break;
+- case RESPONSE_OK:
+- cb_log(4, stack->port, "GOT SETUP OK\n");
++ empty_bc(bc);
++ bc->cause = tmpcause;
++ bc->out_cause = tmp_out_cause;
++ clean_up_bc(bc);
+
+-
+- break;
+- default:
+- break;
+- }
+- }
+-
+- if (event == EVENT_RELEASE_COMPLETE) {
+- /* release bchannel only after we've announced the RELEASE_COMPLETE */
+- int channel=bc->channel;
+- int tmpcause=bc->cause;
+- int tmp_out_cause=bc->out_cause;
+- empty_bc(bc);
+- bc->cause=tmpcause;
+- bc->out_cause=tmp_out_cause;
+- clean_up_bc(bc);
+-
+- if (tmpcause == AST_CAUSE_REQUESTED_CHAN_UNAVAIL) {
+- cb_log(0,stack->port,"**** Received CAUSE:%d, so not cleaning up channel %d\n", AST_CAUSE_REQUESTED_CHAN_UNAVAIL, channel);
+- cb_log(0,stack->port,"**** This channel is now no longer available,\nplease try to restart it with 'misdn send restart <port> <channel>'\n");
+- set_chan_in_stack(stack, channel);
+- bc->channel=channel;
+- misdn_lib_send_restart(stack->port, channel);
+- } else {
+- if (channel>0)
+- empty_chan_in_stack(stack, channel);
+- }
+- bc->in_use=0;
+- }
+-
+- if (event == EVENT_RESTART) {
+- cb_log(0, stack->port, "**** Received RESTART_ACK channel:%d\n", bc->restart_channel);
+- empty_chan_in_stack(stack, bc->restart_channel);
+- }
+-
+- cb_log(5, stack->port, "Freeing Msg on prim:%x \n",frm->prim);
+-
+-
+- free_msg(msg);
+- return 1;
+-#endif
+-
+- } else {
+- struct misdn_bchannel dummybc;
+- if (frm->prim!=(CC_FACILITY|INDICATION))
+- cb_log(0, stack->port, " --> Didn't find BC so temporarily creating dummy BC (l3id:%x) on this port.\n", frm->dinfo);
+- else
+- cb_log(5, stack->port, " --> Using Dummy BC for FACILITY\n");
+-
+- memset (&dummybc,0,sizeof(dummybc));
+- dummybc.port=stack->port;
+- dummybc.l3_id=frm->dinfo;
+- bc=&dummybc;
+- goto handle_frm_bc;
++ if (tmpcause == AST_CAUSE_REQUESTED_CHAN_UNAVAIL) {
++ cb_log(0, stack->port, "**** Received CAUSE:%d, so not cleaning up channel %d\n", AST_CAUSE_REQUESTED_CHAN_UNAVAIL, channel);
++ cb_log(0, stack->port, "**** This channel is now no longer available,\nplease try to restart it with 'misdn send restart <port> <channel>'\n");
++ set_chan_in_stack(stack, channel);
++ bc->channel = channel;
++ misdn_lib_send_restart(stack->port, channel);
++ } else if (channel > 0) {
++ empty_chan_in_stack(stack, channel);
+ }
++ bc->in_use = 0;
++ break;
++ case EVENT_RESTART:
++ cb_log(0, stack->port, "**** Received RESTART_ACK channel:%d\n", bc->restart_channel);
++ empty_chan_in_stack(stack, bc->restart_channel);
++ break;
++ default:
++ break;
+ }
+
+- cb_log(4, stack->port, "TE_FRM_HANDLER: Returning 0 on prim:%x \n",frm->prim);
+- return 0;
++ cb_log(5, stack->port, "Freeing Msg on prim:%x \n", frm->prim);
++ free_msg(msg);
++ return 1;
+ }
+
+
+@@ -2790,7 +2873,7 @@
+ iframe_t *frm = (iframe_t*) msg->data;
+ struct misdn_stack *stack = find_stack_by_addr(frm->addr);
+ int i ;
+-
++
+ if (!stack) return 0 ;
+
+ switch (frm->prim) {
+@@ -2798,9 +2881,9 @@
+ case PH_ACTIVATE | INDICATION:
+ cb_log (3, stack->port, "L1: PH L1Link Up!\n");
+ stack->l1link=1;
+-
++
+ if (stack->nt) {
+-
++
+ if (stack->nst.l1_l2(&stack->nst, msg))
+ free_msg(msg);
+
+@@ -2809,14 +2892,14 @@
+ } else {
+ free_msg(msg);
+ }
+-
++
+ for (i=0;i<=stack->b_num; i++) {
+ if (stack->bc[i].evq != EVENT_NOTHING) {
+ cb_log(4, stack->port, "Firing Queued Event %s because L1 got up\n", isdn_get_info(msgs_g, stack->bc[i].evq, 0));
+ misdn_lib_send_event(&stack->bc[i],stack->bc[i].evq);
+ stack->bc[i].evq=EVENT_NOTHING;
+ }
+-
++
+ }
+ return 1;
+
+@@ -2824,16 +2907,16 @@
+ free_msg(msg);
+ cb_log(3,stack->port,"L1: PH_ACTIVATE|REQUEST \n");
+ return 1;
+-
++
+ case PH_DEACTIVATE | REQUEST:
+ free_msg(msg);
+ cb_log(3,stack->port,"L1: PH_DEACTIVATE|REQUEST \n");
+ return 1;
+-
++
+ case PH_DEACTIVATE | CONFIRM:
+ case PH_DEACTIVATE | INDICATION:
+ cb_log (3, stack->port, "L1: PH L1Link Down! \n");
+-
++
+ #if 0
+ for (i=0; i<=stack->b_num; i++) {
+ if (global_state == MISDN_INITIALIZED) {
+@@ -2841,19 +2924,19 @@
+ }
+ }
+ #endif
+-
++
+ if (stack->nt) {
+ if (stack->nst.l1_l2(&stack->nst, msg))
+ free_msg(msg);
+ } else {
+ free_msg(msg);
+ }
+-
++
+ stack->l1link=0;
+ stack->l2link=0;
+ return 1;
+ }
+-
++
+ return 0;
+ }
+
+@@ -2862,11 +2945,11 @@
+ iframe_t *frm = (iframe_t*) msg->data;
+
+ struct misdn_stack *stack = find_stack_by_addr(frm->addr);
+-
++
+ if (!stack) {
+ return 0 ;
+ }
+-
++
+ switch(frm->prim) {
+
+ case DL_ESTABLISH | REQUEST:
+@@ -2875,13 +2958,13 @@
+ case DL_RELEASE | REQUEST:
+ cb_log(1,stack->port,"DL_RELEASE|REQUEST \n");
+ return 1;
+-
++
+ case DL_ESTABLISH | INDICATION:
+ case DL_ESTABLISH | CONFIRM:
+ {
+ cb_log (3, stack->port, "L2: L2Link Up! \n");
+ if (stack->ptp && stack->l2link) {
+- cb_log (-1, stack->port, "L2: L2Link Up! but it's already UP.. must be faulty, blocking port\n");
++ cb_log (-1, stack->port, "L2: L2Link Up! but it's already UP.. must be faulty, blocking port\n");
+ cb_event(EVENT_PORT_ALARM, &stack->bc[0], glob_mgr->user_data);
+ }
+ stack->l2link=1;
+@@ -2889,13 +2972,13 @@
+ return 1;
+ }
+ break;
+-
++
+ case DL_RELEASE | INDICATION:
+ case DL_RELEASE | CONFIRM:
+ {
+ cb_log (3, stack->port, "L2: L2Link Down! \n");
+ stack->l2link=0;
+-
++
+ free_msg(msg);
+ return 1;
+ }
+@@ -2914,9 +2997,9 @@
+ free_msg(msg);
+ return 1;
+ }
+-
++
+ stack = find_stack_by_addr(frm->addr);
+-
++
+ if (!stack) {
+ if (frm->prim == (MGR_DELLAYER|CONFIRM)) {
+ cb_log(2, 0, "MGMT: DELLAYER|CONFIRM Addr: %x !\n",
+@@ -2924,20 +3007,20 @@
+ free_msg(msg);
+ return 1;
+ }
+-
++
+ return 0;
+ }
+-
++
+ switch(frm->prim) {
+ case MGR_SHORTSTATUS | INDICATION:
+ case MGR_SHORTSTATUS | CONFIRM:
+ cb_log(5, 0, "MGMT: Short status dinfo %x\n",frm->dinfo);
+-
++
+ switch (frm->dinfo) {
+ case SSTATUS_L1_ACTIVATED:
+ cb_log(3, 0, "MGMT: SSTATUS: L1_ACTIVATED \n");
+ stack->l1link=1;
+-
++
+ break;
+ case SSTATUS_L1_DEACTIVATED:
+ cb_log(3, 0, "MGMT: SSTATUS: L1_DEACTIVATED \n");
+@@ -2951,16 +3034,16 @@
+ cb_log(3, stack->port, "MGMT: SSTATUS: L2_ESTABLISH \n");
+ stack->l2link=1;
+ break;
+-
++
+ case SSTATUS_L2_RELEASED:
+ cb_log(3, stack->port, "MGMT: SSTATUS: L2_RELEASED \n");
+ stack->l2link=0;
+ break;
+ }
+-
++
+ free_msg(msg);
+ return 1;
+-
++
+ case MGR_SETSTACK | INDICATION:
+ cb_log(4, stack->port, "MGMT: SETSTACK|IND dinfo %x\n",frm->dinfo);
+ free_msg(msg);
+@@ -2969,21 +3052,21 @@
+ cb_log(4, stack->port, "MGMT: DELLAYER|CNF dinfo %x\n",frm->dinfo) ;
+ free_msg(msg);
+ return 1;
+-
++
+ }
+-
++
+ /*
+ if ( (frm->prim & 0x0f0000) == 0x0f0000) {
+ cb_log(5, 0, "$$$ MGMT FRAME: prim %x addr %x dinfo %x\n",frm->prim, frm->addr, frm->dinfo) ;
+ free_msg(msg);
+ return 1;
+ } */
+-
++
+ return 0;
+ }
+
+
+-static msg_t *fetch_msg(int midev)
++static msg_t *fetch_msg(int midev)
+ {
+ msg_t *msg=alloc_msg(MAX_MSG_SIZE);
+ int r;
+@@ -2996,7 +3079,7 @@
+ AGAIN:
+ r=mISDN_read(midev,msg->data,MAX_MSG_SIZE, TIMEOUT_10SEC);
+ msg->len=r;
+-
++
+ if (r==0) {
+ free_msg(msg); /* danger, cause usually freeing in main_loop */
+ cb_log(6,0,"Got empty Msg..\n");
+@@ -3010,8 +3093,8 @@
+ usleep(5000);
+ goto AGAIN;
+ }
+-
+- cb_log(0,0,"mISDN_read returned :%d error:%s (%d)\n",r,strerror(errno),errno);
++
++ cb_log(0,0,"mISDN_read returned :%d error:%s (%d)\n",r,strerror(errno),errno);
+ }
+
+ #if 0
+@@ -3029,12 +3112,12 @@
+ ;
+
+ if (stack) {
+- cb_log(4, port, "Checking L1 State\n");
++ cb_log(4, port, "Checking L1 State\n");
+ if (!stack->l1link) {
+- cb_log(4, port, "L1 State Down, trying to get it up again\n");
++ cb_log(4, port, "L1 State Down, trying to get it up again\n");
+ misdn_lib_get_short_status(stack);
+- misdn_lib_get_l1_up(stack);
+- misdn_lib_get_l2_up(stack);
++ misdn_lib_get_l1_up(stack);
++ misdn_lib_get_l2_up(stack);
+ }
+ }
+ }
+@@ -3046,19 +3129,19 @@
+ int zero_frm=0 , fff_frm=0 ;
+ int midev= mgr->midev;
+ int port=0;
+-
++
+ while (1) {
+- msg_t *msg = fetch_msg(midev);
++ msg_t *msg = fetch_msg(midev);
+ iframe_t *frm;
+-
+-
++
++
+ if (!msg) continue;
+-
++
+ frm = (iframe_t*) msg->data;
+-
++
+ /** When we make a call from NT2Ast we get these frames **/
+ if (frm->len == 0 && frm->addr == 0 && frm->dinfo == 0 && frm->prim == 0 ) {
+- zero_frm++;
++ zero_frm++;
+ free_msg(msg);
+ continue;
+ } else {
+@@ -3067,10 +3150,10 @@
+ zero_frm = 0 ;
+ }
+ }
+-
++
+ /** I get this sometimes after setup_bc **/
+ if (frm->len == 0 && frm->dinfo == 0 && frm->prim == 0xffffffff ) {
+- fff_frm++;
++ fff_frm++;
+ free_msg(msg);
+ continue;
+ } else {
+@@ -3079,7 +3162,7 @@
+ fff_frm = 0 ;
+ }
+ }
+-
++
+ manager_isdn_handler(frm, msg);
+ }
+
+@@ -3088,31 +3171,29 @@
+
+ /** App Interface **/
+
+-int te_lib_init(void) {
++static int te_lib_init(void)
++{
+ char buff[1025] = "";
+- iframe_t *frm=(iframe_t*)buff;
+- int midev=mISDN_open();
++ iframe_t *frm = (iframe_t *) buff;
++ int midev;
+ int ret;
+
+- if (midev<=0) return midev;
+-
+-/* create entity for layer 3 TE-mode */
++ midev = mISDN_open();
++ if (midev <= 0) {
++ return midev;
++ }
++
++ /* create entity for layer 3 TE-mode */
+ mISDN_write_frame(midev, buff, 0, MGR_NEWENTITY | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
++
+ ret = mISDN_read_frame(midev, frm, sizeof(iframe_t), 0, MGR_NEWENTITY | CONFIRM, TIMEOUT_1SEC);
+-
+- if (ret < mISDN_HEADER_LEN) {
+- noentity:
+- fprintf(stderr, "cannot request MGR_NEWENTITY from mISDN: %s\n",strerror(errno));
++ entity = frm->dinfo & 0xffff;
++ if (ret < mISDN_HEADER_LEN || !entity) {
++ fprintf(stderr, "cannot request MGR_NEWENTITY from mISDN: %s\n", strerror(errno));
+ exit(-1);
+ }
+-
+- entity = frm->dinfo & 0xffff ;
+-
+- if (!entity)
+- goto noentity;
+
+ return midev;
+-
+ }
+
+ void te_lib_destroy(int midev)
+@@ -3136,14 +3217,14 @@
+ {
+ struct misdn_stack *stack;
+ int i;
+-
++
+ for (stack=glob_mgr->stack_list;
+ stack;
+ stack=stack->next) {
+ for (i=0; i<=stack->b_num; i++)
+ if (stack->bc[i].pid == pid) return &stack->bc[i];
+ }
+-
++
+ return NULL;
+ }
+
+@@ -3158,18 +3239,20 @@
+ static int test_inuse(struct misdn_bchannel *bc)
+ {
+ struct timeval now;
+- gettimeofday(&now, NULL);
++
+ if (!bc->in_use) {
+- if (misdn_lib_port_is_pri(bc->port) && bc->last_used.tv_sec == now.tv_sec ) {
+- cb_log(2,bc->port, "channel with stid:%x for one second still in use! (n:%d lu:%d)\n", bc->b_stid, (int) now.tv_sec, (int) bc->last_used.tv_sec);
++ gettimeofday(&now, NULL);
++ if (bc->last_used.tv_sec == now.tv_sec
++ && misdn_lib_port_is_pri(bc->port)) {
++ cb_log(2, bc->port, "channel with stid:%x for one second still in use! (n:%d lu:%d)\n",
++ bc->b_stid, (int) now.tv_sec, (int) bc->last_used.tv_sec);
+ return 1;
+ }
+-
+
+ cb_log(3,bc->port, "channel with stid:%x not in use!\n", bc->b_stid);
+ return 0;
+ }
+-
++
+ cb_log(2,bc->port, "channel with stid:%x in use!\n", bc->b_stid);
+ return 1;
+ }
+@@ -3195,88 +3278,125 @@
+ #endif
+ }
+
+-struct misdn_bchannel* misdn_lib_get_free_bc(int port, int channel, int inout, int dec)
++struct misdn_bchannel *misdn_lib_get_free_bc(int port, int channel, int inout, int dec)
+ {
+ struct misdn_stack *stack;
+ int i;
+-
++ int maxnum;
++
+ if (channel < 0 || channel > MAX_BCHANS) {
+- cb_log(0,port,"Requested channel out of bounds (%d)\n",channel);
++ cb_log(0, port, "Requested channel out of bounds (%d)\n", channel);
+ return NULL;
+ }
+
+ usleep(1000);
+
+- for (stack=glob_mgr->stack_list; stack; stack=stack->next) {
+-
+- if (stack->port == port) {
+- int maxnum;
++ /* Find the port stack structure */
++ stack = find_stack_by_port(port);
++ if (!stack) {
++ cb_log(0, port, "Port is not configured (%d)\n", port);
++ return NULL;
++ }
+
+- if (stack->blocked) {
+- cb_log(0,port,"Port is blocked\n");
+- return NULL;
+- }
+-
+- if (channel > 0) {
+- if (channel <= stack->b_num) {
+- for (i = 0; i < stack->b_num; i++) {
+- if ( stack->bc[i].channel == channel) {
+- if (test_inuse(&stack->bc[i])) {
+- cb_log(0,port,"Requested channel:%d on port:%d is already in use\n",channel, port);
+- return NULL;
++ if (stack->blocked) {
++ cb_log(0, port, "Port is blocked\n");
++ return NULL;
++ }
+
+- } else {
+- prepare_bc(&stack->bc[i], channel);
+- return &stack->bc[i];
+- }
+- }
++ if (channel > 0) {
++ if (channel <= stack->b_num) {
++ for (i = 0; i < stack->b_num; i++) {
++ if (stack->bc[i].channel == channel) {
++ if (test_inuse(&stack->bc[i])) {
++ cb_log(0, port, "Requested channel:%d on port:%d is already in use\n", channel, port);
++ return NULL;
++ } else {
++ prepare_bc(&stack->bc[i], channel);
++ return &stack->bc[i];
+ }
+- } else {
+- cb_log(0,port,"Requested channel:%d is out of bounds on port:%d\n",channel, port);
+- return NULL;
+ }
+ }
++ } else {
++ cb_log(0, port, "Requested channel:%d is out of bounds on port:%d\n", channel, port);
++ return NULL;
++ }
++ }
+
+- maxnum = inout && !stack->pri && !stack->ptp ? stack->b_num + 1 : stack->b_num;
++ /* Note: channel == 0 here */
++ maxnum = (inout && !stack->pri && !stack->ptp) ? stack->b_num + 1 : stack->b_num;
++ if (dec) {
++ for (i = maxnum - 1; i >= 0; --i) {
++ if (!test_inuse(&stack->bc[i])) {
++ /* 3. channel on bri means CW*/
++ if (!stack->pri && i == stack->b_num) {
++ stack->bc[i].cw = 1;
++ }
+
+- if (dec) {
+- for (i = maxnum-1; i>=0; i--) {
+- if (!test_inuse(&stack->bc[i])) {
+- /* 3. channel on bri means CW*/
+- if (!stack->pri && i==stack->b_num)
+- stack->bc[i].cw=1;
+-
+- prepare_bc(&stack->bc[i], channel);
+- stack->bc[i].dec=1;
+- return &stack->bc[i];
+- }
++ prepare_bc(&stack->bc[i], channel);
++ stack->bc[i].dec = 1;
++ return &stack->bc[i];
++ }
++ }
++ } else {
++ for (i = 0; i < maxnum; ++i) {
++ if (!test_inuse(&stack->bc[i])) {
++ /* 3. channel on bri means CW */
++ if (!stack->pri && i == stack->b_num) {
++ stack->bc[i].cw = 1;
+ }
+- } else {
+- for (i = 0; i <maxnum; i++) {
+- if (!test_inuse(&stack->bc[i])) {
+- /* 3. channel on bri means CW*/
+- if (!stack->pri && i==stack->b_num)
+- stack->bc[i].cw=1;
+
+- prepare_bc(&stack->bc[i], channel);
+- return &stack->bc[i];
+- }
+- }
++ prepare_bc(&stack->bc[i], channel);
++ return &stack->bc[i];
+ }
+-
+- cb_log(1,port,"There is no free channel on port (%d)\n",port);
+- return NULL;
+ }
+ }
+
+- cb_log(0,port,"Port is not configured (%d)\n",port);
++ cb_log(1, port, "There is no free channel on port (%d)\n", port);
+ return NULL;
+ }
+
++#if defined(AST_MISDN_ENHANCEMENTS)
++/*!
++ * \brief Allocate a B channel struct from the REGISTER pool
++ *
++ * \param port Logical port number
++ *
++ * \retval B channel struct on success.
++ * \retval NULL on error.
++ */
++struct misdn_bchannel *misdn_lib_get_register_bc(int port)
++{
++ struct misdn_stack *stack;
++ struct misdn_bchannel *bc;
++ unsigned index;
+
++ /* Find the port stack structure */
++ stack = find_stack_by_port(port);
++ if (!stack) {
++ cb_log(0, port, "Port is not configured (%d)\n", port);
++ return NULL;
++ }
+
++ if (stack->blocked) {
++ cb_log(0, port, "Port is blocked\n");
++ return NULL;
++ }
+
+-/* ******************************************************************* */
++ for (index = MAX_BCHANS + 1; index < ARRAY_LEN(stack->bc); ++index) {
++ bc = &stack->bc[index];
++ if (!test_inuse(bc)) {
++ prepare_bc(bc, 0);
++ bc->need_disconnect = 0;
++ bc->need_release = 0;
++ return bc;
++ }
++ }
++
++ cb_log(1, port, "There is no free REGISTER link on port (%d)\n", port);
++ return NULL;
++}
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
+ /*!
+ * \internal
+ * \brief Convert the facility function enum value into a string.
+@@ -3285,36 +3405,96 @@
+ */
+ static const char *fac2str(enum FacFunction facility)
+ {
+- static const struct {
+- enum FacFunction facility;
++ static const struct {
++ enum FacFunction facility;
+ char *name;
+ } arr[] = {
+ /* *INDENT-OFF* */
+ { Fac_None, "Fac_None" },
+- { Fac_GetSupportedServices, "Fac_GetSupportedServices" },
+- { Fac_Listen, "Fac_Listen" },
+- { Fac_Suspend, "Fac_Suspend" },
+- { Fac_Resume, "Fac_Resume" },
++#if defined(AST_MISDN_ENHANCEMENTS)
++ { Fac_ERROR, "Fac_ERROR" },
++ { Fac_RESULT, "Fac_RESULT" },
++ { Fac_REJECT, "Fac_REJECT" },
++
++ { Fac_ActivationDiversion, "Fac_ActivationDiversion" },
++ { Fac_DeactivationDiversion, "Fac_DeactivationDiversion" },
++ { Fac_ActivationStatusNotificationDiv, "Fac_ActivationStatusNotificationDiv" },
++ { Fac_DeactivationStatusNotificationDiv, "Fac_DeactivationStatusNotificationDiv" },
++ { Fac_InterrogationDiversion, "Fac_InterrogationDiversion" },
++ { Fac_DiversionInformation, "Fac_DiversionInformation" },
++ { Fac_CallDeflection, "Fac_CallDeflection" },
++ { Fac_CallRerouteing, "Fac_CallRerouteing" },
++ { Fac_DivertingLegInformation2, "Fac_DivertingLegInformation2" },
++ { Fac_InterrogateServedUserNumbers, "Fac_InterrogateServedUserNumbers" },
++ { Fac_DivertingLegInformation1, "Fac_DivertingLegInformation1" },
++ { Fac_DivertingLegInformation3, "Fac_DivertingLegInformation3" },
++
++ { Fac_EctExecute, "Fac_EctExecute" },
++ { Fac_ExplicitEctExecute, "Fac_ExplicitEctExecute" },
++ { Fac_RequestSubaddress, "Fac_RequestSubaddress" },
++ { Fac_SubaddressTransfer, "Fac_SubaddressTransfer" },
++ { Fac_EctLinkIdRequest, "Fac_EctLinkIdRequest" },
++ { Fac_EctInform, "Fac_EctInform" },
++ { Fac_EctLoopTest, "Fac_EctLoopTest" },
++
++ { Fac_ChargingRequest, "Fac_ChargingRequest" },
++ { Fac_AOCSCurrency, "Fac_AOCSCurrency" },
++ { Fac_AOCSSpecialArr, "Fac_AOCSSpecialArr" },
++ { Fac_AOCDCurrency, "Fac_AOCDCurrency" },
++ { Fac_AOCDChargingUnit, "Fac_AOCDChargingUnit" },
++ { Fac_AOCECurrency, "Fac_AOCECurrency" },
++ { Fac_AOCEChargingUnit, "Fac_AOCEChargingUnit" },
++
++ { Fac_StatusRequest, "Fac_StatusRequest" },
++
++ { Fac_CallInfoRetain, "Fac_CallInfoRetain" },
++ { Fac_EraseCallLinkageID, "Fac_EraseCallLinkageID" },
++ { Fac_CCBSDeactivate, "Fac_CCBSDeactivate" },
++ { Fac_CCBSErase, "Fac_CCBSErase" },
++ { Fac_CCBSRemoteUserFree, "Fac_CCBSRemoteUserFree" },
++ { Fac_CCBSCall, "Fac_CCBSCall" },
++ { Fac_CCBSStatusRequest, "Fac_CCBSStatusRequest" },
++ { Fac_CCBSBFree, "Fac_CCBSBFree" },
++ { Fac_CCBSStopAlerting, "Fac_CCBSStopAlerting" },
++
++ { Fac_CCBSRequest, "Fac_CCBSRequest" },
++ { Fac_CCBSInterrogate, "Fac_CCBSInterrogate" },
++
++ { Fac_CCNRRequest, "Fac_CCNRRequest" },
++ { Fac_CCNRInterrogate, "Fac_CCNRInterrogate" },
++
++ { Fac_CCBS_T_Call, "Fac_CCBS_T_Call" },
++ { Fac_CCBS_T_Suspend, "Fac_CCBS_T_Suspend" },
++ { Fac_CCBS_T_Resume, "Fac_CCBS_T_Resume" },
++ { Fac_CCBS_T_RemoteUserFree, "Fac_CCBS_T_RemoteUserFree" },
++ { Fac_CCBS_T_Available, "Fac_CCBS_T_Available" },
++
++ { Fac_CCBS_T_Request, "Fac_CCBS_T_Request" },
++
++ { Fac_CCNR_T_Request, "Fac_CCNR_T_Request" },
++
++#else
++
+ { Fac_CFActivate, "Fac_CFActivate" },
+ { Fac_CFDeactivate, "Fac_CFDeactivate" },
+- { Fac_CFInterrogateParameters, "Fac_CFInterrogateParameters" },
+- { Fac_CFInterrogateNumbers, "Fac_CFInterrogateNumbers" },
+ { Fac_CD, "Fac_CD" },
++
+ { Fac_AOCDCurrency, "Fac_AOCDCurrency" },
+ { Fac_AOCDChargingUnit, "Fac_AOCDChargingUnit" },
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
+ /* *INDENT-ON* */
+ };
+-
++
+ unsigned index;
+-
++
+ for (index = 0; index < ARRAY_LEN(arr); ++index) {
+ if (arr[index].facility == facility) {
+ return arr[index].name;
+ }
+- } /* end for */
++ }
+
+ return "unknown";
+-} /* end fac2str() */
++}
+
+ void misdn_lib_log_ies(struct misdn_bchannel *bc)
+ {
+@@ -3326,27 +3506,68 @@
+
+ if (!stack) return;
+
+- cb_log(2, stack->port, " --> channel:%d mode:%s cause:%d ocause:%d rad:%s cad:%s\n", bc->channel, stack->nt?"NT":"TE", bc->cause, bc->out_cause, bc->rad, bc->cad);
+-
+ cb_log(2, stack->port,
+- " --> info_dad:%s onumplan:%c dnumplan:%c rnumplan:%c cpnnumplan:%c\n",
+- bc->info_dad,
+- bc->onumplan>=0?'0'+bc->onumplan:' ',
+- bc->dnumplan>=0?'0'+bc->dnumplan:' ',
+- bc->rnumplan>=0?'0'+bc->rnumplan:' ',
+- bc->cpnnumplan>=0?'0'+bc->cpnnumplan:' '
+- );
+-
++ " --> channel:%d mode:%s cause:%d ocause:%d\n",
++ bc->channel,
++ stack->nt ? "NT" : "TE",
++ bc->cause,
++ bc->out_cause);
++
++ cb_log(2, stack->port,
++ " --> info_dad:%s dialed numtype:%d plan:%d\n",
++ bc->info_dad,
++ bc->dialed.number_type,
++ bc->dialed.number_plan);
++
++ cb_log(2, stack->port,
++ " --> caller:\"%s\" <%s> type:%d plan:%d pres:%d screen:%d\n",
++ bc->caller.name,
++ bc->caller.number,
++ bc->caller.number_type,
++ bc->caller.number_plan,
++ bc->caller.presentation,
++ bc->caller.screening);
++
++ cb_log(2, stack->port,
++ " --> redirecting-from:\"%s\" <%s> type:%d plan:%d pres:%d screen:%d\n",
++ bc->redirecting.from.name,
++ bc->redirecting.from.number,
++ bc->redirecting.from.number_type,
++ bc->redirecting.from.number_plan,
++ bc->redirecting.from.presentation,
++ bc->redirecting.from.screening);
++ cb_log(2, stack->port,
++ " --> redirecting-to:\"%s\" <%s> type:%d plan:%d pres:%d screen:%d\n",
++ bc->redirecting.to.name,
++ bc->redirecting.to.number,
++ bc->redirecting.to.number_type,
++ bc->redirecting.to.number_plan,
++ bc->redirecting.to.presentation,
++ bc->redirecting.to.screening);
++ cb_log(2, stack->port,
++ " --> redirecting reason:%d count:%d\n",
++ bc->redirecting.reason,
++ bc->redirecting.count);
++
++ cb_log(2, stack->port,
++ " --> connected:\"%s\" <%s> type:%d plan:%d pres:%d screen:%d\n",
++ bc->connected.name,
++ bc->connected.number,
++ bc->connected.number_type,
++ bc->connected.number_plan,
++ bc->connected.presentation,
++ bc->connected.screening);
++
+ cb_log(3, stack->port, " --> caps:%s pi:%x keypad:%s sending_complete:%d\n", bearer2str(bc->capability),bc->progress_indicator, bc->keypad, bc->sending_complete);
+- cb_log(4, stack->port, " --> screen:%d --> pres:%d\n",
+- bc->screen, bc->pres);
+-
++
++ cb_log(4, stack->port, " --> set_pres:%d pres:%d\n", bc->set_presentation, bc->presentation);
++
+ cb_log(4, stack->port, " --> addr:%x l3id:%x b_stid:%x layer_id:%x\n", bc->addr, bc->l3_id, bc->b_stid, bc->layer_id);
+-
+- cb_log(4, stack->port, " --> facility:%s out_facility:%s\n",fac2str(bc->fac_in.Function),fac2str(bc->fac_out.Function));
+
++ cb_log(4, stack->port, " --> facility in:%s out:%s\n", fac2str(bc->fac_in.Function), fac2str(bc->fac_out.Function));
++
+ cb_log(5, stack->port, " --> urate:%d rate:%d mode:%d user1:%d\n", bc->urate, bc->rate, bc->mode,bc->user1);
+-
++
+ cb_log(5, stack->port, " --> bc:%p h:%d sh:%d\n", bc, bc->holded, bc->stack_holder);
+ }
+
+@@ -3369,19 +3590,29 @@
+
+ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event )
+ {
+- msg_t *msg;
+- int retval=0;
++ msg_t *msg;
++ struct misdn_bchannel *bc2;
++ struct misdn_bchannel *holded_bc;
+ struct misdn_stack *stack;
+-
+- if (!bc) RETURN(-1,OUT_POST_UNLOCK);
+-
++ int retval = 0;
++ int channel;
++ int tmpcause;
++ int tmp_out_cause;
++
++ if (!bc)
++ RETURN(-1,OUT_POST_UNLOCK);
++
+ stack = get_stack_by_bc(bc);
+-
+ if (!stack) {
+- cb_log(0,bc->port,"SENDEVENT: no Stack for event:%s oad:%s dad:%s \n", isdn_get_info(msgs_g, event, 0), bc->oad, bc->dad);
++ cb_log(0,bc->port,
++ "SENDEVENT: no Stack for event:%s caller:\"%s\" <%s> dialed:%s \n",
++ isdn_get_info(msgs_g, event, 0),
++ bc->caller.name,
++ bc->caller.number,
++ bc->dialed.number);
+ RETURN(-1,OUT);
+ }
+-
++
+ misdn_send_lock(bc);
+
+
+@@ -3394,15 +3625,22 @@
+ misdn_lib_get_l1_up(stack);
+ RETURN(0,OUT);
+ }
+-
+- cb_log(1, stack->port, "I SEND:%s oad:%s dad:%s pid:%d\n", isdn_get_info(msgs_g, event, 0), bc->oad, bc->dad, bc->pid);
++
++ cb_log(1, stack->port,
++ "I SEND:%s caller:\"%s\" <%s> dialed:%s pid:%d\n",
++ isdn_get_info(msgs_g, event, 0),
++ bc->caller.name,
++ bc->caller.number,
++ bc->dialed.number,
++ bc->pid);
+ cb_log(4, stack->port, " --> bc_state:%s\n",bc_state2str(bc->bc_state));
+ misdn_lib_log_ies(bc);
+-
++
+ switch (event) {
++ case EVENT_REGISTER:
+ case EVENT_SETUP:
+- if (create_process(glob_mgr->midev, bc)<0) {
+- cb_log(0, stack->port, " No free channel at the moment @ send_event\n");
++ if (create_process(glob_mgr->midev, bc) < 0) {
++ cb_log(0, stack->port, " No free channel at the moment @ send_event\n");
+
+ RETURN(-ENOCHAN,OUT);
+ }
+@@ -3413,10 +3651,10 @@
+ case EVENT_PROCEEDING:
+ case EVENT_SETUP_ACKNOWLEDGE:
+ case EVENT_CONNECT:
+- if (!stack->nt) break;
++ if (!stack->nt)
++ break;
+
+ case EVENT_RETRIEVE_ACKNOWLEDGE:
+-
+ if (stack->nt) {
+ if (bc->channel <=0 ) { /* else we have the channel already */
+ if (find_free_chan_in_stack(stack, bc, 0, 0)<0) {
+@@ -3436,19 +3674,26 @@
+ if (misdn_cap_is_speech(bc->capability)) {
+ if ((event==EVENT_CONNECT)||(event==EVENT_RETRIEVE_ACKNOWLEDGE)) {
+ if ( *bc->crypt_key ) {
+- cb_log(4, stack->port, " --> ENABLING BLOWFISH channel:%d oad%d:%s dad%d:%s \n", bc->channel, bc->onumplan,bc->oad, bc->dnumplan,bc->dad);
+-
++ cb_log(4, stack->port,
++ " --> ENABLING BLOWFISH channel:%d caller%d:\"%s\" <%s> dialed%d:%s\n",
++ bc->channel,
++ bc->caller.number_type,
++ bc->caller.name,
++ bc->caller.number,
++ bc->dialed.number_type,
++ bc->dialed.number);
++
+ manager_ph_control_block(bc, BF_ENABLE_KEY, bc->crypt_key, strlen(bc->crypt_key) );
+ }
+-
++
+ if (!bc->nodsp) manager_ph_control(bc, DTMF_TONE_START, 0);
+ manager_ec_enable(bc);
+-
++
+ if (bc->txgain != 0) {
+ cb_log(4, stack->port, "--> Changing txgain to %d\n", bc->txgain);
+ manager_ph_control(bc, VOL_CHANGE_TX, bc->txgain);
+ }
+-
++
+ if ( bc->rxgain != 0 ) {
+ cb_log(4, stack->port, "--> Changing rxgain to %d\n", bc->rxgain);
+ manager_ph_control(bc, VOL_CHANGE_RX, bc->rxgain);
+@@ -3458,8 +3703,7 @@
+ break;
+
+ case EVENT_HOLD_ACKNOWLEDGE:
+- {
+- struct misdn_bchannel *holded_bc=malloc(sizeof(struct misdn_bchannel));
++ holded_bc = malloc(sizeof(struct misdn_bchannel));
+ if (!holded_bc) {
+ cb_log(0,bc->port, "Could not allocate holded_bc!!!\n");
+ RETURN(-1,OUT);
+@@ -3471,13 +3715,10 @@
+ bc_state_change(holded_bc,BCHAN_CLEANED);
+
+ stack_holder_add(stack,holded_bc);
+-
++
+ /*kill the bridge and clean the bchannel*/
+ if (stack->nt) {
+- int channel;
+ if (bc->bc_state == BCHAN_BRIDGED) {
+- struct misdn_bchannel *bc2;
+-
+ misdn_split_conf(bc,bc->conf_id);
+ bc2 = find_bc_by_confid(bc->conf_id);
+ if (!bc2) {
+@@ -3486,7 +3727,7 @@
+ misdn_split_conf(bc2,bc->conf_id);
+ }
+ }
+-
++
+ channel = bc->channel;
+
+ empty_bc(bc);
+@@ -3495,24 +3736,22 @@
+ if (channel>0)
+ empty_chan_in_stack(stack,channel);
+
+- bc->in_use=0;
++ bc->in_use=0;
+ }
+-
+- }
+- break;
++ break;
+
+ /* finishing the channel eh ? */
+ case EVENT_DISCONNECT:
+ if (!bc->need_disconnect) {
+- cb_log(0,bc->port," --> we have already send Disconnect\n");
++ cb_log(0, bc->port, " --> we have already sent DISCONNECT\n");
+ RETURN(-1,OUT);
+ }
+-
++
+ bc->need_disconnect=0;
+ break;
+ case EVENT_RELEASE:
+ if (!bc->need_release) {
+- cb_log(0,bc->port," --> we have already send Release\n");
++ cb_log(0, bc->port, " --> we have already sent RELEASE\n");
+ RETURN(-1,OUT);
+ }
+ bc->need_disconnect=0;
+@@ -3520,7 +3759,7 @@
+ break;
+ case EVENT_RELEASE_COMPLETE:
+ if (!bc->need_release_complete) {
+- cb_log(0,bc->port," --> we have already send Release_complete\n");
++ cb_log(0, bc->port, " --> we have already sent RELEASE_COMPLETE\n");
+ RETURN(-1,OUT);
+ }
+ bc->need_disconnect=0;
+@@ -3528,33 +3767,32 @@
+ bc->need_release_complete=0;
+
+ if (!stack->nt) {
+- /*create cleanup in TE*/
+- int channel=bc->channel;
++ /* create cleanup in TE */
++ channel = bc->channel;
++ tmpcause = bc->cause;
++ tmp_out_cause = bc->out_cause;
+
+- int tmpcause=bc->cause;
+- int tmp_out_cause=bc->out_cause;
+ empty_bc(bc);
+ bc->cause=tmpcause;
+ bc->out_cause=tmp_out_cause;
+ clean_up_bc(bc);
+-
++
+ if (channel>0)
+ empty_chan_in_stack(stack,channel);
+-
++
+ bc->in_use=0;
+ }
+ break;
+-
++
+ case EVENT_CONNECT_ACKNOWLEDGE:
+-
+ if ( bc->nt || misdn_cap_is_speech(bc->capability)) {
+ int retval=setup_bc(bc);
+ if (retval == -EINVAL){
+ cb_log(0,bc->port,"send_event: setup_bc failed\n");
+-
++
+ }
+ }
+-
++
+ if (misdn_cap_is_speech(bc->capability)) {
+ if ( !bc->nodsp) manager_ph_control(bc, DTMF_TONE_START, 0);
+ manager_ec_enable(bc);
+@@ -3569,21 +3807,32 @@
+ }
+ }
+ break;
+-
++
+ default:
+ break;
+ }
+-
++
+ /* Later we should think about sending bchannel data directly to misdn. */
+ msg = isdn_msg_build_event(msgs_g, bc, event, stack->nt);
+- msg_queue_tail(&stack->downqueue, msg);
+- sem_post(&glob_mgr->new_msg);
+-
++ if (!msg) {
++ /*
++ * The message was not built.
++ *
++ * NOTE: The only time that the message will fail to build
++ * is because the requested FACILITY message is not supported.
++ * A failed malloc() results in exit() being called.
++ */
++ RETURN(-1, OUT);
++ } else {
++ msg_queue_tail(&stack->downqueue, msg);
++ sem_post(&glob_mgr->new_msg);
++ }
++
+ OUT:
+ misdn_send_unlock(bc);
+
+ OUT_POST_UNLOCK:
+- return retval;
++ return retval;
+ }
+
+
+@@ -3601,12 +3850,12 @@
+ cb_log(0,0,"mISDN Msg without Address pr:%x dinfo:%x (already more than 100 of them)\n",frm->prim,frm->dinfo);
+ cnt=0;
+ }
+-
++
+ free_msg(msg);
+ return 1;
+-
++
+ }
+-
++
+ switch (frm->prim) {
+ case MGR_SETSTACK|INDICATION:
+ return handle_bchan(msg);
+@@ -3614,7 +3863,7 @@
+
+ case MGR_SETSTACK|CONFIRM:
+ case MGR_CLEARSTACK|CONFIRM:
+- free_msg(msg) ;
++ free_msg(msg) ;
+ return 1;
+ break;
+
+@@ -3635,13 +3884,13 @@
+ struct misdn_bchannel *bc;
+
+ /*we flush the read buffer here*/
+-
++
+ cb_log(9,0,"BCHAN DATA without BC: addr:%x port:%d channel:%d\n",frm->addr, port,channel);
+-
+- free_msg(msg);
++
++ free_msg(msg);
+ return 1;
+-
+-
++
++
+ bc = find_bc_by_channel(port, channel);
+
+ if (!bc) {
+@@ -3652,7 +3901,7 @@
+ free_msg(msg);
+ return 1;
+ }
+-
++
+ cb_log(0,0," --> bc not found by channel\n");
+ if (stack->l2link)
+ misdn_lib_get_l2_down(stack);
+@@ -3663,7 +3912,7 @@
+ free_msg(msg);
+ return 1;
+ }
+-
++
+ cb_log(3,port," --> BC in state:%s\n", bc_state2str(bc->bc_state));
+ }
+ }
+@@ -3678,7 +3927,7 @@
+ struct misdn_stack *stack;
+ stack=find_stack_by_addr( frm->addr );
+
+-
++
+ if (!stack) {
+ return 0;
+ }
+@@ -3690,7 +3939,7 @@
+ #endif
+
+ int manager_isdn_handler(iframe_t *frm ,msg_t *msg)
+-{
++{
+
+ if (frm->dinfo==0xffffffff && frm->prim==(PH_DATA|CONFIRM)) {
+ cb_log(0,0,"SERIOUS BUG, dinfo == 0xffffffff, prim == PH_DATA | CONFIRM !!!!\n");
+@@ -3701,35 +3950,35 @@
+ if (handle_bchan(msg)) {
+ return 0 ;
+ }
+-
++
+ if (unhandled_bmsg_count==1000) {
+- cb_log(0, 0, "received 1k Unhandled Bchannel Messages: prim %x len %d from addr %x, dinfo %x on this port.\n",frm->prim, frm->len, frm->addr, frm->dinfo);
++ cb_log(0, 0, "received 1k Unhandled Bchannel Messages: prim %x len %d from addr %x, dinfo %x on this port.\n",frm->prim, frm->len, frm->addr, frm->dinfo);
+ unhandled_bmsg_count=0;
+ }
+
+ unhandled_bmsg_count++;
+ free_msg(msg);
+ return 0;
+- }
++ }
+
+ #ifdef RECV_FRM_SYSLOG_DEBUG
+ syslog(LOG_NOTICE,"mISDN recv: P(%02d): ADDR:%x PRIM:%x DINFO:%x\n",stack->port, frm->addr, frm->prim, frm->dinfo);
+ #endif
+
+- if (handle_timers(msg))
++ if (handle_timers(msg))
+ return 0 ;
+
+-
+- if (handle_mgmt(msg))
+- return 0 ;
+-
+- if (handle_l2(msg))
++
++ if (handle_mgmt(msg))
+ return 0 ;
+
++ if (handle_l2(msg))
++ return 0 ;
++
+ /* Its important to handle l1 AFTER l2 */
+- if (handle_l1(msg))
++ if (handle_l1(msg))
+ return 0 ;
+-
++
+ if (handle_frm_nt(msg)) {
+ return 0;
+ }
+@@ -3742,10 +3991,10 @@
+ return 0 ;
+ }
+
+- cb_log(0, 0, "Unhandled Message: prim %x len %d from addr %x, dinfo %x on this port.\n",frm->prim, frm->len, frm->addr, frm->dinfo);
++ cb_log(0, 0, "Unhandled Message: prim %x len %d from addr %x, dinfo %x on this port.\n",frm->prim, frm->len, frm->addr, frm->dinfo);
+ free_msg(msg);
+-
+
++
+ return 0;
+ }
+
+@@ -3773,16 +4022,16 @@
+
+ frm->dinfo = 0;
+ frm->len = 0;
+-
++
+ msg_queue_tail(&glob_mgr->activatequeue, msg);
+ sem_post(&glob_mgr->new_msg);
+
+-
+- return 0;
++
++ return 0;
+ }
+
+
+-int queue_cleanup_bc(struct misdn_bchannel *bc)
++int queue_cleanup_bc(struct misdn_bchannel *bc)
+ {
+ msg_t *msg=alloc_msg(MAX_MSG_SIZE);
+ iframe_t *frm;
+@@ -3799,15 +4048,15 @@
+
+ frm->dinfo = bc->port;
+ frm->len = 0;
+-
++
+ msg_queue_tail(&glob_mgr->activatequeue, msg);
+ sem_post(&glob_mgr->new_msg);
+
+- return 0;
++ return 0;
+
+ }
+
+-int misdn_lib_pid_restart(int pid)
++int misdn_lib_pid_restart(int pid)
+ {
+ struct misdn_bchannel *bc=manager_find_bc_by_pid(pid);
+
+@@ -3824,7 +4073,7 @@
+ struct misdn_bchannel dummybc;
+ /*default is all channels*/
+ cb_log(0, port, "Sending Restarts on this port.\n");
+-
++
+ misdn_make_dummy(&dummybc, stack->port, MISDN_ID_GLOBAL, stack->nt, 0);
+
+ /*default is all channels*/
+@@ -3860,11 +4109,11 @@
+ int misdn_lib_port_restart(int port)
+ {
+ struct misdn_stack *stack=find_stack_by_port(port);
+-
++
+ cb_log(0, port, "Restarting this port.\n");
+ if (stack) {
+ cb_log(0, port, "Stack:%p\n",stack);
+-
++
+ clear_l3(stack);
+ {
+ msg_t *msg=alloc_msg(MAX_MSG_SIZE);
+@@ -3874,7 +4123,7 @@
+ cb_log(0, port, "port_restart: alloc_msg failed\n");
+ return -1;
+ }
+-
++
+ frm=(iframe_t*)msg->data;
+ /* we must activate if we are deactivated */
+ /* activate bchannel */
+@@ -3889,7 +4138,7 @@
+
+ if (stack->nt)
+ misdn_lib_reinit_nt_stack(stack->port);
+-
++
+ }
+
+ return 0;
+@@ -3897,25 +4146,25 @@
+
+
+
+-static sem_t handler_started;
++static sem_t handler_started;
+
+ /* This is a thread */
+ static void manager_event_handler(void *arg)
+ {
+- sem_post(&handler_started);
++ sem_post(&handler_started);
+ while (1) {
+ struct misdn_stack *stack;
+ msg_t *msg;
+-
++
+ /** wait for events **/
+ sem_wait(&glob_mgr->new_msg);
+-
++
+ for (msg=msg_dequeue(&glob_mgr->activatequeue);
+ msg;
+ msg=msg_dequeue(&glob_mgr->activatequeue)
+ )
+ {
+-
++
+ iframe_t *frm = (iframe_t*) msg->data ;
+
+ switch ( frm->prim) {
+@@ -3930,7 +4179,7 @@
+ free_msg(msg);
+ break;
+ }
+-
++
+ bc = find_bc_by_l3id(stack, frm->addr);
+ if (bc) {
+ cb_log(1,bc->port,"CLEARSTACK queued, cleaning up\n");
+@@ -3939,7 +4188,7 @@
+ cb_log(0,stack->port,"bc could not be cleaned correctly !! addr [%x]\n",frm->addr);
+ }
+ }
+- free_msg(msg);
++ free_msg(msg);
+ break;
+ case MGR_SETSTACK | REQUEST :
+ /* Warning: memory leak here if we get this message */
+@@ -3952,10 +4201,10 @@
+
+ for (stack=glob_mgr->stack_list;
+ stack;
+- stack=stack->next ) {
++ stack=stack->next ) {
+
+ while ( (msg=msg_dequeue(&stack->upqueue)) ) {
+- /** Handle L2/3 Signalling after bchans **/
++ /** Handle L2/3 Signalling after bchans **/
+ if (!handle_frm_nt(msg)) {
+ /* Maybe it's TE */
+ if (!handle_frm(msg)) {
+@@ -3965,16 +4214,16 @@
+ }
+ }
+
+- /* Here we should check if we really want to
+- send all the messages we've queued, lets
+- assume we've queued a Disconnect, but
++ /* Here we should check if we really want to
++ send all the messages we've queued, lets
++ assume we've queued a Disconnect, but
+ received it already from the other side!*/
+-
++
+ while ( (msg=msg_dequeue(&stack->downqueue)) ) {
+ if (stack->nt ) {
+ if (stack->nst.manager_l3(&stack->nst, msg))
+ cb_log(0, stack->port, "Error@ Sending Message in NT-Stack.\n");
+-
++
+ } else {
+ iframe_t *frm = (iframe_t *)msg->data;
+ struct misdn_bchannel *bc = find_bc_by_l3id(stack, frm->dinfo);
+@@ -4003,14 +4252,14 @@
+
+ int i = mISDN_open();
+ int max=0;
+-
++
+ if (i<0)
+ return -1;
+
+ max = mISDN_get_stack_count(i);
+-
++
+ mISDN_close(i);
+-
++
+ return max;
+ }
+
+@@ -4027,12 +4276,12 @@
+ #endif
+ }
+
+-void misdn_lib_nt_debug_init( int flags, char *file )
++void misdn_lib_nt_debug_init( int flags, char *file )
+ {
+ static int init=0;
+ char *f;
+-
+- if (!flags)
++
++ if (!flags)
+ f=NULL;
+ else
+ f=file;
+@@ -4053,50 +4302,52 @@
+ char plist[1024];
+ int midev;
+ int port_count=0;
+-
++
+ cb_log = iface->cb_log;
+ cb_event = iface->cb_event;
+ cb_jb_empty = iface->cb_jb_empty;
+-
++
+ glob_mgr = mgr;
+-
++
+ msg_init();
+
+ misdn_lib_nt_debug_init(0,NULL);
+-
++
+ if (!portlist || (*portlist == 0) ) return 1;
+-
++
+ init_flip_bits();
+-
++
+ {
+ strncpy(plist,portlist, 1024);
+ plist[1023] = 0;
+ }
+-
++
+ memcpy(tone_425_flip,tone_425,TONE_425_SIZE);
+ flip_buf_bits(tone_425_flip,TONE_425_SIZE);
+
+ memcpy(tone_silence_flip,tone_SILENCE,TONE_SILENCE_SIZE);
+ flip_buf_bits(tone_silence_flip,TONE_SILENCE_SIZE);
+-
++
+ midev=te_lib_init();
+ mgr->midev=midev;
+
+ port_count=mISDN_get_stack_count(midev);
+-
++
+ msg_queue_init(&mgr->activatequeue);
+-
++
+ if (sem_init(&mgr->new_msg, 1, 0)<0)
+ sem_init(&mgr->new_msg, 0, 0);
+-
++
+ for (tok=strtok_r(plist," ,",&tokb );
+- tok;
++ tok;
+ tok=strtok_r(NULL," ,",&tokb)) {
+ int port = atoi(tok);
+ struct misdn_stack *stack;
+- static int first=1;
++ struct misdn_stack *help;
+ int ptp=0;
+-
++ int i;
++ int r;
++
+ if (strstr(tok, "ptp"))
+ ptp=1;
+
+@@ -4104,53 +4355,59 @@
+ cb_log(0, port, "Couldn't Initialize this port since we have only %d ports\n", port_count);
+ exit(1);
+ }
+- stack=stack_init(midev, port, ptp);
+-
++
++ stack = stack_init(midev, port, ptp);
+ if (!stack) {
+ perror("stack_init");
+ exit(1);
+ }
+-
+- {
+- int i;
+- for(i=0;i<=stack->b_num; i++) {
+- int r;
+- if ((r=init_bc(stack, &stack->bc[i], stack->midev,port,i, "", 1))<0) {
+- cb_log(0, port, "Got Err @ init_bc :%d\n",r);
+- exit(1);
+- }
++
++ /* Initialize the B channel records for real B channels. */
++ for (i = 0; i <= stack->b_num; i++) {
++ r = init_bc(stack, &stack->bc[i], stack->midev, port, i);
++ if (r < 0) {
++ cb_log(0, port, "Got Err @ init_bc :%d\n", r);
++ exit(1);
+ }
+ }
++#if defined(AST_MISDN_ENHANCEMENTS)
++ /* Initialize the B channel records for REGISTER signaling links. */
++ for (i = MAX_BCHANS + 1; i < ARRAY_LEN(stack->bc); ++i) {
++ r = init_bc(stack, &stack->bc[i], stack->midev, port, i);
++ if (r < 0) {
++ cb_log(0, port, "Got Err @ init_bc :%d\n", r);
++ exit(1);
++ }
++ stack->bc[i].is_register_pool = 1;
++ }
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
+
+- if (stack && first) {
+- mgr->stack_list=stack;
+- first=0;
+- continue;
++ /* Add the new stack to the end of the list */
++ help = mgr->stack_list;
++ if (!help) {
++ mgr->stack_list = stack;
++ } else {
++ while (help->next) {
++ help = help->next;
++ }
++ help->next = stack;
+ }
+-
+- if (stack) {
+- struct misdn_stack * help;
+- for ( help=mgr->stack_list; help; help=help->next )
+- if (help->next == NULL) break;
+- help->next=stack;
+- }
+-
+ }
+-
++
+ if (sem_init(&handler_started, 1, 0)<0)
+ sem_init(&handler_started, 0, 0);
+-
++
+ cb_log(8, 0, "Starting Event Handler\n");
+ pthread_create( &mgr->event_handler_thread, NULL,(void*)manager_event_handler, mgr);
+-
++
+ sem_wait(&handler_started) ;
+ cb_log(8, 0, "Starting Event Catcher\n");
+ pthread_create( &mgr->event_thread, NULL, (void*)misdn_lib_isdn_event_catcher, mgr);
+-
++
+ cb_log(8, 0, "Event Catcher started\n");
+
+- global_state= MISDN_INITIALIZED;
+-
++ global_state= MISDN_INITIALIZED;
++
+ return (mgr == NULL);
+ }
+
+@@ -4158,7 +4415,7 @@
+ {
+ struct misdn_stack *help;
+ int i;
+-
++
+ for ( help=glob_mgr->stack_list; help; help=help->next ) {
+ for(i=0;i<=help->b_num; i++) {
+ char buf[1024];
+@@ -4168,21 +4425,21 @@
+ cb_log (1, help->port, "Destroying this port.\n");
+ stack_destroy(help);
+ }
+-
++
+ if (global_state == MISDN_INITIALIZED) {
+ cb_log(4, 0, "Killing Handler Thread\n");
+ if ( pthread_cancel(glob_mgr->event_handler_thread) == 0 ) {
+ cb_log(4, 0, "Joining Handler Thread\n");
+ pthread_join(glob_mgr->event_handler_thread, NULL);
+ }
+-
++
+ cb_log(4, 0, "Killing Main Thread\n");
+ if ( pthread_cancel(glob_mgr->event_thread) == 0 ) {
+ cb_log(4, 0, "Joining Main Thread\n");
+ pthread_join(glob_mgr->event_thread, NULL);
+ }
+ }
+-
++
+ cb_log(1, 0, "Closing mISDN device\n");
+ te_lib_destroy(glob_mgr->midev);
+ }
+@@ -4202,12 +4459,12 @@
+ cb_log(0, bc->port, "bchannel_activate: Stack not found !");
+ return ;
+ }
+-
++
+ /* we must activate if we are deactivated */
+ clear_ibuffer(bc->astbuf);
+-
++
+ cb_log(5, stack->port, "$$$ Bchan Activated addr %x\n", bc->addr);
+-
++
+ mISDN_write_frame(stack->midev, buf, bc->addr | FLG_MSG_DOWN, DL_ESTABLISH | REQUEST, 0,0, NULL, TIMEOUT_1SEC);
+
+ return ;
+@@ -4218,7 +4475,7 @@
+ {
+ struct misdn_stack *stack=get_stack_by_bc(bc);
+ iframe_t dact;
+- char buf[128];
++ char buf[128];
+
+ switch (bc->bc_state) {
+ case BCHAN_ACTIVATED:
+@@ -4231,11 +4488,11 @@
+ return ;
+
+ }
+-
++
+ cb_log(5, stack->port, "$$$ Bchan deActivated addr %x\n", bc->addr);
+-
++
+ bc->generate_tone=0;
+-
++
+ dact.prim = DL_RELEASE | REQUEST;
+ dact.addr = bc->addr | FLG_MSG_DOWN;
+ dact.dinfo = 0;
+@@ -4243,9 +4500,9 @@
+ mISDN_write_frame(stack->midev, buf, bc->addr | FLG_MSG_DOWN, DL_RELEASE|REQUEST,0,0,NULL, TIMEOUT_1SEC);
+
+ clear_ibuffer(bc->astbuf);
+-
++
+ bc_state_change(bc,BCHAN_RELEASE);
+-
++
+ return;
+ }
+
+@@ -4265,19 +4522,19 @@
+ cb_log(3, bc->port, "BC not yet activated (state:%s)\n",bc_state2str(bc->bc_state));
+ return -1;
+ }
+-
++
+ frm->prim = DL_DATA|REQUEST;
+ frm->dinfo = 0;
+ frm->addr = bc->addr | FLG_MSG_DOWN ;
+-
++
+ frm->len = len;
+ memcpy(&buf[mISDN_HEADER_LEN], data,len);
+-
+- if ( misdn_cap_is_speech(bc->capability) )
++
++ if ( misdn_cap_is_speech(bc->capability) )
+ flip_buf_bits( &buf[mISDN_HEADER_LEN], len);
+ else
+ cb_log(6, stack->port, "Writing %d data bytes\n",len);
+-
++
+ cb_log(9, stack->port, "Writing %d bytes 2 mISDN\n",len);
+ r=mISDN_write(stack->midev, buf, frm->len + mISDN_HEADER_LEN, TIMEOUT_INFINIT);
+ return 0;
+@@ -4294,9 +4551,9 @@
+ iframe_t *ctrl = (iframe_t *)buffer; /* preload data */
+ unsigned int *d = (unsigned int*)&ctrl->data.p;
+ /*struct misdn_stack *stack=get_stack_by_bc(bc);*/
+-
++
+ cb_log(4,bc->port,"ph_control: c1:%x c2:%x\n",c1,c2);
+-
++
+ ctrl->prim = PH_CONTROL | REQUEST;
+ ctrl->addr = bc->addr | FLG_MSG_DOWN;
+ ctrl->dinfo = 0;
+@@ -4345,7 +4602,7 @@
+ iframe_t *ctrl = (iframe_t *)buffer;
+ unsigned int *d = (unsigned int *)&ctrl->data.p;
+ /*struct misdn_stack *stack=get_stack_by_bc(bc);*/
+-
++
+ ctrl->prim = PH_CONTROL | REQUEST;
+ ctrl->addr = bc->addr | FLG_MSG_DOWN;
+ ctrl->dinfo = 0;
+@@ -4361,13 +4618,14 @@
+ void manager_clean_bc(struct misdn_bchannel *bc )
+ {
+ struct misdn_stack *stack=get_stack_by_bc(bc);
+-
+- if (bc->channel>0)
++
++ if (stack && bc->channel > 0) {
+ empty_chan_in_stack(stack, bc->channel);
++ }
+ empty_bc(bc);
+ bc->in_use=0;
+
+- cb_event(EVENT_CLEANUP, bc, NULL);
++ cb_event(EVENT_CLEANUP, bc, NULL);
+ }
+
+
+@@ -4375,15 +4633,15 @@
+ {
+ struct misdn_bchannel *help;
+ cb_log(4,stack->port, "*HOLDER: add %x\n",holder->l3_id);
+-
++
+ holder->stack_holder=1;
+ holder->next=NULL;
+-
++
+ if (!stack->holding) {
+ stack->holding = holder;
+ return;
+ }
+-
++
+ for (help=stack->holding;
+ help;
+ help=help->next) {
+@@ -4392,7 +4650,7 @@
+ break;
+ }
+ }
+-
++
+ }
+
+ void stack_holder_remove(struct misdn_stack *stack, struct misdn_bchannel *holder)
+@@ -4400,17 +4658,17 @@
+ struct misdn_bchannel *h1;
+
+ if (!holder->stack_holder) return;
+-
++
+ holder->stack_holder=0;
+-
++
+ cb_log(4,stack->port, "*HOLDER: remove %x\n",holder->l3_id);
+ if (!stack || ! stack->holding) return;
+-
++
+ if (holder == stack->holding) {
+ stack->holding = stack->holding->next;
+ return;
+ }
+-
++
+ for (h1=stack->holding;
+ h1;
+ h1=h1->next) {
+@@ -4426,9 +4684,9 @@
+ struct misdn_bchannel *help;
+
+ cb_log(4,stack?stack->port:0, "*HOLDER: find_bychan %c\n", chan);
+-
++
+ if (!stack) return NULL;
+-
++
+ for (help=stack->holding;
+ help;
+ help=help->next) {
+@@ -4448,9 +4706,9 @@
+ struct misdn_bchannel *help;
+
+ cb_log(4,stack?stack->port:0, "*HOLDER: find %lx\n",l3id);
+-
++
+ if (!stack) return NULL;
+-
++
+ for (help=stack->holding;
+ help;
+ help=help->next) {
+@@ -4466,34 +4724,34 @@
+
+
+
+-void misdn_lib_send_tone(struct misdn_bchannel *bc, enum tone_e tone)
++void misdn_lib_send_tone(struct misdn_bchannel *bc, enum tone_e tone)
+ {
+ char buf[mISDN_HEADER_LEN + 128] = "";
+ iframe_t *frm = (iframe_t*)buf;
+
+ switch(tone) {
+ case TONE_DIAL:
+- manager_ph_control(bc, TONE_PATT_ON, TONE_GERMAN_DIALTONE);
++ manager_ph_control(bc, TONE_PATT_ON, TONE_GERMAN_DIALTONE);
+ break;
+-
++
+ case TONE_ALERTING:
+- manager_ph_control(bc, TONE_PATT_ON, TONE_GERMAN_RINGING);
++ manager_ph_control(bc, TONE_PATT_ON, TONE_GERMAN_RINGING);
+ break;
+-
++
+ case TONE_HANGUP:
+- manager_ph_control(bc, TONE_PATT_ON, TONE_GERMAN_HANGUP);
++ manager_ph_control(bc, TONE_PATT_ON, TONE_GERMAN_HANGUP);
+ break;
+
+ case TONE_NONE:
+ default:
+- manager_ph_control(bc, TONE_PATT_OFF, TONE_GERMAN_HANGUP);
++ manager_ph_control(bc, TONE_PATT_OFF, TONE_GERMAN_HANGUP);
+ }
+
+ frm->prim=DL_DATA|REQUEST;
+ frm->addr=bc->addr|FLG_MSG_DOWN;
+ frm->dinfo=0;
+ frm->len=128;
+-
++
+ mISDN_write(glob_mgr->midev, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
+ }
+
+@@ -4501,7 +4759,7 @@
+ void manager_ec_enable(struct misdn_bchannel *bc)
+ {
+ struct misdn_stack *stack=get_stack_by_bc(bc);
+-
++
+ cb_log(4, stack?stack->port:0,"ec_enable\n");
+
+ if (!misdn_cap_is_speech(bc->capability)) {
+@@ -4518,7 +4776,7 @@
+
+ if (bc->ec_enable) {
+ cb_log(3, stack?stack->port:0,"Sending Control ECHOCAN_ON taps:%d\n",bc->ec_deftaps);
+-
++
+ switch (bc->ec_deftaps) {
+ case 4:
+ case 8:
+@@ -4535,10 +4793,10 @@
+ cb_log(0, stack->port, "Taps should be power of 2\n");
+ bc->ec_deftaps=128;
+ }
+-
++
+ ec_arr[0]=bc->ec_deftaps;
+ ec_arr[1]=0;
+-
++
+ manager_ph_control_block(bc, ECHOCAN_ON, ec_arr, sizeof(ec_arr));
+ }
+ #endif
+@@ -4550,7 +4808,7 @@
+ void manager_ec_disable(struct misdn_bchannel *bc)
+ {
+ struct misdn_stack *stack=get_stack_by_bc(bc);
+-
++
+ cb_log(4, stack?stack->port:0," --> ec_disable\n");
+
+ if (!misdn_cap_is_speech(bc->capability)) {
+@@ -4568,7 +4826,8 @@
+ #endif
+ }
+
+-struct misdn_stack* get_misdn_stack(void) {
++struct misdn_stack *get_misdn_stack(void)
++{
+ return glob_mgr->stack_list;
+ }
+
+@@ -4605,10 +4864,10 @@
+
+ cb_log(4, bc1->port, "I Send: BRIDGE from:%d to:%d\n",bc1->port,bc2->port);
+
+- for (bc=bc_list; *bc; bc++) {
++ for (bc=bc_list; *bc; bc++) {
+ (*bc)->conf_id=conf_id;
+ cb_log(4, (*bc)->port, " --> bc_addr:%x\n",(*bc)->addr);
+-
++
+ switch((*bc)->bc_state) {
+ case BCHAN_ACTIVATED:
+ misdn_join_conf(*bc,conf_id);
+@@ -4627,15 +4886,15 @@
+ bc1,bc2,NULL
+ };
+ struct misdn_bchannel **bc;
+-
+- for (bc=bc_list; *bc; bc++) {
++
++ for (bc=bc_list; *bc; bc++) {
+ if ( (*bc)->bc_state == BCHAN_BRIDGED){
+ misdn_split_conf( *bc, (*bc)->conf_id);
+ } else {
+ cb_log( 2, (*bc)->port, "BC not bridged (state:%s) so not splitting it\n",bc_state2str((*bc)->bc_state));
+ }
+ }
+-
++
+ }
+
+
+@@ -4651,37 +4910,37 @@
+ void misdn_lib_reinit_nt_stack(int port)
+ {
+ struct misdn_stack *stack=find_stack_by_port(port);
+-
++
+ if (stack) {
+ stack->l2link=0;
+ stack->blocked=0;
+-
++
+ cleanup_Isdnl3(&stack->nst);
+ cleanup_Isdnl2(&stack->nst);
+
+
+ memset(&stack->nst, 0, sizeof(net_stack_t));
+ memset(&stack->mgr, 0, sizeof(manager_t));
+-
++
+ stack->mgr.nst = &stack->nst;
+ stack->nst.manager = &stack->mgr;
+-
++
+ stack->nst.l3_manager = handle_event_nt;
+ stack->nst.device = glob_mgr->midev;
+ stack->nst.cardnr = port;
+ stack->nst.d_stid = stack->d_stid;
+-
++
+ stack->nst.feature = FEATURE_NET_HOLD;
+ if (stack->ptp)
+ stack->nst.feature |= FEATURE_NET_PTP;
+ if (stack->pri)
+ stack->nst.feature |= FEATURE_NET_CRLEN2 | FEATURE_NET_EXTCID;
+-
++
+ stack->nst.l1_id = stack->lower_id;
+ stack->nst.l2_id = stack->upper_id;
+-
++
+ msg_queue_init(&stack->nst.down_queue);
+-
++
+ Isdnl2Init(&stack->nst);
+ Isdnl3Init(&stack->nst);
+
+Index: channels/misdn/isdn_lib_intern.h
+===================================================================
+--- a/channels/misdn/isdn_lib_intern.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/channels/misdn/isdn_lib_intern.h (.../trunk) (revision 202568)
+@@ -41,7 +41,6 @@
+ struct isdn_msg {
+ unsigned long misdn_msg;
+
+- enum layer_e layer;
+ enum event_e event;
+
+ void (*msg_parser)(struct isdn_msg *msgs, msg_t *msg, struct misdn_bchannel *bc, int nt);
+@@ -52,7 +51,15 @@
+ /* for isdn_msg_parser.c */
+ msg_t *create_l3msg(int prim, int mt, int dinfo , int size, int nt);
+
++#if defined(AST_MISDN_ENHANCEMENTS)
++/* Max call-completion REGISTER signaling links per stack/port */
++#define MISDN_MAX_REGISTER_LINKS MAX_BCHANS
++#else
++/* Max call-completion REGISTER signaling links per stack/port */
++#define MISDN_MAX_REGISTER_LINKS 0
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
+
++#define MAXPROCS 0x100
+
+ struct misdn_stack {
+ /** is first element because &nst equals &mISDNlist **/
+@@ -88,8 +95,6 @@
+ /*! \brief TRUE if Layer 2 is UP */
+ int l2link;
+
+- time_t l2establish; /* Not used */
+-
+ /*! \brief TRUE if Layer 1 is UP */
+ int l1link;
+
+@@ -106,7 +111,7 @@
+ int pri;
+
+ /*! \brief CR Process ID allocation table. TRUE if ID allocated */
+- int procids[0x100+1];
++ int procids[MAXPROCS];
+
+ /*! \brief Queue of Event messages to send to mISDN */
+ msg_queue_t downqueue;
+@@ -116,14 +121,18 @@
+ /*! \brief Logical Layer 1 port associated with this stack */
+ int port;
+
+- /*! \brief B Channel record pool array */
+- struct misdn_bchannel bc[MAX_BCHANS + 1];
++ /*!
++ * \brief B Channel record pool array
++ * (Must be dimensioned the same as struct misdn_stack.channels[])
++ */
++ struct misdn_bchannel bc[MAX_BCHANS + 1 + MISDN_MAX_REGISTER_LINKS];
+
+- struct misdn_bchannel* bc_list; /* Not used */
++ /*!
++ * \brief Array of B channels in use (a[0] = B1). TRUE if B channel in use.
++ * (Must be dimensioned the same as struct misdn_stack.bc[])
++ */
++ char channels[MAX_BCHANS + 1 + MISDN_MAX_REGISTER_LINKS];
+
+- /*! \brief Array of B channels in use (a[0] = B1). TRUE if B channel in use */
+- int channels[MAX_BCHANS + 1];
+-
+ /*! \brief List of holded channels */
+ struct misdn_bchannel *holding;
+
+Index: channels/misdn/isdn_lib.h
+===================================================================
+--- a/channels/misdn/isdn_lib.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/channels/misdn/isdn_lib.h (.../trunk) (revision 202568)
+@@ -96,15 +96,23 @@
+ ENOCHAN=1
+ };
+
+-
+ enum mISDN_NUMBER_PLAN {
+- NUMPLAN_UNINITIALIZED=-1,
+- NUMPLAN_INTERNATIONAL=0x1,
+- NUMPLAN_NATIONAL=0x2,
+- NUMPLAN_SUBSCRIBER=0x4,
+- NUMPLAN_UNKNOWN=0x0
++ NUMPLAN_UNKNOWN = 0x0,
++ NUMPLAN_ISDN = 0x1, /* ISDN/Telephony numbering plan E.164 */
++ NUMPLAN_DATA = 0x3, /* Data numbering plan X.121 */
++ NUMPLAN_TELEX = 0x4, /* Telex numbering plan F.69 */
++ NUMPLAN_NATIONAL = 0x8,
++ NUMPLAN_PRIVATE = 0x9
+ };
+
++enum mISDN_NUMBER_TYPE {
++ NUMTYPE_UNKNOWN = 0x0,
++ NUMTYPE_INTERNATIONAL = 0x1,
++ NUMTYPE_NATIONAL = 0x2,
++ NUMTYPE_NETWORK_SPECIFIC = 0x3,
++ NUMTYPE_SUBSCRIBER = 0x4,
++ NUMTYPE_ABBREVIATED = 0x5
++};
+
+ enum event_response_e {
+ RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE,
+@@ -125,6 +133,7 @@
+ EVENT_PROCEEDING,
+ EVENT_PROGRESS,
+ EVENT_SETUP,
++ EVENT_REGISTER,
+ EVENT_ALERTING,
+ EVENT_CONNECT,
+ EVENT_SETUP_ACKNOWLEDGE,
+@@ -189,6 +198,44 @@
+ INFO_PI_INTERWORKING_NO_RELEASE_POST_ANSWER =0x13
+ };
+
++/*!
++ * \brief Q.931 encoded redirecting reason
++ */
++enum mISDN_REDIRECTING_REASON {
++ mISDN_REDIRECTING_REASON_UNKNOWN = 0x0,
++ /*! Call forwarding busy or called DTE busy */
++ mISDN_REDIRECTING_REASON_CALL_FWD_BUSY = 0x1,
++ /*! Call forwarding no reply */
++ mISDN_REDIRECTING_REASON_NO_REPLY = 0x2,
++ /*! Call deflection */
++ mISDN_REDIRECTING_REASON_DEFLECTION = 0x4,
++ /*! Called DTE out of order */
++ mISDN_REDIRECTING_REASON_OUT_OF_ORDER = 0x9,
++ /*! Call forwarding by the called DTE */
++ mISDN_REDIRECTING_REASON_CALL_FWD_DTE = 0xA,
++ /*! Call forwarding unconditional or systematic call redirection */
++ mISDN_REDIRECTING_REASON_CALL_FWD = 0xF
++};
++
++/*!
++ * \brief Notification description code enumeration
++ */
++enum mISDN_NOTIFY_CODE {
++ mISDN_NOTIFY_CODE_INVALID = -1,
++ /*! Call is placed on hold (Q.931) */
++ mISDN_NOTIFY_CODE_USER_SUSPEND = 0x00,
++ /*! Call is taken off of hold (Q.931) */
++ mISDN_NOTIFY_CODE_USER_RESUME = 0x01,
++ /*! Call is diverting (EN 300 207-1 Section 7.2.1) */
++ mISDN_NOTIFY_CODE_CALL_IS_DIVERTING = 0x7B,
++ /*! Call diversion is enabled (cfu, cfb, cfnr) (EN 300 207-1 Section 7.2.1) */
++ mISDN_NOTIFY_CODE_DIVERSION_ACTIVATED = 0x68,
++ /*! Call transfer, alerting (EN 300 369-1 Section 7.2) */
++ mISDN_NOTIFY_CODE_CALL_TRANSFER_ALERTING = 0x69,
++ /*! Call transfer, active(answered) (EN 300 369-1 Section 7.2) */
++ mISDN_NOTIFY_CODE_CALL_TRANSFER_ACTIVE = 0x6A,
++};
++
+ enum { /*CODECS*/
+ INFO_CODEC_ULAW=2,
+ INFO_CODEC_ALAW=3
+@@ -202,12 +249,116 @@
+ UNKNOWN
+ };
+
++/*! Maximum phone number (address) length plus null terminator */
++#define MISDN_MAX_NUMBER_LEN (31 + 1)
+
++/*! Maximum name length plus null terminator (From ECMA-164) */
++#define MISDN_MAX_NAME_LEN (50 + 1)
+
++/*! Maximum subaddress length plus null terminator */
++#define MISDN_MAX_SUBADDRESS_LEN (23 + 1)
++
++/*! Maximum keypad facility content length plus null terminator */
++#define MISDN_MAX_KEYPAD_LEN (31 + 1)
++
++/*! \brief Dialed/Called information struct */
++struct misdn_party_dialing {
++ /*! \brief Type-of-number in ISDN terms for the dialed/called number */
++ enum mISDN_NUMBER_TYPE number_type;
++
++ /*! \brief Type-of-number numbering plan. */
++ enum mISDN_NUMBER_PLAN number_plan;
++
++ /*! \brief Dialed/Called Phone Number (Address) */
++ char number[MISDN_MAX_NUMBER_LEN];
++
++ /*! \brief Dialed/Called Subaddress number */
++ char subaddress[MISDN_MAX_SUBADDRESS_LEN];
++};
++
++/*! \brief Connected-Line/Calling/Redirecting ID info struct */
++struct misdn_party_id {
++ /*! \brief Number presentation restriction code
++ * 0=Allowed, 1=Restricted, 2=Unavailable
++ */
++ int presentation;
++
++ /*! \brief Number screening code
++ * 0=Unscreened, 1=Passed Screen, 2=Failed Screen, 3=Network Number
++ */
++ int screening;
++
++ /*! \brief Type-of-number in ISDN terms for the number */
++ enum mISDN_NUMBER_TYPE number_type;
++
++ /*! \brief Type-of-number numbering plan. */
++ enum mISDN_NUMBER_PLAN number_plan;
++
++ /*! \brief Subscriber Name
++ * \note The name is currently obtained from Asterisk for
++ * potential use in display ie's since basic ISDN does
++ * not support names directly.
++ */
++ char name[MISDN_MAX_NAME_LEN];
++
++ /*! \brief Phone number (Address) */
++ char number[MISDN_MAX_NUMBER_LEN];
++
++ /*! \brief Subaddress number */
++ char subaddress[MISDN_MAX_SUBADDRESS_LEN];
++};
++
++/*! \brief Redirecting information struct */
++struct misdn_party_redirecting {
++ /*! \brief Who is redirecting the call (Sent to the party the call is redirected toward) */
++ struct misdn_party_id from;
++
++ /*! \brief Where the call is being redirected toward (Sent to the calling party) */
++ struct misdn_party_id to;
++
++ /*! \brief Reason a call is being redirected (Q.931 field value) */
++ enum mISDN_REDIRECTING_REASON reason;
++
++ /*! \brief Number of times the call has been redirected */
++ int count;
++
++ /*! \brief TRUE if the redirecting.to information has changed */
++ int to_changed;
++};
++
++
++/*! \brief B channel control structure */
+ struct misdn_bchannel {
+ /*! \brief B channel send locking structure */
+ struct send_lock *send_lock;
+
++#if defined(AST_MISDN_ENHANCEMENTS)
++ /*! \brief The BC, HLC (optional) and LLC (optional) contents from the SETUP message. */
++ struct Q931_Bc_Hlc_Llc setup_bc_hlc_llc;
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
++ /*!
++ * \brief Dialed/Called information struct
++ * \note The number_type element is set to "dialplan" in /etc/asterisk/misdn.conf for outgoing calls
++ */
++ struct misdn_party_dialing dialed;
++
++ /*! \brief Originating/Caller ID information struct
++ * \note The number_type element can be set to "localdialplan" in /etc/asterisk/misdn.conf for outgoing calls
++ * \note The number element can be set to "callerid" in /etc/asterisk/misdn.conf for outgoing calls
++ */
++ struct misdn_party_id caller;
++
++ /*! \brief Connected-Party/Connected-Line ID information struct
++ * \note The number_type element can be set to "cpndialplan" in /etc/asterisk/misdn.conf for outgoing calls
++ */
++ struct misdn_party_id connected;
++
++ /*! \brief Redirecting information struct (Where a call diversion or transfer was invoked)
++ * \note The redirecting subaddress is not defined in Q.931 so it is not used.
++ */
++ struct misdn_party_redirecting redirecting;
++
+ /*! \brief TRUE if this is a dummy BC record */
+ int dummy;
+
+@@ -264,6 +415,9 @@
+ /*! \brief TRUE if the B channel number is preselected */
+ int channel_preselected;
+
++ /*! \brief TRUE if the B channel is allocated from the REGISTER pool */
++ int is_register_pool;
++
+ /*! \brief TRUE if B channel record is in use */
+ int in_use;
+
+@@ -286,8 +440,6 @@
+ /*! \brief Not used. Contents are setup but not used. */
+ void *astbuf;
+
+- void *misdnbuf; /* Not used */
+-
+ /*! \brief TRUE if the TE side should choose the B channel to use
+ * \note This value is user configurable in /etc/asterisk/misdn.conf
+ */
+@@ -326,26 +478,6 @@
+ /*! \brief TRUE if we will not use the jitter buffer system */
+ int nojitter;
+
+- /*! \brief Type-of-number in ISDN terms for the dialed/called number
+- * \note This value is set to "dialplan" in /etc/asterisk/misdn.conf for outgoing calls
+- */
+- enum mISDN_NUMBER_PLAN dnumplan;
+-
+- /*! \brief Type-of-number in ISDN terms for the redirecting number which a call diversion or transfer was invoked.
+- * \note Collected from the incoming SETUP message but not used.
+- */
+- enum mISDN_NUMBER_PLAN rnumplan;
+-
+- /*! \brief Type-of-number in ISDN terms for the originating/calling number (Caller-ID)
+- * \note This value is set to "localdialplan" in /etc/asterisk/misdn.conf for outgoing calls
+- */
+- enum mISDN_NUMBER_PLAN onumplan;
+-
+- /*! \brief Type-of-number in ISDN terms for the connected party number
+- * \note This value is set to "cpndialplan" in /etc/asterisk/misdn.conf for outgoing calls
+- */
+- enum mISDN_NUMBER_PLAN cpnnumplan;
+-
+ /*! \brief Progress Indicator IE coding standard field.
+ * \note Collected from the incoming messages but not used.
+ */
+@@ -361,6 +493,18 @@
+ */
+ int progress_indicator;
+
++#if defined(AST_MISDN_ENHANCEMENTS)
++ /*!
++ * \brief TRUE if waiting for DivertingLegInformation3 to queue redirecting update.
++ */
++ int div_leg_3_rx_wanted;
++
++ /*!
++ * \brief TRUE if a DivertingLegInformation3 needs to be sent with CONNECT.
++ */
++ int div_leg_3_tx_pending;
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
++
+ /*! \brief Inbound FACILITY message function type and contents */
+ struct FacParm fac_in;
+
+@@ -421,17 +565,51 @@
+ */
+ int stack_holder;
+
+- /*! \brief Caller ID presentation restriction code
++ /*!
++ * \brief Put a display ie in the CONNECT message
++ * \details
++ * Put a display ie in the CONNECT message containing the following
++ * information if it is available (nt port only):
++ * 0 - Do not put the connected line information in the display ie.
++ * 1 - Put the available connected line name in the display ie.
++ * 2 - Put the available connected line number in the display ie.
++ * 3 - Put the available connected line name and number in the display ie.
++ */
++ int display_connected;
++
++ /*!
++ * \brief Put a display ie in the SETUP message
++ * \details
++ * Put a display ie in the SETUP message containing the following
++ * information if it is available (nt port only):
++ * 0 - Do not put the caller information in the display ie.
++ * 1 - Put the available caller name in the display ie.
++ * 2 - Put the available caller number in the display ie.
++ * 3 - Put the available caller name and number in the display ie.
++ */
++ int display_setup;
++
++ /*!
++ * \brief Select what to do with outgoing COLP information.
++ * \details
++ * 0 - pass (Send out COLP information unaltered.)
++ * 1 - restricted (Force COLP to restricted on all outgoing COLP information.)
++ * 2 - block (Do not send COLP information.)
++ */
++ int outgoing_colp;
++
++ /*! \brief User set presentation restriction code
+ * 0=Allowed, 1=Restricted, 2=Unavailable
+ * \note It is settable by the misdn_set_opt() application.
+ */
+- int pres;
++ int presentation;
+
+- /*! \brief Caller ID screening code
+- * 0=Unscreened, 1=Passed Screen, 2=Failed Screen, 3=Network Number
+- */
+- int screen;
++ /*! \brief TRUE if the user set the presentation restriction code */
++ int set_presentation;
+
++ /*! \brief Notification indicator ie description code */
++ enum mISDN_NOTIFY_CODE notify_description_code;
++
+ /*! \brief SETUP message bearer capability field code value */
+ int capability;
+
+@@ -468,40 +646,18 @@
+ */
+ char display[84];
+
+- /*! \brief Not used. Contents are setup but not used. */
+- char msn[32];
+-
+- /*! \brief Originating/Calling Phone Number (Address)
+- * \note This value can be set to "callerid" in /etc/asterisk/misdn.conf for outgoing calls
+- */
+- char oad[32];
+-
+- /*! \brief Redirecting Phone Number (Address) where a call diversion or transfer was invoked */
+- char rad[32];
+-
+- /*! \brief Dialed/Called Phone Number (Address) */
+- char dad[32];
+-
+- /*! \brief Connected Party/Line Phone Number (Address) */
+- char cad[32];
+-
+- /*! \brief Original Dialed/Called Phone Number (Address) before national/international dialing prefix added.
+- * \note Not used. Contents are setup but not used.
+- */
+- char orig_dad[32];
+-
+ /*! \brief Q.931 Keypad Facility IE contents
+ * \note Contents exported and imported to Asterisk variable MISDN_KEYPAD
+ */
+- char keypad[32];
++ char keypad[MISDN_MAX_KEYPAD_LEN];
+
+ /*! \brief Current overlap dialing digits to/from INFORMATION messages */
+- char info_dad[64];
++ char info_dad[MISDN_MAX_NUMBER_LEN];
+
+ /*! \brief Collected digits to go into info_dad[] while waiting for a SETUP_ACKNOWLEDGE to come in. */
+- char infos_pending[64];
++ char infos_pending[MISDN_MAX_NUMBER_LEN];
+
+-/* unsigned char info_keypad[32]; */
++/* unsigned char info_keypad[MISDN_MAX_KEYPAD_LEN]; */
+ /* unsigned char clisub[24]; */
+ /* unsigned char cldsub[24]; */
+
+@@ -600,6 +756,9 @@
+ void misdn_lib_transfer(struct misdn_bchannel* holded_bc);
+
+ struct misdn_bchannel* misdn_lib_get_free_bc(int port, int channel, int inout, int dec);
++#if defined(AST_MISDN_ENHANCEMENTS)
++struct misdn_bchannel *misdn_lib_get_register_bc(int port);
++#endif /* defined(AST_MISDN_ENHANCEMENTS) */
+
+ void manager_bchannel_activate(struct misdn_bchannel *bc);
+ void manager_bchannel_deactivate(struct misdn_bchannel * bc);
+@@ -679,4 +838,4 @@
+ void misdn_make_dummy(struct misdn_bchannel *dummybc, int port, int l3id, int nt, int channel);
+
+
+-#endif
++#endif /* TE_LIB */
+Index: channels/misdn/Makefile
+===================================================================
+--- a/channels/misdn/Makefile (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/channels/misdn/Makefile (.../trunk) (revision 202568)
+@@ -13,5 +13,5 @@
+ portinfo: portinfo.o
+ $(CC) -o $@ $^ -lisdnnet -lmISDN -lpthread
+
+-clean:
++clean:
+ rm -rf *.a *.o *.so portinfo *.i
+Index: channels/misdn/chan_misdn_config.h
+===================================================================
+--- a/channels/misdn/chan_misdn_config.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/channels/misdn/chan_misdn_config.h (.../trunk) (revision 202568)
+@@ -11,7 +11,7 @@
+ * the GNU General Public License
+ */
+
+-/*! \file
++/*! \file
+ * \brief Interface to mISDN - Config
+ * \author Christian Richter <crich@beronet.com>
+ */
+@@ -46,10 +46,16 @@
+ MISDN_CFG_DIALPLAN, /* int */
+ MISDN_CFG_LOCALDIALPLAN, /* int */
+ MISDN_CFG_CPNDIALPLAN, /* int */
+- MISDN_CFG_NATPREFIX, /* char[] */
+- MISDN_CFG_INTERNATPREFIX, /* char[] */
++ MISDN_CFG_TON_PREFIX_UNKNOWN, /* char[] */
++ MISDN_CFG_TON_PREFIX_INTERNATIONAL, /* char[] */
++ MISDN_CFG_TON_PREFIX_NATIONAL, /* char[] */
++ MISDN_CFG_TON_PREFIX_NETWORK_SPECIFIC,/* char[] */
++ MISDN_CFG_TON_PREFIX_SUBSCRIBER, /* char[] */
++ MISDN_CFG_TON_PREFIX_ABBREVIATED, /* char[] */
+ MISDN_CFG_PRES, /* int */
+ MISDN_CFG_SCREEN, /* int */
++ MISDN_CFG_DISPLAY_CONNECTED, /* int */
++ MISDN_CFG_DISPLAY_SETUP, /* int */
+ MISDN_CFG_ALWAYS_IMMEDIATE, /* int (bool) */
+ MISDN_CFG_NODIALTONE, /* int (bool) */
+ MISDN_CFG_IMMEDIATE, /* int (bool) */
+@@ -59,6 +65,8 @@
+ MISDN_CFG_EARLY_BCONNECT, /* int (bool) */
+ MISDN_CFG_INCOMING_EARLY_AUDIO, /* int (bool) */
+ MISDN_CFG_ECHOCANCEL, /* int */
++ MISDN_CFG_CC_REQUEST_RETENTION,/* bool */
++ MISDN_CFG_OUTGOING_COLP, /* int */
+ #ifdef MISDN_1_2
+ MISDN_CFG_PIPELINE, /* char[] */
+ #endif
+@@ -89,7 +97,7 @@
+ MISDN_CFG_FAXDETECT_TIMEOUT, /* int */
+ MISDN_CFG_PTP, /* int (bool) */
+ MISDN_CFG_LAST,
+-
++
+ /* general config items */
+ MISDN_GEN_FIRST,
+ #ifndef MISDN_1_2
+@@ -116,19 +124,19 @@
+ };
+
+ /* you must call misdn_cfg_init before any other function of this header file */
+-int misdn_cfg_init(int max_ports, int reload);
++int misdn_cfg_init(int max_ports, int reload);
+ void misdn_cfg_reload(void);
+ void misdn_cfg_destroy(void);
+
+ void misdn_cfg_update_ptp( void );
+
+-/* if you requst a general config element, the port value is ignored. if the requested
+- * value is not available, or the buffer is too small, the buffer will be nulled (in
++/* if you requst a general config element, the port value is ignored. if the requested
++ * value is not available, or the buffer is too small, the buffer will be nulled (in
+ * case of a char* only its first byte will be nulled). */
+ void misdn_cfg_get(int port, enum misdn_cfg_elements elem, void* buf, int bufsize);
+
+ /* returns the enum element for the given name, returns MISDN_CFG_FIRST if none was found */
+-enum misdn_cfg_elements misdn_cfg_get_elem (char *name);
++enum misdn_cfg_elements misdn_cfg_get_elem (const char *name);
+
+ /* fills the buffer with the name of the given config element */
+ void misdn_cfg_get_name (enum misdn_cfg_elements elem, void *buf, int bufsize);
+Index: channels/misdn/ie.c
+===================================================================
+--- a/channels/misdn/ie.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/channels/misdn/ie.c (.../trunk) (revision 202568)
+@@ -1,4 +1,3 @@
+-
+ /*
+ * Chan_Misdn -- Channel Driver for Asterisk
+ *
+@@ -15,7 +14,7 @@
+ * the GNU General Public License
+ */
+
+-/*! \file
++/*! \file
+ * \brief Interface to mISDN
+ * \author Christian Richter <crich@beronet.com>
+ */
+@@ -39,11 +38,11 @@
+ #define MISDN_IE_DEBG 0
+
+ /* support stuff */
+-static void strnncpy(char *dest, char *src, int len, int dst_len)
++static void strnncpy(char *dest, const char *src, size_t len, size_t dst_len)
+ {
+ if (len > dst_len-1)
+ len = dst_len-1;
+- strncpy((char *)dest, (char *)src, len);
++ strncpy(dest, src, len);
+ dest[len] = '\0';
+ }
+
+@@ -153,7 +152,7 @@
+ p[4+(multi>=0)] = 0xa0 + user;
+ }
+
+-static void dec_ie_bearer(unsigned char *p, Q931_info_t *qi, int *coding, int *capability, int *mode, int *rate, int *multi, int *user,
++static void dec_ie_bearer(unsigned char *p, Q931_info_t *qi, int *coding, int *capability, int *mode, int *rate, int *multi, int *user,
+ int *async, int *urate, int *stopbits, int *dbits, int *parity, int nt, struct misdn_bchannel *bc)
+ {
+ int octet;
+@@ -168,13 +167,13 @@
+ *stopbits = -1;
+ *dbits = -1;
+ *parity = -1;
+-
++
+ if (!nt)
+ {
+ p = NULL;
+ #ifdef LLC_SUPPORT
+ if (qi->QI_ELEMENT(llc)) {
+-
++
+ p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(llc) + 1;
+ }
+ #endif
+@@ -189,7 +188,7 @@
+ printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
+ return;
+ }
+-
++
+ *coding = (p[1]&0x60) >> 5;
+ *capability = p[1] & 0x1f;
+ octet = 2;
+@@ -221,7 +220,7 @@
+
+ if (p[0] <= octet)
+ goto done;
+-
++
+ if (p[octet++] & 0x80)
+ goto l2;
+
+@@ -231,7 +230,7 @@
+
+ if (p[0] <= octet)
+ goto done;
+-
++
+ if (p[octet++] & 0x80)
+ goto l2;
+
+@@ -239,7 +238,7 @@
+
+ if (p[0] <= octet)
+ goto done;
+-
++
+ if (p[octet++] & 0x80)
+ goto l2;
+
+@@ -247,20 +246,20 @@
+
+ if (p[0] <= octet)
+ goto done;
+-
++
+ if (!p[octet++] & 0x80)
+ goto l2;
+
+ /* Wheee. V.110 speed information */
+
+ *stopbits = (p[octet] & 0x60) >> 5;
+- *dbits = (p[octet] & 0x18) >> 3;
++ *dbits = (p[octet] & 0x18) >> 3;
+ *parity = p[octet] & 7;
+
+ octet++;
+ }
+ l2: /* Nobody seems to want the rest so we don't bother (yet) */
+- done:
++ done:
+ if (MISDN_IE_DEBG) printf(" coding=%d capability=%d mode=%d rate=%d multi=%d user=%d async=%d urate=%d stopbits=%d dbits=%d parity=%d\n", *coding, *capability, *mode, *rate, *multi, *user, *async, *urate, *stopbits, *dbits, *parity);
+ }
+
+@@ -292,7 +291,7 @@
+ if (MISDN_IE_DEBG) printf(debug+(i*3), " %02x", callid[i]);
+ i++;
+ }
+-
++
+ if (MISDN_IE_DEBG) printf(" callid%s\n", debug);
+
+ l = callid_len;
+@@ -338,7 +337,7 @@
+ if (MISDN_IE_DEBG) printf(debug+(i*3), " %02x", callid[i]);
+ i++;
+ }
+-
++
+ if (MISDN_IE_DEBG) printf(" callid%s\n", debug);
+ }
+ #endif
+@@ -380,7 +379,7 @@
+ strncpy((char *)p+3, (char *)number, strlen((char *)number));
+ }
+
+-static void dec_ie_called_pn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, char *number, int number_len, int nt, struct misdn_bchannel *bc)
++static void dec_ie_called_pn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, char *number, size_t number_len, int nt, struct misdn_bchannel *bc)
+ {
+ *type = -1;
+ *plan = -1;
+@@ -464,7 +463,7 @@
+ }
+ }
+
+-static void dec_ie_calling_pn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, int *present, int *screen, char *number, int number_len, int nt, struct misdn_bchannel *bc)
++static void dec_ie_calling_pn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, int *present, int *screen, char *number, size_t number_len, int nt, struct misdn_bchannel *bc)
+ {
+ *type = -1;
+ *plan = -1;
+@@ -501,7 +500,7 @@
+ } else
+ {
+ strnncpy(number, (char *)p+2, p[0]-1, number_len);
+- /* SPECIAL workarround for IBT software bug */
++ /* SPECIAL workarround for IBT software bug */
+ /* if (number[0]==0x80) */
+ /* strcpy((char *)number, (char *)number+1); */
+ }
+@@ -566,7 +565,7 @@
+ }
+ }
+
+-static void dec_ie_connected_pn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, int *present, int *screen, char *number, int number_len, int nt, struct misdn_bchannel *bc)
++static void dec_ie_connected_pn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, int *present, int *screen, char *number, size_t number_len, int nt, struct misdn_bchannel *bc)
+ {
+ *type = -1;
+ *plan = -1;
+@@ -691,7 +690,7 @@
+ int l;
+ struct misdn_stack *stack=get_stack_by_bc(bc);
+ int pri = stack->pri;
+-
++
+ if (exclusive<0 || exclusive>1)
+ {
+ printf("%s: ERROR: exclusive(%d) is out of range.\n", __FUNCTION__, exclusive);
+@@ -707,8 +706,8 @@
+ }
+
+ /* if (MISDN_IE_DEBG) printf(" exclusive=%d channel=%d\n", exclusive, channel); */
+-
+
++
+ if (!pri)
+ {
+ /* BRI */
+@@ -884,7 +883,7 @@
+ static void enc_ie_display(unsigned char **ntmode, msg_t *msg, char *display, int nt, struct misdn_bchannel *bc)
+ {
+ unsigned char *p;
+- Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
++ Q931_info_t *qi = (Q931_info_t *) (msg->data + mISDN_HEADER_LEN);
+ int l;
+
+ if (!display[0])
+@@ -893,27 +892,28 @@
+ return;
+ }
+
+- if (strlen((char *)display) > 80)
++ l = strlen(display);
++ if (80 < l)
+ {
+- printf("%s: WARNING: display text too long (max 80 chars), cutting.\n", __FUNCTION__);
+- display[80] = '\0';
++ l = 80;
++ printf("%s: WARNING: display text too long (max %d chars), cutting.\n", __FUNCTION__, l);
++ display[l] = '\0';
+ }
+
+- /* if (MISDN_IE_DEBG) printf(" display='%s' (len=%d)\n", display, strlen((char *)display)); */
++ /* if (MISDN_IE_DEBG) printf(" display='%s' (len=%d)\n", display, l); */
+
+- l = strlen((char *)display);
+- p = msg_put(msg, l+2);
++ p = msg_put(msg, l + 2);
+ if (nt)
+- *ntmode = p+1;
++ *ntmode = p + 1;
+ else
+- qi->QI_ELEMENT(display) = p - (unsigned char *)qi - sizeof(Q931_info_t);
++ qi->QI_ELEMENT(display) = p - (unsigned char *) qi - sizeof(Q931_info_t);
+ p[0] = IE_DISPLAY;
+ p[1] = l;
+- strncpy((char *)p+2, (char *)display, strlen((char *)display));
++ strncpy((char *) p + 2, display, l);
+ }
+
+ #if 0
+-static void dec_ie_display(unsigned char *p, Q931_info_t *qi, char *display, int display_len, int nt, struct misdn_bchannel *bc)
++static void dec_ie_display(unsigned char *p, Q931_info_t *qi, char *display, size_t display_len, int nt, struct misdn_bchannel *bc)
+ {
+ *display = '\0';
+
+@@ -965,7 +965,7 @@
+ }
+ #endif
+
+-static void dec_ie_keypad(unsigned char *p, Q931_info_t *qi, char *keypad, int keypad_len, int nt, struct misdn_bchannel *bc)
++static void dec_ie_keypad(unsigned char *p, Q931_info_t *qi, char *keypad, size_t keypad_len, int nt, struct misdn_bchannel *bc)
+ {
+ *keypad = '\0';
+
+@@ -990,7 +990,6 @@
+
+
+ /* IE_NOTIFY */
+-#if 0
+ static void enc_ie_notify(unsigned char **ntmode, msg_t *msg, int notify, int nt, struct misdn_bchannel *bc)
+ {
+ unsigned char *p;
+@@ -1015,9 +1014,7 @@
+ p[1] = l;
+ p[2] = 0x80 + notify;
+ }
+-#endif
+
+-#if 0
+ static void dec_ie_notify(unsigned char *p, Q931_info_t *qi, int *notify, int nt, struct misdn_bchannel *bc)
+ {
+ *notify = -1;
+@@ -1040,7 +1037,6 @@
+
+ if (MISDN_IE_DEBG) printf(" notify=%d\n", *notify);
+ }
+-#endif
+
+
+ /* IE_PROGRESS */
+@@ -1086,7 +1082,7 @@
+ *location = -1;
+ //*progress = -1;
+ *progress = 0;
+-
++
+ if (!nt)
+ {
+ p = NULL;
+@@ -1184,7 +1180,7 @@
+ }
+ }
+
+-static void dec_ie_redir_nr(unsigned char *p, Q931_info_t *qi, int *type, int *plan, int *present, int *screen, int *reason, char *number, int number_len, int nt, struct misdn_bchannel *bc)
++static void dec_ie_redir_nr(unsigned char *p, Q931_info_t *qi, int *type, int *plan, int *present, int *screen, int *reason, char *number, size_t number_len, int nt, struct misdn_bchannel *bc)
+ {
+ *type = -1;
+ *plan = -1;
+@@ -1231,11 +1227,10 @@
+
+
+ /* IE_REDIR_DN (redirection = during MT_NOTIFY) */
+-#if 0
+ static void enc_ie_redir_dn(unsigned char **ntmode, msg_t *msg, int type, int plan, int present, char *number, int nt, struct misdn_bchannel *bc)
+ {
+ unsigned char *p;
+-/* Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN); */
++ Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
+ int l;
+
+ if (type<0 || type>7)
+@@ -1264,9 +1259,9 @@
+ p = msg_put(msg, l+2);
+ if (nt)
+ *ntmode = p+1;
+- else
+-/* #warning REINSERT redir_dn, when included in te-mode */
+- /*qi->QI_ELEMENT(redir_dn) = p - (unsigned char *)qi - sizeof(Q931_info_t)*/;
++ else {
++ qi->QI_ELEMENT(redirect_dn) = p - (unsigned char *)qi - sizeof(Q931_info_t);
++ }
+ p[0] = IE_REDIR_DN;
+ p[1] = l;
+ if (present >= 0)
+@@ -1282,10 +1277,8 @@
+ strncpy((char *)p+3, (char *)number, strlen((char *)number));
+ }
+ }
+-#endif
+
+-#if 0
+-static void dec_ie_redir_dn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, int *present, char *number, int number_len, int nt, struct misdn_bchannel *bc)
++static void dec_ie_redir_dn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, int *present, char *number, size_t number_len, int nt, struct misdn_bchannel *bc)
+ {
+ *type = -1;
+ *plan = -1;
+@@ -1295,9 +1288,8 @@
+ if (!nt)
+ {
+ p = NULL;
+-/* #warning REINSERT redir_dn, when included in te-mode */
+-/* if (qi->QI_ELEMENT(redir_dn)) */
+-/* p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(redir_dn) + 1; */
++ if (qi->QI_ELEMENT(redirect_dn))
++ p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(redirect_dn) + 1;
+ }
+ if (!p)
+ return;
+@@ -1320,7 +1312,6 @@
+
+ if (MISDN_IE_DEBG) printf(" type=%d plan=%d present=%d number='%s'\n", *type, *plan, *present, number);
+ }
+-#endif
+
+
+ /* IE_USERUSER */
+@@ -1331,9 +1322,6 @@
+ Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
+ int l;
+
+- char debug[768];
+- int i;
+-
+ if (protocol<0 || protocol>127)
+ {
+ printf("%s: ERROR: protocol(%d) is out of range.\n", __FUNCTION__, protocol);
+@@ -1344,14 +1332,16 @@
+ return;
+ }
+
+- i = 0;
+- while(i < user_len)
+- {
+- if (MISDN_IE_DEBG) sprintf(debug+(i*3), " %02x", user[i]);
+- i++;
++ if (MISDN_IE_DEBG) {
++ size_t i;
++ char debug[768];
++
++ for (i = 0; i < user_len; ++i) {
++ sprintf(debug + (i * 3), " %02x", user[i]);
++ }
++ debug[i * 3] = 0;
++ printf(" protocol=%d user-user%s\n", protocol, debug);
+ }
+-
+- if (MISDN_IE_DEBG) printf(" protocol=%d user-user%s\n", protocol, debug);
+
+ l = user_len+1;
+ p = msg_put(msg, l+3);
+@@ -1369,9 +1359,6 @@
+ #if 1
+ static void dec_ie_useruser(unsigned char *p, Q931_info_t *qi, int *protocol, char *user, int *user_len, int nt, struct misdn_bchannel *bc)
+ {
+- char debug[768];
+- int i;
+-
+ *user_len = 0;
+ *protocol = -1;
+
+@@ -1390,15 +1377,16 @@
+ *protocol = p[1];
+ memcpy(user, p+2, (*user_len<=128)?*(user_len):128); /* clip to 128 maximum */
+
+- i = 0;
+- while(i < *user_len)
+- {
+- if (MISDN_IE_DEBG) sprintf(debug+(i*3), " %02x", user[i]);
+- i++;
++ if (MISDN_IE_DEBG) {
++ int i;
++ char debug[768];
++
++ for (i = 0; i < *user_len; ++i) {
++ sprintf(debug + (i * 3), " %02x", user[i]);
++ }
++ debug[i * 3] = 0;
++ printf(" protocol=%d user-user%s\n", *protocol, debug);
+ }
+- debug[i*3] = '\0';
+-
+- if (MISDN_IE_DEBG) printf(" protocol=%d user-user%s\n", *protocol, debug);
+ }
+ #endif
+
+Index: channels/chan_gtalk.c
+===================================================================
+--- a/channels/chan_gtalk.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/channels/chan_gtalk.c (.../trunk) (revision 202568)
+@@ -52,7 +52,8 @@
+ #include "asterisk/pbx.h"
+ #include "asterisk/sched.h"
+ #include "asterisk/io.h"
+-#include "asterisk/rtp.h"
++#include "asterisk/rtp_engine.h"
++#include "asterisk/stun.h"
+ #include "asterisk/acl.h"
+ #include "asterisk/callerid.h"
+ #include "asterisk/file.h"
+@@ -112,8 +113,8 @@
+ char cid_name[80]; /*!< Caller ID name */
+ char exten[80]; /*!< Called extension */
+ struct ast_channel *owner; /*!< Master Channel */
+- struct ast_rtp *rtp; /*!< RTP audio session */
+- struct ast_rtp *vrtp; /*!< RTP video session */
++ struct ast_rtp_instance *rtp; /*!< RTP audio session */
++ struct ast_rtp_instance *vrtp; /*!< RTP video session */
+ int jointcapability; /*!< Supported capability at both ends (codecs ) */
+ int peercapability;
+ struct gtalk_pvt *next; /* Next entity */
+@@ -183,11 +184,6 @@
+ static struct gtalk_pvt *gtalk_alloc(struct gtalk *client, const char *us, const char *them, const char *sid);
+ static char *gtalk_do_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
+ static char *gtalk_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
+-/*----- RTP interface functions */
+-static int gtalk_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp,
+- struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active);
+-static enum ast_rtp_get_result gtalk_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp);
+-static int gtalk_get_codec(struct ast_channel *chan);
+
+ /*! \brief PBX interface structure for channel registration */
+ static const struct ast_channel_tech gtalk_tech = {
+@@ -197,7 +193,7 @@
+ .requester = gtalk_request,
+ .send_digit_begin = gtalk_digit_begin,
+ .send_digit_end = gtalk_digit_end,
+- .bridge = ast_rtp_bridge,
++ .bridge = ast_rtp_instance_bridge,
+ .call = gtalk_call,
+ .hangup = gtalk_hangup,
+ .answer = gtalk_answer,
+@@ -216,14 +212,6 @@
+ static struct io_context *io; /*!< The IO context */
+ static struct in_addr __ourip;
+
+-/*! \brief RTP driver interface */
+-static struct ast_rtp_protocol gtalk_rtp = {
+- type: "Gtalk",
+- get_rtp_info: gtalk_get_rtp_peer,
+- set_rtp_peer: gtalk_set_rtp_peer,
+- get_codec: gtalk_get_codec,
+-};
+-
+ static struct ast_cli_entry gtalk_cli[] = {
+ AST_CLI_DEFINE(gtalk_do_reload, "Reload GoogleTalk configuration"),
+ AST_CLI_DEFINE(gtalk_show_channels, "Show GoogleTalk channels"),
+@@ -371,7 +359,7 @@
+ iks_insert_node(dcodecs, payload_gsm);
+ res++;
+ }
+- ast_rtp_lookup_code(p->rtp, 1, codec);
++
+ return res;
+ }
+
+@@ -523,18 +511,19 @@
+ return res;
+ }
+
+-static enum ast_rtp_get_result gtalk_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
++static enum ast_rtp_glue_result gtalk_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
+ {
+ struct gtalk_pvt *p = chan->tech_pvt;
+- enum ast_rtp_get_result res = AST_RTP_GET_FAILED;
++ enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_FORBID;
+
+ if (!p)
+ return res;
+
+ ast_mutex_lock(&p->lock);
+ if (p->rtp){
+- *rtp = p->rtp;
+- res = AST_RTP_TRY_PARTIAL;
++ ao2_ref(p->rtp, +1);
++ *instance = p->rtp;
++ res = AST_RTP_GLUE_RESULT_LOCAL;
+ }
+ ast_mutex_unlock(&p->lock);
+
+@@ -547,7 +536,7 @@
+ return p->peercapability;
+ }
+
+-static int gtalk_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active)
++static int gtalk_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, int codecs, int nat_active)
+ {
+ struct gtalk_pvt *p;
+
+@@ -567,6 +556,13 @@
+ return 0;
+ }
+
++static struct ast_rtp_glue gtalk_rtp_glue = {
++ .type = "Gtalk",
++ .get_rtp_info = gtalk_get_rtp_peer,
++ .get_codec = gtalk_get_codec,
++ .update_peer = gtalk_set_rtp_peer,
++};
++
+ static int gtalk_response(struct gtalk *client, char *from, ikspak *pak, const char *reasonstr, const char *reasonstr2)
+ {
+ iks *response = NULL, *error = NULL, *reason = NULL;
+@@ -617,13 +613,13 @@
+ /* codec points to the first <payload-type/> tag */
+ codec = iks_first_tag(iks_first_tag(iks_first_tag(pak->x)));
+ while (codec) {
+- ast_rtp_set_m_type(tmp->rtp, atoi(iks_find_attrib(codec, "id")));
+- ast_rtp_set_rtpmap_type(tmp->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0);
++ ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(tmp->rtp), tmp->rtp, atoi(iks_find_attrib(codec, "id")));
++ ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(tmp->rtp), tmp->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0);
+ codec = iks_next_tag(codec);
+ }
+
+ /* Now gather all of the codecs that we are asked for */
+- ast_rtp_get_current_formats(tmp->rtp, &tmp->peercapability, &peernoncodeccapability);
++ ast_rtp_codecs_payload_formats(ast_rtp_instance_get_codecs(tmp->rtp), &tmp->peercapability, &peernoncodeccapability);
+
+ /* at this point, we received an awser from the remote Gtalk client,
+ which allows us to compare capabilities */
+@@ -774,7 +770,7 @@
+ struct gtalk_candidate *tmp;
+ struct aji_client *c = client->connection;
+ struct gtalk_candidate *ours1 = NULL, *ours2 = NULL;
+- struct sockaddr_in sin;
++ struct sockaddr_in sin = { 0, };
+ struct sockaddr_in dest;
+ struct in_addr us;
+ iks *iq, *gtalk, *candidate, *transport;
+@@ -810,7 +806,7 @@
+ goto safeout;
+ }
+
+- ast_rtp_get_us(p->rtp, &sin);
++ ast_rtp_instance_get_local_address(p->rtp, &sin);
+ ast_find_ourip(&us, bindaddr);
+ if (!strcmp(ast_inet_ntoa(us), "127.0.0.1")) {
+ ast_log(LOG_WARNING, "Found a loopback IP on the system, check your network configuration or set the bindaddr attribute.");
+@@ -951,8 +947,13 @@
+ tmp->initiator = 1;
+ }
+ /* clear codecs */
+- tmp->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
+- ast_rtp_pt_clear(tmp->rtp);
++ if (!(tmp->rtp = ast_rtp_instance_new(NULL, sched, &bindaddr, NULL))) {
++ ast_log(LOG_ERROR, "Failed to create a new RTP instance (possibly an invalid bindaddr?)\n");
++ ast_free(tmp);
++ return NULL;
++ }
++ ast_rtp_instance_set_prop(tmp->rtp, AST_RTP_PROPERTY_RTCP, 1);
++ ast_rtp_codecs_payloads_clear(ast_rtp_instance_get_codecs(tmp->rtp), tmp->rtp);
+
+ /* add user configured codec capabilites */
+ if (client->capability)
+@@ -1014,20 +1015,20 @@
+
+ /* Set Frame packetization */
+ if (i->rtp)
+- ast_rtp_codec_setpref(i->rtp, &i->prefs);
++ ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(i->rtp), i->rtp, &i->prefs);
+
+ tmp->nativeformats = ast_codec_choose(&i->prefs, what, 1) | (i->jointcapability & AST_FORMAT_VIDEO_MASK);
+ fmt = ast_best_codec(tmp->nativeformats);
+
+ if (i->rtp) {
+- ast_rtp_setstun(i->rtp, 1);
+- ast_channel_set_fd(tmp, 0, ast_rtp_fd(i->rtp));
+- ast_channel_set_fd(tmp, 1, ast_rtcp_fd(i->rtp));
++ ast_rtp_instance_set_prop(i->rtp, AST_RTP_PROPERTY_STUN, 1);
++ ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(i->rtp, 0));
++ ast_channel_set_fd(tmp, 1, ast_rtp_instance_fd(i->rtp, 1));
+ }
+ if (i->vrtp) {
+- ast_rtp_setstun(i->rtp, 1);
+- ast_channel_set_fd(tmp, 2, ast_rtp_fd(i->vrtp));
+- ast_channel_set_fd(tmp, 3, ast_rtcp_fd(i->vrtp));
++ ast_rtp_instance_set_prop(i->vrtp, AST_RTP_PROPERTY_STUN, 1);
++ ast_channel_set_fd(tmp, 2, ast_rtp_instance_fd(i->vrtp, 0));
++ ast_channel_set_fd(tmp, 3, ast_rtp_instance_fd(i->vrtp, 1));
+ }
+ if (state == AST_STATE_RING)
+ tmp->rings = 1;
+@@ -1142,9 +1143,9 @@
+ if (p->owner)
+ ast_log(LOG_WARNING, "Uh oh, there's an owner, this is going to be messy.\n");
+ if (p->rtp)
+- ast_rtp_destroy(p->rtp);
++ ast_rtp_instance_destroy(p->rtp);
+ if (p->vrtp)
+- ast_rtp_destroy(p->vrtp);
++ ast_rtp_instance_destroy(p->vrtp);
+ gtalk_free_candidates(p->theircandidates);
+ ast_free(p);
+ }
+@@ -1207,13 +1208,13 @@
+ codec = iks_first_tag(iks_first_tag(iks_first_tag(pak->x)));
+
+ while (codec) {
+- ast_rtp_set_m_type(p->rtp, atoi(iks_find_attrib(codec, "id")));
+- ast_rtp_set_rtpmap_type(p->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0);
++ ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id")));
++ ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0);
+ codec = iks_next_tag(codec);
+ }
+
+ /* Now gather all of the codecs that we are asked for */
+- ast_rtp_get_current_formats(p->rtp, &p->peercapability, &peernoncodeccapability);
++ ast_rtp_codecs_payload_formats(ast_rtp_instance_get_codecs(p->rtp), &p->peercapability, &peernoncodeccapability);
+ p->jointcapability = p->capability & p->peercapability;
+ ast_mutex_unlock(&p->lock);
+
+@@ -1226,7 +1227,7 @@
+ gtalk_action(client, p, "reject");
+ p->alreadygone = 1;
+ gtalk_hangup(chan);
+- ast_channel_free(chan);
++ ast_channel_release(chan);
+ return -1;
+ }
+
+@@ -1257,8 +1258,8 @@
+ struct gtalk_candidate *tmp;
+ struct hostent *hp;
+ struct ast_hostent ahp;
+- struct sockaddr_in sin;
+- struct sockaddr_in aux;
++ struct sockaddr_in sin = { 0, };
++ struct sockaddr_in aux = { 0, };
+
+ if (time(NULL) == p->laststun)
+ return 0;
+@@ -1277,16 +1278,16 @@
+ p->ourcandidates->username);
+
+ /* Find out the result of the STUN */
+- ast_rtp_get_peer(p->rtp, &aux);
++ ast_rtp_instance_get_remote_address(p->rtp, &aux);
+
+ /* If the STUN result is different from the IP of the hostname,
+ lock on the stun IP of the hostname advertised by the
+ remote client */
+ if (aux.sin_addr.s_addr &&
+ aux.sin_addr.s_addr != sin.sin_addr.s_addr)
+- ast_rtp_stun_request(p->rtp, &aux, username);
++ ast_rtp_instance_stun_request(p->rtp, &aux, username);
+ else
+- ast_rtp_stun_request(p->rtp, &sin, username);
++ ast_rtp_instance_stun_request(p->rtp, &sin, username);
+
+ if (aux.sin_addr.s_addr) {
+ ast_debug(4, "Receiving RTP traffic from IP %s, matches with remote candidate's IP %s\n", ast_inet_ntoa(aux.sin_addr), tmp->ip);
+@@ -1387,7 +1388,7 @@
+
+ if (!p->rtp)
+ return &ast_null_frame;
+- f = ast_rtp_read(p->rtp);
++ f = ast_rtp_instance_read(p->rtp, 0);
+ gtalk_update_stun(p->parent, p);
+ if (p->owner) {
+ /* We already hold the channel lock */
+@@ -1438,7 +1439,7 @@
+ if (p) {
+ ast_mutex_lock(&p->lock);
+ if (p->rtp) {
+- res = ast_rtp_write(p->rtp, frame);
++ res = ast_rtp_instance_write(p->rtp, frame);
+ }
+ ast_mutex_unlock(&p->lock);
+ }
+@@ -1447,7 +1448,7 @@
+ if (p) {
+ ast_mutex_lock(&p->lock);
+ if (p->vrtp) {
+- res = ast_rtp_write(p->vrtp, frame);
++ res = ast_rtp_instance_write(p->vrtp, frame);
+ }
+ ast_mutex_unlock(&p->lock);
+ }
+@@ -2062,7 +2063,7 @@
+ return 0;
+ }
+
+- ast_rtp_proto_register(&gtalk_rtp);
++ ast_rtp_glue_register(&gtalk_rtp_glue);
+ ast_cli_register_multiple(gtalk_cli, ARRAY_LEN(gtalk_cli));
+
+ /* Make sure we can register our channel type */
+@@ -2086,7 +2087,7 @@
+ ast_cli_unregister_multiple(gtalk_cli, ARRAY_LEN(gtalk_cli));
+ /* First, take us out of the channel loop */
+ ast_channel_unregister(&gtalk_tech);
+- ast_rtp_proto_unregister(&gtalk_rtp);
++ ast_rtp_glue_unregister(&gtalk_rtp_glue);
+
+ if (!ast_mutex_lock(&gtalklock)) {
+ /* Hangup all interfaces if they have an owner */
+Index: channels/iax2-parser.c
+===================================================================
+--- a/channels/iax2-parser.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/channels/iax2-parser.c (.../trunk) (revision 202568)
+@@ -279,7 +279,7 @@
+ { IAX_IE_OSPTOKEN, "OSPTOKEN" },
+ };
+
+-static struct iax2_ie prov_ies[] = {
++static const struct iax2_ie prov_ies[] = {
+ { PROV_IE_USEDHCP, "USEDHCP" },
+ { PROV_IE_IPADDR, "IPADDR", dump_ipaddr },
+ { PROV_IE_SUBNET, "SUBNET", dump_ipaddr },
+@@ -576,6 +576,9 @@
+ "VIDUPDT",
+ "T38 ",
+ "SRCUPDT",
++ "TXFER ",
++ "CNLINE ",
++ "REDIR ",
+ };
+ struct ast_iax2_full_hdr *fh;
+ char retries[20];
+Index: CREDITS
+===================================================================
+--- a/CREDITS (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/CREDITS (.../trunk) (revision 202568)
+@@ -200,6 +200,10 @@
+ Eliel C. Sardanons - XML documentation implementation, and various other contributions
+ eliels(AT)gmail.com
+
++Sean Bright - Snom call pickup, newt interface for menuselect, cdr_tds rewrite,
++ countless other improvements, fixes, and good ideas.
++ sean(AT)malleable.com
++
+ === OTHER CONTRIBUTIONS ===
+ John Todd - Monkey sounds and associated teletorture prompt
+ Michael Jerris - bug marshaling
+Index: BUGS
+===================================================================
+--- a/BUGS (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/BUGS (.../trunk) (revision 202568)
+@@ -4,7 +4,7 @@
+ To learn about and report Asterisk bugs, please visit
+ the official Asterisk Bug Tracker at:
+
+- http://bugs.digium.com
++ https://issues.asterisk.org
+
+ For more information on using the bug tracker, or to
+ learn how you can contribute by acting as a bug marshal
+Index: tests/test_logger.c
+===================================================================
+--- a/tests/test_logger.c (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/tests/test_logger.c (.../trunk) (revision 202568)
+@@ -0,0 +1,209 @@
++/*
++ * Asterisk -- An open source telephony toolkit.
++ *
++ * Copyright (C) 2009, Digium, Inc.
++ *
++ * Kevin P. Fleming <kpfleming@digium.com>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * 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.
++ */
++
++/*! \file
++ *
++ * \brief Test module for the logging subsystem
++ *
++ * \author\verbatim Kevin P. Fleming <kpfleming@digium.com> \endverbatim
++ *
++ * \ingroup tests
++ */
++
++/*** MODULEINFO
++ <defaultenabled>no</defaultenabled>
++ ***/
++
++#include "asterisk.h"
++
++ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
++
++#include "asterisk/file.h"
++#include "asterisk/channel.h"
++#include "asterisk/pbx.h"
++#include "asterisk/module.h"
++#include "asterisk/lock.h"
++#include "asterisk/app.h"
++#include "asterisk/cli.h"
++
++struct test {
++ const char *name;
++ unsigned int x_success;
++ unsigned int x_failure;
++ unsigned int u_success;
++ unsigned int u_failure;
++};
++
++static void output_tests(struct test *tests, size_t num_tests, int fd)
++{
++ unsigned int x;
++
++ for (x = 0; x < num_tests; x++) {
++ ast_cli(fd, "Test %d: %s\n", x + 1, tests[x].name);
++ ast_cli(fd, "\tExpected Successes: %d\n", tests[x].x_success);
++ ast_cli(fd, "\tExpected Failures: %d\n", tests[x].x_failure);
++ ast_cli(fd, "\tUnexpected Successes: %d\n", tests[x].u_success);
++ ast_cli(fd, "\tUnexpected Failures: %d\n", tests[x].u_failure);
++ ast_cli(fd, "Test %d Result: %s\n", x + 1, (tests[x].u_success + tests[x].u_failure) ? "FAIL" : "PASS");
++ }
++}
++
++static char *handle_cli_dynamic_level_test(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
++{
++ unsigned int level;
++ unsigned int x;
++ unsigned int test;
++ struct test tests[] = {
++ { .name = "Simple register/message/unregister",
++ },
++ { .name = "Register multiple levels",
++ },
++ };
++
++ switch (cmd) {
++ case CLI_INIT:
++ e->command = "logger test dynamic";
++ e->usage = ""
++ "Usage: logger test dynamic\n"
++ "";
++ return NULL;
++ case CLI_GENERATE:
++ return NULL;
++ }
++
++ for (test = 0; test < ARRAY_LEN(tests); test++) {
++ ast_cli(a->fd, "Test %d: %s.\n", test + 1, tests[test].name);
++ switch (test) {
++ case 0:
++ if ((level = ast_logger_register_level("test")) != -1) {
++ ast_cli(a->fd, "Test: got level %d\n", level);
++ ast_log_dynamic_level(level, "Logger Dynamic Test: Test 1\n");
++ ast_logger_unregister_level("test");
++ tests[test].x_success++;
++ } else {
++ ast_cli(a->fd, "Test: Failed, could not register level 'test'.\n");
++ tests[test].u_failure++;
++ }
++ break;
++ case 1:
++ {
++ char level_name[18][8];
++
++ for (x = 0; x < ARRAY_LEN(level_name); x++) {
++ sprintf(level_name[x], "level%02d", x);
++ if ((level = ast_logger_register_level(level_name[x])) == -1) {
++ if (x < 16) {
++ tests[test].u_failure++;
++ } else {
++ tests[test].x_failure++;
++ }
++ level_name[x][0] = '\0';
++ } else {
++ ast_cli(a->fd, "Test: registered '%s', got level %d\n", level_name[x], level);
++ if (x < 16) {
++ tests[test].x_success++;
++ } else {
++ tests[test].u_success++;
++ }
++ }
++ }
++
++ for (x = 0; x < ARRAY_LEN(level_name); x++) {
++ if (!ast_strlen_zero(level_name[x])) {
++ ast_logger_unregister_level(level_name[x]);
++ }
++ }
++ }
++ }
++ }
++
++ output_tests(tests, ARRAY_LEN(tests), a->fd);
++
++ return CLI_SUCCESS;
++}
++
++static char *handle_cli_performance_test(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
++{
++ unsigned int level;
++ unsigned int test;
++ struct test tests[] = {
++ { .name = "Log 10,000 messages",
++ },
++ };
++
++ switch (cmd) {
++ case CLI_INIT:
++ e->command = "logger test performance";
++ e->usage = ""
++ "Usage: logger test performance\n"
++ "";
++ return NULL;
++ case CLI_GENERATE:
++ return NULL;
++ }
++
++ for (test = 0; test < ARRAY_LEN(tests); test++) {
++ ast_cli(a->fd, "Test %d: %s.\n", test + 1, tests[test].name);
++ switch (test) {
++ case 0:
++ if ((level = ast_logger_register_level("perftest")) != -1) {
++ unsigned int x;
++ struct timeval start, end;
++ int elapsed;
++
++ ast_cli(a->fd, "Test: got level %d\n", level);
++ start = ast_tvnow();
++ for (x = 0; x < 10000; x++) {
++ ast_log_dynamic_level(level, "Performance test log message\n");
++ }
++ end = ast_tvnow();
++ elapsed = ast_tvdiff_ms(end, start);
++ ast_cli(a->fd, "Test: 10,000 messages in %f seconds.\n", (float) elapsed / 1000);
++ ast_logger_unregister_level("perftest");
++ tests[test].x_success++;
++ } else {
++ ast_cli(a->fd, "Test: Failed, could not register level 'perftest'.\n");
++ tests[test].u_failure++;
++ }
++ break;
++ }
++ }
++
++ output_tests(tests, ARRAY_LEN(tests), a->fd);
++
++ return CLI_SUCCESS;
++}
++
++static struct ast_cli_entry cli_logger[] = {
++ AST_CLI_DEFINE(handle_cli_dynamic_level_test, "Test the dynamic logger level implementation"),
++ AST_CLI_DEFINE(handle_cli_performance_test, "Test the logger performance"),
++};
++
++static int unload_module(void)
++{
++ ast_cli_unregister_multiple(cli_logger, ARRAY_LEN(cli_logger));
++ return 0;
++}
++
++static int load_module(void)
++{
++ ast_cli_register_multiple(cli_logger, ARRAY_LEN(cli_logger));
++ return AST_MODULE_LOAD_SUCCESS;
++}
++
++AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Logger Test Module");
+
+Property changes on: tests/test_logger.c
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+
+Index: tests/test_sched.c
+===================================================================
+--- a/tests/test_sched.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/tests/test_sched.c (.../trunk) (revision 202568)
+@@ -168,7 +168,7 @@
+ case CLI_INIT:
+ e->command = "sched benchmark";
+ e->usage = ""
+- "Usage: sched test <num>\n"
++ "Usage: sched benchmark <num>\n"
+ "";
+ return NULL;
+ case CLI_GENERATE:
+Index: tests/test_substitution.c
+===================================================================
+--- a/tests/test_substitution.c (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/tests/test_substitution.c (.../trunk) (revision 202568)
+@@ -0,0 +1,241 @@
++/*
++ * Asterisk -- An open source telephony toolkit.
++ *
++ * Copyright (C) 2009, Digium, Inc.
++ *
++ * Tilghman Lesher <tlesher AT digium DOT com>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * 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.
++ */
++
++/*! \file
++ *
++ * \brief Substitution Test
++ *
++ * \author\verbatim Tilghman Lesher <tlesher AT digium DOT com> \endverbatim
++ *
++ * \ingroup tests
++ */
++
++/*** MODULEINFO
++ <defaultenabled>no</defaultenabled>
++ ***/
++
++#include "asterisk.h"
++
++ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
++
++#include "asterisk/file.h"
++#include "asterisk/channel.h"
++#include "asterisk/pbx.h"
++#include "asterisk/module.h"
++#include "asterisk/lock.h"
++#include "asterisk/app.h"
++#include "asterisk/strings.h"
++#include "asterisk/stringfields.h"
++#include "asterisk/threadstorage.h"
++#include "asterisk/cli.h"
++
++AST_THREADSTORAGE(buf_buf);
++AST_THREADSTORAGE(var_buf);
++
++static void test_chan_integer(int fd, struct ast_channel *c, int *ifield, const char *expression)
++{
++ int i, okay = 1, value1 = -1, value2 = -1;
++ char workspace[4096];
++ struct ast_str *str = ast_str_thread_get(&buf_buf, 16);
++
++ for (i = 0; i < 256; i++) {
++ *ifield = i;
++ ast_str_substitute_variables(&str, 0, c, expression);
++ pbx_substitute_variables_helper(c, expression, workspace, sizeof(workspace));
++ if (sscanf(workspace, "%d", &value1) != 1 || value1 != i || sscanf(ast_str_buffer(str), "%d", &value2) != 1 || value2 != i) {
++ ast_cli(fd, "%s != %s and/or %d != %d != %d\n", ast_str_buffer(str), workspace, value1, value2, i);
++ okay = 0;
++ break;
++ }
++ }
++ ast_cli(fd, "Testing '%s' . . . . . %s\n", expression, okay ? "passed" : "FAILED");
++}
++
++static void test_chan_string(int fd, struct ast_channel *c, char *cfield, size_t cfieldsize, const char *expression)
++{
++ const char *values[] = { "one", "three", "reallylongdinosaursoundingthingwithwordsinit" };
++ int i, okay = 1;
++ char workspace[4096];
++ struct ast_str *str = ast_str_thread_get(&buf_buf, 16);
++
++ for (i = 0; i < ARRAY_LEN(values); i++) {
++ ast_copy_string(cfield, values[i], cfieldsize);
++ ast_str_substitute_variables(&str, 0, c, expression);
++ pbx_substitute_variables_helper(c, expression, workspace, sizeof(workspace));
++ if (strcmp(cfield, ast_str_buffer(str)) != 0 || strcmp(cfield, workspace) != 0) {
++ ast_cli(fd, "%s != %s != %s\n", cfield, ast_str_buffer(str), workspace);
++ okay = 0;
++ break;
++ }
++ }
++ ast_cli(fd, "Testing '%s' . . . . . %s\n", expression, okay ? "passed" : "FAILED");
++}
++
++static void test_chan_variable(int fd, struct ast_channel *c, const char *varname)
++{
++ const char *values[] = { "one", "three", "reallylongdinosaursoundingthingwithwordsinit" };
++ int i, okay = 1;
++ char workspace[4096];
++ struct ast_str *str = ast_str_thread_get(&buf_buf, 16);
++ struct ast_str *var = ast_str_thread_get(&var_buf, 16);
++
++ ast_str_set(&var, 0, "${%s}", varname);
++ for (i = 0; i < ARRAY_LEN(values); i++) {
++ pbx_builtin_setvar_helper(c, varname, values[i]);
++ ast_str_substitute_variables(&str, 0, c, ast_str_buffer(var));
++ pbx_substitute_variables_helper(c, ast_str_buffer(var), workspace, sizeof(workspace));
++ if (strcmp(values[i], ast_str_buffer(str)) != 0 || strcmp(values[i], workspace) != 0) {
++ ast_cli(fd, "%s != %s != %s\n", values[i], ast_str_buffer(str), workspace);
++ okay = 0;
++ break;
++ }
++ }
++ ast_cli(fd, "Testing '%s' . . . . . %s\n", ast_str_buffer(var), okay ? "passed" : "FAILED");
++}
++
++static void test_chan_function(int fd, struct ast_channel *c, const char *expression)
++{
++ int okay = 1;
++ char workspace[4096];
++ struct ast_str *str = ast_str_thread_get(&buf_buf, 16);
++
++ ast_str_substitute_variables(&str, 0, c, expression);
++ pbx_substitute_variables_helper(c, expression, workspace, sizeof(workspace));
++ if (strcmp(workspace, ast_str_buffer(str)) != 0) {
++ ast_cli(fd, "%s != %s\n", ast_str_buffer(str), workspace);
++ okay = 0;
++ }
++ ast_cli(fd, "Testing '%s' . . . . . %s\n", expression, okay ? "passed" : "FAILED");
++}
++
++static void test_2way_function(int fd, struct ast_channel *c, const char *encode1, const char *encode2, const char *decode1, const char *decode2)
++{
++ struct ast_str *str = ast_str_thread_get(&buf_buf, 16), *expression = ast_str_alloca(120);
++
++ ast_str_set(&expression, 0, "%s%s%s", encode1, "foobarbaz", encode2);
++ ast_str_substitute_variables(&str, 0, c, ast_str_buffer(expression));
++ ast_str_set(&expression, 0, "%s%s%s", decode1, ast_str_buffer(str), decode2);
++ ast_str_substitute_variables(&str, 0, c, ast_str_buffer(expression));
++ ast_cli(fd, "Testing '%s%s' and '%s%s' . . . . . %s\n", encode1, encode2, decode1, decode2, !strcmp(ast_str_buffer(str), "foobarbaz") ? "passed" : "FAILED");
++ if (strcmp(ast_str_buffer(str), "foobarbaz")) {
++ ast_cli(fd, " '%s' != 'foobarbaz'\n", ast_str_buffer(str));
++ }
++}
++
++static void test_expected_result(int fd, struct ast_channel *c, const char *expression, const char *result)
++{
++ struct ast_str *str = ast_str_thread_get(&buf_buf, 16);
++ ast_str_substitute_variables(&str, 0, c, expression);
++ ast_cli(fd, "Testing '%s' ('%s') == '%s' . . . . . %s\n", ast_str_buffer(str), expression, result, !strcmp(ast_str_buffer(str), result) ? "passed" : "FAILED");
++}
++
++static char *handle_cli_test_substitution(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
++{
++ struct ast_channel *c;
++ int i;
++
++ switch (cmd) {
++ case CLI_INIT:
++ e->command = "test substitution";
++ e->usage = ""
++ "Usage: test substitution\n"
++ " Test variable and function substitution.\n";
++ return NULL;
++ case CLI_GENERATE:
++ return NULL;
++ }
++
++ if (a->argc != e->args) {
++ return CLI_SHOWUSAGE;
++ }
++
++ ast_cli(a->fd, "Testing variable substitution ...\n");
++ c = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Test/substitution");
++
++ test_chan_integer(a->fd, c, &c->cid.cid_pres, "${CALLINGPRES}");
++ test_chan_integer(a->fd, c, &c->cid.cid_ani2, "${CALLINGANI2}");
++ test_chan_integer(a->fd, c, &c->cid.cid_ton, "${CALLINGTON}");
++ test_chan_integer(a->fd, c, &c->cid.cid_tns, "${CALLINGTNS}");
++ test_chan_integer(a->fd, c, &c->hangupcause, "${HANGUPCAUSE}");
++ test_chan_integer(a->fd, c, &c->priority, "${PRIORITY}");
++ test_chan_string(a->fd, c, c->context, sizeof(c->context), "${CONTEXT}");
++ test_chan_string(a->fd, c, c->exten, sizeof(c->exten), "${EXTEN}");
++ test_chan_variable(a->fd, c, "CHANNEL(language)");
++ test_chan_variable(a->fd, c, "CHANNEL(musicclass)");
++ test_chan_variable(a->fd, c, "CHANNEL(parkinglot)");
++ test_chan_variable(a->fd, c, "CALLERID(name)");
++ test_chan_variable(a->fd, c, "CURLOPT(proxyuserpwd)");
++ test_chan_variable(a->fd, c, "CDR(foo)");
++ test_chan_variable(a->fd, c, "ENV(foo)");
++ test_chan_variable(a->fd, c, "GLOBAL(foo)");
++ test_chan_variable(a->fd, c, "GROUP()");
++ test_2way_function(a->fd, c, "${AES_ENCRYPT(abcdefghijklmnop,", ")}", "${AES_DECRYPT(abcdefghijklmnop,", ")}");
++ test_2way_function(a->fd, c, "${BASE64_ENCODE(", ")}", "${BASE64_DECODE(", ")}");
++ pbx_builtin_setvar_helper(c, "foo", "123");
++ pbx_builtin_setvar_helper(c, "bar", "foo");
++ pbx_builtin_setvar_helper(c, "baz", "fo");
++ test_expected_result(a->fd, c, "${foo}${foo}", "123123");
++ test_expected_result(a->fd, c, "A${foo}A${foo}A", "A123A123A");
++ test_expected_result(a->fd, c, "A${${bar}}A", "A123A");
++ test_expected_result(a->fd, c, "A${${baz}o}A", "A123A");
++ test_expected_result(a->fd, c, "A${${baz}o:1}A", "A23A");
++ test_expected_result(a->fd, c, "A${${baz}o:1:1}A", "A2A");
++ test_expected_result(a->fd, c, "A${${baz}o:1:-1}A", "A2A");
++ test_expected_result(a->fd, c, "A${${baz}o:-1:1}A", "A3A");
++ test_expected_result(a->fd, c, "A${${baz}o:-2:1}A", "A2A");
++ test_expected_result(a->fd, c, "A${${baz}o:-2:-1}A", "A2A");
++
++ /* For testing dialplan functions */
++ for (i = 0; ; i++) {
++ char *cmd = ast_cli_generator("core show function", "", i);
++ if (cmd == NULL) {
++ break;
++ }
++ if (strcmp(cmd, "CHANNEL") && strcmp(cmd, "CALLERID") && strcmp(cmd, "CURLOPT") && strncmp(cmd, "AES", 3) && strncmp(cmd, "BASE64", 6) && strcmp(cmd, "CDR") && strcmp(cmd, "ENV") && strcmp(cmd, "GLOBAL") && strcmp(cmd, "GROUP") && strcmp(cmd, "CUT") && strcmp(cmd, "LISTFILTER") && strcmp(cmd, "PP_EACH_EXTENSION") && strcmp(cmd, "SET")) {
++ struct ast_custom_function *acf = ast_custom_function_find(cmd);
++ if (acf->read && acf->read2) {
++ char expression[80];
++ snprintf(expression, sizeof(expression), "${%s(foo)}", cmd);
++ test_chan_function(a->fd, c, expression);
++ }
++ }
++ ast_free(cmd);
++ }
++
++ ast_hangup(c);
++
++ return CLI_SUCCESS;
++}
++
++static struct ast_cli_entry cli_substitution[] = {
++ AST_CLI_DEFINE(handle_cli_test_substitution, "Test variable substitution"),
++};
++
++static int unload_module(void)
++{
++ ast_cli_unregister_multiple(cli_substitution, ARRAY_LEN(cli_substitution));
++ return 0;
++}
++
++static int load_module(void)
++{
++ ast_cli_register_multiple(cli_substitution, ARRAY_LEN(cli_substitution));
++ return AST_MODULE_LOAD_SUCCESS;
++}
++
++AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Substitution tests");
+
+Property changes on: tests/test_substitution.c
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+
+Index: tests/test_skel.c
+===================================================================
+--- a/tests/test_skel.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/tests/test_skel.c (.../trunk) (revision 202568)
+@@ -40,6 +40,7 @@
+ #include "asterisk/module.h"
+ #include "asterisk/lock.h"
+ #include "asterisk/app.h"
++#include "asterisk/cli.h"
+
+ static int unload_module(void)
+ {
+Index: configure.ac
+===================================================================
+--- a/configure.ac (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configure.ac (.../trunk) (revision 202568)
+@@ -244,6 +244,7 @@
+ AST_EXT_LIB_SETUP([GTK2], [gtk2 libraries], [gtk2])
+ AST_EXT_LIB_SETUP([GMIME], [GMime library], [gmime])
+ AST_EXT_LIB_SETUP([HOARD], [Hoard Memory Allocator], [hoard])
++AST_EXT_LIB_SETUP([ICAL], [ical libraries], [ical])
+ AST_EXT_LIB_SETUP([ICONV], [Iconv Library], [iconv])
+ AST_EXT_LIB_SETUP([IKSEMEL], [Iksemel Jabber Library], [iksemel])
+ AST_EXT_LIB_SETUP([IMAP_TK], [UW IMAP Toolkit], [imap])
+@@ -258,6 +259,7 @@
+ AST_EXT_LIB_SETUP([MISDN], [mISDN User Library], [misdn])
+ AST_EXT_LIB_SETUP([NBS], [Network Broadcast Sound], [nbs])
+ AST_EXT_LIB_SETUP([NCURSES], [ncurses], [ncurses])
++AST_EXT_LIB_SETUP([NEON], [neon], [neon])
+ AST_EXT_LIB_SETUP([NETSNMP], [Net-SNMP], [netsnmp])
+ AST_EXT_LIB_SETUP([NEWT], [newt], [newt])
+ AST_EXT_LIB_SETUP([OGG], [OGG], [ogg])
+@@ -512,9 +514,8 @@
+ AST_GCC_ATTRIBUTE(deprecated)
+ AST_GCC_ATTRIBUTE(sentinel)
+ AST_GCC_ATTRIBUTE(warn_unused_result)
+-AST_GCC_ATTRIBUTE(weak)
++AST_GCC_ATTRIBUTE(weakref, [weakref("foo")], static)
+ AST_GCC_ATTRIBUTE(weak_import)
+-AST_GCC_ATTRIBUTE(alias, [alias("foo")])
+
+ AC_MSG_CHECKING(for -ffunction-sections support)
+ saved_CFLAGS="${CFLAGS}"
+@@ -627,6 +628,10 @@
+ AC_MSG_RESULT(no)
+ )
+
++AST_C_DEFINE_CHECK([GLOB_NOMAGIC], [GLOB_NOMAGIC], [glob.h])
++
++AST_C_DEFINE_CHECK([GLOB_BRACE], [GLOB_BRACE], [glob.h])
++
+ AST_C_DEFINE_CHECK([IP_MTU_DISCOVER], [IP_MTU_DISCOVER], [netinet/in.h])
+
+ AC_CHECK_HEADER([libkern/OSAtomic.h],
+@@ -650,6 +655,8 @@
+
+ AST_C_COMPILE_CHECK([DAHDI_LINEREVERSE_VMWI], [struct dahdi_vmwi_info booger], [dahdi/user.h], , [enhanced dahdi vmwi support])
+
++AST_C_COMPILE_CHECK([DAHDI_ECHOCANCEL_FAX_MODE], [int foo = DAHDI_ECHOCANCEL_FAX_MODE], [dahdi/user.h])
++
+ # BSD might not have exp2, and/or log2
+ AST_EXT_LIB_CHECK([EXP2L], [m], [exp2l])
+ AST_EXT_LIB_CHECK([LOG2L], [m], [log2l])
+@@ -773,6 +780,8 @@
+ PBX_ICONV=1
+ fi
+
++AST_EXT_LIB_CHECK([ICAL], [ical], [icaltimezone_new], [libical/ical.h], [-lpthread])
++
+ AST_EXT_LIB_CHECK([IKSEMEL], [iksemel], [iks_start_sasl], [iksemel.h])
+
+ if test "${USE_IMAP_TK}" != "no"; then
+@@ -1344,6 +1353,8 @@
+
+ AST_EXT_LIB_CHECK([NCURSES], [ncurses], [initscr], [curses.h])
+
++AST_EXT_TOOL_CHECK([NEON], [neon])
++
+ AST_EXT_TOOL_CHECK([NETSNMP], [net-snmp], , [--agent-libs],
+ [#include <net-snmp/net-snmp-config.h>
+ #include <net-snmp/net-snmp-includes.h>
+@@ -1422,6 +1433,8 @@
+
+ AST_EXT_LIB_CHECK([PRI_INBANDDISCONNECT], [pri], [pri_set_inbanddisconnect], [libpri.h])
+
++AST_EXT_LIB_CHECK([PRI_SERVICE_MESSAGES], [pri], [pri_maintenance_service], [libpri.h])
++
+ AST_EXT_LIB_CHECK([RESAMPLE], [resample], [resample_open], [libresample.h], [-lm])
+
+ AST_C_COMPILE_CHECK([SPANDSP], [
+Index: apps/app_dahdiscan.c
+===================================================================
+--- a/apps/app_dahdiscan.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_dahdiscan.c (.../trunk) (revision 202568)
+@@ -1,378 +0,0 @@
+-/*
+- * Asterisk -- An open source telephony toolkit.
+- *
+- * Copyright (C) 1999 - 2005, Digium, Inc.
+- *
+- * Mark Spencer <markster@digium.com>
+- *
+- * Modified from app_zapbarge by David Troy <dave@toad.net>
+- *
+- * Special thanks to comphealth.com for sponsoring this
+- * GPL application.
+- *
+- * See http://www.asterisk.org for more information about
+- * the Asterisk project. Please do not directly contact
+- * any of the maintainers of this project for assistance;
+- * the project provides a web site, mailing lists and IRC
+- * channels for your use.
+- *
+- * 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.
+- */
+-
+-/*! \file
+- *
+- * \brief DAHDI Scanner
+- *
+- * \author Mark Spencer <markster@digium.com>
+- *
+- * \ingroup applications
+- */
+-
+-/*** MODULEINFO
+- <depend>dahdi</depend>
+- ***/
+-
+-#include "asterisk.h"
+-
+-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 153365 $")
+-
+-#include <dahdi/user.h>
+-
+-#include "asterisk/lock.h"
+-#include "asterisk/file.h"
+-#include "asterisk/channel.h"
+-#include "asterisk/pbx.h"
+-#include "asterisk/module.h"
+-#include "asterisk/config.h"
+-#include "asterisk/app.h"
+-#include "asterisk/utils.h"
+-#include "asterisk/cli.h"
+-#include "asterisk/say.h"
+-#include "asterisk/options.h"
+-
+-/*** DOCUMENTATION
+- <application name="DAHDIScan" language="en_US">
+- <synopsis>
+- Scan DAHDI channels to monitor calls.
+- </synopsis>
+- <syntax>
+- <parameter name="group">
+- <para>Limit scanning to a channel <replaceable>group</replaceable> by setting this option.</para>
+- </parameter>
+- </syntax>
+- <description>
+- <para>Allows a call center manager to monitor DAHDI channels in a
+- convenient way. Use <literal>#</literal> to select the next channel and use <literal>*</literal> to exit.</para>
+- </description>
+- </application>
+- ***/
+-static char *app = "DAHDIScan";
+-
+-#define CONF_SIZE 160
+-
+-static struct ast_channel *get_dahdi_channel_locked(int num) {
+- char name[80];
+-
+- snprintf(name, sizeof(name), "DAHDI/%d-1", num);
+- return ast_get_channel_by_name_locked(name);
+-}
+-
+-static int careful_write(int fd, unsigned char *data, int len)
+-{
+- int res;
+- while (len) {
+- res = write(fd, data, len);
+- if (res < 1) {
+- if (errno != EAGAIN) {
+- ast_log(LOG_WARNING, "Failed to write audio data to conference: %s\n", strerror(errno));
+- return -1;
+- } else {
+- return 0;
+- }
+- }
+- len -= res;
+- data += res;
+- }
+- return 0;
+-}
+-
+-static int conf_run(struct ast_channel *chan, int confno, int confflags)
+-{
+- int fd;
+- struct dahdi_confinfo dahdic;
+- struct ast_frame *f;
+- struct ast_channel *c;
+- struct ast_frame fr;
+- int outfd;
+- int ms;
+- int nfds;
+- int res;
+- int flags;
+- int retrydahdi;
+- int origfd;
+- int ret = -1;
+- char input[4];
+- int ic = 0;
+-
+- struct dahdi_bufferinfo bi;
+- char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET];
+- char *buf = __buf + AST_FRIENDLY_OFFSET;
+-
+- /* Set it into U-law mode (write) */
+- if (ast_set_write_format(chan, AST_FORMAT_ULAW) < 0) {
+- ast_log(LOG_WARNING, "Unable to set '%s' to write ulaw mode\n", chan->name);
+- goto outrun;
+- }
+-
+- /* Set it into U-law mode (read) */
+- if (ast_set_read_format(chan, AST_FORMAT_ULAW) < 0) {
+- ast_log(LOG_WARNING, "Unable to set '%s' to read ulaw mode\n", chan->name);
+- goto outrun;
+- }
+- ast_indicate(chan, -1);
+- retrydahdi = strcasecmp(chan->tech->type, "DAHDI");
+- dahdiretry:
+- origfd = chan->fds[0];
+- if (retrydahdi) {
+- fd = open("/dev/dahdi/pseudo", O_RDWR);
+- if (fd < 0) {
+- ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
+- goto outrun;
+- }
+- /* Make non-blocking */
+- flags = fcntl(fd, F_GETFL);
+- if (flags < 0) {
+- ast_log(LOG_WARNING, "Unable to get flags: %s\n", strerror(errno));
+- close(fd);
+- goto outrun;
+- }
+- if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) {
+- ast_log(LOG_WARNING, "Unable to set flags: %s\n", strerror(errno));
+- close(fd);
+- goto outrun;
+- }
+- /* Setup buffering information */
+- memset(&bi, 0, sizeof(bi));
+- bi.bufsize = CONF_SIZE;
+- bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
+- bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
+- bi.numbufs = 4;
+- if (ioctl(fd, DAHDI_SET_BUFINFO, &bi)) {
+- ast_log(LOG_WARNING, "Unable to set buffering information: %s\n", strerror(errno));
+- close(fd);
+- goto outrun;
+- }
+- nfds = 1;
+- } else {
+- /* XXX Make sure we're not running on a pseudo channel XXX */
+- fd = chan->fds[0];
+- nfds = 0;
+- }
+- memset(&dahdic, 0, sizeof(dahdic));
+- /* Check to see if we're in a conference... */
+- dahdic.chan = 0;
+- if (ioctl(fd, DAHDI_GETCONF, &dahdic)) {
+- ast_log(LOG_WARNING, "Error getting conference\n");
+- close(fd);
+- goto outrun;
+- }
+- if (dahdic.confmode) {
+- /* Whoa, already in a conference... Retry... */
+- if (!retrydahdi) {
+- ast_debug(1, "DAHDI channel is in a conference already, retrying with pseudo\n");
+- retrydahdi = 1;
+- goto dahdiretry;
+- }
+- }
+- memset(&dahdic, 0, sizeof(dahdic));
+- /* Add us to the conference */
+- dahdic.chan = 0;
+- dahdic.confno = confno;
+- dahdic.confmode = DAHDI_CONF_MONITORBOTH;
+-
+- if (ioctl(fd, DAHDI_SETCONF, &dahdic)) {
+- ast_log(LOG_WARNING, "Error setting conference\n");
+- close(fd);
+- goto outrun;
+- }
+- ast_debug(1, "Placed channel %s in DAHDI channel %d monitor\n", chan->name, confno);
+-
+- for (;;) {
+- outfd = -1;
+- ms = -1;
+- c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms);
+- if (c) {
+- if (c->fds[0] != origfd) {
+- if (retrydahdi) {
+- /* Kill old pseudo */
+- close(fd);
+- }
+- ast_debug(1, "Ooh, something swapped out under us, starting over\n");
+- retrydahdi = 0;
+- goto dahdiretry;
+- }
+- f = ast_read(c);
+- if (!f) {
+- break;
+- }
+- if (f->frametype == AST_FRAME_DTMF) {
+- if (f->subclass == '#') {
+- ret = 0;
+- break;
+- } else if (f->subclass == '*') {
+- ret = -1;
+- break;
+- } else {
+- input[ic++] = f->subclass;
+- }
+- if (ic == 3) {
+- input[ic++] = '\0';
+- ic = 0;
+- ret = atoi(input);
+- ast_verb(3, "DAHDIScan: change channel to %d\n", ret);
+- break;
+- }
+- }
+-
+- if (fd != chan->fds[0]) {
+- if (f->frametype == AST_FRAME_VOICE) {
+- if (f->subclass == AST_FORMAT_ULAW) {
+- /* Carefully write */
+- careful_write(fd, f->data.ptr, f->datalen);
+- } else {
+- ast_log(LOG_WARNING, "Huh? Got a non-ulaw (%d) frame in the conference\n", f->subclass);
+- }
+- }
+- }
+- ast_frfree(f);
+- } else if (outfd > -1) {
+- res = read(outfd, buf, CONF_SIZE);
+- if (res > 0) {
+- memset(&fr, 0, sizeof(fr));
+- fr.frametype = AST_FRAME_VOICE;
+- fr.subclass = AST_FORMAT_ULAW;
+- fr.datalen = res;
+- fr.samples = res;
+- fr.data.ptr = buf;
+- fr.offset = AST_FRIENDLY_OFFSET;
+- if (ast_write(chan, &fr) < 0) {
+- ast_log(LOG_WARNING, "Unable to write frame to channel: %s\n", strerror(errno));
+- /* break; */
+- }
+- } else {
+- ast_log(LOG_WARNING, "Failed to read frame: %s\n", strerror(errno));
+- }
+- }
+- }
+- if (f) {
+- ast_frfree(f);
+- }
+- if (fd != chan->fds[0]) {
+- close(fd);
+- } else {
+- /* Take out of conference */
+- /* Add us to the conference */
+- dahdic.chan = 0;
+- dahdic.confno = 0;
+- dahdic.confmode = 0;
+- if (ioctl(fd, DAHDI_SETCONF, &dahdic)) {
+- ast_log(LOG_WARNING, "Error setting conference\n");
+- }
+- }
+-
+- outrun:
+-
+- return ret;
+-}
+-
+-static int conf_exec(struct ast_channel *chan, void *data)
+-{
+- int res=-1;
+- int confflags = 0;
+- int confno = 0;
+- char confnostr[80] = "", *tmp = NULL;
+- struct ast_channel *tempchan = NULL, *lastchan = NULL, *ichan = NULL;
+- struct ast_frame *f;
+- char *desired_group;
+- int input = 0, search_group = 0;
+-
+- if (chan->_state != AST_STATE_UP)
+- ast_answer(chan);
+-
+- desired_group = ast_strdupa(data);
+- if (!ast_strlen_zero(desired_group)) {
+- ast_verb(3, "Scanning for group %s\n", desired_group);
+- search_group = 1;
+- }
+-
+- for (;;) {
+- if (ast_waitfor(chan, 100) < 0)
+- break;
+-
+- f = ast_read(chan);
+- if (!f)
+- break;
+- if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '*')) {
+- ast_frfree(f);
+- break;
+- }
+- ast_frfree(f);
+- ichan = NULL;
+- if(input) {
+- ichan = get_dahdi_channel_locked(input);
+- input = 0;
+- }
+-
+- tempchan = ichan ? ichan : ast_channel_walk_locked(tempchan);
+-
+- if (!tempchan && !lastchan) {
+- break;
+- }
+-
+- if (tempchan && search_group) {
+- const char *mygroup;
+- if ((mygroup = pbx_builtin_getvar_helper(tempchan, "GROUP")) && (!strcmp(mygroup, desired_group))) {
+- ast_verb(3, "Found Matching Channel %s in group %s\n", tempchan->name, desired_group);
+- } else {
+- ast_channel_unlock(tempchan);
+- lastchan = tempchan;
+- continue;
+- }
+- }
+- if (tempchan && (!strcmp(tempchan->tech->type, "DAHDI")) && (tempchan != chan)) {
+- ast_verb(3, "DAHDI channel %s is in-use, monitoring...\n", tempchan->name);
+- ast_copy_string(confnostr, tempchan->name, sizeof(confnostr));
+- ast_channel_unlock(tempchan);
+- if ((tmp = strchr(confnostr, '-'))) {
+- *tmp = '\0';
+- }
+- confno = atoi(strchr(confnostr, '/') + 1);
+- ast_stopstream(chan);
+- ast_say_number(chan, confno, AST_DIGIT_ANY, chan->language, (char *) NULL);
+- res = conf_run(chan, confno, confflags);
+- if (res < 0) {
+- break;
+- }
+- input = res;
+- } else if (tempchan) {
+- ast_channel_unlock(tempchan);
+- }
+- lastchan = tempchan;
+- }
+- return res;
+-}
+-
+-static int unload_module(void)
+-{
+- return ast_unregister_application(app);
+-}
+-
+-static int load_module(void)
+-{
+- return ((ast_register_application_xml(app, conf_exec)) ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_SUCCESS);
+-}
+-
+-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Scan DAHDI channels application");
+-
+Index: apps/app_stack.c
+===================================================================
+--- a/apps/app_stack.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_stack.c (.../trunk) (revision 202568)
+@@ -164,12 +164,27 @@
+ <ref type="application">Return</ref>
+ </see-also>
+ </function>
++ <agi name="gosub" language="en_US">
++ <synopsis>
++ Cause the channel to execute the specified dialplan subroutine.
++ </synopsis>
++ <syntax>
++ <parameter name="context" required="true" />
++ <parameter name="extension" required="true" />
++ <parameter name="priority" required="true" />
++ <parameter name="optional-argument" />
++ </syntax>
++ <description>
++ <para>Cause the channel to execute the specified dialplan subroutine,
++ returning to the dialplan with execution of a Return().</para>
++ </description>
++ </agi>
+ ***/
+
+-static const char *app_gosub = "Gosub";
+-static const char *app_gosubif = "GosubIf";
+-static const char *app_return = "Return";
+-static const char *app_pop = "StackPop";
++static const char * const app_gosub = "Gosub";
++static const char * const app_gosubif = "GosubIf";
++static const char * const app_return = "Return";
++static const char * const app_pop = "StackPop";
+
+ static void gosub_free(void *data);
+
+@@ -266,7 +281,7 @@
+ ast_free(oldlist);
+ }
+
+-static int pop_exec(struct ast_channel *chan, void *data)
++static int pop_exec(struct ast_channel *chan, const char *data)
+ {
+ struct ast_datastore *stack_store = ast_channel_datastore_find(chan, &stack_info, NULL);
+ struct gosub_stack_frame *oldframe;
+@@ -290,12 +305,12 @@
+ return 0;
+ }
+
+-static int return_exec(struct ast_channel *chan, void *data)
++static int return_exec(struct ast_channel *chan, const char *data)
+ {
+ struct ast_datastore *stack_store = ast_channel_datastore_find(chan, &stack_info, NULL);
+ struct gosub_stack_frame *oldframe;
+ AST_LIST_HEAD(, gosub_stack_frame) *oldlist;
+- char *retval = data;
++ const char *retval = data;
+
+ if (!stack_store) {
+ ast_log(LOG_ERROR, "Return without Gosub: stack is unallocated\n");
+@@ -320,7 +335,7 @@
+ return 0;
+ }
+
+-static int gosub_exec(struct ast_channel *chan, void *data)
++static int gosub_exec(struct ast_channel *chan, const char *data)
+ {
+ struct ast_datastore *stack_store = ast_channel_datastore_find(chan, &stack_info, NULL);
+ AST_LIST_HEAD(, gosub_stack_frame) *oldlist;
+@@ -410,7 +425,7 @@
+ return 0;
+ }
+
+-static int gosubif_exec(struct ast_channel *chan, void *data)
++static int gosubif_exec(struct ast_channel *chan, const char *data)
+ {
+ char *args;
+ int res=0;
+@@ -537,7 +552,7 @@
+ .read = peek_read,
+ };
+
+-static int handle_gosub(struct ast_channel *chan, AGI *agi, int argc, char **argv)
++static int handle_gosub(struct ast_channel *chan, AGI *agi, int argc, const char * const *argv)
+ {
+ int old_priority, priority;
+ char old_context[AST_MAX_CONTEXT], old_extension[AST_MAX_EXTENSION];
+@@ -627,19 +642,12 @@
+ return RESULT_SUCCESS;
+ }
+
+-static char usage_gosub[] =
+-" Usage: GOSUB <context> <extension> <priority> [<optional-argument>]\n"
+-" Cause the channel to execute the specified dialplan subroutine, returning\n"
+-" to the dialplan with execution of a Return()\n";
++static struct agi_command gosub_agi_command =
++ { { "gosub", NULL }, handle_gosub, NULL, NULL, 0 };
+
+-struct agi_command gosub_agi_command =
+- { { "gosub", NULL }, handle_gosub, "Execute a dialplan subroutine", usage_gosub , 0 };
+-
+ static int unload_module(void)
+ {
+- if (ast_agi_unregister) {
+- ast_agi_unregister(ast_module_info->self, &gosub_agi_command);
+- }
++ ast_agi_unregister(ast_module_info->self, &gosub_agi_command);
+
+ ast_unregister_application(app_return);
+ ast_unregister_application(app_pop);
+@@ -653,9 +661,7 @@
+
+ static int load_module(void)
+ {
+- if (ast_agi_register) {
+- ast_agi_register(ast_module_info->self, &gosub_agi_command);
+- }
++ ast_agi_register(ast_module_info->self, &gosub_agi_command);
+
+ ast_register_application_xml(app_pop, pop_exec);
+ ast_register_application_xml(app_return, return_exec);
+Index: apps/app_chanspy.c
+===================================================================
+--- a/apps/app_chanspy.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_chanspy.c (.../trunk) (revision 202568)
+@@ -50,6 +50,7 @@
+ #include "asterisk/module.h"
+ #include "asterisk/lock.h"
+ #include "asterisk/options.h"
++#include "asterisk/autochan.h"
+
+ #define AST_NAME_STRLEN 256
+ #define NUM_SPYGROUPS 128
+@@ -141,6 +142,16 @@
+ name of the last channel that was spied on will be stored
+ in the <variable>SPY_CHANNEL</variable> variable.</para>
+ </option>
++ <option name="x">
++ <argument name="digit" required="true">
++ <para>Specify a DTMF digit that can be used to exit the application.</para>
++ </argument>
++ </option>
++ <option name="c">
++ <argument name="digit" required="true">
++ <para>Specify a DTMF digit that can be used to spy on the next available channel.</para>
++ </argument>
++ </option>
+ <option name="e">
+ <argument name="ext" required="true" />
+ <para>Enable <emphasis>enforced</emphasis> mode, so the spying channel can
+@@ -262,6 +273,16 @@
+ name of the last channel that was spied on will be stored
+ in the <variable>SPY_CHANNEL</variable> variable.</para>
+ </option>
++ <option name="x">
++ <argument name="digit" required="true">
++ <para>Specify a DTMF digit that can be used to exit the application.</para>
++ </argument>
++ </option>
++ <option name="c">
++ <argument name="digit" required="true">
++ <para>Specify a DTMF digit that can be used to spy on the next available channel.</para>
++ </argument>
++ </option>
+ <option name="e">
+ <argument name="ext" required="true" />
+ <para>Enable <emphasis>enforced</emphasis> mode, so the spying channel can
+@@ -287,12 +308,29 @@
+ <ref type="application">ChanSpy</ref>
+ </see-also>
+ </application>
+-
++
++ <application name="DAHDIScan" language="en_US">
++ <synopsis>
++ Scan DAHDI channels to monitor calls.
++ </synopsis>
++ <syntax>
++ <parameter name="group">
++ <para>Limit scanning to a channel <replaceable>group</replaceable> by setting this option.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Allows a call center manager to monitor DAHDI channels in a
++ convenient way. Use <literal>#</literal> to select the next channel and use <literal>*</literal> to exit.</para>
++ </description>
++ </application>
+ ***/
+-static const char *app_chan = "ChanSpy";
+
+-static const char *app_ext = "ExtenSpy";
++static const char app_chan[] = "ChanSpy";
+
++static const char app_ext[] = "ExtenSpy";
++
++static const char app_dahdiscan[] = "DAHDIScan";
++
+ enum {
+ OPTION_QUIET = (1 << 0), /* Quiet, no announcement */
+ OPTION_BRIDGED = (1 << 1), /* Only look at bridged calls */
+@@ -307,8 +345,11 @@
+ OPTION_NOTECH = (1 << 10), /* Skip technology name playback */
+ OPTION_BARGE = (1 << 11), /* Barge mode (whisper to both channels) */
+ OPTION_NAME = (1 << 12), /* Say the name of the person on whom we will spy */
+- OPTION_DTMF_SWITCH_MODES = (1 << 13), /*Allow numeric DTMF to switch between chanspy modes */
+-} chanspy_opt_flags;
++ OPTION_DTMF_SWITCH_MODES = (1 << 13), /* Allow numeric DTMF to switch between chanspy modes */
++ OPTION_DTMF_EXIT = (1 << 14), /* Set DTMF to exit, added for DAHDIScan integration */
++ OPTION_DTMF_CYCLE = (1 << 15), /* Custom DTMF for cycling next avaliable channel, (default is '*') */
++ OPTION_DAHDI_SCAN = (1 << 16), /* Scan groups in DAHDIScan mode */
++};
+
+ enum {
+ OPT_ARG_VOLUME = 0,
+@@ -316,8 +357,10 @@
+ OPT_ARG_RECORD,
+ OPT_ARG_ENFORCED,
+ OPT_ARG_NAME,
++ OPT_ARG_EXIT,
++ OPT_ARG_CYCLE,
+ OPT_ARG_ARRAY_SIZE,
+-} chanspy_opt_args;
++};
+
+ AST_APP_OPTIONS(spy_opts, {
+ AST_APP_OPTION('q', OPTION_QUIET),
+@@ -334,10 +377,10 @@
+ AST_APP_OPTION('s', OPTION_NOTECH),
+ AST_APP_OPTION_ARG('n', OPTION_NAME, OPT_ARG_NAME),
+ AST_APP_OPTION('d', OPTION_DTMF_SWITCH_MODES),
++ AST_APP_OPTION_ARG('x', OPTION_DTMF_EXIT, OPT_ARG_EXIT),
++ AST_APP_OPTION_ARG('c', OPTION_DTMF_CYCLE, OPT_ARG_CYCLE),
+ });
+
+-static int next_unique_id_to_use = 0;
+-
+ struct chanspy_translation_helper {
+ /* spy data */
+ struct ast_audiohook spy_audiohook;
+@@ -347,6 +390,12 @@
+ int volfactor;
+ };
+
++struct spy_dtmf_options {
++ char exit;
++ char cycle;
++ char volume;
++};
++
+ static void *spy_alloc(struct ast_channel *chan, void *data)
+ {
+ /* just store the data pointer in the channel structure */
+@@ -361,7 +410,7 @@
+ static int spy_generate(struct ast_channel *chan, void *data, int len, int samples)
+ {
+ struct chanspy_translation_helper *csth = data;
+- struct ast_frame *f = NULL;
++ struct ast_frame *f, *cur;
+
+ ast_audiohook_lock(&csth->spy_audiohook);
+ if (csth->spy_audiohook.status != AST_AUDIOHOOK_STATUS_RUNNING) {
+@@ -377,14 +426,16 @@
+ if (!f)
+ return 0;
+
+- if (ast_write(chan, f)) {
+- ast_frfree(f);
+- return -1;
+- }
++ for (cur = f; cur; cur = AST_LIST_NEXT(cur, frame_list)) {
++ if (ast_write(chan, cur)) {
++ ast_frfree(f);
++ return -1;
++ }
+
+- if (csth->fd) {
+- if (write(csth->fd, f->data.ptr, f->datalen) < 0) {
+- ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
++ if (csth->fd) {
++ if (write(csth->fd, cur->data.ptr, cur->datalen) < 0) {
++ ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
++ }
+ }
+ }
+
+@@ -399,28 +450,22 @@
+ .generate = spy_generate,
+ };
+
+-static int start_spying(struct ast_channel *chan, const char *spychan_name, struct ast_audiohook *audiohook)
++static int start_spying(struct ast_autochan *autochan, const char *spychan_name, struct ast_audiohook *audiohook)
+ {
+ int res = 0;
+ struct ast_channel *peer = NULL;
+
+- ast_log(LOG_NOTICE, "Attaching %s to %s\n", spychan_name, chan->name);
++ ast_log(LOG_NOTICE, "Attaching %s to %s\n", spychan_name, autochan->chan->name);
+
+ ast_set_flag(audiohook, AST_AUDIOHOOK_TRIGGER_SYNC | AST_AUDIOHOOK_SMALL_QUEUE);
+- res = ast_audiohook_attach(chan, audiohook);
++ res = ast_audiohook_attach(autochan->chan, audiohook);
+
+- if (!res && ast_test_flag(chan, AST_FLAG_NBRIDGE) && (peer = ast_bridged_channel(chan))) {
++ if (!res && ast_test_flag(autochan->chan, AST_FLAG_NBRIDGE) && (peer = ast_bridged_channel(autochan->chan))) {
+ ast_softhangup(peer, AST_SOFTHANGUP_UNBRIDGE);
+ }
+ return res;
+ }
+
+-struct chanspy_ds {
+- struct ast_channel *chan;
+- char unique_id[20];
+- ast_mutex_t lock;
+-};
+-
+ static void change_spy_mode(const char digit, struct ast_flags *flags)
+ {
+ if (digit == '4') {
+@@ -435,8 +480,9 @@
+ }
+ }
+
+-static int channel_spy(struct ast_channel *chan, struct chanspy_ds *spyee_chanspy_ds,
+- int *volfactor, int fd, struct ast_flags *flags, char *exitcontext)
++static int channel_spy(struct ast_channel *chan, struct ast_autochan *spyee_autochan,
++ int *volfactor, int fd, struct spy_dtmf_options *user_options, struct ast_flags *flags,
++ char *exitcontext)
+ {
+ struct chanspy_translation_helper csth;
+ int running = 0, res, x = 0;
+@@ -444,32 +490,22 @@
+ char *name;
+ struct ast_frame *f;
+ struct ast_silence_generator *silgen = NULL;
+- struct ast_channel *spyee = NULL, *spyee_bridge = NULL;
++ struct ast_autochan *spyee_bridge_autochan = NULL;
+ const char *spyer_name;
+
+ ast_channel_lock(chan);
+ spyer_name = ast_strdupa(chan->name);
+ ast_channel_unlock(chan);
+
+- ast_mutex_lock(&spyee_chanspy_ds->lock);
+- if (spyee_chanspy_ds->chan) {
+- spyee = spyee_chanspy_ds->chan;
+- ast_channel_lock(spyee);
+- }
+- ast_mutex_unlock(&spyee_chanspy_ds->lock);
+-
+- if (!spyee) {
+- return 0;
+- }
+-
+ /* We now hold the channel lock on spyee */
+
+- if (ast_check_hangup(chan) || ast_check_hangup(spyee)) {
+- ast_channel_unlock(spyee);
++ if (ast_check_hangup(chan) || ast_check_hangup(spyee_autochan->chan)) {
+ return 0;
+ }
+
+- name = ast_strdupa(spyee->name);
++ ast_channel_lock(spyee_autochan->chan);
++ name = ast_strdupa(spyee_autochan->chan->name);
++ ast_channel_unlock(spyee_autochan->chan);
+
+ ast_verb(2, "Spying on channel %s\n", name);
+ manager_event(EVENT_FLAG_CALL, "ChanSpyStart",
+@@ -481,26 +517,23 @@
+
+ ast_audiohook_init(&csth.spy_audiohook, AST_AUDIOHOOK_TYPE_SPY, "ChanSpy");
+
+- if (start_spying(spyee, spyer_name, &csth.spy_audiohook)) {
++ if (start_spying(spyee_autochan, spyer_name, &csth.spy_audiohook)) {
+ ast_audiohook_destroy(&csth.spy_audiohook);
+- ast_channel_unlock(spyee);
+ return 0;
+ }
+
+- ast_audiohook_init(&csth.whisper_audiohook, AST_AUDIOHOOK_TYPE_WHISPER, "ChanSpy");
++ ast_audiohook_init(&csth.whisper_audiohook, AST_AUDIOHOOK_TYPE_WHISPER, "ChanSpy");
+ ast_audiohook_init(&csth.bridge_whisper_audiohook, AST_AUDIOHOOK_TYPE_WHISPER, "Chanspy");
+- if (start_spying(spyee, spyer_name, &csth.whisper_audiohook)) {
+- ast_log(LOG_WARNING, "Unable to attach whisper audiohook to spyee %s. Whisper mode disabled!\n", spyee->name);
++ if (start_spying(spyee_autochan, spyer_name, &csth.whisper_audiohook)) {
++ ast_log(LOG_WARNING, "Unable to attach whisper audiohook to spyee %s. Whisper mode disabled!\n", name);
+ }
+- if ((spyee_bridge = ast_bridged_channel(spyee))) {
+- ast_channel_lock(spyee_bridge);
+- if (start_spying(spyee_bridge, spyer_name, &csth.bridge_whisper_audiohook)) {
+- ast_log(LOG_WARNING, "Unable to attach barge audiohook on spyee %s. Barge mode disabled!\n", spyee->name);
++ if ((spyee_bridge_autochan = ast_autochan_setup(ast_bridged_channel(spyee_autochan->chan)))) {
++ ast_channel_lock(spyee_bridge_autochan->chan);
++ if (start_spying(spyee_bridge_autochan, spyer_name, &csth.bridge_whisper_audiohook)) {
++ ast_log(LOG_WARNING, "Unable to attach barge audiohook on spyee %s. Barge mode disabled!\n", name);
+ }
+- ast_channel_unlock(spyee_bridge);
++ ast_channel_unlock(spyee_bridge_autochan->chan);
+ }
+- ast_channel_unlock(spyee);
+- spyee = NULL;
+
+ ast_channel_lock(chan);
+ ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
+@@ -590,10 +623,13 @@
+ }
+ }
+
+- if (res == '*') {
++ if (res == user_options->cycle) {
+ running = 0;
+ break;
+- } else if (res == '#') {
++ } else if (res == user_options->exit) {
++ running = -2;
++ break;
++ } else if (res == user_options->volume) {
+ if (!ast_strlen_zero(inp)) {
+ running = atoi(inp);
+ break;
+@@ -633,128 +669,45 @@
+ ast_audiohook_detach(&csth.spy_audiohook);
+ ast_audiohook_unlock(&csth.spy_audiohook);
+ ast_audiohook_destroy(&csth.spy_audiohook);
+-
++
++ if (spyee_bridge_autochan) {
++ ast_autochan_destroy(spyee_bridge_autochan);
++ }
++
+ ast_verb(2, "Done Spying on channel %s\n", name);
+ manager_event(EVENT_FLAG_CALL, "ChanSpyStop", "SpyeeChannel: %s\r\n", name);
+
+ return running;
+ }
+
+-/*!
+- * \note This relies on the embedded lock to be recursive, as it may be called
+- * due to a call to chanspy_ds_free with the lock held there.
+- */
+-static void chanspy_ds_destroy(void *data)
++static struct ast_autochan *next_channel(struct ast_channel_iterator *iter,
++ struct ast_autochan *autochan, struct ast_channel *chan)
+ {
+- struct chanspy_ds *chanspy_ds = data;
++ struct ast_channel *next;
++ const size_t pseudo_len = strlen("DAHDI/pseudo");
+
+- /* Setting chan to be NULL is an atomic operation, but we don't want this
+- * value to change while this lock is held. The lock is held elsewhere
+- * while it performs non-atomic operations with this channel pointer */
+-
+- ast_mutex_lock(&chanspy_ds->lock);
+- chanspy_ds->chan = NULL;
+- ast_mutex_unlock(&chanspy_ds->lock);
+-}
+-
+-static void chanspy_ds_chan_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
+-{
+- struct chanspy_ds *chanspy_ds = data;
+-
+- ast_mutex_lock(&chanspy_ds->lock);
+- chanspy_ds->chan = new_chan;
+- ast_mutex_unlock(&chanspy_ds->lock);
+-}
+-
+-static const struct ast_datastore_info chanspy_ds_info = {
+- .type = "chanspy",
+- .destroy = chanspy_ds_destroy,
+- .chan_fixup = chanspy_ds_chan_fixup,
+-};
+-
+-static struct chanspy_ds *chanspy_ds_free(struct chanspy_ds *chanspy_ds)
+-{
+- if (!chanspy_ds)
++ if (!iter) {
+ return NULL;
+-
+- ast_mutex_lock(&chanspy_ds->lock);
+- if (chanspy_ds->chan) {
+- struct ast_datastore *datastore;
+- struct ast_channel *chan;
+-
+- chan = chanspy_ds->chan;
+-
+- ast_channel_lock(chan);
+- if ((datastore = ast_channel_datastore_find(chan, &chanspy_ds_info, chanspy_ds->unique_id))) {
+- ast_channel_datastore_remove(chan, datastore);
+- /* chanspy_ds->chan is NULL after this call */
+- chanspy_ds_destroy(datastore->data);
+- datastore->data = NULL;
+- ast_datastore_free(datastore);
+- }
+- ast_channel_unlock(chan);
+ }
+- ast_mutex_unlock(&chanspy_ds->lock);
+
+- return NULL;
+-}
+-
+-/*! \note Returns the channel in the chanspy_ds locked as well as the chanspy_ds locked */
+-static struct chanspy_ds *setup_chanspy_ds(struct ast_channel *chan, struct chanspy_ds *chanspy_ds)
+-{
+- struct ast_datastore *datastore = NULL;
+-
+- ast_mutex_lock(&chanspy_ds->lock);
+-
+- if (!(datastore = ast_datastore_alloc(&chanspy_ds_info, chanspy_ds->unique_id))) {
+- ast_mutex_unlock(&chanspy_ds->lock);
+- chanspy_ds = chanspy_ds_free(chanspy_ds);
+- ast_channel_unlock(chan);
++redo:
++ if (!(next = ast_channel_iterator_next(iter))) {
+ return NULL;
+ }
+-
+- chanspy_ds->chan = chan;
+- datastore->data = chanspy_ds;
+- ast_channel_datastore_add(chan, datastore);
+
+- return chanspy_ds;
+-}
+-
+-static struct chanspy_ds *next_channel(struct ast_channel *chan,
+- const struct ast_channel *last, const char *spec,
+- const char *exten, const char *context, struct chanspy_ds *chanspy_ds)
+-{
+- struct ast_channel *next;
+- const size_t pseudo_len = strlen("DAHDI/pseudo");
+-
+-redo:
+- if (!ast_strlen_zero(spec))
+- next = ast_walk_channel_by_name_prefix_locked(last, spec, strlen(spec));
+- else if (!ast_strlen_zero(exten))
+- next = ast_walk_channel_by_exten_locked(last, exten, context);
+- else
+- next = ast_channel_walk_locked(last);
+-
+- if (!next)
+- return NULL;
+-
+ if (!strncmp(next->name, "DAHDI/pseudo", pseudo_len)) {
+- last = next;
+- ast_channel_unlock(next);
+ goto redo;
+ } else if (next == chan) {
+- last = next;
+- ast_channel_unlock(next);
+ goto redo;
+ }
+
+- return setup_chanspy_ds(next, chanspy_ds);
++ return ast_autochan_setup(next);
+ }
+
+ static int common_exec(struct ast_channel *chan, struct ast_flags *flags,
+- int volfactor, const int fd, const char *mygroup, const char *myenforced,
+- const char *spec, const char *exten, const char *context, const char *mailbox,
+- const char *name_context)
++ int volfactor, const int fd, struct spy_dtmf_options *user_options,
++ const char *mygroup, const char *myenforced, const char *spec, const char *exten,
++ const char *context, const char *mailbox, const char *name_context)
+ {
+ char nameprefix[AST_NAME_STRLEN];
+ char peer_name[AST_NAME_STRLEN + 5];
+@@ -765,7 +718,7 @@
+ char *ptr;
+ int num;
+ int num_spyed_upon = 1;
+- struct chanspy_ds chanspy_ds = { 0, };
++ struct ast_channel_iterator *iter = NULL;
+
+ if (ast_test_flag(flags, OPTION_EXIT)) {
+ const char *c;
+@@ -780,10 +733,6 @@
+ ast_channel_unlock(chan);
+ }
+
+- ast_mutex_init(&chanspy_ds.lock);
+-
+- snprintf(chanspy_ds.unique_id, sizeof(chanspy_ds.unique_id), "%d", ast_atomic_fetchadd_int(&next_unique_id_to_use, +1));
+-
+ if (chan->_state != AST_STATE_UP)
+ ast_answer(chan);
+
+@@ -792,8 +741,8 @@
+ waitms = 100;
+
+ for (;;) {
+- struct chanspy_ds *peer_chanspy_ds = NULL, *next_chanspy_ds = NULL;
+- struct ast_channel *prev = NULL, *peer = NULL;
++ struct ast_autochan *autochan = NULL, *next_autochan = NULL;
++ struct ast_channel *prev = NULL;
+
+ if (!ast_test_flag(flags, OPTION_QUIET) && num_spyed_upon) {
+ res = ast_streamfile(chan, "beep", chan->language);
+@@ -814,6 +763,19 @@
+ }
+ }
+
++ /* Set up the iterator we'll be using during this call */
++ if (!ast_strlen_zero(spec)) {
++ iter = ast_channel_iterator_by_name_new(0, spec, strlen(spec));
++ } else if (!ast_strlen_zero(exten)) {
++ iter = ast_channel_iterator_by_exten_new(0, exten, context);
++ } else {
++ iter = ast_channel_iterator_all_new(0);
++ }
++
++ if (!iter) {
++ return -1;
++ }
++
+ res = ast_waitfordigit(chan, waitms);
+ if (res < 0) {
+ ast_clear_flag(chan, AST_FLAG_SPYING);
+@@ -833,38 +795,30 @@
+ waitms = 100;
+ num_spyed_upon = 0;
+
+- for (peer_chanspy_ds = next_channel(chan, prev, spec, exten, context, &chanspy_ds);
+- peer_chanspy_ds;
+- chanspy_ds_free(peer_chanspy_ds), prev = peer,
+- peer_chanspy_ds = next_chanspy_ds ? next_chanspy_ds :
+- next_channel(chan, prev, spec, exten, context, &chanspy_ds), next_chanspy_ds = NULL) {
++ for (autochan = next_channel(iter, autochan, chan);
++ autochan;
++ prev = autochan->chan, ast_autochan_destroy(autochan),
++ autochan = next_autochan ? next_autochan :
++ next_channel(iter, autochan, chan), next_autochan = NULL) {
+ int igrp = !mygroup;
+ int ienf = !myenforced;
+ char *s;
+
+- peer = peer_chanspy_ds->chan;
+-
+- ast_mutex_unlock(&peer_chanspy_ds->lock);
+-
+- if (peer == prev) {
+- ast_channel_unlock(peer);
+- chanspy_ds_free(peer_chanspy_ds);
++ if (autochan->chan == prev) {
++ ast_autochan_destroy(autochan);
+ break;
+ }
+
+ if (ast_check_hangup(chan)) {
+- ast_channel_unlock(peer);
+- chanspy_ds_free(peer_chanspy_ds);
++ ast_autochan_destroy(autochan);
+ break;
+ }
+
+- if (ast_test_flag(flags, OPTION_BRIDGED) && !ast_bridged_channel(peer)) {
+- ast_channel_unlock(peer);
++ if (ast_test_flag(flags, OPTION_BRIDGED) && !ast_bridged_channel(autochan->chan)) {
+ continue;
+ }
+
+- if (ast_check_hangup(peer) || ast_test_flag(peer, AST_FLAG_SPYING)) {
+- ast_channel_unlock(peer);
++ if (ast_check_hangup(autochan->chan) || ast_test_flag(autochan->chan, AST_FLAG_SPYING)) {
+ continue;
+ }
+
+@@ -875,14 +829,22 @@
+ char dup_mygroup[512];
+ char *groups[NUM_SPYGROUPS];
+ char *mygroups[NUM_SPYGROUPS];
+- const char *group;
++ const char *group = NULL;
+ int x;
+ int y;
+ ast_copy_string(dup_mygroup, mygroup, sizeof(dup_mygroup));
+ num_mygroups = ast_app_separate_args(dup_mygroup, ':', mygroups,
+ ARRAY_LEN(mygroups));
+
+- if ((group = pbx_builtin_getvar_helper(peer, "SPYGROUP"))) {
++ /* Before dahdi scan was part of chanspy, it would use the "GROUP" variable
++ * rather than "SPYGROUP", this check is done to preserve expected behavior */
++ if (ast_test_flag(flags, OPTION_DAHDI_SCAN)) {
++ group = pbx_builtin_getvar_helper(autochan->chan, "GROUP");
++ } else {
++ group = pbx_builtin_getvar_helper(autochan->chan, "SPYGROUP");
++ }
++
++ if (!ast_strlen_zero(group)) {
+ ast_copy_string(dup_group, group, sizeof(dup_group));
+ num_groups = ast_app_separate_args(dup_group, ':', groups,
+ ARRAY_LEN(groups));
+@@ -899,10 +861,8 @@
+ }
+
+ if (!igrp) {
+- ast_channel_unlock(peer);
+ continue;
+ }
+-
+ if (myenforced) {
+ char ext[AST_CHANNEL_NAME + 3];
+ char buffer[512];
+@@ -910,7 +870,7 @@
+
+ snprintf(buffer, sizeof(buffer) - 1, ":%s:", myenforced);
+
+- ast_copy_string(ext + 1, peer->name, sizeof(ext) - 1);
++ ast_copy_string(ext + 1, autochan->chan->name, sizeof(ext) - 1);
+ if ((end = strchr(ext, '-'))) {
+ *end++ = ':';
+ *end = '\0';
+@@ -928,18 +888,13 @@
+ }
+
+ strcpy(peer_name, "spy-");
+- strncat(peer_name, peer->name, AST_NAME_STRLEN - 4 - 1);
++ strncat(peer_name, autochan->chan->name, AST_NAME_STRLEN - 4 - 1);
+ ptr = strchr(peer_name, '/');
+ *ptr++ = '\0';
+ ptr = strsep(&ptr, "-");
+
+ for (s = peer_name; s < ptr; s++)
+ *s = tolower(*s);
+- /* We have to unlock the peer channel here to avoid a deadlock.
+- * So, when we need to dereference it again, we have to lock the
+- * datastore and get the pointer from there to see if the channel
+- * is still valid. */
+- ast_channel_unlock(peer);
+
+ if (!ast_test_flag(flags, OPTION_QUIET)) {
+ if (ast_test_flag(flags, OPTION_NAME)) {
+@@ -955,7 +910,7 @@
+ res = ast_waitstream(chan, "");
+ }
+ if (res) {
+- chanspy_ds_free(peer_chanspy_ds);
++ ast_autochan_destroy(autochan);
+ break;
+ }
+ } else {
+@@ -967,42 +922,38 @@
+ }
+ }
+
+- res = channel_spy(chan, peer_chanspy_ds, &volfactor, fd, flags, exitcontext);
+- num_spyed_upon++;
++ res = channel_spy(chan, autochan, &volfactor, fd, user_options, flags, exitcontext);
++ num_spyed_upon++;
+
+ if (res == -1) {
+- chanspy_ds_free(peer_chanspy_ds);
++ ast_autochan_destroy(autochan);
+ goto exit;
+ } else if (res == -2) {
+ res = 0;
+- chanspy_ds_free(peer_chanspy_ds);
++ ast_autochan_destroy(autochan);
+ goto exit;
+ } else if (res > 1 && spec) {
+ struct ast_channel *next;
+
+ snprintf(nameprefix, AST_NAME_STRLEN, "%s/%d", spec, res);
+
+- if ((next = ast_get_channel_by_name_prefix_locked(nameprefix, strlen(nameprefix)))) {
+- peer_chanspy_ds = chanspy_ds_free(peer_chanspy_ds);
+- next_chanspy_ds = setup_chanspy_ds(next, &chanspy_ds);
++ if ((next = ast_channel_get_by_name_prefix(nameprefix, strlen(nameprefix)))) {
++ next_autochan = ast_autochan_setup(next);
++ next = ast_channel_unref(next);
+ } else {
+ /* stay on this channel, if it is still valid */
+-
+- ast_mutex_lock(&peer_chanspy_ds->lock);
+- if (peer_chanspy_ds->chan) {
+- ast_channel_lock(peer_chanspy_ds->chan);
+- next_chanspy_ds = peer_chanspy_ds;
+- peer_chanspy_ds = NULL;
++ if (!ast_check_hangup(autochan->chan)) {
++ next_autochan = ast_autochan_setup(autochan->chan);
+ } else {
+ /* the channel is gone */
+- ast_mutex_unlock(&peer_chanspy_ds->lock);
+- next_chanspy_ds = NULL;
++ next_autochan = NULL;
+ }
+ }
+-
+- peer = NULL;
+ }
+ }
++
++ iter = ast_channel_iterator_destroy(iter);
++
+ if (res == -1 || ast_check_hangup(chan))
+ break;
+ }
+@@ -1012,20 +963,21 @@
+
+ ast_channel_setoption(chan, AST_OPTION_TXGAIN, &zero_volume, sizeof(zero_volume), 0);
+
+- ast_mutex_lock(&chanspy_ds.lock);
+- ast_mutex_unlock(&chanspy_ds.lock);
+- ast_mutex_destroy(&chanspy_ds.lock);
+-
+ return res;
+ }
+
+-static int chanspy_exec(struct ast_channel *chan, void *data)
++static int chanspy_exec(struct ast_channel *chan, const char *data)
+ {
+ char *myenforced = NULL;
+ char *mygroup = NULL;
+ char *recbase = NULL;
+ int fd = 0;
+ struct ast_flags flags;
++ struct spy_dtmf_options user_options = {
++ .cycle = '*',
++ .volume = '#',
++ .exit = '\0',
++ };
+ int oldwf = 0;
+ int volfactor = 0;
+ int res;
+@@ -1036,14 +988,15 @@
+ AST_APP_ARG(options);
+ );
+ char *opts[OPT_ARG_ARRAY_SIZE];
++ char *parse = ast_strdupa(data);
+
+- data = ast_strdupa(data);
+- AST_STANDARD_APP_ARGS(args, data);
++ AST_STANDARD_APP_ARGS(args, parse);
+
+ if (args.spec && !strcmp(args.spec, "all"))
+ args.spec = NULL;
+
+ if (args.options) {
++ char tmp;
+ ast_app_parse_options(spy_opts, &flags, opts, args.options);
+ if (ast_test_flag(&flags, OPTION_GROUP))
+ mygroup = opts[OPT_ARG_GROUP];
+@@ -1052,6 +1005,24 @@
+ !(recbase = opts[OPT_ARG_RECORD]))
+ recbase = "chanspy";
+
++ if (ast_test_flag(&flags, OPTION_DTMF_EXIT) && opts[OPT_ARG_EXIT]) {
++ tmp = opts[OPT_ARG_EXIT][0];
++ if (strchr("0123456789*#", tmp) && tmp != '\0') {
++ user_options.exit = tmp;
++ } else {
++ ast_log(LOG_NOTICE, "Argument for option 'x' must be a valid DTMF digit.");
++ }
++ }
++
++ if (ast_test_flag(&flags, OPTION_DTMF_CYCLE) && opts[OPT_ARG_CYCLE]) {
++ tmp = opts[OPT_ARG_CYCLE][0];
++ if (strchr("0123456789*#", tmp) && tmp != '\0') {
++ user_options.cycle = tmp;
++ } else {
++ ast_log(LOG_NOTICE, "Argument for option 'c' must be a valid DTMF digit.");
++ }
++ }
++
+ if (ast_test_flag(&flags, OPTION_VOLUME) && opts[OPT_ARG_VOLUME]) {
+ int vol;
+
+@@ -1066,7 +1037,7 @@
+
+ if (ast_test_flag(&flags, OPTION_ENFORCED))
+ myenforced = opts[OPT_ARG_ENFORCED];
+-
++
+ if (ast_test_flag(&flags, OPTION_NAME)) {
+ if (!ast_strlen_zero(opts[OPT_ARG_NAME])) {
+ char *delimiter;
+@@ -1079,10 +1050,9 @@
+ }
+ }
+ }
+-
+-
+- } else
++ } else {
+ ast_clear_flag(&flags, AST_FLAGS_ALL);
++ }
+
+ oldwf = chan->writeformat;
+ if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
+@@ -1100,7 +1070,7 @@
+ }
+ }
+
+- res = common_exec(chan, &flags, volfactor, fd, mygroup, myenforced, args.spec, NULL, NULL, mailbox, name_context);
++ res = common_exec(chan, &flags, volfactor, fd, &user_options, mygroup, myenforced, args.spec, NULL, NULL, mailbox, name_context);
+
+ if (fd)
+ close(fd);
+@@ -1111,13 +1081,18 @@
+ return res;
+ }
+
+-static int extenspy_exec(struct ast_channel *chan, void *data)
++static int extenspy_exec(struct ast_channel *chan, const char *data)
+ {
+ char *ptr, *exten = NULL;
+ char *mygroup = NULL;
+ char *recbase = NULL;
+ int fd = 0;
+ struct ast_flags flags;
++ struct spy_dtmf_options user_options = {
++ .cycle = '*',
++ .volume = '#',
++ .exit = '\0',
++ };
+ int oldwf = 0;
+ int volfactor = 0;
+ int res;
+@@ -1127,10 +1102,9 @@
+ AST_APP_ARG(context);
+ AST_APP_ARG(options);
+ );
++ char *parse = ast_strdupa(data);
+
+- data = ast_strdupa(data);
+-
+- AST_STANDARD_APP_ARGS(args, data);
++ AST_STANDARD_APP_ARGS(args, parse);
+ if (!ast_strlen_zero(args.context) && (ptr = strchr(args.context, '@'))) {
+ exten = args.context;
+ *ptr++ = '\0';
+@@ -1142,6 +1116,7 @@
+
+ if (args.options) {
+ char *opts[OPT_ARG_ARRAY_SIZE];
++ char tmp;
+
+ ast_app_parse_options(spy_opts, &flags, opts, args.options);
+ if (ast_test_flag(&flags, OPTION_GROUP))
+@@ -1151,6 +1126,24 @@
+ !(recbase = opts[OPT_ARG_RECORD]))
+ recbase = "chanspy";
+
++ if (ast_test_flag(&flags, OPTION_DTMF_EXIT) && opts[OPT_ARG_EXIT]) {
++ tmp = opts[OPT_ARG_EXIT][0];
++ if (strchr("0123456789*#", tmp) && tmp != '\0') {
++ user_options.exit = tmp;
++ } else {
++ ast_log(LOG_NOTICE, "Argument for option 'x' must be a valid DTMF digit.");
++ }
++ }
++
++ if (ast_test_flag(&flags, OPTION_DTMF_CYCLE) && opts[OPT_ARG_CYCLE]) {
++ tmp = opts[OPT_ARG_CYCLE][0];
++ if (strchr("0123456789*#", tmp) && tmp != '\0') {
++ user_options.cycle = tmp;
++ } else {
++ ast_log(LOG_NOTICE, "Argument for option 'c' must be a valid DTMF digit.");
++ }
++ }
++
+ if (ast_test_flag(&flags, OPTION_VOLUME) && opts[OPT_ARG_VOLUME]) {
+ int vol;
+
+@@ -1163,7 +1156,6 @@
+ if (ast_test_flag(&flags, OPTION_PRIVATE))
+ ast_set_flag(&flags, OPTION_WHISPER);
+
+-
+ if (ast_test_flag(&flags, OPTION_NAME)) {
+ if (!ast_strlen_zero(opts[OPT_ARG_NAME])) {
+ char *delimiter;
+@@ -1177,8 +1169,9 @@
+ }
+ }
+
+- } else
++ } else {
+ ast_clear_flag(&flags, AST_FLAGS_ALL);
++ }
+
+ oldwf = chan->writeformat;
+ if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
+@@ -1197,7 +1190,7 @@
+ }
+
+
+- res = common_exec(chan, &flags, volfactor, fd, mygroup, NULL, NULL, exten, args.context, mailbox, name_context);
++ res = common_exec(chan, &flags, volfactor, fd, &user_options, mygroup, NULL, NULL, exten, args.context, mailbox, name_context);
+
+ if (fd)
+ close(fd);
+@@ -1208,12 +1201,49 @@
+ return res;
+ }
+
++static int dahdiscan_exec(struct ast_channel *chan, const char *data)
++{
++ const char *spec = "DAHDI";
++ struct ast_flags flags;
++ struct spy_dtmf_options user_options = {
++ .cycle = '#',
++ .volume = '\0',
++ .exit = '*',
++ };
++ int oldwf = 0;
++ int res;
++ char *mygroup = NULL;
++
++ ast_clear_flag(&flags, AST_FLAGS_ALL);
++
++ if (!ast_strlen_zero(data)) {
++ mygroup = ast_strdupa(data);
++ }
++ ast_set_flag(&flags, OPTION_DTMF_EXIT);
++ ast_set_flag(&flags, OPTION_DTMF_CYCLE);
++ ast_set_flag(&flags, OPTION_DAHDI_SCAN);
++
++ oldwf = chan->writeformat;
++ if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
++ ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
++ return -1;
++ }
++
++ res = common_exec(chan, &flags, 0, 0, &user_options, mygroup, NULL, spec, NULL, NULL, NULL, NULL);
++
++ if (oldwf && ast_set_write_format(chan, oldwf) < 0)
++ ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
++
++ return res;
++}
++
+ static int unload_module(void)
+ {
+ int res = 0;
+
+ res |= ast_unregister_application(app_chan);
+ res |= ast_unregister_application(app_ext);
++ res |= ast_unregister_application(app_dahdiscan);
+
+ return res;
+ }
+@@ -1224,6 +1254,7 @@
+
+ res |= ast_register_application_xml(app_chan, chanspy_exec);
+ res |= ast_register_application_xml(app_ext, extenspy_exec);
++ res |= ast_register_application_xml(app_dahdiscan, dahdiscan_exec);
+
+ return res;
+ }
+Index: apps/app_jack.c
+===================================================================
+--- a/apps/app_jack.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_jack.c (.../trunk) (revision 202568)
+@@ -26,7 +26,7 @@
+ * and output jack port so that the audio can be processed through
+ * another application, or to play audio from another application.
+ *
+- * \arg http://www.jackaudio.org/
++ * \extref http://www.jackaudio.org/
+ *
+ * \note To install libresample, check it out of the following repository:
+ * <code>$ svn co http://svn.digium.com/svn/thirdparty/libresample/trunk</code>
+@@ -106,14 +106,15 @@
+ </parameter>
+ </syntax>
+ <description>
+- <para>When executing this application, two jack ports will be created;
+- one input and one output. Other applications can be hooked up to
++ <para>When executing this application, two jack ports will be created;
++ one input and one output. Other applications can be hooked up to
+ these ports to access audio coming from, or being send to the channel.</para>
+ </description>
+ </application>
+ ***/
+-static char *jack_app = "JACK";
+
++static const char jack_app[] = "JACK";
++
+ struct jack_data {
+ AST_DECLARE_STRING_FIELDS(
+ AST_STRING_FIELD(server_name);
+@@ -181,7 +182,7 @@
+ } else
+ ast_str_append(&str, 0, ", %s", jack_status_to_str((1 << i)));
+ }
+-
++
+ ast_log(LOG_NOTICE, "%s: %s\n", prefix, ast_str_buffer(str));
+ }
+
+@@ -201,10 +202,10 @@
+
+ /* XXX Hard coded 8 kHz */
+
+- to_srate = input ? 8000.0 : jack_srate;
++ to_srate = input ? 8000.0 : jack_srate;
+ from_srate = input ? jack_srate : 8000.0;
+
+- resample_factor = input ? &jack_data->input_resample_factor :
++ resample_factor = input ? &jack_data->input_resample_factor :
+ &jack_data->output_resample_factor;
+
+ if (from_srate == to_srate) {
+@@ -219,9 +220,9 @@
+ resampler = input ? &jack_data->input_resampler :
+ &jack_data->output_resampler;
+
+- if (!(*resampler = resample_open(RESAMPLE_QUALITY,
++ if (!(*resampler = resample_open(RESAMPLE_QUALITY,
+ *resample_factor, *resample_factor))) {
+- ast_log(LOG_ERROR, "Failed to open %s resampler\n",
++ ast_log(LOG_ERROR, "Failed to open %s resampler\n",
+ input ? "input" : "output");
+ return -1;
+ }
+@@ -233,9 +234,9 @@
+ * \brief Handle jack input port
+ *
+ * Read nframes number of samples from the input buffer, resample it
+- * if necessary, and write it into the appropriate ringbuffer.
++ * if necessary, and write it into the appropriate ringbuffer.
+ */
+-static void handle_input(void *buf, jack_nframes_t nframes,
++static void handle_input(void *buf, jack_nframes_t nframes,
+ struct jack_data *jack_data)
+ {
+ short s_buf[nframes];
+@@ -266,7 +267,7 @@
+
+ total_out_buf_used += out_buf_used;
+ total_in_buf_used += in_buf_used;
+-
++
+ if (total_out_buf_used == ARRAY_LEN(f_buf)) {
+ ast_log(LOG_ERROR, "Output buffer filled ... need to increase its size, "
+ "nframes '%d', total_out_buf_used '%d'\n", nframes, total_out_buf_used);
+@@ -276,7 +277,7 @@
+
+ for (i = 0; i < total_out_buf_used; i++)
+ s_buf[i] = f_buf[i] * (SHRT_MAX / 1.0);
+-
++
+ write_len = total_out_buf_used * sizeof(int16_t);
+ } else {
+ /* No resampling needed */
+@@ -298,7 +299,7 @@
+ * Read nframes number of samples from the ringbuffer and write it out to the
+ * output port buffer.
+ */
+-static void handle_output(void *buf, jack_nframes_t nframes,
++static void handle_output(void *buf, jack_nframes_t nframes,
+ struct jack_data *jack_data)
+ {
+ size_t res, len;
+@@ -368,7 +369,7 @@
+ resample_close(jack_data->output_resampler);
+ jack_data->output_resampler = NULL;
+ }
+-
++
+ if (jack_data->input_resampler) {
+ resample_close(jack_data->input_resampler);
+ jack_data->input_resampler = NULL;
+@@ -539,10 +540,10 @@
+ int in_buf_used;
+ int out_buf_used;
+
+- out_buf_used = resample_process(jack_data->output_resampler,
++ out_buf_used = resample_process(jack_data->output_resampler,
+ jack_data->output_resample_factor,
+- &in_buf[total_in_buf_used], ARRAY_LEN(in_buf) - total_in_buf_used,
+- 0, &in_buf_used,
++ &in_buf[total_in_buf_used], ARRAY_LEN(in_buf) - total_in_buf_used,
++ 0, &in_buf_used,
+ &f_buf[total_out_buf_used], ARRAY_LEN(f_buf) - total_out_buf_used);
+
+ if (out_buf_used < 0)
+@@ -599,7 +600,7 @@
+ */
+ static void handle_jack_audio(struct ast_channel *chan, struct jack_data *jack_data,
+ struct ast_frame *out_frame)
+-{
++{
+ short buf[160];
+ struct ast_frame f = {
+ .frametype = AST_FRAME_VOICE,
+@@ -677,7 +678,7 @@
+
+ if (!(jack_data = ast_calloc(1, sizeof(*jack_data))))
+ return NULL;
+-
++
+ if (ast_string_field_init(jack_data, 32)) {
+ ast_free(jack_data);
+ return NULL;
+@@ -740,19 +741,14 @@
+ return 0;
+ }
+
+-static int jack_exec(struct ast_channel *chan, void *data)
++static int jack_exec(struct ast_channel *chan, const char *data)
+ {
+ struct jack_data *jack_data;
+- AST_DECLARE_APP_ARGS(args,
+- AST_APP_ARG(options);
+- );
+
+ if (!(jack_data = jack_data_alloc()))
+ return -1;
+
+- args.options = data;
+-
+- if (!ast_strlen_zero(args.options) && handle_options(jack_data, args.options)) {
++ if (!ast_strlen_zero(data) && handle_options(jack_data, data)) {
+ destroy_jack_data(jack_data);
+ return -1;
+ }
+@@ -816,7 +812,7 @@
+ .destroy = jack_hook_ds_destroy,
+ };
+
+-static int jack_hook_callback(struct ast_audiohook *audiohook, struct ast_channel *chan,
++static int jack_hook_callback(struct ast_audiohook *audiohook, struct ast_channel *chan,
+ struct ast_frame *frame, enum ast_audiohook_direction direction)
+ {
+ struct ast_datastore *datastore;
+@@ -875,7 +871,7 @@
+ }
+
+ if (ast_strlen_zero(args.mode) || strcasecmp(args.mode, "manipulate")) {
+- ast_log(LOG_ERROR, "'%s' is not a supported mode. Only manipulate is supported.\n",
++ ast_log(LOG_ERROR, "'%s' is not a supported mode. Only manipulate is supported.\n",
+ S_OR(args.mode, "<none>"));
+ goto return_error;
+ }
+@@ -945,7 +941,7 @@
+ return 0;
+ }
+
+-static int jack_hook_write(struct ast_channel *chan, const char *cmd, char *data,
++static int jack_hook_write(struct ast_channel *chan, const char *cmd, char *data,
+ const char *value)
+ {
+ int res;
+@@ -955,7 +951,7 @@
+ else if (!strcasecmp(value, "off"))
+ res = disable_jack_hook(chan);
+ else {
+- ast_log(LOG_ERROR, "'%s' is not a valid value for JACK_HOOK()\n", value);
++ ast_log(LOG_ERROR, "'%s' is not a valid value for JACK_HOOK()\n", value);
+ res = -1;
+ }
+
+Index: apps/app_cdr.c
+===================================================================
+--- a/apps/app_cdr.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_cdr.c (.../trunk) (revision 202568)
+@@ -44,9 +44,9 @@
+ </application>
+ ***/
+
+-static char *nocdr_app = "NoCDR";
++static const char nocdr_app[] = "NoCDR";
+
+-static int nocdr_exec(struct ast_channel *chan, void *data)
++static int nocdr_exec(struct ast_channel *chan, const char *data)
+ {
+ if (chan->cdr)
+ ast_set_flag(chan->cdr, AST_CDR_FLAG_POST_DISABLED);
+Index: apps/app_adsiprog.c
+===================================================================
+--- a/apps/app_adsiprog.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_adsiprog.c (.../trunk) (revision 202568)
+@@ -45,7 +45,7 @@
+ #include "asterisk/utils.h"
+ #include "asterisk/lock.h"
+
+-static char *app = "ADSIProg";
++static const char app[] = "ADSIProg";
+
+ /*** DOCUMENTATION
+ <application name="ADSIProg" language="en_US">
+@@ -71,10 +71,10 @@
+
+ struct adsi_event {
+ int id;
+- char *name;
++ const char *name;
+ };
+
+-static struct adsi_event events[] = {
++static const struct adsi_event events[] = {
+ { 1, "CALLERID" },
+ { 2, "VMWI" },
+ { 3, "NEARANSWER" },
+@@ -101,7 +101,7 @@
+ { 24, "CPEID" },
+ };
+
+-static struct adsi_event justify[] = {
++static const struct adsi_event justify[] = {
+ { 0, "CENTER" },
+ { 1, "RIGHT" },
+ { 2, "LEFT" },
+@@ -232,7 +232,7 @@
+ return 0;
+ }
+
+-static char *get_token(char **buf, char *script, int lineno)
++static char *get_token(char **buf, const char *script, int lineno)
+ {
+ char *tmp = *buf, *keyword;
+ int quoted = 0;
+@@ -264,7 +264,7 @@
+
+ static char *validdtmf = "123456789*0#ABCD";
+
+-static int send_dtmf(char *buf, char *name, int id, char *args, struct adsi_script *state, char *script, int lineno)
++static int send_dtmf(char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
+ {
+ char dtmfstr[80], *a;
+ int bytes = 0;
+@@ -294,7 +294,7 @@
+ return bytes;
+ }
+
+-static int goto_line(char *buf, char *name, int id, char *args, struct adsi_script *state, char *script, int lineno)
++static int goto_line(char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
+ {
+ char *page = get_token(&args, script, lineno);
+ char *gline = get_token(&args, script, lineno);
+@@ -327,7 +327,7 @@
+ return 2;
+ }
+
+-static int goto_line_rel(char *buf, char *name, int id, char *args, struct adsi_script *state, char *script, int lineno)
++static int goto_line_rel(char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
+ {
+ char *dir = get_token(&args, script, lineno);
+ char *gline = get_token(&args, script, lineno);
+@@ -360,7 +360,7 @@
+ return 2;
+ }
+
+-static int send_delay(char *buf, char *name, int id, char *args, struct adsi_script *state, char *script, int lineno)
++static int send_delay(char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
+ {
+ char *gtime = get_token(&args, script, lineno);
+ int ms;
+@@ -385,7 +385,7 @@
+ return 2;
+ }
+
+-static int set_state(char *buf, char *name, int id, char *args, struct adsi_script *istate, char *script, int lineno)
++static int set_state(char *buf, char *name, int id, char *args, struct adsi_script *istate, const char *script, int lineno)
+ {
+ char *gstate = get_token(&args, script, lineno);
+ int state;
+@@ -406,7 +406,7 @@
+ return 2;
+ }
+
+-static int cleartimer(char *buf, char *name, int id, char *args, struct adsi_script *istate, char *script, int lineno)
++static int cleartimer(char *buf, char *name, int id, char *args, struct adsi_script *istate, const char *script, int lineno)
+ {
+ char *tok = get_token(&args, script, lineno);
+
+@@ -424,7 +424,7 @@
+ return 2;
+ }
+
+-static struct adsi_flag *getflagbyname(struct adsi_script *state, char *name, char *script, int lineno, int create)
++static struct adsi_flag *getflagbyname(struct adsi_script *state, char *name, const char *script, int lineno, int create)
+ {
+ int x;
+
+@@ -449,7 +449,7 @@
+ return &state->flags[state->numflags-1];
+ }
+
+-static int setflag(char *buf, char *name, int id, char *args, struct adsi_script *state, char *script, int lineno)
++static int setflag(char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
+ {
+ char *tok = get_token(&args, script, lineno);
+ char sname[80];
+@@ -476,7 +476,7 @@
+ return 2;
+ }
+
+-static int clearflag(char *buf, char *name, int id, char *args, struct adsi_script *state, char *script, int lineno)
++static int clearflag(char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
+ {
+ char *tok = get_token(&args, script, lineno);
+ struct adsi_flag *flag;
+@@ -503,7 +503,7 @@
+ return 2;
+ }
+
+-static int starttimer(char *buf, char *name, int id, char *args, struct adsi_script *istate, char *script, int lineno)
++static int starttimer(char *buf, char *name, int id, char *args, struct adsi_script *istate, const char *script, int lineno)
+ {
+ char *tok = get_token(&args, script, lineno);
+ int secs;
+@@ -549,7 +549,7 @@
+ return -1;
+ }
+
+-static struct adsi_soft_key *getkeybyname(struct adsi_script *state, char *name, char *script, int lineno)
++static struct adsi_soft_key *getkeybyname(struct adsi_script *state, char *name, const char *script, int lineno)
+ {
+ int x;
+
+@@ -570,7 +570,7 @@
+ return &state->keys[state->numkeys-1];
+ }
+
+-static struct adsi_subscript *getsubbyname(struct adsi_script *state, char *name, char *script, int lineno)
++static struct adsi_subscript *getsubbyname(struct adsi_script *state, char *name, const char *script, int lineno)
+ {
+ int x;
+
+@@ -591,7 +591,7 @@
+ return &state->subs[state->numsubs-1];
+ }
+
+-static struct adsi_state *getstatebyname(struct adsi_script *state, char *name, char *script, int lineno, int create)
++static struct adsi_state *getstatebyname(struct adsi_script *state, char *name, const char *script, int lineno, int create)
+ {
+ int x;
+
+@@ -616,7 +616,7 @@
+ return &state->states[state->numstates-1];
+ }
+
+-static struct adsi_display *getdisplaybyname(struct adsi_script *state, char *name, char *script, int lineno, int create)
++static struct adsi_display *getdisplaybyname(struct adsi_script *state, char *name, const char *script, int lineno, int create)
+ {
+ int x;
+
+@@ -641,7 +641,7 @@
+ return &state->displays[state->numdisplays-1];
+ }
+
+-static int showkeys(char *buf, char *name, int id, char *args, struct adsi_script *state, char *script, int lineno)
++static int showkeys(char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
+ {
+ char *tok, newkey[80];
+ int bytes, x, flagid = 0;
+@@ -688,7 +688,7 @@
+ return 2 + x;
+ }
+
+-static int showdisplay(char *buf, char *name, int id, char *args, struct adsi_script *state, char *script, int lineno)
++static int showdisplay(char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
+ {
+ char *tok, dispname[80];
+ int line = 0, flag = 0, cmd = 3;
+@@ -739,7 +739,7 @@
+ return 3;
+ }
+
+-static int cleardisplay(char *buf, char *name, int id, char *args, struct adsi_script *istate, char *script, int lineno)
++static int cleardisplay(char *buf, char *name, int id, char *args, struct adsi_script *istate, const char *script, int lineno)
+ {
+ char *tok = get_token(&args, script, lineno);
+
+@@ -751,7 +751,7 @@
+ return 2;
+ }
+
+-static int digitdirect(char *buf, char *name, int id, char *args, struct adsi_script *istate, char *script, int lineno)
++static int digitdirect(char *buf, char *name, int id, char *args, struct adsi_script *istate, const char *script, int lineno)
+ {
+ char *tok = get_token(&args, script, lineno);
+
+@@ -763,7 +763,7 @@
+ return 2;
+ }
+
+-static int clearcbone(char *buf, char *name, int id, char *args, struct adsi_script *istate, char *script, int lineno)
++static int clearcbone(char *buf, char *name, int id, char *args, struct adsi_script *istate, const char *script, int lineno)
+ {
+ char *tok = get_token(&args, script, lineno);
+
+@@ -775,7 +775,7 @@
+ return 2;
+ }
+
+-static int digitcollect(char *buf, char *name, int id, char *args, struct adsi_script *istate, char *script, int lineno)
++static int digitcollect(char *buf, char *name, int id, char *args, struct adsi_script *istate, const char *script, int lineno)
+ {
+ char *tok = get_token(&args, script, lineno);
+
+@@ -787,7 +787,7 @@
+ return 2;
+ }
+
+-static int subscript(char *buf, char *name, int id, char *args, struct adsi_script *state, char *script, int lineno)
++static int subscript(char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
+ {
+ char *tok = get_token(&args, script, lineno);
+ char subscr[80];
+@@ -812,7 +812,7 @@
+ return 2;
+ }
+
+-static int onevent(char *buf, char *name, int id, char *args, struct adsi_script *state, char *script, int lineno)
++static int onevent(char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
+ {
+ char *tok = get_token(&args, script, lineno);
+ char subscr[80], sname[80];
+@@ -879,10 +879,10 @@
+ struct adsi_key_cmd {
+ char *name;
+ int id;
+- int (*add_args)(char *buf, char *name, int id, char *args, struct adsi_script *state, char *script, int lineno);
++ int (*add_args)(char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno);
+ };
+
+-static struct adsi_key_cmd kcmds[] = {
++static const struct adsi_key_cmd kcmds[] = {
+ { "SENDDTMF", 0, send_dtmf },
+ /* Encoded DTMF would go here */
+ { "ONHOOK", 0x81 },
+@@ -924,7 +924,7 @@
+ { "EXIT", 0xa0 },
+ };
+
+-static struct adsi_key_cmd opcmds[] = {
++static const struct adsi_key_cmd opcmds[] = {
+
+ /* 1 - Branch on event -- handled specially */
+ { "SHOWKEYS", 2, showkeys },
+@@ -944,7 +944,7 @@
+ };
+
+
+-static int process_returncode(struct adsi_soft_key *key, char *code, char *args, struct adsi_script *state, char *script, int lineno)
++static int process_returncode(struct adsi_soft_key *key, char *code, char *args, struct adsi_script *state, const char *script, int lineno)
+ {
+ int x, res;
+ char *unused;
+@@ -973,7 +973,7 @@
+ return -1;
+ }
+
+-static int process_opcode(struct adsi_subscript *sub, char *code, char *args, struct adsi_script *state, char *script, int lineno)
++static int process_opcode(struct adsi_subscript *sub, char *code, char *args, struct adsi_script *state, const char *script, int lineno)
+ {
+ int x, res, max = sub->id ? MAX_SUB_LEN : MAX_MAIN_LEN;
+ char *unused;
+@@ -1010,7 +1010,7 @@
+ return -1;
+ }
+
+-static int adsi_process(struct adsi_script *state, char *buf, char *script, int lineno)
++static int adsi_process(struct adsi_script *state, char *buf, const char *script, int lineno)
+ {
+ char *keyword = get_token(&buf, script, lineno);
+ char *args, vname[256], tmp[80], tmp2[80];
+@@ -1358,7 +1358,7 @@
+ return 0;
+ }
+
+-static struct adsi_script *compile_script(char *script)
++static struct adsi_script *compile_script(const char *script)
+ {
+ FILE *f;
+ char fn[256], buf[256], *c;
+@@ -1451,7 +1451,7 @@
+ }
+ #endif
+
+-static int adsi_prog(struct ast_channel *chan, char *script)
++static int adsi_prog(struct ast_channel *chan, const char *script)
+ {
+ struct adsi_script *scr;
+ int x, bytes;
+@@ -1562,7 +1562,7 @@
+ return 0;
+ }
+
+-static int adsi_exec(struct ast_channel *chan, void *data)
++static int adsi_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+
+Index: apps/app_read.c
+===================================================================
+--- a/apps/app_read.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_read.c (.../trunk) (revision 202568)
+@@ -108,11 +108,11 @@
+ </application>
+ ***/
+
+-enum {
++enum read_option_flags {
+ OPT_SKIP = (1 << 0),
+ OPT_INDICATION = (1 << 1),
+ OPT_NOANSWER = (1 << 2),
+-} read_option_flags;
++};
+
+ AST_APP_OPTIONS(read_app_options, {
+ AST_APP_OPTION('s', OPT_SKIP),
+@@ -122,9 +122,7 @@
+
+ static char *app = "Read";
+
+-#define ast_next_data(instr,ptr,delim) if((ptr=strchr(instr,delim))) { *(ptr) = '\0' ; ptr++;}
+-
+-static int read_exec(struct ast_channel *chan, void *data)
++static int read_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+ char tmp[256] = "";
+Index: apps/app_dictate.c
+===================================================================
+--- a/apps/app_dictate.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_dictate.c (.../trunk) (revision 202568)
+@@ -55,7 +55,7 @@
+ </application>
+ ***/
+
+-static char *app = "Dictate";
++static const char app[] = "Dictate";
+
+ typedef enum {
+ DFLAG_RECORD = (1 << 0),
+@@ -81,7 +81,7 @@
+ return res;
+ }
+
+-static int dictate_exec(struct ast_channel *chan, void *data)
++static int dictate_exec(struct ast_channel *chan, const char *data)
+ {
+ char *path = NULL, filein[256], *filename = "";
+ char *parse;
+Index: apps/app_festival.c
+===================================================================
+--- a/apps/app_festival.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_festival.c (.../trunk) (revision 202568)
+@@ -264,7 +264,7 @@
+ return res;
+ }
+
+-static int festival_exec(struct ast_channel *chan, void *vdata)
++static int festival_exec(struct ast_channel *chan, const char *vdata)
+ {
+ int usecache;
+ int res = 0;
+Index: apps/app_softhangup.c
+===================================================================
+--- a/apps/app_softhangup.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_softhangup.c (.../trunk) (revision 202568)
+@@ -69,7 +69,7 @@
+ AST_APP_OPTION('a', OPTION_ALL),
+ });
+
+-static int softhangup_exec(struct ast_channel *chan, void *data)
++static int softhangup_exec(struct ast_channel *chan, const char *data)
+ {
+ struct ast_channel *c = NULL;
+ char *cut, *opts[0];
+@@ -80,6 +80,7 @@
+ AST_APP_ARG(channel);
+ AST_APP_ARG(options);
+ );
++ struct ast_channel_iterator *iter;
+
+ if (ast_strlen_zero(data)) {
+ ast_log(LOG_WARNING, "SoftHangup requires an argument (Technology/resource)\n");
+@@ -93,9 +94,12 @@
+ ast_app_parse_options(app_opts, &flags, opts, args.options);
+ lenmatch = strlen(args.channel);
+
+- for (c = ast_walk_channel_by_name_prefix_locked(NULL, args.channel, lenmatch);
+- c;
+- c = ast_walk_channel_by_name_prefix_locked(c, args.channel, lenmatch)) {
++ if (!(iter = ast_channel_iterator_by_name_new(0, args.channel, lenmatch))) {
++ return -1;
++ }
++
++ while ((c = ast_channel_iterator_next(iter))) {
++ ast_channel_lock(c);
+ ast_copy_string(name, c->name, sizeof(name));
+ if (ast_test_flag(&flags, OPTION_ALL)) {
+ /* CAPI is set up like CAPI[foo/bar]/clcnt */
+@@ -113,12 +117,16 @@
+ ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
+ if (!ast_test_flag(&flags, OPTION_ALL)) {
+ ast_channel_unlock(c);
++ c = ast_channel_unref(c);
+ break;
+ }
+ }
+ ast_channel_unlock(c);
++ c = ast_channel_unref(c);
+ }
+
++ ast_channel_iterator_destroy(iter);
++
+ return 0;
+ }
+
+Index: apps/app_playtones.c
+===================================================================
+--- a/apps/app_playtones.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_playtones.c (.../trunk) (revision 202568)
+@@ -72,7 +72,7 @@
+ </application>
+ ***/
+
+-static int handle_playtones(struct ast_channel *chan, void *data)
++static int handle_playtones(struct ast_channel *chan, const char *data)
+ {
+ struct ast_tone_zone_sound *ts;
+ int res;
+@@ -99,7 +99,7 @@
+ return res;
+ }
+
+-static int handle_stopplaytones(struct ast_channel *chan, void *data)
++static int handle_stopplaytones(struct ast_channel *chan, const char *data)
+ {
+ ast_playtones_stop(chan);
+
+Index: apps/app_alarmreceiver.c
+===================================================================
+--- a/apps/app_alarmreceiver.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_alarmreceiver.c (.../trunk) (revision 202568)
+@@ -62,7 +62,7 @@
+
+ typedef struct event_node event_node_t;
+
+-static char *app = "AlarmReceiver";
++static const char app[] = "AlarmReceiver";
+ /*** DOCUMENTATION
+ <application name="AlarmReceiver" language="en_US">
+ <synopsis>
+@@ -416,7 +416,7 @@
+ *
+ * The function will return 0 when the caller hangs up, else a -1 if there was a problem.
+ */
+-static int receive_ademco_contact_id( struct ast_channel *chan, void *data, int fdto, int sdto, int tldn, event_node_t **ehead)
++static int receive_ademco_contact_id(struct ast_channel *chan, const void *data, int fdto, int sdto, int tldn, event_node_t **ehead)
+ {
+ int i, j;
+ int res = 0;
+@@ -564,7 +564,7 @@
+ * This is the main function called by Asterisk Core whenever the App is invoked in the extension logic.
+ * This function will always return 0.
+ */
+-static int alarmreceiver_exec(struct ast_channel *chan, void *data)
++static int alarmreceiver_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+ event_node_t *elp, *efree;
+Index: apps/app_image.c
+===================================================================
+--- a/apps/app_image.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_image.c (.../trunk) (revision 202568)
+@@ -69,7 +69,7 @@
+ </application>
+ ***/
+
+-static int sendimage_exec(struct ast_channel *chan, void *data)
++static int sendimage_exec(struct ast_channel *chan, const char *data)
+ {
+
+ if (ast_strlen_zero(data)) {
+Index: apps/app_getcpeid.c
+===================================================================
+--- a/apps/app_getcpeid.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_getcpeid.c (.../trunk) (revision 202568)
+@@ -61,7 +61,7 @@
+ return ast_adsi_print(chan, tmp, justify, voice);
+ }
+
+-static int cpeid_exec(struct ast_channel *chan, void *idata)
++static int cpeid_exec(struct ast_channel *chan, const char *idata)
+ {
+ int res=0;
+ unsigned char cpeid[4];
+Index: apps/app_talkdetect.c
+===================================================================
+--- a/apps/app_talkdetect.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_talkdetect.c (.../trunk) (revision 202568)
+@@ -73,7 +73,7 @@
+
+ static char *app = "BackgroundDetect";
+
+-static int background_detect_exec(struct ast_channel *chan, void *data)
++static int background_detect_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+ char *tmp;
+Index: apps/app_db.c
+===================================================================
+--- a/apps/app_db.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_db.c (.../trunk) (revision 202568)
+@@ -79,11 +79,10 @@
+ </application>
+ ***/
+
+-/*! \todo XXX Remove this application after 1.4 is relased */
+-static char *d_app = "DBdel";
+-static char *dt_app = "DBdeltree";
++static const char d_app[] = "DBdel";
++static const char dt_app[] = "DBdeltree";
+
+-static int deltree_exec(struct ast_channel *chan, void *data)
++static int deltree_exec(struct ast_channel *chan, const char *data)
+ {
+ char *argv, *family, *keytree;
+
+@@ -114,7 +113,7 @@
+ return 0;
+ }
+
+-static int del_exec(struct ast_channel *chan, void *data)
++static int del_exec(struct ast_channel *chan, const char *data)
+ {
+ char *argv, *family, *key;
+ static int deprecation_warning = 0;
+Index: apps/app_controlplayback.c
+===================================================================
+--- a/apps/app_controlplayback.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_controlplayback.c (.../trunk) (revision 202568)
+@@ -92,7 +92,7 @@
+ </description>
+ </application>
+ ***/
+-static const char *app = "ControlPlayback";
++static const char app[] = "ControlPlayback";
+
+ enum {
+ OPT_OFFSET = (1 << 1),
+@@ -125,7 +125,7 @@
+ return 0;
+ }
+
+-static int controlplayback_exec(struct ast_channel *chan, void *data)
++static int controlplayback_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+ int skipms = 0;
+Index: apps/app_setcallerid.c
+===================================================================
+--- a/apps/app_setcallerid.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_setcallerid.c (.../trunk) (revision 202568)
+@@ -84,7 +84,7 @@
+
+ static char *app2 = "SetCallerPres";
+
+-static int setcallerid_pres_exec(struct ast_channel *chan, void *data)
++static int setcallerid_pres_exec(struct ast_channel *chan, const char *data)
+ {
+ int pres = -1;
+ static int deprecated = 0;
+Index: apps/Makefile
+===================================================================
+--- a/apps/Makefile (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/Makefile (.../trunk) (revision 202568)
+@@ -18,11 +18,9 @@
+ MENUSELECT_OPTS_app_directory:=$(MENUSELECT_OPTS_app_voicemail)
+ ifneq ($(findstring ODBC_STORAGE,$(MENUSELECT_OPTS_app_voicemail)),)
+ MENUSELECT_DEPENDS_app_voicemail+=$(MENUSELECT_DEPENDS_ODBC_STORAGE)
+- MENUSELECT_DEPENDS_app_directory+=$(MENUSELECT_DEPENDS_ODBC_STORAGE)
+ endif
+ ifneq ($(findstring IMAP_STORAGE,$(MENUSELECT_OPTS_app_voicemail)),)
+ MENUSELECT_DEPENDS_app_voicemail+=$(MENUSELECT_DEPENDS_IMAP_STORAGE)
+- MENUSELECT_DEPENDS_app_directory+=$(MENUSELECT_DEPENDS_IMAP_STORAGE)
+ endif
+
+ all: _all
+Index: apps/app_mp3.c
+===================================================================
+--- a/apps/app_mp3.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_mp3.c (.../trunk) (revision 202568)
+@@ -64,7 +64,7 @@
+ ***/
+ static char *app = "MP3Player";
+
+-static int mp3play(char *filename, int fd)
++static int mp3play(const char *filename, int fd)
+ {
+ int res;
+
+@@ -117,7 +117,7 @@
+
+ }
+
+-static int mp3_exec(struct ast_channel *chan, void *data)
++static int mp3_exec(struct ast_channel *chan, const char *data)
+ {
+ int res=0;
+ int fds[2];
+@@ -152,8 +152,8 @@
+ return -1;
+ }
+
+- res = mp3play((char *)data, fds[1]);
+- if (!strncasecmp((char *)data, "http://", 7)) {
++ res = mp3play(data, fds[1]);
++ if (!strncasecmp(data, "http://", 7)) {
+ timeout = 10000;
+ }
+ /* Wait 1000 ms first */
+Index: apps/app_zapateller.c
+===================================================================
+--- a/apps/app_zapateller.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_zapateller.c (.../trunk) (revision 202568)
+@@ -74,7 +74,7 @@
+
+ static char *app = "Zapateller";
+
+-static int zapateller_exec(struct ast_channel *chan, void *data)
++static int zapateller_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+ int i, answer = 0, nocallerid = 0;
+Index: apps/app_senddtmf.c
+===================================================================
+--- a/apps/app_senddtmf.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_senddtmf.c (.../trunk) (revision 202568)
+@@ -59,10 +59,27 @@
+ <ref type="application">Read</ref>
+ </see-also>
+ </application>
++ <manager name="PlayDTMF" language="en_US">
++ <synopsis>
++ Play DTMF signal on a specific channel.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Channel" required="true">
++ <para>Channel name to send digit to.</para>
++ </parameter>
++ <parameter name="Digit" required="true">
++ <para>The DTMF digit to play.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Plays a dtmf digit on the specified channel.</para>
++ </description>
++ </manager>
+ ***/
+ static char *app = "SendDTMF";
+
+-static int senddtmf_exec(struct ast_channel *chan, void *vdata)
++static int senddtmf_exec(struct ast_channel *chan, const char *vdata)
+ {
+ int res = 0;
+ char *data;
+@@ -90,33 +107,29 @@
+ return res;
+ }
+
+-static char mandescr_playdtmf[] =
+-"Description: Plays a dtmf digit on the specified channel.\n"
+-"Variables: (all are required)\n"
+-" Channel: Channel name to send digit to\n"
+-" Digit: The dtmf digit to play\n";
+-
+ static int manager_play_dtmf(struct mansession *s, const struct message *m)
+ {
+ const char *channel = astman_get_header(m, "Channel");
+ const char *digit = astman_get_header(m, "Digit");
+- struct ast_channel *chan = ast_get_channel_by_name_locked(channel);
+-
+- if (!chan) {
+- astman_send_error(s, m, "Channel not specified");
++ struct ast_channel *chan;
++
++ if (!(chan = ast_channel_get_by_name(channel))) {
++ astman_send_error(s, m, "Channel not found");
+ return 0;
+ }
++
+ if (ast_strlen_zero(digit)) {
+ astman_send_error(s, m, "No digit specified");
+- ast_channel_unlock(chan);
++ chan = ast_channel_unref(chan);
+ return 0;
+ }
+
+ ast_senddigit(chan, *digit, 0);
+
+- ast_channel_unlock(chan);
++ chan = ast_channel_unref(chan);
++
+ astman_send_ack(s, m, "DTMF successfully queued");
+-
++
+ return 0;
+ }
+
+@@ -134,7 +147,7 @@
+ {
+ int res;
+
+- res = ast_manager_register2( "PlayDTMF", EVENT_FLAG_CALL, manager_play_dtmf, "Play DTMF signal on a specific channel.", mandescr_playdtmf );
++ res = ast_manager_register_xml("PlayDTMF", EVENT_FLAG_CALL, manager_play_dtmf);
+ res |= ast_register_application_xml(app, senddtmf_exec);
+
+ return res;
+Index: apps/app_rpt.c
+===================================================================
+--- a/apps/app_rpt.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_rpt.c (.../trunk) (revision 202568)
+@@ -439,7 +439,7 @@
+ static int debug = 0; /* Set this >0 for extra debug output */
+ static int nrpts = 0;
+
+-static char remdtmfstr[] = "0123456789*#ABCD";
++static const char remdtmfstr[] = "0123456789*#ABCD";
+
+ enum {TOP_TOP,TOP_WON,WON_BEFREAD,BEFREAD_AFTERREAD};
+
+@@ -1957,7 +1957,11 @@
+ if (!myrpt->p.statpost_url) return;
+ str = ast_malloc(strlen(pairs) + strlen(myrpt->p.statpost_url) + 200);
+ astr = ast_strdup(myrpt->p.statpost_program);
+- if ((!str) || (!astr)) return;
++ if ((!str) || (!astr)) {
++ ast_free(str);
++ ast_free(astr);
++ return;
++ }
+ n = finddelim(astr,astrs,100);
+ if (n < 1) return;
+ ast_mutex_lock(&myrpt->statpost_lock);
+@@ -2895,12 +2899,8 @@
+ for(j = 0; j < numoflinks; j++){ /* ast_free() all link names */
+ ast_free(listoflinks[j]);
+ }
+- if(called_number){
+- ast_free(called_number);
+- }
+- if(lastdtmfcommand){
+- ast_free(lastdtmfcommand);
+- }
++ ast_free(called_number);
++ ast_free(lastdtmfcommand);
+ return RESULT_SUCCESS;
+ }
+ }
+@@ -3646,8 +3646,7 @@
+ if(res)
+ break;
+ }
+- if(p)
+- ast_free(p);
++ ast_free(p);
+ if(!res)
+ res = play_tone_pair(chan, 0, 0, 100, 0); /* This is needed to ensure the last tone segment is timed correctly */
+
+@@ -3828,8 +3827,7 @@
+ else{
+ res = -1;
+ }
+- if(telemetry_save)
+- ast_free(telemetry_save);
++ ast_free(telemetry_save);
+ return res;
+ }
+
+@@ -3907,8 +3905,7 @@
+ interval = 0;
+ break;
+ }
+- if(wait_times_save)
+- ast_free(wait_times_save);
++ ast_free(wait_times_save);
+ return interval;
+ }
+
+@@ -3940,7 +3937,7 @@
+ struct rpt *myrpt;
+ struct rpt_link *l,*l1,linkbase;
+ struct ast_channel *mychannel;
+-int id_malloc, vmajor, vminor, m;
++int vmajor, vminor, m;
+ char *p,*ct,*ct_copy,*ident, *nodename,*cp;
+ time_t t;
+ #ifdef NEW_ASTERISK
+@@ -3987,14 +3984,10 @@
+ ast_free(mytele);
+ pthread_exit(NULL);
+ }
+- else{
+- id_malloc = 1;
+- }
+ }
+ else
+ {
+ ident = "";
+- id_malloc = 0;
+ }
+ rpt_mutex_unlock(&myrpt->lock);
+
+@@ -4010,8 +4003,7 @@
+ ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode); /*@@@@@@@@@@@*/
+ rpt_mutex_unlock(&myrpt->lock);
+ ast_free(nodename);
+- if(id_malloc)
+- ast_free(ident);
++ ast_free(ident);
+ ast_free(mytele);
+ pthread_exit(NULL);
+ }
+@@ -4057,8 +4049,7 @@
+ rpt_mutex_unlock(&myrpt->lock);
+ ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode); /*@@@@@@@@@@@*/
+ ast_free(nodename);
+- if(id_malloc)
+- ast_free(ident);
++ ast_free(ident);
+ ast_free(mytele);
+ ast_hangup(mychannel);
+ pthread_exit(NULL);
+@@ -4252,8 +4243,7 @@
+ rpt_mutex_unlock(&myrpt->lock);
+ ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode); /*@@@@@@@@@@@*/
+ ast_free(nodename);
+- if(id_malloc)
+- ast_free(ident);
++ ast_free(ident);
+ ast_free(mytele);
+ ast_hangup(mychannel);
+ pthread_exit(NULL);
+@@ -4293,8 +4283,7 @@
+ rpt_mutex_unlock(&myrpt->lock);
+ ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode); /*@@@@@@@@@@@*/
+ ast_free(nodename);
+- if(id_malloc)
+- ast_free(ident);
++ ast_free(ident);
+ ast_free(mytele);
+ ast_hangup(mychannel);
+ pthread_exit(NULL);
+@@ -4816,8 +4805,7 @@
+ rpt_mutex_unlock(&myrpt->lock);
+ ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode); /*@@@@@@@@@@@*/
+ ast_free(nodename);
+- if(id_malloc)
+- ast_free(ident);
++ ast_free(ident);
+ ast_free(mytele);
+ ast_hangup(mychannel);
+ pthread_exit(NULL);
+@@ -5193,8 +5181,7 @@
+ myrpt->active_telem = NULL;
+ rpt_mutex_unlock(&myrpt->lock);
+ ast_free(nodename);
+- if(id_malloc)
+- ast_free(ident);
++ ast_free(ident);
+ ast_free(mytele);
+ ast_hangup(mychannel);
+ #ifdef APP_RPT_LOCK_DEBUG
+@@ -13114,7 +13101,7 @@
+ pthread_exit(NULL);
+ }
+
+-static int rpt_exec(struct ast_channel *chan, void *data)
++static int rpt_exec(struct ast_channel *chan, const void *data)
+ {
+ int res=-1,i,rem_totx,rem_rx,remkeyed,n,phone_mode = 0;
+ int iskenwood_pci4,authtold,authreq,setting,notremming,reming;
+Index: apps/app_mixmonitor.c
+===================================================================
+--- a/apps/app_mixmonitor.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_mixmonitor.c (.../trunk) (revision 202568)
+@@ -45,11 +45,13 @@
+ #include "asterisk/cli.h"
+ #include "asterisk/app.h"
+ #include "asterisk/channel.h"
++#include "asterisk/autochan.h"
+
+ /*** DOCUMENTATION
+ <application name="MixMonitor" language="en_US">
+ <synopsis>
+- Record a call and mix the audio during the recording.
++ Record a call and mix the audio during the recording. Use of StopMixMonitor is required
++ to guarantee the audio file is available for processing during dialplan execution.
+ </synopsis>
+ <syntax>
+ <parameter name="file" required="true" argsep=".">
+@@ -111,7 +113,7 @@
+ </application>
+ <application name="StopMixMonitor" language="en_US">
+ <synopsis>
+- Stop recording a call through MixMonitor.
++ Stop recording a call through MixMonitor, and free the recording's file handle.
+ </synopsis>
+ <syntax />
+ <description>
+@@ -127,37 +129,36 @@
+
+ #define get_volfactor(x) x ? ((x > 0) ? (1 << x) : ((1 << abs(x)) * -1)) : 0
+
+-static const char *app = "MixMonitor";
++static const char * const app = "MixMonitor";
+
+-static const char *stop_app = "StopMixMonitor";
++static const char * const stop_app = "StopMixMonitor";
+
+-struct module_symbols *me;
++static const char * const mixmonitor_spy_type = "MixMonitor";
+
+-static const char *mixmonitor_spy_type = "MixMonitor";
+-
+ struct mixmonitor {
+ struct ast_audiohook audiohook;
+ char *filename;
+ char *post_process;
+ char *name;
+ unsigned int flags;
++ struct ast_autochan *autochan;
+ struct mixmonitor_ds *mixmonitor_ds;
+ };
+
+-enum {
++enum mixmonitor_flags {
+ MUXFLAG_APPEND = (1 << 1),
+ MUXFLAG_BRIDGED = (1 << 2),
+ MUXFLAG_VOLUME = (1 << 3),
+ MUXFLAG_READVOLUME = (1 << 4),
+ MUXFLAG_WRITEVOLUME = (1 << 5),
+-} mixmonitor_flags;
++};
+
+-enum {
++enum mixmonitor_args {
+ OPT_ARG_READVOLUME = 0,
+ OPT_ARG_WRITEVOLUME,
+ OPT_ARG_VOLUME,
+ OPT_ARG_ARRAY_SIZE,
+-} mixmonitor_args;
++};
+
+ AST_APP_OPTIONS(mixmonitor_opts, {
+ AST_APP_OPTION('a', MUXFLAG_APPEND),
+@@ -167,48 +168,43 @@
+ AST_APP_OPTION_ARG('W', MUXFLAG_VOLUME, OPT_ARG_VOLUME),
+ });
+
+-/* This structure is used as a means of making sure that our pointer to
+- * the channel we are monitoring remains valid. This is very similar to
+- * what is used in app_chanspy.c.
+- */
+ struct mixmonitor_ds {
+- struct ast_channel *chan;
+- /* These condition variables are used to be sure that the channel
+- * hangup code completes before the mixmonitor thread attempts to
+- * free this structure. The combination of a bookean flag and a
+- * ast_cond_t ensure that no matter what order the threads run in,
+- * we are guaranteed to never have the waiting thread block forever
+- * in the case that the signaling thread runs first.
+- */
+ unsigned int destruction_ok;
+ ast_cond_t destruction_condition;
+ ast_mutex_t lock;
++
++ /* The filestream is held in the datastore so it can be stopped
++ * immediately during stop_mixmonitor or channel destruction. */
++ int fs_quit;
++ struct ast_filestream *fs;
++
+ };
+
+-static void mixmonitor_ds_destroy(void *data)
++static void mixmonitor_ds_close_fs(struct mixmonitor_ds *mixmonitor_ds)
+ {
+- struct mixmonitor_ds *mixmonitor_ds = data;
+-
+ ast_mutex_lock(&mixmonitor_ds->lock);
+- mixmonitor_ds->chan = NULL;
+- mixmonitor_ds->destruction_ok = 1;
+- ast_cond_signal(&mixmonitor_ds->destruction_condition);
++ if (mixmonitor_ds->fs) {
++ ast_closestream(mixmonitor_ds->fs);
++ mixmonitor_ds->fs = NULL;
++ mixmonitor_ds->fs_quit = 1;
++ ast_verb(2, "MixMonitor close filestream\n");
++ }
+ ast_mutex_unlock(&mixmonitor_ds->lock);
+ }
+
+-static void mixmonitor_ds_chan_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
++static void mixmonitor_ds_destroy(void *data)
+ {
+ struct mixmonitor_ds *mixmonitor_ds = data;
+
+ ast_mutex_lock(&mixmonitor_ds->lock);
+- mixmonitor_ds->chan = new_chan;
++ mixmonitor_ds->destruction_ok = 1;
++ ast_cond_signal(&mixmonitor_ds->destruction_condition);
+ ast_mutex_unlock(&mixmonitor_ds->lock);
+ }
+
+ static struct ast_datastore_info mixmonitor_ds_info = {
+ .type = "mixmonitor",
+ .destroy = mixmonitor_ds_destroy,
+- .chan_fixup = mixmonitor_ds_chan_fixup,
+ };
+
+ static int startmon(struct ast_channel *chan, struct ast_audiohook *audiohook)
+@@ -229,19 +225,32 @@
+
+ #define SAMPLES_PER_FRAME 160
+
++static void mixmonitor_free(struct mixmonitor *mixmonitor)
++{
++ if (mixmonitor) {
++ if (mixmonitor->mixmonitor_ds) {
++ ast_mutex_destroy(&mixmonitor->mixmonitor_ds->lock);
++ ast_cond_destroy(&mixmonitor->mixmonitor_ds->destruction_condition);
++ ast_free(mixmonitor->mixmonitor_ds);
++ }
++ ast_free(mixmonitor);
++ }
++}
+ static void *mixmonitor_thread(void *obj)
+ {
+ struct mixmonitor *mixmonitor = obj;
+- struct ast_filestream *fs = NULL;
++ struct ast_filestream **fs = NULL;
+ unsigned int oflags;
+ char *ext;
+ int errflag = 0;
+
+ ast_verb(2, "Begin MixMonitor Recording %s\n", mixmonitor->name);
+-
++
+ ast_audiohook_lock(&mixmonitor->audiohook);
+
+- while (mixmonitor->audiohook.status == AST_AUDIOHOOK_STATUS_RUNNING) {
++ fs = &mixmonitor->mixmonitor_ds->fs;
++
++ while (mixmonitor->audiohook.status == AST_AUDIOHOOK_STATUS_RUNNING && !mixmonitor->mixmonitor_ds->fs_quit) {
+ struct ast_frame *fr = NULL;
+
+ ast_audiohook_trigger_wait(&mixmonitor->audiohook);
+@@ -252,32 +261,34 @@
+ if (!(fr = ast_audiohook_read_frame(&mixmonitor->audiohook, SAMPLES_PER_FRAME, AST_AUDIOHOOK_DIRECTION_BOTH, AST_FORMAT_SLINEAR)))
+ continue;
+
+- ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock);
+- if (!ast_test_flag(mixmonitor, MUXFLAG_BRIDGED) || (mixmonitor->mixmonitor_ds->chan && ast_bridged_channel(mixmonitor->mixmonitor_ds->chan))) {
+- ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock);
++ if (!ast_test_flag(mixmonitor, MUXFLAG_BRIDGED) || (mixmonitor->autochan->chan && ast_bridged_channel(mixmonitor->autochan->chan))) {
++ ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock);
+ /* Initialize the file if not already done so */
+- if (!fs && !errflag) {
++ if (!*fs && !errflag && !mixmonitor->mixmonitor_ds->fs_quit) {
+ oflags = O_CREAT | O_WRONLY;
+ oflags |= ast_test_flag(mixmonitor, MUXFLAG_APPEND) ? O_APPEND : O_TRUNC;
+-
++
+ if ((ext = strrchr(mixmonitor->filename, '.')))
+ *(ext++) = '\0';
+ else
+ ext = "raw";
+-
+- if (!(fs = ast_writefile(mixmonitor->filename, ext, NULL, oflags, 0, 0666))) {
++
++ if (!(*fs = ast_writefile(mixmonitor->filename, ext, NULL, oflags, 0, 0666))) {
+ ast_log(LOG_ERROR, "Cannot open %s.%s\n", mixmonitor->filename, ext);
+ errflag = 1;
+ }
+ }
+-
+- /* Write out frame */
+- if (fs)
+- ast_writestream(fs, fr);
+- } else {
++
++ /* Write out the frame(s) */
++ if (*fs) {
++ struct ast_frame *cur;
++
++ for (cur = fr; cur; cur = AST_LIST_NEXT(cur, frame_list)) {
++ ast_writestream(*fs, cur);
++ }
++ }
+ ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock);
+ }
+-
+ /* All done! free it. */
+ ast_frame_free(fr, 0);
+
+@@ -287,26 +298,25 @@
+ ast_audiohook_unlock(&mixmonitor->audiohook);
+ ast_audiohook_destroy(&mixmonitor->audiohook);
+
+- ast_verb(2, "End MixMonitor Recording %s\n", mixmonitor->name);
++ mixmonitor_ds_close_fs(mixmonitor->mixmonitor_ds);
+
+- if (fs)
+- ast_closestream(fs);
+
+ if (mixmonitor->post_process) {
+ ast_verb(2, "Executing [%s]\n", mixmonitor->post_process);
+ ast_safe_system(mixmonitor->post_process);
+ }
+
++ ast_autochan_destroy(mixmonitor->autochan);
++
+ ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock);
+ if (!mixmonitor->mixmonitor_ds->destruction_ok) {
+ ast_cond_wait(&mixmonitor->mixmonitor_ds->destruction_condition, &mixmonitor->mixmonitor_ds->lock);
+ }
+ ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock);
+- ast_mutex_destroy(&mixmonitor->mixmonitor_ds->lock);
+- ast_cond_destroy(&mixmonitor->mixmonitor_ds->destruction_condition);
+- ast_free(mixmonitor->mixmonitor_ds);
+- ast_free(mixmonitor);
+
++
++ ast_verb(2, "End MixMonitor Recording %s\n", mixmonitor->name);
++ mixmonitor_free(mixmonitor);
+ return NULL;
+ }
+
+@@ -318,17 +328,17 @@
+ if (!(mixmonitor_ds = ast_calloc(1, sizeof(*mixmonitor_ds)))) {
+ return -1;
+ }
+-
++
+ ast_mutex_init(&mixmonitor_ds->lock);
+ ast_cond_init(&mixmonitor_ds->destruction_condition, NULL);
+
+ if (!(datastore = ast_datastore_alloc(&mixmonitor_ds_info, NULL))) {
++ ast_mutex_destroy(&mixmonitor_ds->lock);
++ ast_cond_destroy(&mixmonitor_ds->destruction_condition);
+ ast_free(mixmonitor_ds);
+ return -1;
+ }
+
+- /* No need to lock mixmonitor_ds since this is still operating in the channel's thread */
+- mixmonitor_ds->chan = chan;
+ datastore->data = mixmonitor_ds;
+
+ ast_channel_lock(chan);
+@@ -372,7 +382,14 @@
+
+ /* Copy over flags and channel name */
+ mixmonitor->flags = flags;
++ if (!(mixmonitor->autochan = ast_autochan_setup(chan))) {
++ mixmonitor_free(mixmonitor);
++ return;
++ }
++
+ if (setup_mixmonitor_ds(mixmonitor, chan)) {
++ ast_autochan_destroy(mixmonitor->autochan);
++ mixmonitor_free(mixmonitor);
+ return;
+ }
+ mixmonitor->name = (char *) mixmonitor + sizeof(*mixmonitor);
+@@ -409,7 +426,7 @@
+ ast_pthread_create_detached_background(&thread, NULL, mixmonitor_thread, mixmonitor);
+ }
+
+-static int mixmonitor_exec(struct ast_channel *chan, void *data)
++static int mixmonitor_exec(struct ast_channel *chan, const char *data)
+ {
+ int x, readvol = 0, writevol = 0;
+ struct ast_flags flags = {0};
+@@ -490,8 +507,16 @@
+ return 0;
+ }
+
+-static int stop_mixmonitor_exec(struct ast_channel *chan, void *data)
++static int stop_mixmonitor_exec(struct ast_channel *chan, const char *data)
+ {
++ struct ast_datastore *datastore = NULL;
++
++ /* closing the filestream here guarantees the file is avaliable to the dialplan
++ * after calling StopMixMonitor */
++ if ((datastore = ast_channel_datastore_find(chan, &mixmonitor_ds_info, NULL))) {
++ mixmonitor_ds_close_fs(datastore->data);
++ }
++
+ ast_audiohook_detach_source(chan, mixmonitor_spy_type);
+ return 0;
+ }
+@@ -515,12 +540,14 @@
+ if (a->argc < 3)
+ return CLI_SHOWUSAGE;
+
+- if (!(chan = ast_get_channel_by_name_prefix_locked(a->argv[2], strlen(a->argv[2])))) {
++ if (!(chan = ast_channel_get_by_name_prefix(a->argv[2], strlen(a->argv[2])))) {
+ ast_cli(a->fd, "No channel matching '%s' found.\n", a->argv[2]);
+ /* Technically this is a failure, but we don't want 2 errors printing out */
+ return CLI_SUCCESS;
+ }
+
++ ast_channel_lock(chan);
++
+ if (!strcasecmp(a->argv[1], "start")) {
+ mixmonitor_exec(chan, a->argv[3]);
+ ast_channel_unlock(chan);
+@@ -529,6 +556,8 @@
+ ast_audiohook_detach_source(chan, mixmonitor_spy_type);
+ }
+
++ chan = ast_channel_unref(chan);
++
+ return CLI_SUCCESS;
+ }
+
+Index: apps/app_ivrdemo.c
+===================================================================
+--- a/apps/app_ivrdemo.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_ivrdemo.c (.../trunk) (revision 202568)
+@@ -59,7 +59,7 @@
+
+ static int ivr_demo_func(struct ast_channel *chan, void *data)
+ {
+- ast_verbose("IVR Demo, data is %s!\n", (char *)data);
++ ast_verbose("IVR Demo, data is %s!\n", (char *) data);
+ return 0;
+ }
+
+@@ -93,22 +93,24 @@
+ { NULL },
+ });
+
+-
+-static int skel_exec(struct ast_channel *chan, void *data)
++static int skel_exec(struct ast_channel *chan, const char *data)
+ {
+ int res=0;
++ char *tmp;
+
+ if (ast_strlen_zero(data)) {
+ ast_log(LOG_WARNING, "skel requires an argument (filename)\n");
+ return -1;
+ }
+
++ tmp = ast_strdupa(data);
++
+ /* Do our thing here */
+
+ if (chan->_state != AST_STATE_UP)
+ res = ast_answer(chan);
+ if (!res)
+- res = ast_ivr_menu_run(chan, &ivr_demo, data);
++ res = ast_ivr_menu_run(chan, &ivr_demo, tmp);
+
+ return res;
+ }
+Index: apps/app_milliwatt.c
+===================================================================
+--- a/apps/app_milliwatt.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_milliwatt.c (.../trunk) (revision 202568)
+@@ -55,9 +55,9 @@
+ </application>
+ ***/
+
+-static char *app = "Milliwatt";
++static const char app[] = "Milliwatt";
+
+-static char digital_milliwatt[] = {0x1e,0x0b,0x0b,0x1e,0x9e,0x8b,0x8b,0x9e} ;
++static const char digital_milliwatt[] = {0x1e,0x0b,0x0b,0x1e,0x9e,0x8b,0x8b,0x9e} ;
+
+ static void *milliwatt_alloc(struct ast_channel *chan, void *params)
+ {
+@@ -139,7 +139,7 @@
+ return -1;
+ }
+
+-static int milliwatt_exec(struct ast_channel *chan, void *data)
++static int milliwatt_exec(struct ast_channel *chan, const char *data)
+ {
+ const char *options = data;
+ struct ast_app *playtones_app;
+Index: apps/app_parkandannounce.c
+===================================================================
+--- a/apps/app_parkandannounce.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_parkandannounce.c (.../trunk) (revision 202568)
+@@ -85,7 +85,7 @@
+
+ static char *app = "ParkAndAnnounce";
+
+-static int parkandannounce_exec(struct ast_channel *chan, void *data)
++static int parkandannounce_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = -1;
+ int lot, timeout = 0, dres;
+Index: apps/app_readfile.c
+===================================================================
+--- a/apps/app_readfile.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_readfile.c (.../trunk) (revision 202568)
+@@ -67,7 +67,7 @@
+
+ static char *app_readfile = "ReadFile";
+
+-static int readfile_exec(struct ast_channel *chan, void *data)
++static int readfile_exec(struct ast_channel *chan, const char *data)
+ {
+ int res=0;
+ char *s, *varname=NULL, *file=NULL, *length=NULL, *returnvar=NULL;
+Index: apps/app_meetme.c
+===================================================================
+--- a/apps/app_meetme.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_meetme.c (.../trunk) (revision 202568)
+@@ -420,6 +420,80 @@
+ </variablelist>
+ </description>
+ </application>
++ <function name="MEETME_INFO" language="en_US">
++ <synopsis>
++ Query a given conference of various properties.
++ </synopsis>
++ <syntax>
++ <parameter name="keyword" required="true">
++ <para>Options:</para>
++ <enumlist>
++ <enum name="lock">
++ <para>Boolean of whether the corresponding conference is locked.</para>
++ </enum>
++ <enum name="parties">
++ <para>Number of parties in a given conference</para>
++ </enum>
++ <enum name="activity">
++ <para>Duration of conference in seconds.</para>
++ </enum>
++ <enum name="dynamic">
++ <para>Boolean of whether the corresponding conference is dynamic.</para>
++ </enum>
++ </enumlist>
++ </parameter>
++ <parameter name="confno" required="true">
++ <para>Conference number to retrieve information from.</para>
++ </parameter>
++ </syntax>
++ <description />
++ <see-also>
++ <ref type="application">MeetMe</ref>
++ <ref type="application">MeetMeCount</ref>
++ <ref type="application">MeetMeAdmin</ref>
++ <ref type="application">MeetMeChannelAdmin</ref>
++ </see-also>
++ </function>
++ <manager name="MeetmeMute" language="en_US">
++ <synopsis>
++ Mute a Meetme user.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Meetme" required="true" />
++ <parameter name="Usernum" required="true" />
++ </syntax>
++ <description>
++ </description>
++ </manager>
++ <manager name="MeetmeUnmute" language="en_US">
++ <synopsis>
++ Unmute a Meetme user.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Meetme" required="true" />
++ <parameter name="Usernum" required="true" />
++ </syntax>
++ <description>
++ </description>
++ </manager>
++ <manager name="MeetmeList" language="en_US">
++ <synopsis>
++ List participants in a conference.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Conference" required="true">
++ <para>Conference number.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Lists all users in a particular MeetMe conference.
++ MeetmeList will follow as separate events, followed by a final event called
++ MeetmeListComplete.</para>
++ </description>
++ </manager>
+ ***/
+
+ #define CONFIG_FILE_NAME "meetme.conf"
+@@ -565,12 +639,12 @@
+ AST_APP_OPTION_ARG('L', CONFFLAG_DURATION_LIMIT, OPT_ARG_DURATION_LIMIT),
+ END_OPTIONS );
+
+-static const char *app = "MeetMe";
+-static const char *app2 = "MeetMeCount";
+-static const char *app3 = "MeetMeAdmin";
+-static const char *app4 = "MeetMeChannelAdmin";
+-static const char *slastation_app = "SLAStation";
+-static const char *slatrunk_app = "SLATrunk";
++static const char * const app = "MeetMe";
++static const char * const app2 = "MeetMeCount";
++static const char * const app3 = "MeetMeAdmin";
++static const char * const app4 = "MeetMeChannelAdmin";
++static const char * const slastation_app = "SLAStation";
++static const char * const slatrunk_app = "SLATrunk";
+
+ /* Lookup RealTime conferences based on confno and current time */
+ static int rt_schedule;
+@@ -861,7 +935,7 @@
+ * conversion... the numbers have been modified
+ * to give the user a better level of adjustability
+ */
+-static char const gain_map[] = {
++static const char gain_map[] = {
+ -15,
+ -13,
+ -10,
+@@ -876,7 +950,7 @@
+ };
+
+
+-static int admin_exec(struct ast_channel *chan, void *data);
++static int admin_exec(struct ast_channel *chan, const char *data);
+ static void *recordthread(void *args);
+
+ static char *istalking(int x)
+@@ -1144,7 +1218,7 @@
+
+ static char *complete_meetmecmd(const char *line, const char *word, int pos, int state)
+ {
+- static char *cmds[] = {"concise", "lock", "unlock", "mute", "unmute", "kick", "list", NULL};
++ static const char * const cmds[] = {"concise", "lock", "unlock", "mute", "unmute", "kick", "list", NULL};
+
+ int len = strlen(word);
+ int which = 0;
+@@ -3195,9 +3269,18 @@
+ }
+ }
+ if (conf->transframe[idx]) {
+- if (conf->transframe[idx]->frametype != AST_FRAME_NULL) {
+- if (can_write(chan, confflags) && ast_write(chan, conf->transframe[idx])) {
+- ast_log(LOG_WARNING, "Unable to write frame to channel %s\n", chan->name);
++ if ((conf->transframe[idx]->frametype != AST_FRAME_NULL) &&
++ can_write(chan, confflags)) {
++ struct ast_frame *cur;
++
++ /* the translator may have returned a list of frames, so
++ write each one onto the channel
++ */
++ for (cur = conf->transframe[idx]; cur; cur = AST_LIST_NEXT(cur, frame_list)) {
++ if (ast_write(chan, cur)) {
++ ast_log(LOG_WARNING, "Unable to write frame to channel %s\n", chan->name);
++ break;
++ }
+ }
+ }
+ } else {
+@@ -3600,7 +3683,7 @@
+ }
+
+ /*! \brief The MeetmeCount application */
+-static int count_exec(struct ast_channel *chan, void *data)
++static int count_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+ struct ast_conference *conf;
+@@ -3646,7 +3729,7 @@
+ }
+
+ /*! \brief The meetme() application */
+-static int conf_exec(struct ast_channel *chan, void *data)
++static int conf_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = -1;
+ char confno[MAX_CONFNUM] = "";
+@@ -3657,7 +3740,8 @@
+ int dynamic = 0;
+ int empty = 0, empty_no_pin = 0;
+ int always_prompt = 0;
+- char *notdata, *info, the_pin[MAX_PIN] = "";
++ const char *notdata;
++ char *info, the_pin[MAX_PIN] = "";
+ AST_DECLARE_APP_ARGS(args,
+ AST_APP_ARG(confno);
+ AST_APP_ARG(options);
+@@ -3920,7 +4004,7 @@
+
+ /*! \brief The MeetMeadmin application */
+ /* MeetMeAdmin(confno, command, caller) */
+-static int admin_exec(struct ast_channel *chan, void *data) {
++static int admin_exec(struct ast_channel *chan, const char *data) {
+ char *params;
+ struct ast_conference *cnf;
+ struct ast_conf_user *user = NULL;
+@@ -4102,7 +4186,7 @@
+
+ /*--- channel_admin_exec: The MeetMeChannelAdmin application */
+ /* MeetMeChannelAdmin(channel, command) */
+-static int channel_admin_exec(struct ast_channel *chan, void *data) {
++static int channel_admin_exec(struct ast_channel *chan, const char *data) {
+ char *params;
+ struct ast_conference *conf = NULL;
+ struct ast_conf_user *user = NULL;
+@@ -4235,14 +4319,6 @@
+ return meetmemute(s, m, 0);
+ }
+
+-static char mandescr_meetmelist[] =
+-"Description: Lists all users in a particular MeetMe conference.\n"
+-"MeetmeList will follow as separate events, followed by a final event called\n"
+-"MeetmeListComplete.\n"
+-"Variables:\n"
+-" *ActionId: <id>\n"
+-" *Conference: <confno>\n";
+-
+ static int action_meetmelist(struct mansession *s, const struct message *m)
+ {
+ const char *actionid = astman_get_header(m, "ActionID");
+@@ -5552,7 +5628,7 @@
+ return trunk_ref;
+ }
+
+-static int sla_station_exec(struct ast_channel *chan, void *data)
++static int sla_station_exec(struct ast_channel *chan, const char *data)
+ {
+ char *station_name, *trunk_name;
+ struct sla_station *station;
+@@ -5759,7 +5835,7 @@
+ AST_APP_OPTION_ARG('M', SLA_TRUNK_OPT_MOH, SLA_TRUNK_OPT_ARG_MOH_CLASS),
+ END_OPTIONS );
+
+-static int sla_trunk_exec(struct ast_channel *chan, void *data)
++static int sla_trunk_exec(struct ast_channel *chan, const char *data)
+ {
+ char conf_name[MAX_CONFNUM];
+ struct ast_conference *conf;
+@@ -6357,16 +6433,7 @@
+
+ static struct ast_custom_function meetme_info_acf = {
+ .name = "MEETME_INFO",
+- .synopsis = "Query a given conference of various properties.",
+- .syntax = "MEETME_INFO(<keyword>,<confno>)",
+ .read = acf_meetme_info,
+- .desc =
+-"Returns information from a given keyword. (For booleans 1-true, 0-false)\n"
+-" Options:\n"
+-" lock - boolean of whether the corresponding conference is locked\n"
+-" parties - number of parties in a given conference\n"
+-" activity - duration of conference in seconds\n"
+-" dynamic - boolean of whether the corresponding coference is dynamic\n",
+ };
+
+
+@@ -6417,12 +6484,9 @@
+ res |= load_config(0);
+
+ ast_cli_register_multiple(cli_meetme, ARRAY_LEN(cli_meetme));
+- res |= ast_manager_register("MeetmeMute", EVENT_FLAG_CALL,
+- action_meetmemute, "Mute a Meetme user");
+- res |= ast_manager_register("MeetmeUnmute", EVENT_FLAG_CALL,
+- action_meetmeunmute, "Unmute a Meetme user");
+- res |= ast_manager_register2("MeetmeList", EVENT_FLAG_REPORTING,
+- action_meetmelist, "List participants in a conference", mandescr_meetmelist);
++ res |= ast_manager_register_xml("MeetmeMute", EVENT_FLAG_CALL, action_meetmemute);
++ res |= ast_manager_register_xml("MeetmeUnmute", EVENT_FLAG_CALL, action_meetmeunmute);
++ res |= ast_manager_register_xml("MeetmeList", EVENT_FLAG_REPORTING, action_meetmelist);
+ res |= ast_register_application_xml(app4, channel_admin_exec);
+ res |= ast_register_application_xml(app3, admin_exec);
+ res |= ast_register_application_xml(app2, count_exec);
+Index: apps/app_test.c
+===================================================================
+--- a/apps/app_test.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_test.c (.../trunk) (revision 202568)
+@@ -132,7 +132,7 @@
+ return (noise / samples);
+ }
+
+-static int sendnoise(struct ast_channel *chan, int ms)
++static int sendnoise(struct ast_channel *chan, int ms)
+ {
+ int res;
+ res = ast_tonepair_start(chan, 1537, 2195, ms, 8192);
+@@ -140,51 +140,51 @@
+ res = ast_waitfordigit(chan, ms);
+ ast_tonepair_stop(chan);
+ }
+- return res;
++ return res;
+ }
+
+-static int testclient_exec(struct ast_channel *chan, void *data)
++static int testclient_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+- char *testid=data;
++ const char *testid=data;
+ char fn[80];
+ char serverver[80];
+ FILE *f;
+-
++
+ /* Check for test id */
+ if (ast_strlen_zero(testid)) {
+ ast_log(LOG_WARNING, "TestClient requires an argument - the test id\n");
+ return -1;
+ }
+-
++
+ if (chan->_state != AST_STATE_UP)
+ res = ast_answer(chan);
+-
++
+ /* Wait a few just to be sure things get started */
+ res = ast_safe_sleep(chan, 3000);
+ /* Transmit client version */
+ if (!res)
+ res = ast_dtmf_stream(chan, NULL, "8378*1#", 0, 0);
+ ast_debug(1, "Transmit client version\n");
+-
++
+ /* Read server version */
+ ast_debug(1, "Read server version\n");
+- if (!res)
++ if (!res)
+ res = ast_app_getdata(chan, NULL, serverver, sizeof(serverver) - 1, 0);
+ if (res > 0)
+ res = 0;
+ ast_debug(1, "server version: %s\n", serverver);
+-
++
+ if (res > 0)
+ res = 0;
+
+ if (!res)
+ res = ast_safe_sleep(chan, 1000);
+ /* Send test id */
+- if (!res)
+- res = ast_dtmf_stream(chan, NULL, testid, 0, 0);
+- if (!res)
+- res = ast_dtmf_stream(chan, NULL, "#", 0, 0);
++ if (!res)
++ res = ast_dtmf_stream(chan, NULL, testid, 0, 0);
++ if (!res)
++ res = ast_dtmf_stream(chan, NULL, "#", 0, 0);
+ ast_debug(1, "send test identifier: %s\n", testid);
+
+ if ((res >=0) && (!ast_strlen_zero(testid))) {
+@@ -198,7 +198,7 @@
+ fprintf(f, "CLIENTTEST ID: %s\n", testid);
+ fprintf(f, "ANSWER: PASS\n");
+ res = 0;
+-
++
+ if (!res) {
+ /* Step 1: Wait for "1" */
+ ast_debug(1, "TestClient: 2. Wait DTMF 1\n");
+@@ -209,8 +209,9 @@
+ else
+ res = -1;
+ }
+- if (!res)
++ if (!res) {
+ res = ast_safe_sleep(chan, 1000);
++ }
+ if (!res) {
+ /* Step 2: Send "2" */
+ ast_debug(1, "TestClient: 2. Send DTMF 2\n");
+@@ -226,7 +227,7 @@
+ fprintf(f, "WAIT 1 SEC: %s\n", (res < 0) ? "FAIL" : "PASS");
+ if (res > 0)
+ res = 0;
+- }
++ }
+ if (!res) {
+ /* Step 4: Measure noise */
+ ast_debug(1, "TestClient: 4. Measure noise\n");
+@@ -272,7 +273,7 @@
+ }
+ if (!res) {
+ /* Step 9: Measure noise */
+- ast_debug(1, "TestClient: 6. Measure tone\n");
++ ast_debug(1, "TestClient: 9. Measure tone\n");
+ res = measurenoise(chan, 4000, "TestClient");
+ fprintf(f, "MEASURETONE: %s (%d)\n", (res < 0) ? "FAIL" : "PASS", res);
+ if (res > 0)
+@@ -280,7 +281,7 @@
+ }
+ if (!res) {
+ /* Step 10: Send "7" */
+- ast_debug(1, "TestClient: 7. Send DTMF 7\n");
++ ast_debug(1, "TestClient: 10. Send DTMF 7\n");
+ res = ast_dtmf_stream(chan, NULL, "7", 0, 0);
+ fprintf(f, "SEND DTMF 7: %s\n", (res < 0) ? "FAIL" : "PASS");
+ if (res > 0)
+@@ -297,6 +298,9 @@
+ res = -1;
+ }
+ if (!res) {
++ res = ast_safe_sleep(chan, 1000);
++ }
++ if (!res) {
+ /* Step 12: Hangup! */
+ ast_debug(1, "TestClient: 12. Hangup\n");
+ }
+@@ -314,7 +318,7 @@
+ return res;
+ }
+
+-static int testserver_exec(struct ast_channel *chan, void *data)
++static int testserver_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+ char testid[80]="";
+@@ -324,7 +328,7 @@
+ res = ast_answer(chan);
+ /* Read version */
+ ast_debug(1, "Read client version\n");
+- if (!res)
++ if (!res)
+ res = ast_app_getdata(chan, NULL, testid, sizeof(testid) - 1, 0);
+ if (res > 0)
+ res = 0;
+@@ -338,8 +342,8 @@
+ if (res > 0)
+ res = 0;
+
+- if (!res)
+- res = ast_app_getdata(chan, NULL, testid, sizeof(testid) - 1, 0);
++ if (!res)
++ res = ast_app_getdata(chan, NULL, testid, sizeof(testid) - 1, 0);
+ ast_debug(1, "read test identifier: %s\n", testid);
+ /* Check for sneakyness */
+ if (strchr(testid, '/'))
+@@ -391,7 +395,6 @@
+ if (res > 0)
+ res = 0;
+ }
+-
+ if (!res) {
+ /* Step 5: Wait one second */
+ ast_debug(1, "TestServer: 5. Wait one second\n");
+@@ -400,7 +403,6 @@
+ if (res > 0)
+ res = 0;
+ }
+-
+ if (!res) {
+ /* Step 6: Measure noise */
+ ast_debug(1, "TestServer: 6. Measure tone\n");
+@@ -409,7 +411,6 @@
+ if (res > 0)
+ res = 0;
+ }
+-
+ if (!res) {
+ /* Step 7: Send "5" */
+ ast_debug(1, "TestServer: 7. Send DTMF 5\n");
+@@ -418,14 +419,13 @@
+ if (res > 0)
+ res = 0;
+ }
+-
+ if (!res) {
+ /* Step 8: Transmit tone noise */
+ ast_debug(1, "TestServer: 8. Transmit tone\n");
+ res = sendnoise(chan, 6000);
+ fprintf(f, "SENDTONE: %s\n", (res < 0) ? "FAIL" : "PASS");
+ }
+-
++
+ if (!res || (res == '7')) {
+ /* Step 9: Wait for "7" */
+ ast_debug(1, "TestServer: 9. Wait DTMF 7\n");
+@@ -437,8 +437,9 @@
+ else
+ res = -1;
+ }
+- if (!res)
++ if (!res) {
+ res = ast_safe_sleep(chan, 1000);
++ }
+ if (!res) {
+ /* Step 10: Send "8" */
+ ast_debug(1, "TestServer: 10. Send DTMF 8\n");
+@@ -474,7 +475,7 @@
+ res = ast_unregister_application(testc_app);
+ res |= ast_unregister_application(tests_app);
+
+- return res;
++ return res;
+ }
+
+ static int load_module(void)
+Index: apps/app_morsecode.c
+===================================================================
+--- a/apps/app_morsecode.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_morsecode.c (.../trunk) (revision 202568)
+@@ -63,9 +63,9 @@
+ </see-also>
+ </application>
+ ***/
+-static char *app_morsecode = "Morsecode";
++static const char app_morsecode[] = "Morsecode";
+
+-static char *morsecode[] = {
++static const char * const morsecode[] = {
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /* 0-15 */
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /* 16-31 */
+ " ", /* 32 - <space> */
+@@ -118,10 +118,10 @@
+ ast_playtones_stop(chan);
+ }
+
+-static int morsecode_exec(struct ast_channel *chan, void *data)
++static int morsecode_exec(struct ast_channel *chan, const char *data)
+ {
+ int res=0, ditlen, tone;
+- char *digit;
++ const char *digit;
+ const char *ditlenc, *tonec;
+
+ if (ast_strlen_zero(data)) {
+@@ -147,7 +147,7 @@
+
+ for (digit = data; *digit; digit++) {
+ int digit2 = *digit;
+- char *dahdit;
++ const char *dahdit;
+ if (digit2 < 0) {
+ continue;
+ }
+Index: apps/app_ices.c
+===================================================================
+--- a/apps/app_ices.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_ices.c (.../trunk) (revision 202568)
+@@ -58,7 +58,7 @@
+ <description>
+ <para>Streams to an icecast server using ices (available separately).
+ A configuration file must be supplied for ices (see contrib/asterisk-ices.xml).</para>
+- <note><para>ICES version 2 cient and server required.</para></note>
++ <note><para>ICES version 2 client and server required.</para></note>
+ </description>
+ </application>
+
+@@ -104,7 +104,7 @@
+ _exit(0);
+ }
+
+-static int ices_exec(struct ast_channel *chan, void *data)
++static int ices_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+ int fds[2];
+Index: apps/app_exec.c
+===================================================================
+--- a/apps/app_exec.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_exec.c (.../trunk) (revision 202568)
+@@ -125,63 +125,68 @@
+ * affecting the dialplan.
+ */
+
+-static char *app_exec = "Exec";
+-static char *app_tryexec = "TryExec";
+-static char *app_execif = "ExecIf";
++static const char app_exec[] = "Exec";
++static const char app_tryexec[] = "TryExec";
++static const char app_execif[] = "ExecIf";
+
+-static int exec_exec(struct ast_channel *chan, void *data)
++static int exec_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+- char *s, *appname, *endargs, args[MAXRESULT];
++ char *s, *appname, *endargs;
+ struct ast_app *app;
++ struct ast_str *args = NULL;
+
+ if (ast_strlen_zero(data))
+ return 0;
+
+ s = ast_strdupa(data);
+- args[0] = 0;
+ appname = strsep(&s, "(");
+ if (s) {
+ endargs = strrchr(s, ')');
+ if (endargs)
+ *endargs = '\0';
+- pbx_substitute_variables_helper(chan, s, args, MAXRESULT - 1);
++ if ((args = ast_str_create(16))) {
++ ast_str_substitute_variables(&args, 0, chan, s);
++ }
+ }
+ if (appname) {
+ app = pbx_findapp(appname);
+ if (app) {
+- res = pbx_exec(chan, app, args);
++ res = pbx_exec(chan, app, args ? ast_str_buffer(args) : NULL);
+ } else {
+ ast_log(LOG_WARNING, "Could not find application (%s)\n", appname);
+ res = -1;
+ }
+ }
+
++ ast_free(args);
+ return res;
+ }
+
+-static int tryexec_exec(struct ast_channel *chan, void *data)
++static int tryexec_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+- char *s, *appname, *endargs, args[MAXRESULT];
++ char *s, *appname, *endargs;
+ struct ast_app *app;
++ struct ast_str *args = NULL;
+
+ if (ast_strlen_zero(data))
+ return 0;
+
+ s = ast_strdupa(data);
+- args[0] = 0;
+ appname = strsep(&s, "(");
+ if (s) {
+ endargs = strrchr(s, ')');
+ if (endargs)
+ *endargs = '\0';
+- pbx_substitute_variables_helper(chan, s, args, MAXRESULT - 1);
++ if ((args = ast_str_create(16))) {
++ ast_str_substitute_variables(&args, 0, chan, s);
++ }
+ }
+ if (appname) {
+ app = pbx_findapp(appname);
+ if (app) {
+- res = pbx_exec(chan, app, args);
++ res = pbx_exec(chan, app, args ? ast_str_buffer(args) : NULL);
+ pbx_builtin_setvar_helper(chan, "TRYSTATUS", res ? "FAILED" : "SUCCESS");
+ } else {
+ ast_log(LOG_WARNING, "Could not find application (%s)\n", appname);
+@@ -189,10 +194,11 @@
+ }
+ }
+
++ ast_free(args);
+ return 0;
+ }
+
+-static int execif_exec(struct ast_channel *chan, void *data)
++static int execif_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+ char *truedata = NULL, *falsedata = NULL, *end, *firstcomma, *firstquestion;
+Index: apps/app_channelredirect.c
+===================================================================
+--- a/apps/app_channelredirect.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_channelredirect.c (.../trunk) (revision 202568)
+@@ -60,9 +60,9 @@
+ </description>
+ </application>
+ ***/
+-static char *app = "ChannelRedirect";
++static const char app[] = "ChannelRedirect";
+
+-static int asyncgoto_exec(struct ast_channel *chan, void *data)
++static int asyncgoto_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = -1;
+ char *info;
+@@ -86,8 +86,7 @@
+ return -1;
+ }
+
+- chan2 = ast_get_channel_by_name_locked(args.channel);
+- if (!chan2) {
++ if (!(chan2 = ast_channel_get_by_name(args.channel))) {
+ ast_log(LOG_WARNING, "No such channel: %s\n", args.channel);
+ pbx_builtin_setvar_helper(chan, "CHANNELREDIRECT_STATUS", "NOCHANNEL");
+ return 0;
+@@ -96,9 +95,12 @@
+ if (chan2->pbx) {
+ ast_set_flag(chan2, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
+ }
++
+ res = ast_async_parseable_goto(chan2, args.label);
++
++ chan2 = ast_channel_unref(chan2);
++
+ pbx_builtin_setvar_helper(chan, "CHANNELREDIRECT_STATUS", "SUCCESS");
+- ast_channel_unlock(chan2);
+
+ return res;
+ }
+Index: apps/app_forkcdr.c
+===================================================================
+--- a/apps/app_forkcdr.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_forkcdr.c (.../trunk) (revision 202568)
+@@ -226,7 +226,7 @@
+ ast_set_flag(cdr, AST_CDR_FLAG_CHILD | AST_CDR_FLAG_LOCKED);
+ }
+
+-static int forkcdr_exec(struct ast_channel *chan, void *data)
++static int forkcdr_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+ char *argcopy = NULL;
+Index: apps/app_skel.c
+===================================================================
+--- a/apps/app_skel.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_skel.c (.../trunk) (revision 202568)
+@@ -74,18 +74,18 @@
+
+ static char *app = "Skel";
+
+-enum {
++enum option_flags {
+ OPTION_A = (1 << 0),
+ OPTION_B = (1 << 1),
+ OPTION_C = (1 << 2),
+-} option_flags;
++};
+
+-enum {
++enum option_args {
+ OPTION_ARG_B = 0,
+ OPTION_ARG_C = 1,
+ /* This *must* be the last value in this enum! */
+ OPTION_ARG_ARRAY_SIZE = 2,
+-} option_args;
++};
+
+ AST_APP_OPTIONS(app_opts,{
+ AST_APP_OPTION('a', OPTION_A),
+@@ -94,7 +94,7 @@
+ });
+
+
+-static int app_exec(struct ast_channel *chan, void *data)
++static int app_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+ struct ast_flags flags;
+Index: apps/app_directed_pickup.c
+===================================================================
+--- a/apps/app_directed_pickup.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_directed_pickup.c (.../trunk) (revision 202568)
+@@ -40,6 +40,7 @@
+ #include "asterisk/lock.h"
+ #include "asterisk/app.h"
+ #include "asterisk/features.h"
++#include "asterisk/callerid.h"
+
+ #define PICKUPMARK "PICKUPMARK"
+
+@@ -83,17 +84,31 @@
+ </application>
+ ***/
+
+-static const char *app = "Pickup";
+-static const char *app2 = "PickupChan";
++static const char app[] = "Pickup";
++static const char app2[] = "PickupChan";
+ /*! \todo This application should return a result code, like PICKUPRESULT */
+
+ /* Perform actual pickup between two channels */
+ static int pickup_do(struct ast_channel *chan, struct ast_channel *target)
+ {
+ int res = 0;
++ struct ast_party_connected_line connected_caller;
+
+ ast_debug(1, "Call pickup on '%s' by '%s'\n", target->name, chan->name);
+
++ connected_caller = target->connected;
++ connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
++ if (ast_channel_connected_line_macro(NULL, chan, &connected_caller, 0, 0)) {
++ ast_channel_update_connected_line(chan, &connected_caller);
++ }
++
++ ast_channel_lock(chan);
++ ast_connected_line_copy_from_caller(&connected_caller, &chan->cid);
++ ast_channel_unlock(chan);
++ connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
++ ast_channel_queue_connected_line_update(chan, &connected_caller);
++ ast_party_connected_line_free(&connected_caller);
++
+ if ((res = ast_answer(chan))) {
+ ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
+ return -1;
+@@ -121,17 +136,35 @@
+ return 0;
+ }
+
++struct pickup_by_name_args {
++ const char *name;
++ size_t len;
++};
++
++static int pickup_by_name_cb(void *obj, void *arg, void *data, int flags)
++{
++ struct ast_channel *chan = obj;
++ struct pickup_by_name_args *args = data;
++
++ ast_channel_lock(chan);
++ if (!strncasecmp(chan->name, args->name, args->len) && can_pickup(chan)) {
++ /* Return with the channel still locked on purpose */
++ return CMP_MATCH | CMP_STOP;
++ }
++ ast_channel_unlock(chan);
++
++ return 0;
++}
++
+ /*! \brief Helper Function to walk through ALL channels checking NAME and STATE */
+ static struct ast_channel *my_ast_get_channel_by_name_locked(const char *channame)
+ {
+- struct ast_channel *chan;
+ char *chkchan;
+- size_t channame_len, chkchan_len;
++ struct pickup_by_name_args pickup_args;
+
+- channame_len = strlen(channame);
+- chkchan_len = channame_len + 2;
++ pickup_args.len = strlen(channame) + 2;
+
+- chkchan = alloca(chkchan_len);
++ chkchan = alloca(pickup_args.len);
+
+ /* need to append a '-' for the comparison so we check full channel name,
+ * i.e SIP/hgc- , use a temporary variable so original stays the same for
+@@ -140,15 +173,9 @@
+ strcpy(chkchan, channame);
+ strcat(chkchan, "-");
+
+- for (chan = ast_walk_channel_by_name_prefix_locked(NULL, channame, channame_len);
+- chan;
+- chan = ast_walk_channel_by_name_prefix_locked(chan, channame, channame_len)) {
+- if (!strncasecmp(chan->name, chkchan, chkchan_len) && can_pickup(chan)) {
+- return chan;
+- }
+- ast_channel_unlock(chan);
+- }
+- return NULL;
++ pickup_args.name = chkchan;
++
++ return ast_channel_callback(pickup_by_name_cb, NULL, &pickup_args, 0);
+ }
+
+ /*! \brief Attempt to pick up specified channel named , does not use context */
+@@ -157,80 +184,86 @@
+ int res = 0;
+ struct ast_channel *target;
+
+- if (!(target = my_ast_get_channel_by_name_locked(pickup)))
++ if (!(target = my_ast_get_channel_by_name_locked(pickup))) {
+ return -1;
++ }
+
+ /* Just check that we are not picking up the SAME as target */
+- if (chan->name != target->name && chan != target) {
++ if (chan != target) {
+ res = pickup_do(chan, target);
+ }
++
+ ast_channel_unlock(target);
++ target = ast_channel_unref(target);
+
+ return res;
+ }
+
+-struct pickup_criteria {
+- const char *exten;
+- const char *context;
+-};
+-
+-static int find_by_exten(struct ast_channel *c, void *data)
+-{
+- struct pickup_criteria *info = data;
+-
+- return (!strcasecmp(c->macroexten, info->exten) || !strcasecmp(c->exten, info->exten)) &&
+- !strcasecmp(c->dialcontext, info->context) &&
+- can_pickup(c);
+-}
+-
+ /* Attempt to pick up specified extension with context */
+ static int pickup_by_exten(struct ast_channel *chan, const char *exten, const char *context)
+ {
+ struct ast_channel *target = NULL;
+- struct pickup_criteria search = {
+- .exten = exten,
+- .context = context,
+- };
++ struct ast_channel_iterator *iter;
++ int res = -1;
+
+- target = ast_channel_search_locked(find_by_exten, &search);
++ if (!(iter = ast_channel_iterator_by_exten_new(0, exten, context))) {
++ return -1;
++ }
+
++ while ((target = ast_channel_iterator_next(iter))) {
++ ast_channel_lock(target);
++ if (can_pickup(target)) {
++ break;
++ }
++ ast_channel_unlock(target);
++ target = ast_channel_unref(target);
++ }
++
+ if (target) {
+- int res = pickup_do(chan, target);
++ res = pickup_do(chan, target);
+ ast_channel_unlock(target);
+- target = NULL;
+- return res;
++ target = ast_channel_unref(target);
+ }
+
+- return -1;
++ return res;
+ }
+
+-static int find_by_mark(struct ast_channel *c, void *data)
++static int find_by_mark(void *obj, void *arg, void *data, int flags)
+ {
++ struct ast_channel *c = obj;
+ const char *mark = data;
+ const char *tmp;
++ int res;
+
+- return (tmp = pbx_builtin_getvar_helper(c, PICKUPMARK)) &&
++ ast_channel_lock(c);
++
++ res = (tmp = pbx_builtin_getvar_helper(c, PICKUPMARK)) &&
+ !strcasecmp(tmp, mark) &&
+ can_pickup(c);
++
++ ast_channel_unlock(c);
++
++ return res ? CMP_MATCH | CMP_STOP : 0;
+ }
+
+ /* Attempt to pick up specified mark */
+ static int pickup_by_mark(struct ast_channel *chan, const char *mark)
+ {
+- struct ast_channel *target = ast_channel_search_locked(find_by_mark, (char *) mark);
++ struct ast_channel *target;
++ int res = -1;
+
+- if (target) {
+- int res = pickup_do(chan, target);
++ if ((target = ast_channel_callback(find_by_mark, NULL, (char *) mark, 0))) {
++ ast_channel_lock(target);
++ res = pickup_do(chan, target);
+ ast_channel_unlock(target);
+- target = NULL;
+- return res;
++ target = ast_channel_unref(target);
+ }
+
+- return -1;
++ return res;
+ }
+
+ /* application entry point for Pickup() */
+-static int pickup_exec(struct ast_channel *chan, void *data)
++static int pickup_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+ char *tmp = ast_strdupa(data);
+@@ -259,7 +292,7 @@
+ }
+
+ /* application entry point for PickupChan() */
+-static int pickupchan_exec(struct ast_channel *chan, void *data)
++static int pickupchan_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+ char *tmp = ast_strdupa(data);
+Index: apps/app_minivm.c
+===================================================================
+--- a/apps/app_minivm.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_minivm.c (.../trunk) (revision 202568)
+@@ -400,6 +400,99 @@
+ subscribed to the mailbox passed in the first parameter.</para>
+ </description>
+ </application>
++<function name="MINIVMCOUNTER" language="en_US">
++ <synopsis>
++ Reads or sets counters for MiniVoicemail message.
++ </synopsis>
++ <syntax argsep=":">
++ <parameter name="account" required="true">
++ <para>If account is given and it exists, the counter is specific for the account.</para>
++ <para>If account is a domain and the domain directory exists, counters are specific for a domain.</para>
++ </parameter>
++ <parameter name="name" required="true">
++ <para>The name of the counter is a string, up to 10 characters.</para>
++ </parameter>
++ <parameter name="operand">
++ <para>The counters never goes below zero. Valid operands for changing the value of a counter when assigning a value are:</para>
++ <enumlist>
++ <enum name="i"><para>Increment by value.</para></enum>
++ <enum name="d"><para>Decrement by value.</para></enum>
++ <enum name="s"><para>Set to value.</para></enum>
++ </enumlist>
++ </parameter>
++ </syntax>
++ <description>
++ <para>The operation is atomic and the counter is locked while changing the value. The counters are stored as text files in the minivm account directories. It might be better to use realtime functions if you are using a database to operate your Asterisk.</para>
++ </description>
++ <see-also>
++ <ref type="application">MinivmRecord</ref>
++ <ref type="application">MinivmGreet</ref>
++ <ref type="application">MinivmNotify</ref>
++ <ref type="application">MinivmDelete</ref>
++ <ref type="application">MinivmAccMess</ref>
++ <ref type="application">MinivmMWI</ref>
++ <ref type="function">MINIVMACCOUNT</ref>
++ </see-also>
++</function>
++<function name="MINIVMACCOUNT" language="en_US">
++ <synopsis>
++ Gets MiniVoicemail account information.
++ </synopsis>
++ <syntax argsep=":">
++ <parameter name="account" required="true" />
++ <parameter name="item" required="true">
++ <para>Valid items are:</para>
++ <enumlist>
++ <enum name="path">
++ <para>Path to account mailbox (if account exists, otherwise temporary mailbox).</para>
++ </enum>
++ <enum name="hasaccount">
++ <para>1 is static Minivm account exists, 0 otherwise.</para>
++ </enum>
++ <enum name="fullname">
++ <para>Full name of account owner.</para>
++ </enum>
++ <enum name="email">
++ <para>Email address used for account.</para>
++ </enum>
++ <enum name="etemplate">
++ <para>Email template for account (default template if none is configured).</para>
++ </enum>
++ <enum name="ptemplate">
++ <para>Pager template for account (default template if none is configured).</para>
++ </enum>
++ <enum name="accountcode">
++ <para>Account code for the voicemail account.</para>
++ </enum>
++ <enum name="pincode">
++ <para>Pin code for voicemail account.</para>
++ </enum>
++ <enum name="timezone">
++ <para>Time zone for voicemail account.</para>
++ </enum>
++ <enum name="language">
++ <para>Language for voicemail account.</para>
++ </enum>
++ <enum name="&lt;channel variable name&gt;">
++ <para>Channel variable value (set in configuration for account).</para>
++ </enum>
++ </enumlist>
++ </parameter>
++ </syntax>
++ <description>
++ <para />
++ </description>
++ <see-also>
++ <ref type="application">MinivmRecord</ref>
++ <ref type="application">MinivmGreet</ref>
++ <ref type="application">MinivmNotify</ref>
++ <ref type="application">MinivmDelete</ref>
++ <ref type="application">MinivmAccMess</ref>
++ <ref type="application">MinivmMWI</ref>
++ <ref type="function">MINIVMCOUNTER</ref>
++ </see-also>
++</function>
++
+ ***/
+
+ #ifndef TRUE
+@@ -455,19 +548,19 @@
+
+
+
+-enum {
++enum minivm_option_flags {
+ OPT_SILENT = (1 << 0),
+ OPT_BUSY_GREETING = (1 << 1),
+ OPT_UNAVAIL_GREETING = (1 << 2),
+ OPT_TEMP_GREETING = (1 << 3),
+ OPT_NAME_GREETING = (1 << 4),
+ OPT_RECORDGAIN = (1 << 5),
+-} minivm_option_flags;
++};
+
+-enum {
++enum minivm_option_args {
+ OPT_ARG_RECORDGAIN = 0,
+ OPT_ARG_ARRAY_SIZE = 1,
+-} minivm_option_args;
++};
+
+ AST_APP_OPTIONS(minivm_app_options, {
+ AST_APP_OPTION('s', OPT_SILENT),
+@@ -483,11 +576,12 @@
+ AST_APP_OPTION('n', OPT_NAME_GREETING),
+ });
+
+-/*! \brief Structure for linked list of Mini-Voicemail users: \ref minivm_accounts */
++/*!\internal
++ * \brief Structure for linked list of Mini-Voicemail users: \ref minivm_accounts */
+ struct minivm_account {
+ char username[AST_MAX_CONTEXT]; /*!< Mailbox username */
+ char domain[AST_MAX_CONTEXT]; /*!< Voicemail domain */
+-
++
+ char pincode[10]; /*!< Secret pin code, numbers only */
+ char fullname[120]; /*!< Full name, for directory app */
+ char email[80]; /*!< E-mail address - override */
+@@ -502,18 +596,20 @@
+ char attachfmt[80]; /*!< Format for voicemail audio file attachment */
+ char etemplate[80]; /*!< Pager template */
+ char ptemplate[80]; /*!< Voicemail format */
+- unsigned int flags; /*!< MVM_ flags */
++ unsigned int flags; /*!< MVM_ flags */
+ struct ast_variable *chanvars; /*!< Variables for e-mail template */
+ double volgain; /*!< Volume gain for voicemails sent via e-mail */
+- AST_LIST_ENTRY(minivm_account) list;
++ AST_LIST_ENTRY(minivm_account) list;
+ };
+
+-/*! \brief The list of e-mail accounts */
++/*!\internal
++ * \brief The list of e-mail accounts */
+ static AST_LIST_HEAD_STATIC(minivm_accounts, minivm_account);
+
+-/*! \brief Linked list of e-mail templates in various languages
+- These are used as templates for e-mails, pager messages and jabber messages
+- \ref message_templates
++/*!\internal
++ * \brief Linked list of e-mail templates in various languages
++ * These are used as templates for e-mails, pager messages and jabber messages
++ * \ref message_templates
+ */
+ struct minivm_template {
+ char name[80]; /*!< Template name */
+@@ -574,7 +670,7 @@
+ AST_MUTEX_DEFINE_STATIC(minivmlock); /*!< Lock to protect voicemail system */
+ AST_MUTEX_DEFINE_STATIC(minivmloglock); /*!< Lock to protect voicemail system log file */
+
+-FILE *minivmlogfile; /*!< The minivm log file */
++static FILE *minivmlogfile; /*!< The minivm log file */
+
+ static int global_vmminmessage; /*!< Minimum duration of messages */
+ static int global_vmmaxmessage; /*!< Maximum duration of message */
+@@ -588,11 +684,11 @@
+
+ static struct ast_flags globalflags = {0}; /*!< Global voicemail flags */
+ static int global_saydurationminfo;
+-static char global_charset[32]; /*!< Global charset in messages */
+
+ static double global_volgain; /*!< Volume gain for voicmemail via e-mail */
+
+-/*! \brief Default dateformat, can be overridden in configuration file */
++/*!\internal
++ * \brief Default dateformat, can be overridden in configuration file */
+ #define DEFAULT_DATEFORMAT "%A, %B %d, %Y at %r"
+ #define DEFAULT_CHARSET "ISO-8859-1"
+
+@@ -603,7 +699,8 @@
+ static struct minivm_account *find_user_realtime(const char *domain, const char *username);
+ static char *handle_minivm_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
+
+-/*! \brief Create message template */
++/*!\internal
++ * \brief Create message template */
+ static struct minivm_template *message_template_create(const char *name)
+ {
+ struct minivm_template *template;
+@@ -622,7 +719,8 @@
+ return template;
+ }
+
+-/*! \brief Release memory allocated by message template */
++/*!\internal
++ * \brief Release memory allocated by message template */
+ static void message_template_free(struct minivm_template *template)
+ {
+ if (template->body)
+@@ -631,7 +729,8 @@
+ ast_free (template);
+ }
+
+-/*! \brief Build message template from configuration */
++/*!\internal
++ * \brief Build message template from configuration */
+ static int message_template_build(const char *name, struct ast_variable *var)
+ {
+ struct minivm_template *template;
+@@ -693,7 +792,8 @@
+ return error;
+ }
+
+-/*! \brief Find named template */
++/*!\internal
++ * \brief Find named template */
+ static struct minivm_template *message_template_find(const char *name)
+ {
+ struct minivm_template *this, *res = NULL;
+@@ -714,18 +814,21 @@
+ }
+
+
+-/*! \brief Clear list of templates */
++/*!\internal
++ * \brief Clear list of templates */
+ static void message_destroy_list(void)
+ {
+ struct minivm_template *this;
+ AST_LIST_LOCK(&message_templates);
+- while ((this = AST_LIST_REMOVE_HEAD(&message_templates, list)))
++ while ((this = AST_LIST_REMOVE_HEAD(&message_templates, list))) {
+ message_template_free(this);
+-
++ }
++
+ AST_LIST_UNLOCK(&message_templates);
+ }
+
+-/*! \brief read buffer from file (base64 conversion) */
++/*!\internal
++ * \brief read buffer from file (base64 conversion) */
+ static int b64_inbuf(struct b64_baseio *bio, FILE *fi)
+ {
+ int l;
+@@ -747,7 +850,8 @@
+ return 1;
+ }
+
+-/*! \brief read character from file to buffer (base64 conversion) */
++/*!\internal
++ * \brief read character from file to buffer (base64 conversion) */
+ static int b64_inchar(struct b64_baseio *bio, FILE *fi)
+ {
+ if (bio->iocp >= bio->iolen) {
+@@ -758,7 +862,8 @@
+ return bio->iobuf[bio->iocp++];
+ }
+
+-/*! \brief write buffer to file (base64 conversion) */
++/*!\internal
++ * \brief write buffer to file (base64 conversion) */
+ static int b64_ochar(struct b64_baseio *bio, int c, FILE *so)
+ {
+ if (bio->linelength >= B64_BASELINELEN) {
+@@ -776,7 +881,8 @@
+ return 1;
+ }
+
+-/*! \brief Encode file to base64 encoding for email attachment (base64 conversion) */
++/*!\internal
++ * \brief Encode file to base64 encoding for email attachment (base64 conversion) */
+ static int base_encode(char *filename, FILE *so)
+ {
+ unsigned char dtable[B64_BASEMAXINLINE];
+@@ -859,7 +965,8 @@
+ }
+
+
+-/*! \brief Free user structure - if it's allocated */
++/*!\internal
++ * \brief Free user structure - if it's allocated */
+ static void free_user(struct minivm_account *vmu)
+ {
+ if (vmu->chanvars)
+@@ -869,8 +976,9 @@
+
+
+
+-/*! \brief Prepare for voicemail template by adding channel variables
+- to the channel
++/*!\internal
++ * \brief Prepare for voicemail template by adding channel variables
++ * to the channel
+ */
+ static void prep_email_sub_vars(struct ast_channel *channel, const struct minivm_account *vmu, const char *cidnum, const char *cidname, const char *dur, const char *date, const char *counter)
+ {
+@@ -899,7 +1007,8 @@
+ pbx_builtin_setvar_helper(channel, "MVM_COUNTER", counter);
+ }
+
+-/*! \brief Set default values for Mini-Voicemail users */
++/*!\internal
++ * \brief Set default values for Mini-Voicemail users */
+ static void populate_defaults(struct minivm_account *vmu)
+ {
+ ast_copy_flags(vmu, (&globalflags), AST_FLAGS_ALL);
+@@ -907,26 +1016,8 @@
+ vmu->volgain = global_volgain;
+ }
+
+-/*! \brief Fix quote of mail headers for non-ascii characters */
+-static char *mailheader_quote(const char *from, char *to, size_t len)
+-{
+- char *ptr = to;
+- *ptr++ = '"';
+- for (; ptr < to + len - 1; from++) {
+- if (*from == '"')
+- *ptr++ = '\\';
+- else if (*from == '\0')
+- break;
+- *ptr++ = *from;
+- }
+- if (ptr < to + len - 1)
+- *ptr++ = '"';
+- *ptr = '\0';
+- return to;
+-}
+-
+-
+-/*! \brief Allocate new vm user and set default values */
++/*!\internal
++ * \brief Allocate new vm user and set default values */
+ static struct minivm_account *mvm_user_alloc(void)
+ {
+ struct minivm_account *new;
+@@ -940,7 +1031,8 @@
+ }
+
+
+-/*! \brief Clear list of users */
++/*!\internal
++ * \brief Clear list of users */
+ static void vmaccounts_destroy_list(void)
+ {
+ struct minivm_account *this;
+@@ -951,7 +1043,8 @@
+ }
+
+
+-/*! \brief Find user from static memory object list */
++/*!\internal
++ * \brief Find user from static memory object list */
+ static struct minivm_account *find_account(const char *domain, const char *username, int createtemp)
+ {
+ struct minivm_account *vmu = NULL, *cur;
+@@ -992,8 +1085,9 @@
+ return vmu;
+ }
+
+-/*! \brief Find user in realtime storage
+- Returns pointer to minivm_account structure
++/*!\internal
++ * \brief Find user in realtime storage
++ * \return pointer to minivm_account structure
+ */
+ static struct minivm_account *find_user_realtime(const char *domain, const char *username)
+ {
+@@ -1023,7 +1117,102 @@
+ return retval;
+ }
+
+-/*! \brief Send voicemail with audio file as an attachment */
++/*!\internal
++ * \brief Check if the string would need encoding within the MIME standard, to
++ * avoid confusing certain mail software that expects messages to be 7-bit
++ * clean.
++ */
++static int check_mime(const char *str)
++{
++ for (; *str; str++) {
++ if (*str > 126 || *str < 32 || strchr("()<>@,:;/\"[]?.=", *str)) {
++ return 1;
++ }
++ }
++ return 0;
++}
++
++/*!\internal
++ * \brief Encode a string according to the MIME rules for encoding strings
++ * that are not 7-bit clean or contain control characters.
++ *
++ * Additionally, if the encoded string would exceed the MIME limit of 76
++ * characters per line, then the encoding will be broken up into multiple
++ * sections, separated by a space character, in order to facilitate
++ * breaking up the associated header across multiple lines.
++ *
++ * \param end An expandable buffer for holding the result
++ * \param maxlen \see ast_str
++ * \param charset Character set in which the result should be encoded
++ * \param start A string to be encoded
++ * \param preamble The length of the first line already used for this string,
++ * to ensure that each line maintains a maximum length of 76 chars.
++ * \param postamble the length of any additional characters appended to the
++ * line, used to ensure proper field wrapping.
++ * \return The encoded string.
++ */
++static const char *ast_str_encode_mime(struct ast_str **end, ssize_t maxlen, const char *charset, const char *start, size_t preamble, size_t postamble)
++{
++ struct ast_str *tmp = ast_str_alloca(80);
++ int first_section = 1;
++ *end = '\0';
++
++ ast_str_reset(*end);
++ ast_str_set(&tmp, -1, "=?%s?Q?", charset);
++ for (; *start; start++) {
++ int need_encoding = 0;
++ if (*start < 33 || *start > 126 || strchr("()<>@,:;/\"[]?.=_", *start)) {
++ need_encoding = 1;
++ }
++ if ((first_section && need_encoding && preamble + ast_str_strlen(tmp) > 70) ||
++ (first_section && !need_encoding && preamble + ast_str_strlen(tmp) > 72) ||
++ (!first_section && need_encoding && ast_str_strlen(tmp) > 70) ||
++ (!first_section && !need_encoding && ast_str_strlen(tmp) > 72)) {
++ /* Start new line */
++ ast_str_append(end, maxlen, "%s%s?=", first_section ? "" : " ", ast_str_buffer(tmp));
++ ast_str_set(&tmp, -1, "=?%s?Q?", charset);
++ first_section = 0;
++ }
++ if (need_encoding && *start == ' ') {
++ ast_str_append(&tmp, -1, "_");
++ } else if (need_encoding) {
++ ast_str_append(&tmp, -1, "=%hhX", *start);
++ } else {
++ ast_str_append(&tmp, -1, "%c", *start);
++ }
++ }
++ ast_str_append(end, maxlen, "%s%s?=%s", first_section ? "" : " ", ast_str_buffer(tmp), ast_str_strlen(tmp) + postamble > 74 ? " " : "");
++ return ast_str_buffer(*end);
++}
++
++/*!\internal
++ * \brief Wraps a character sequence in double quotes, escaping occurences of quotes within the string.
++ * \param from The string to work with.
++ * \param buf The destination buffer to write the modified quoted string.
++ * \param maxlen Always zero. \see ast_str
++ *
++ * \return The destination string with quotes wrapped on it (the to field).
++ */
++static const char *ast_str_quote(struct ast_str **buf, ssize_t maxlen, const char *from)
++{
++ const char *ptr;
++
++ /* We're only ever passing 0 to maxlen, so short output isn't possible */
++ ast_str_set(buf, maxlen, "\"");
++ for (ptr = from; *ptr; ptr++) {
++ if (*ptr == '"' || *ptr == '\\') {
++ ast_str_append(buf, maxlen, "\\%c", *ptr);
++ } else {
++ ast_str_append(buf, maxlen, "%c", *ptr);
++ }
++ }
++ ast_str_append(buf, maxlen, "\"");
++
++ return ast_str_buffer(*buf);
++}
++
++/*!\internal
++ * \brief Send voicemail with audio file as an attachment */
+ static int sendmail(struct minivm_template *template, struct minivm_account *vmu, char *cidnum, char *cidname, const char *filename, char *format, int duration, int attach_user_voicemail, enum mvm_messagetype type, const char *counter)
+ {
+ FILE *p = NULL;
+@@ -1039,14 +1228,18 @@
+ struct timeval now;
+ struct ast_tm tm;
+ struct minivm_zone *the_zone = NULL;
+- int len_passdata;
+ struct ast_channel *ast;
+ char *finalfilename;
+- char *passdata = NULL;
+- char *passdata2 = NULL;
++ struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16);
+ char *fromaddress;
+ char *fromemail;
+
++ if (!str1 || !str2) {
++ ast_free(str1);
++ ast_free(str2);
++ return -1;
++ }
++
+ if (type == MVM_MESSAGE_EMAIL) {
+ if (vmu && !ast_strlen_zero(vmu->email)) {
+ ast_copy_string(email, vmu->email, sizeof(email));
+@@ -1160,51 +1353,71 @@
+ if (ast_strlen_zero(fromaddress)) {
+ fprintf(p, "From: Asterisk PBX <%s>\n", who);
+ } else {
+- /* Allocate a buffer big enough for variable substitution */
+- int vmlen = strlen(fromaddress) * 3 + 200;
+-
+ ast_debug(4, "Fromaddress template: %s\n", fromaddress);
+- if ((passdata = alloca(vmlen))) {
+- pbx_substitute_variables_helper(ast, fromaddress, passdata, vmlen);
+- len_passdata = strlen(passdata) * 2 + 3;
+- passdata2 = alloca(len_passdata);
+- fprintf(p, "From: %s <%s>\n", mailheader_quote(passdata, passdata2, len_passdata), who);
+- } else {
+- ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
+- fclose(p);
+- return -1;
++ ast_str_substitute_variables(&str1, 0, ast, fromaddress);
++ if (check_mime(ast_str_buffer(str1))) {
++ int first_line = 1;
++ char *ptr;
++ ast_str_encode_mime(&str2, 0, template->charset, ast_str_buffer(str1), strlen("From: "), strlen(who) + 3);
++ while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
++ *ptr = '\0';
++ fprintf(p, "%s %s\n", first_line ? "From:" : "", ast_str_buffer(str2));
++ first_line = 0;
++ /* Substring is smaller, so this will never grow */
++ ast_str_set(&str2, 0, "%s", ptr + 1);
++ }
++ fprintf(p, "%s %s <%s>\n", first_line ? "From:" : "", ast_str_buffer(str2), who);
++ } else {
++ fprintf(p, "From: %s <%s>\n", ast_str_quote(&str2, 0, ast_str_buffer(str1)), who);
+ }
+ }
+- ast_debug(4, "Fromstring now: %s\n", ast_strlen_zero(passdata) ? "-default-" : passdata);
+
+ fprintf(p, "Message-ID: <Asterisk-%d-%s-%d-%s>\n", (unsigned int)ast_random(), vmu->username, (int)getpid(), who);
+- len_passdata = strlen(vmu->fullname) * 2 + 3;
+- passdata2 = alloca(len_passdata);
+- if (!ast_strlen_zero(vmu->email))
+- fprintf(p, "To: %s <%s>\n", mailheader_quote(vmu->fullname, passdata2, len_passdata), vmu->email);
+- else
+- fprintf(p, "To: %s <%s@%s>\n", mailheader_quote(vmu->fullname, passdata2, len_passdata), vmu->username, vmu->domain);
+
++ if (ast_strlen_zero(vmu->email)) {
++ snprintf(email, sizeof(email), "%s@%s", vmu->username, vmu->domain);
++ } else {
++ ast_copy_string(email, vmu->email, sizeof(email));
++ }
++
++ if (check_mime(vmu->fullname)) {
++ int first_line = 1;
++ char *ptr;
++ ast_str_encode_mime(&str2, 0, template->charset, vmu->fullname, strlen("To: "), strlen(email) + 3);
++ while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
++ *ptr = '\0';
++ fprintf(p, "%s %s\n", first_line ? "To:" : "", ast_str_buffer(str2));
++ first_line = 0;
++ /* Substring is smaller, so this will never grow */
++ ast_str_set(&str2, 0, "%s", ptr + 1);
++ }
++ fprintf(p, "%s %s <%s>\n", first_line ? "To:" : "", ast_str_buffer(str2), email);
++ } else {
++ fprintf(p, "To: %s <%s>\n", ast_str_quote(&str2, 0, vmu->fullname), email);
++ }
++
+ if (!ast_strlen_zero(template->subject)) {
+- char *pass_data;
+- int vmlen = strlen(template->subject) * 3 + 200;
+- if ((pass_data = alloca(vmlen))) {
+- pbx_substitute_variables_helper(ast, template->subject, pass_data, vmlen);
+- fprintf(p, "Subject: %s\n", pass_data);
++ ast_str_substitute_variables(&str1, 0, ast, template->subject);
++ if (check_mime(ast_str_buffer(str1))) {
++ int first_line = 1;
++ char *ptr;
++ ast_str_encode_mime(&str2, 0, template->charset, ast_str_buffer(str1), strlen("Subject: "), 0);
++ while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
++ *ptr = '\0';
++ fprintf(p, "%s %s\n", first_line ? "Subject:" : "", ast_str_buffer(str2));
++ first_line = 0;
++ /* Substring is smaller, so this will never grow */
++ ast_str_set(&str2, 0, "%s", ptr + 1);
++ }
++ fprintf(p, "%s %s\n", first_line ? "Subject:" : "", ast_str_buffer(str2));
+ } else {
+- ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
+- fclose(p);
+- return -1;
++ fprintf(p, "Subject: %s\n", ast_str_buffer(str1));
+ }
+-
+- ast_debug(4, "Subject now: %s\n", pass_data);
+-
+- } else {
++ } else {
+ fprintf(p, "Subject: New message in mailbox %s@%s\n", vmu->username, vmu->domain);
+ ast_debug(1, "Using default subject for this email \n");
+ }
+
+-
+ if (option_debug > 2)
+ fprintf(p, "X-Asterisk-debug: template %s user account %s@%s\n", template->name, vmu->username, vmu->domain);
+ fprintf(p, "MIME-Version: 1.0\n");
+@@ -1215,19 +1428,13 @@
+ fprintf(p, "Content-Type: multipart/mixed; boundary=\"%s\"\n\n\n", bound);
+
+ fprintf(p, "--%s\n", bound);
+- fprintf(p, "Content-Type: text/plain; charset=%s\nContent-Transfer-Encoding: 8bit\n\n", global_charset);
++ fprintf(p, "Content-Type: text/plain; charset=%s\nContent-Transfer-Encoding: 8bit\n\n", template->charset);
+ if (!ast_strlen_zero(template->body)) {
+- char *pass_data;
+- int vmlen = strlen(template->body)*3 + 200;
+- if ((pass_data = alloca(vmlen))) {
+- pbx_substitute_variables_helper(ast, template->body, pass_data, vmlen);
+- ast_debug(3, "Message now: %s\n-----\n", pass_data);
+- fprintf(p, "%s\n", pass_data);
+- } else
+- ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
++ ast_str_substitute_variables(&str1, 0, ast, template->body);
++ ast_debug(3, "Message now: %s\n-----\n", ast_str_buffer(str1));
++ fprintf(p, "%s\n", ast_str_buffer(str1));
+ } else {
+ fprintf(p, "Dear %s:\n\n\tJust wanted to let you know you were just left a %s long message \n"
+-
+ "in mailbox %s from %s, on %s so you might\n"
+ "want to check it when you get a chance. Thanks!\n\n\t\t\t\t--Asterisk\n\n", vmu->fullname,
+ dur, vmu->username, (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")), date);
+@@ -1239,7 +1446,7 @@
+ ast_debug(3, "Attaching file to message: %s\n", fname);
+ if (!strcasecmp(format, "ogg"))
+ ctype = "application/";
+-
++
+ fprintf(p, "--%s\n", bound);
+ fprintf(p, "Content-Type: %s%s; name=\"voicemailmsg.%s\"\n", ctype, format, format);
+ fprintf(p, "Content-Transfer-Encoding: base64\n");
+@@ -1254,18 +1461,23 @@
+ ast_safe_system(tmp2);
+ ast_debug(1, "Sent message to %s with command '%s' - %s\n", vmu->email, global_mailcmd, template->attachment ? "(media attachment)" : "");
+ ast_debug(3, "Actual command used: %s\n", tmp2);
+- if (ast)
+- ast_channel_free(ast);
++ if (ast) {
++ ast = ast_channel_release(ast);
++ }
++ ast_free(str1);
++ ast_free(str2);
+ return 0;
+ }
+
+-/*! \brief Create directory based on components */
++/*!\internal
++ * \brief Create directory based on components */
+ static int make_dir(char *dest, int len, const char *domain, const char *username, const char *folder)
+ {
+ return snprintf(dest, len, "%s%s/%s%s%s", MVM_SPOOL_DIR, domain, username, ast_strlen_zero(folder) ? "" : "/", folder ? folder : "");
+ }
+
+-/*! \brief Checks if directory exists. Does not create directory, but builds string in dest
++/*!\internal
++ * \brief Checks if directory exists. Does not create directory, but builds string in dest
+ * \param dest String. base directory.
+ * \param len Int. Length base directory string.
+ * \param domain String. Ignored if is null or empty string.
+@@ -1283,11 +1495,12 @@
+ return TRUE;
+ }
+
+-/*! \brief basically mkdir -p $dest/$domain/$username/$folder
++/*!\internal
++ * \brief basically mkdir -p $dest/$domain/$username/$folder
+ * \param dest String. base directory.
+ * \param len Length of directory string
+ * \param domain String. Ignored if is null or empty string.
+- * \param folder String. Ignored if is null or empty string.
++ * \param folder String. Ignored if is null or empty string.
+ * \param username String. Ignored if is null or empty string.
+ * \return -1 on failure, 0 on success.
+ */
+@@ -1304,8 +1517,9 @@
+ }
+
+
+-/*! \brief Play intro message before recording voicemail
+-*/
++/*!\internal
++ * \brief Play intro message before recording voicemail
++ */
+ static int invent_message(struct ast_channel *chan, char *domain, char *username, int busy, char *ecodes)
+ {
+ int res;
+@@ -1327,7 +1541,7 @@
+ char *i = username;
+
+ ast_debug(2, "No personal prompts. Using default prompt set for language\n");
+-
++
+ while (*i) {
+ ast_debug(2, "Numeric? Checking %c\n", *i);
+ if (!isdigit(*i)) {
+@@ -1338,16 +1552,16 @@
+ }
+
+ if (numericusername) {
+- if(ast_streamfile(chan, "vm-theperson", chan->language))
++ if (ast_streamfile(chan, "vm-theperson", chan->language))
+ return -1;
+ if ((res = ast_waitstream(chan, ecodes)))
+ return res;
+-
++
+ res = ast_say_digit_str(chan, username, ecodes, chan->language);
+ if (res)
+ return res;
+ } else {
+- if(ast_streamfile(chan, "vm-theextensionis", chan->language))
++ if (ast_streamfile(chan, "vm-theextensionis", chan->language))
+ return -1;
+ if ((res = ast_waitstream(chan, ecodes)))
+ return res;
+@@ -1361,7 +1575,8 @@
+ return res;
+ }
+
+-/*! \brief Delete media files and attribute file */
++/*!\internal
++ * \brief Delete media files and attribute file */
+ static int vm_delete(char *file)
+ {
+ int res;
+@@ -1374,30 +1589,31 @@
+ }
+
+
+-/*! \brief Record voicemail message & let caller review or re-record it, or set options if applicable */
++/*!\internal
++ * \brief Record voicemail message & let caller review or re-record it, or set options if applicable */
+ static int play_record_review(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt,
+ int outsidecaller, struct minivm_account *vmu, int *duration, const char *unlockdir,
+ signed char record_gain)
+ {
+- int cmd = 0;
+- int max_attempts = 3;
+- int attempts = 0;
+- int recorded = 0;
+- int message_exists = 0;
++ int cmd = 0;
++ int max_attempts = 3;
++ int attempts = 0;
++ int recorded = 0;
++ int message_exists = 0;
+ signed char zero_gain = 0;
+ char *acceptdtmf = "#";
+ char *canceldtmf = "";
+
+- /* Note that urgent and private are for flagging messages as such in the future */
+-
++ /* Note that urgent and private are for flagging messages as such in the future */
++
+ /* barf if no pointer passed to store duration in */
+ if (duration == NULL) {
+ ast_log(LOG_WARNING, "Error play_record_review called without duration pointer\n");
+ return -1;
+ }
+
+- cmd = '3'; /* Want to start by recording */
+-
++ cmd = '3'; /* Want to start by recording */
++
+ while ((cmd >= 0) && (cmd != 't')) {
+ switch (cmd) {
+ case '1':
+@@ -1405,23 +1621,23 @@
+ ast_stream_and_wait(chan, "vm-msgsaved", "");
+ cmd = 't';
+ break;
+- case '2':
+- /* Review */
++ case '2':
++ /* Review */
+ ast_verb(3, "Reviewing the message\n");
+- ast_streamfile(chan, recordfile, chan->language);
+- cmd = ast_waitstream(chan, AST_DIGIT_ANY);
+- break;
+- case '3':
+- message_exists = 0;
+- /* Record */
+- if (recorded == 1)
++ ast_streamfile(chan, recordfile, chan->language);
++ cmd = ast_waitstream(chan, AST_DIGIT_ANY);
++ break;
++ case '3':
++ message_exists = 0;
++ /* Record */
++ if (recorded == 1)
+ ast_verb(3, "Re-recording the message\n");
+- else
++ else
+ ast_verb(3, "Recording the message\n");
+ if (recorded && outsidecaller)
+- cmd = ast_play_and_wait(chan, "beep");
+- recorded = 1;
+- /* After an attempt has been made to record message, we have to take care of INTRO and beep for incoming messages, but not for greetings */
++ cmd = ast_play_and_wait(chan, "beep");
++ recorded = 1;
++ /* After an attempt has been made to record message, we have to take care of INTRO and beep for incoming messages, but not for greetings */
+ if (record_gain)
+ ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
+ if (ast_test_flag(vmu, MVM_OPERATOR))
+@@ -1429,10 +1645,10 @@
+ cmd = ast_play_and_record_full(chan, playfile, recordfile, maxtime, fmt, duration, global_silencethreshold, global_maxsilence, unlockdir, acceptdtmf, canceldtmf);
+ if (record_gain)
+ ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
+- if (cmd == -1) /* User has hung up, no options to give */
+- return cmd;
+- if (cmd == '0')
+- break;
++ if (cmd == -1) /* User has hung up, no options to give */
++ return cmd;
++ if (cmd == '0')
++ break;
+ else if (cmd == '*')
+ break;
+ else {
+@@ -1483,7 +1699,7 @@
+ if (!cmd)
+ cmd = ast_waitfordigit(chan, 600);
+ }
+-
++
+ if (!cmd && outsidecaller && ast_test_flag(vmu, MVM_OPERATOR)) {
+ cmd = ast_play_and_wait(chan, "vm-reachoper");
+ if (!cmd)
+@@ -1499,7 +1715,7 @@
+ }
+ }
+ }
+- if (outsidecaller)
++ if (outsidecaller)
+ ast_play_and_wait(chan, "vm-goodbye");
+ if (cmd == 't')
+ cmd = 0;
+@@ -1520,10 +1736,11 @@
+ chan->cid.cid_name, chan->cid.cid_num);
+
+ ast_debug(1, "Executing: %s\n", arguments);
+- ast_safe_system(arguments);
++ ast_safe_system(arguments);
+ }
+
+-/*! \brief Send message to voicemail account owner */
++/*!\internal
++ * \brief Send message to voicemail account owner */
+ static int notify_new_message(struct ast_channel *chan, const char *templatename, struct minivm_account *vmu, const char *filename, long duration, const char *format, char *cidnum, char *cidname)
+ {
+ char *stringp;
+@@ -1536,8 +1753,9 @@
+ if (!ast_strlen_zero(vmu->attachfmt)) {
+ if (strstr(format, vmu->attachfmt)) {
+ format = vmu->attachfmt;
+- } else
++ } else {
+ ast_log(LOG_WARNING, "Attachment format '%s' is not one of the recorded formats '%s'. Falling back to default format for '%s@%s'.\n", vmu->attachfmt, format, vmu->username, vmu->domain);
++ }
+ }
+
+ etemplate = message_template_find(vmu->etemplate);
+@@ -1594,13 +1812,15 @@
+
+ run_externnotify(chan, vmu); /* Run external notification */
+
+- if (etemplate->locale)
++ if (etemplate->locale) {
+ setlocale(LC_TIME, oldlocale); /* Rest to old locale */
++ }
+ return res;
+ }
+
+
+-/*! \brief Record voicemail message, store into file prepared for sending e-mail */
++/*!\internal
++ * \brief Record voicemail message, store into file prepared for sending e-mail */
+ static int leave_voicemail(struct ast_channel *chan, char *username, struct leave_vm_options *options)
+ {
+ char tmptxtfile[PATH_MAX];
+@@ -1662,7 +1882,6 @@
+
+
+ snprintf(tmptxtfile, sizeof(tmptxtfile), "%s/XXXXXX", tmpdir);
+-
+
+ /* XXX This file needs to be in temp directory */
+ txtdes = mkstemp(tmptxtfile);
+@@ -1699,7 +1918,7 @@
+ get_date(date, sizeof(date));
+ ast_localtime(&now, &tm, NULL);
+ ast_strftime(timebuf, sizeof(timebuf), "%H:%M:%S", &tm);
+-
++
+ snprintf(logbuf, sizeof(logbuf),
+ /* "Mailbox:domain:macrocontext:exten:priority:callerchan:callerid:origdate:origtime:duration:durationstatus:accountcode" */
+ "%s:%s:%s:%s:%d:%s:%s:%s:%s:%d:%s:%s\n",
+@@ -1750,12 +1969,14 @@
+ }
+ global_stats.lastreceived = ast_tvnow();
+ global_stats.receivedmessages++;
+-// /* Go ahead and delete audio files from system, they're not needed any more */
+-// if (ast_fileexists(tmptxtfile, NULL, NULL) <= 0) {
+-// ast_filedelete(tmptxtfile, NULL);
+-// /* Even not being used at the moment, it's better to convert ast_log to ast_debug anyway */
+-// ast_debug(2, "-_-_- Deleted audio file after notification :: %s \n", tmptxtfile);
+-// }
++#if 0
++ /* Go ahead and delete audio files from system, they're not needed any more */
++ if (ast_fileexists(tmptxtfile, NULL, NULL) <= 0) {
++ ast_filedelete(tmptxtfile, NULL);
++ /* Even not being used at the moment, it's better to convert ast_log to ast_debug anyway */
++ ast_debug(2, "-_-_- Deleted audio file after notification :: %s \n", tmptxtfile);
++ }
++#endif
+
+ if (res > 0)
+ res = 0;
+@@ -1767,7 +1988,8 @@
+ return res;
+ }
+
+-/*! \brief Queue a message waiting event */
++/*!\internal
++ * \brief Queue a message waiting event */
+ static void queue_mwi_event(const char *mbx, const char *ctx, int urgent, int new, int old)
+ {
+ struct ast_event *event;
+@@ -1791,8 +2013,9 @@
+ ast_event_queue_and_cache(event);
+ }
+
+-/*! \brief Send MWI using interal Asterisk event subsystem */
+-static int minivm_mwi_exec(struct ast_channel *chan, void *data)
++/*!\internal
++ * \brief Send MWI using interal Asterisk event subsystem */
++static int minivm_mwi_exec(struct ast_channel *chan, const char *data)
+ {
+ int argc;
+ char *argv[4];
+@@ -1802,38 +2025,39 @@
+ char *mailbox;
+ char *domain;
+ if (ast_strlen_zero(data)) {
+- ast_log(LOG_ERROR, "Minivm needs at least an account argument \n");
+- return -1;
+- }
+- tmpptr = ast_strdupa((char *)data);
+- if (!tmpptr) {
+- ast_log(LOG_ERROR, "Out of memory\n");
+- return -1;
+- }
+- argc = ast_app_separate_args(tmpptr, ',', argv, ARRAY_LEN(argv));
++ ast_log(LOG_ERROR, "Minivm needs at least an account argument \n");
++ return -1;
++ }
++ tmpptr = ast_strdupa((char *)data);
++ if (!tmpptr) {
++ ast_log(LOG_ERROR, "Out of memory\n");
++ return -1;
++ }
++ argc = ast_app_separate_args(tmpptr, ',', argv, ARRAY_LEN(argv));
+ if (argc < 4) {
+ ast_log(LOG_ERROR, "%d arguments passed to MiniVM_MWI, need 4.\n", argc);
+ return -1;
+ }
+- ast_copy_string(tmp, argv[0], sizeof(tmp));
+- mailbox = tmp;
+- domain = strchr(tmp, '@');
+- if (domain) {
+- *domain = '\0';
+- domain++;
+- }
+- if (ast_strlen_zero(domain) || ast_strlen_zero(mailbox)) {
+- ast_log(LOG_ERROR, "Need mailbox@context as argument. Sorry. Argument 0 %s\n", argv[0]);
+- return -1;
+- }
++ ast_copy_string(tmp, argv[0], sizeof(tmp));
++ mailbox = tmp;
++ domain = strchr(tmp, '@');
++ if (domain) {
++ *domain = '\0';
++ domain++;
++ }
++ if (ast_strlen_zero(domain) || ast_strlen_zero(mailbox)) {
++ ast_log(LOG_ERROR, "Need mailbox@context as argument. Sorry. Argument 0 %s\n", argv[0]);
++ return -1;
++ }
+ queue_mwi_event(mailbox, domain, atoi(argv[1]), atoi(argv[2]), atoi(argv[3]));
+
+ return res;
+ }
+
+
+-/*! \brief Notify voicemail account owners - either generic template or user specific */
+-static int minivm_notify_exec(struct ast_channel *chan, void *data)
++/*!\internal
++ * \brief Notify voicemail account owners - either generic template or user specific */
++static int minivm_notify_exec(struct ast_channel *chan, const char *data)
+ {
+ int argc;
+ char *argv[2];
+@@ -1847,7 +2071,7 @@
+ const char *filename;
+ const char *format;
+ const char *duration_string;
+-
++
+ if (ast_strlen_zero(data)) {
+ ast_log(LOG_ERROR, "Minivm needs at least an account argument \n");
+ return -1;
+@@ -1911,8 +2135,9 @@
+
+ }
+
+-/*! \brief Dialplan function to record voicemail */
+-static int minivm_record_exec(struct ast_channel *chan, void *data)
++/*!\internal
++ * \brief Dialplan function to record voicemail */
++static int minivm_record_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+ char *tmp;
+@@ -1921,7 +2146,7 @@
+ char *argv[2];
+ struct ast_flags flags = { 0 };
+ char *opts[OPT_ARG_ARRAY_SIZE];
+-
++
+ memset(&leave_options, 0, sizeof(leave_options));
+
+ /* Answer channel if it's not already answered */
+@@ -1967,8 +2192,9 @@
+ return res;
+ }
+
+-/*! \brief Play voicemail prompts - either generic or user specific */
+-static int minivm_greet_exec(struct ast_channel *chan, void *data)
++/*!\internal
++ * \brief Play voicemail prompts - either generic or user specific */
++static int minivm_greet_exec(struct ast_channel *chan, const char *data)
+ {
+ struct leave_vm_options leave_options = { 0, '\0'};
+ int argc;
+@@ -2153,12 +2379,13 @@
+
+ }
+
+-/*! \brief Dialplan application to delete voicemail */
+-static int minivm_delete_exec(struct ast_channel *chan, void *data)
++/*!\internal
++ * \brief Dialplan application to delete voicemail */
++static int minivm_delete_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+ char filename[BUFSIZ];
+-
++
+ if (!ast_strlen_zero(data)) {
+ ast_copy_string(filename, (char *) data, sizeof(filename));
+ } else {
+@@ -2192,7 +2419,7 @@
+ }
+
+ /*! \brief Record specific messages for voicemail account */
+-static int minivm_accmess_exec(struct ast_channel *chan, void *data)
++static int minivm_accmess_exec(struct ast_channel *chan, const char *data)
+ {
+ int argc = 0;
+ char *argv[2];
+@@ -2608,7 +2835,6 @@
+ ast_copy_string(default_vmformat, "wav", sizeof(default_vmformat));
+ ast_set2_flag((&globalflags), FALSE, MVM_REVIEW);
+ ast_set2_flag((&globalflags), FALSE, MVM_OPERATOR);
+- strcpy(global_charset, "ISO-8859-1");
+ /* Reset statistics */
+ memset(&global_stats, 0, sizeof(global_stats));
+ global_stats.reset = ast_tvnow();
+@@ -3228,41 +3454,13 @@
+
+ static struct ast_custom_function minivm_counter_function = {
+ .name = "MINIVMCOUNTER",
+- .synopsis = "Reads or sets counters for MiniVoicemail message",
+- .syntax = "MINIVMCOUNTER(<account>:name[:operand])",
+ .read = minivm_counter_func_read,
+ .write = minivm_counter_func_write,
+- .desc = "Valid operands for changing the value of a counter when assigning a value are:\n"
+- "- i Increment by value\n"
+- "- d Decrement by value\n"
+- "- s Set to value\n"
+- "\nThe counters never goes below zero.\n"
+- "- The name of the counter is a string, up to 10 characters\n"
+- "- If account is given and it exists, the counter is specific for the account\n"
+- "- If account is a domain and the domain directory exists, counters are specific for a domain\n"
+- "The operation is atomic and the counter is locked while changing the value\n"
+- "\nThe counters are stored as text files in the minivm account directories. It might be better to use\n"
+- "realtime functions if you are using a database to operate your Asterisk\n",
+ };
+
+ static struct ast_custom_function minivm_account_function = {
+ .name = "MINIVMACCOUNT",
+- .synopsis = "Gets MiniVoicemail account information",
+- .syntax = "MINIVMACCOUNT(<account>:item)",
+ .read = minivm_account_func_read,
+- .desc = "Valid items are:\n"
+- "- path Path to account mailbox (if account exists, otherwise temporary mailbox)\n"
+- "- hasaccount 1 if static Minivm account exists, 0 otherwise\n"
+- "- fullname Full name of account owner\n"
+- "- email Email address used for account\n"
+- "- etemplate E-mail template for account (default template if none is configured)\n"
+- "- ptemplate Pager template for account (default template if none is configured)\n"
+- "- accountcode Account code for voicemail account\n"
+- "- pincode Pin code for voicemail account\n"
+- "- timezone Time zone for voicemail account\n"
+- "- language Language for voicemail account\n"
+- "- <channel variable name> Channel variable value (set in configuration for account)\n"
+- "\n",
+ };
+
+ /*! \brief Load mini voicemail module */
+Index: apps/app_dumpchan.c
+===================================================================
+--- a/apps/app_dumpchan.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_dumpchan.c (.../trunk) (revision 202568)
+@@ -60,7 +60,7 @@
+ </application>
+ ***/
+
+-static char *app = "DumpChan";
++static const char app[] = "DumpChan";
+
+ static int serialize_showchan(struct ast_channel *c, char *buf, size_t size)
+ {
+@@ -147,7 +147,7 @@
+ return 0;
+ }
+
+-static int dumpchan_exec(struct ast_channel *chan, void *data)
++static int dumpchan_exec(struct ast_channel *chan, const char *data)
+ {
+ struct ast_str *vars = ast_str_thread_get(&ast_str_thread_global_buf, 16);
+ char info[1024];
+Index: apps/app_macro.c
+===================================================================
+--- a/apps/app_macro.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_macro.c (.../trunk) (revision 202568)
+@@ -36,6 +36,7 @@
+ #include "asterisk/config.h"
+ #include "asterisk/utils.h"
+ #include "asterisk/lock.h"
++#include "asterisk/app.h"
+
+ /*** DOCUMENTATION
+ <application name="Macro" language="en_US">
+@@ -158,7 +159,7 @@
+
+ static void macro_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan);
+
+-struct ast_datastore_info macro_ds_info = {
++static struct ast_datastore_info macro_ds_info = {
+ .type = "MACRO",
+ .chan_fixup = macro_fixup,
+ };
+@@ -216,7 +217,7 @@
+ return NULL;
+ }
+
+-static int _macro_exec(struct ast_channel *chan, void *data, int exclusive)
++static int _macro_exec(struct ast_channel *chan, const char *data, int exclusive)
+ {
+ const char *s;
+ char *tmp;
+@@ -236,13 +237,14 @@
+ int offset, depth = 0, maxdepth = 7;
+ int setmacrocontext=0;
+ int autoloopflag, inhangup = 0;
++ struct ast_str *tmp_subst = NULL;
+
+ char *save_macro_exten;
+ char *save_macro_context;
+ char *save_macro_priority;
+ char *save_macro_offset;
+ struct ast_datastore *macro_store = ast_channel_datastore_find(chan, &macro_ds_info, NULL);
+-
++
+ if (ast_strlen_zero(data)) {
+ ast_log(LOG_WARNING, "Macro() requires arguments. See \"core show application macro\" for help.\n");
+ return -1;
+@@ -286,7 +288,6 @@
+ return 0;
+ }
+ snprintf(depthc, sizeof(depthc), "%d", depth + 1);
+- pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc);
+
+ tmp = ast_strdupa(data);
+ rest = tmp;
+@@ -316,7 +317,11 @@
+ }
+ ast_autoservice_stop(chan);
+ }
+-
++
++ if (!(tmp_subst = ast_str_create(16))) {
++ return -1;
++ }
++
+ /* Save old info */
+ oldpriority = chan->priority;
+ ast_copy_string(oldexten, chan->exten, sizeof(oldexten));
+@@ -342,6 +347,8 @@
+ save_macro_offset = ast_strdup(pbx_builtin_getvar_helper(chan, "MACRO_OFFSET"));
+ pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", NULL);
+
++ pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc);
++
+ /* Setup environment for new run */
+ chan->exten[0] = 's';
+ chan->exten[1] = '\0';
+@@ -420,8 +427,10 @@
+ gosub_level++;
+ ast_debug(1, "Incrementing gosub_level\n");
+ } else if (!strcasecmp(runningapp, "GOSUBIF")) {
+- char tmp2[1024], *cond, *app_arg, *app2 = tmp2;
+- pbx_substitute_variables_helper(chan, runningdata, tmp2, sizeof(tmp2) - 1);
++ char *cond, *app_arg;
++ char *app2;
++ ast_str_substitute_variables(&tmp_subst, 0, chan, runningdata);
++ app2 = ast_str_buffer(tmp_subst);
+ cond = strsep(&app2, "?");
+ app_arg = strsep(&app2, ":");
+ if (pbx_checkcondition(cond)) {
+@@ -443,19 +452,23 @@
+ ast_debug(1, "Decrementing gosub_level\n");
+ } else if (!strncasecmp(runningapp, "EXEC", 4)) {
+ /* Must evaluate args to find actual app */
+- char tmp2[1024], *tmp3 = NULL;
+- pbx_substitute_variables_helper(chan, runningdata, tmp2, sizeof(tmp2) - 1);
++ char *tmp2, *tmp3 = NULL;
++ ast_str_substitute_variables(&tmp_subst, 0, chan, runningdata);
++ tmp2 = ast_str_buffer(tmp_subst);
+ if (!strcasecmp(runningapp, "EXECIF")) {
+- tmp3 = strchr(tmp2, '|');
+- if (tmp3)
++ if ((tmp3 = strchr(tmp2, '|'))) {
+ *tmp3++ = '\0';
+- if (!pbx_checkcondition(tmp2))
++ }
++ if (!pbx_checkcondition(tmp2)) {
+ tmp3 = NULL;
+- } else
++ }
++ } else {
+ tmp3 = tmp2;
++ }
+
+- if (tmp3)
++ if (tmp3) {
+ ast_debug(1, "Last app: %s\n", tmp3);
++ }
+
+ if (tmp3 && !strncasecmp(tmp3, "GOSUB", 5)) {
+ gosub_level++;
+@@ -552,21 +565,22 @@
+ }
+ }
+ ast_channel_unlock(chan);
++ ast_free(tmp_subst);
+
+ return res;
+ }
+
+-static int macro_exec(struct ast_channel *chan, void *data)
++static int macro_exec(struct ast_channel *chan, const char *data)
+ {
+ return _macro_exec(chan, data, 0);
+ }
+
+-static int macroexclusive_exec(struct ast_channel *chan, void *data)
++static int macroexclusive_exec(struct ast_channel *chan, const char *data)
+ {
+ return _macro_exec(chan, data, 1);
+ }
+
+-static int macroif_exec(struct ast_channel *chan, void *data)
++static int macroif_exec(struct ast_channel *chan, const char *data)
+ {
+ char *expr = NULL, *label_a = NULL, *label_b = NULL;
+ int res = 0;
+@@ -591,7 +605,7 @@
+ return res;
+ }
+
+-static int macro_exit_exec(struct ast_channel *chan, void *data)
++static int macro_exit_exec(struct ast_channel *chan, const char *data)
+ {
+ return MACRO_EXIT_RESULT;
+ }
+Index: apps/app_sms.c
+===================================================================
+--- a/apps/app_sms.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_sms.c (.../trunk) (revision 202568)
+@@ -123,7 +123,7 @@
+ * To pick the two carriers (1300Hz for '1' and 2100 Hz for '0') used by
+ * the modulation, we should take one every 13 and 21 samples respectively.
+ */
+-static signed short wave[] = {
++static const signed short wave[] = {
+ 0, 392, 782, 1167, 1545, 1913, 2270, 2612, 2939, 3247, 3536, 3802, 4045, 4263, 4455, 4619, 4755, 4862, 4938, 4985,
+ 5000, 4985, 4938, 4862, 4755, 4619, 4455, 4263, 4045, 3802, 3536, 3247, 2939, 2612, 2270, 1913, 1545, 1167, 782, 392,
+ 0, -392, -782, -1167,
+@@ -815,7 +815,7 @@
+ char line[1000];
+ FILE *s;
+ char dcsset = 0; /* if DSC set */
+- ast_log(LOG_EVENT, "Sending %s\n", fn);
++ ast_log(LOG_NOTICE, "Sending %s\n", fn);
+ h->rx = h->udl = *h->oa = *h->da = h->pid = h->srr = h->udhi = h->rp = h->vp = h->udhl = 0;
+ h->mr = -1;
+ h->dcs = 0xF1; /* normal messages class 1 */
+@@ -1080,7 +1080,7 @@
+ if (rename(fn, fn2)) {
+ unlink(fn);
+ } else {
+- ast_log(LOG_EVENT, "Received to %s\n", fn2);
++ ast_log(LOG_NOTICE, "Received to %s\n", fn2);
+ }
+ }
+
+@@ -1832,19 +1832,19 @@
+ * - AST_APP_OPTIONS() to drive the parsing routine
+ * - in the function, AST_DECLARE_APP_ARGS(...) for the arguments.
+ */
+-enum {
++enum sms_flags {
+ OPTION_BE_SMSC = (1 << 0), /* act as sms center */
+ OPTION_ANSWER = (1 << 1), /* answer on incoming calls */
+ OPTION_TWO = (1 << 2), /* Use Protocol Two */
+ OPTION_PAUSE = (1 << 3), /* pause before sending data, in ms */
+ OPTION_SRR = (1 << 4), /* set srr */
+ OPTION_DCS = (1 << 5), /* set dcs */
+-} sms_flags;
++};
+
+-enum {
++enum sms_opt_args {
+ OPTION_ARG_PAUSE = 0,
+ OPTION_ARG_ARRAY_SIZE
+-} sms_opt_args;
++};
+
+ AST_APP_OPTIONS(sms_options, {
+ AST_APP_OPTION('s', OPTION_BE_SMSC),
+@@ -1855,7 +1855,7 @@
+ AST_APP_OPTION_ARG('p', OPTION_PAUSE, OPTION_ARG_PAUSE),
+ } );
+
+-static int sms_exec(struct ast_channel *chan, void *data)
++static int sms_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = -1;
+ sms_t h = { 0 };
+Index: apps/app_confbridge.c
+===================================================================
+--- a/apps/app_confbridge.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_confbridge.c (.../trunk) (revision 202568)
+@@ -111,7 +111,7 @@
+ * bridge lock if it is important.
+ */
+
+-static const char *app = "ConfBridge";
++static const char app[] = "ConfBridge";
+
+ enum {
+ OPTION_ADMIN = (1 << 0), /*!< Set if the caller is an administrator */
+@@ -683,7 +683,7 @@
+ }
+
+ /*! \brief The ConfBridge application */
+-static int confbridge_exec(struct ast_channel *chan, void *data)
++static int confbridge_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = 0, volume_adjustments[2];
+ char *parse;
+Index: apps/app_verbose.c
+===================================================================
+--- a/apps/app_verbose.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_verbose.c (.../trunk) (revision 202568)
+@@ -72,7 +72,7 @@
+ ***/
+
+
+-static int verbose_exec(struct ast_channel *chan, void *data)
++static int verbose_exec(struct ast_channel *chan, const char *data)
+ {
+ int vsize;
+ char *parse;
+@@ -118,7 +118,7 @@
+ return 0;
+ }
+
+-static int log_exec(struct ast_channel *chan, void *data)
++static int log_exec(struct ast_channel *chan, const char *data)
+ {
+ char *parse;
+ int lnum = -1;
+@@ -146,8 +146,6 @@
+ lnum = __LOG_VERBOSE;
+ } else if (!strcasecmp(args.level, "DTMF")) {
+ lnum = __LOG_DTMF;
+- } else if (!strcasecmp(args.level, "EVENT")) {
+- lnum = __LOG_EVENT;
+ } else {
+ ast_log(LOG_ERROR, "Unknown log level: '%s'\n", args.level);
+ }
+Index: apps/app_voicemail.c
+===================================================================
+--- a/apps/app_voicemail.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_voicemail.c (.../trunk) (revision 202568)
+@@ -46,15 +46,22 @@
+
+ /*** MAKEOPTS
+ <category name="MENUSELECT_OPTS_app_voicemail" displayname="Voicemail Build Options" positive_output="yes" remove_on_change="apps/app_voicemail.o apps/app_voicemail.so apps/app_directory.o apps/app_directory.so">
++ <member name="FILE_STORAGE" displayname="Storage of Voicemail using filesystem">
++ <conflict>ODBC_STORAGE</conflict>
++ <conflict>IMAP_STORAGE</conflict>
++ <defaultenabled>yes</defaultenabled>
++ </member>
+ <member name="ODBC_STORAGE" displayname="Storage of Voicemail using ODBC">
+ <depend>generic_odbc</depend>
+ <depend>ltdl</depend>
+ <conflict>IMAP_STORAGE</conflict>
++ <conflict>FILE_STORAGE</conflict>
+ <defaultenabled>no</defaultenabled>
+ </member>
+ <member name="IMAP_STORAGE" displayname="Storage of Voicemail using IMAP4">
+ <depend>imap_tk</depend>
+ <conflict>ODBC_STORAGE</conflict>
++ <conflict>FILE_STORAGE</conflict>
+ <use>openssl</use>
+ <defaultenabled>no</defaultenabled>
+ </member>
+@@ -298,6 +305,16 @@
+ context.</para>
+ </description>
+ </function>
++ <manager name="VoicemailUsersList" language="en_US">
++ <synopsis>
++ List All Voicemail User Information.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ </syntax>
++ <description>
++ </description>
++ </manager>
+ ***/
+
+ #ifdef IMAP_STORAGE
+@@ -415,16 +432,16 @@
+ #define ERROR_LOCK_PATH -100
+
+
+-enum {
++enum vm_box {
+ NEW_FOLDER,
+ OLD_FOLDER,
+ WORK_FOLDER,
+ FAMILY_FOLDER,
+ FRIENDS_FOLDER,
+ GREETINGS_FOLDER
+-} vm_box;
++};
+
+-enum {
++enum vm_option_flags {
+ OPT_SILENT = (1 << 0),
+ OPT_BUSY_GREETING = (1 << 1),
+ OPT_UNAVAIL_GREETING = (1 << 2),
+@@ -434,15 +451,15 @@
+ OPT_DTMFEXIT = (1 << 7),
+ OPT_MESSAGE_Urgent = (1 << 8),
+ OPT_MESSAGE_PRIORITY = (1 << 9)
+-} vm_option_flags;
++};
+
+-enum {
++enum vm_option_args {
+ OPT_ARG_RECORDGAIN = 0,
+ OPT_ARG_PLAYFOLDER = 1,
+ OPT_ARG_DTMFEXIT = 2,
+ /* This *must* be the last value in this enum! */
+ OPT_ARG_ARRAY_SIZE = 3,
+-} vm_option_args;
++};
+
+ AST_APP_OPTIONS(vm_app_options, {
+ AST_APP_OPTION('s', OPT_SILENT),
+@@ -1417,7 +1434,7 @@
+
+ static const char *mbox(int id)
+ {
+- static const char *msgs[] = {
++ static const char * const msgs[] = {
+ #ifdef IMAP_STORAGE
+ imapfolder,
+ #else
+@@ -3332,7 +3349,8 @@
+ char *c;
+ struct ast_config *cfg=NULL;
+ struct odbc_obj *obj;
+- struct insert_data idata = { .sql = sql, .msgnums = msgnums, .dir = dir, .mailboxuser = mailboxuser, .mailboxcontext = mailboxcontext };
++ struct insert_data idata = { .sql = sql, .msgnums = msgnums, .dir = dir, .mailboxuser = mailboxuser, .mailboxcontext = mailboxcontext,
++ .context = "", .macrocontext = "", .callerid = "", .origtime = "", .duration = "", .category = "", .flag = "" };
+ struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE };
+
+ delete_file(dir, msgnum);
+@@ -3846,9 +3864,10 @@
+ return 1;
+ }
+
+-static void prep_email_sub_vars(struct ast_channel *ast, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, char *dur, char *date, char *passdata, size_t passdatasize, const char *category, const char *flag)
++static void prep_email_sub_vars(struct ast_channel *ast, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, char *dur, char *date, const char *category, const char *flag)
+ {
+ char callerid[256];
++ char num[12];
+ char fromdir[256], fromfile[256];
+ struct ast_config *msg_cfg;
+ const char *origcallerid, *origtime;
+@@ -3859,8 +3878,8 @@
+ /* Prepare variables for substitution in email body and subject */
+ pbx_builtin_setvar_helper(ast, "VM_NAME", vmu->fullname);
+ pbx_builtin_setvar_helper(ast, "VM_DUR", dur);
+- snprintf(passdata, passdatasize, "%d", msgnum);
+- pbx_builtin_setvar_helper(ast, "VM_MSGNUM", passdata);
++ snprintf(num, sizeof(num), "%d", msgnum);
++ pbx_builtin_setvar_helper(ast, "VM_MSGNUM", num);
+ pbx_builtin_setvar_helper(ast, "VM_CONTEXT", context);
+ pbx_builtin_setvar_helper(ast, "VM_MAILBOX", mailbox);
+ pbx_builtin_setvar_helper(ast, "VM_CALLERID", (!ast_strlen_zero(cidname) || !ast_strlen_zero(cidnum)) ?
+@@ -3904,30 +3923,32 @@
+ /*!
+ * \brief Wraps a character sequence in double quotes, escaping occurences of quotes within the string.
+ * \param from The string to work with.
+- * \param to The string to write the modified quoted string. This buffer should be sufficiently larger than the from string, so as to allow it to be expanded by the surrounding quotes and escaping of internal quotes.
++ * \param buf The buffer into which to write the modified quoted string.
++ * \param maxlen Always zero, but see \see ast_str
+ *
+ * \return The destination string with quotes wrapped on it (the to field).
+ */
+-static char *quote(const char *from, char *to, size_t len)
++static const char *ast_str_quote(struct ast_str **buf, ssize_t maxlen, const char *from)
+ {
+- char *ptr = to;
+- *ptr++ = '"';
+- for (; ptr < to + len - 1; from++) {
+- if (*from == '"')
+- *ptr++ = '\\';
+- else if (*from == '\0')
+- break;
+- *ptr++ = *from;
++ const char *ptr;
++
++ /* We're only ever passing 0 to maxlen, so short output isn't possible */
++ ast_str_set(buf, maxlen, "\"");
++ for (ptr = from; *ptr; ptr++) {
++ if (*ptr == '"' || *ptr == '\\') {
++ ast_str_append(buf, maxlen, "\\%c", *ptr);
++ } else {
++ ast_str_append(buf, maxlen, "%c", *ptr);
++ }
+ }
+- if (ptr < to + len - 1)
+- *ptr++ = '"';
+- *ptr = '\0';
+- return to;
++ ast_str_append(buf, maxlen, "\"");
++
++ return ast_str_buffer(*buf);
+ }
+
+ /*! \brief
+ * fill in *tm for current time according to the proper timezone, if any.
+- * Return tm so it can be used as a function argument.
++ * \return tm so it can be used as a function argument.
+ */
+ static const struct ast_tm *vmu_tm(const struct ast_vm_user *vmu, struct ast_tm *tm)
+ {
+@@ -3970,46 +3991,46 @@
+ * sections, separated by a space character, in order to facilitate
+ * breaking up the associated header across multiple lines.
+ *
++ * \param end An expandable buffer for holding the result
++ * \param maxlen Always zero, but see \see ast_str
+ * \param start A string to be encoded
+- * \param end An expandable buffer for holding the result
+ * \param preamble The length of the first line already used for this string,
+ * to ensure that each line maintains a maximum length of 76 chars.
+ * \param postamble the length of any additional characters appended to the
+ * line, used to ensure proper field wrapping.
+ * \retval The encoded string.
+ */
+-static char *encode_mime_str(const char *start, char *end, size_t endsize, size_t preamble, size_t postamble)
++static const char *ast_str_encode_mime(struct ast_str **end, ssize_t maxlen, const char *start, size_t preamble, size_t postamble)
+ {
+- char tmp[80];
++ struct ast_str *tmp = ast_str_alloca(80);
+ int first_section = 1;
+- size_t endlen = 0, tmplen = 0;
+- *end = '\0';
+
+- tmplen = snprintf(tmp, sizeof(tmp), "=?%s?Q?", charset);
++ ast_str_reset(*end);
++ ast_str_set(&tmp, -1, "=?%s?Q?", charset);
+ for (; *start; start++) {
+ int need_encoding = 0;
+ if (*start < 33 || *start > 126 || strchr("()<>@,:;/\"[]?.=_", *start)) {
+ need_encoding = 1;
+ }
+- if ((first_section && need_encoding && preamble + tmplen > 70) ||
+- (first_section && !need_encoding && preamble + tmplen > 72) ||
+- (!first_section && need_encoding && tmplen > 70) ||
+- (!first_section && !need_encoding && tmplen > 72)) {
++ if ((first_section && need_encoding && preamble + ast_str_strlen(tmp) > 70) ||
++ (first_section && !need_encoding && preamble + ast_str_strlen(tmp) > 72) ||
++ (!first_section && need_encoding && ast_str_strlen(tmp) > 70) ||
++ (!first_section && !need_encoding && ast_str_strlen(tmp) > 72)) {
+ /* Start new line */
+- endlen += snprintf(end + endlen, endsize - endlen, "%s%s?=", first_section ? "" : " ", tmp);
+- tmplen = snprintf(tmp, sizeof(tmp), "=?%s?Q?", charset);
++ ast_str_append(end, maxlen, "%s%s?=", first_section ? "" : " ", ast_str_buffer(tmp));
++ ast_str_set(&tmp, -1, "=?%s?Q?", charset);
+ first_section = 0;
+ }
+ if (need_encoding && *start == ' ') {
+- tmplen += snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "_");
++ ast_str_append(&tmp, -1, "_");
+ } else if (need_encoding) {
+- tmplen += snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "=%hhX", *start);
++ ast_str_append(&tmp, -1, "=%hhX", *start);
+ } else {
+- tmplen += snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "%c", *start);
++ ast_str_append(&tmp, -1, "%c", *start);
+ }
+ }
+- snprintf(end + endlen, endsize - endlen, "%s%s?=%s", first_section ? "" : " ", tmp, endlen + postamble > 74 ? " " : "");
+- return end;
++ ast_str_append(end, maxlen, "%s%s?=%s", first_section ? "" : " ", ast_str_buffer(tmp), ast_str_strlen(tmp) + postamble > 74 ? " " : "");
++ return ast_str_buffer(*end);
+ }
+
+ /*!
+@@ -4041,28 +4062,21 @@
+ char dur[256];
+ struct ast_tm tm;
+ char enc_cidnum[256] = "", enc_cidname[256] = "";
+- char *passdata = NULL, *passdata2;
+- size_t len_passdata = 0, len_passdata2, tmplen;
++ struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16);
+ char *greeting_attachment;
+ char filename[256];
+
++ if (!str1 || !str2) {
++ ast_free(str1);
++ ast_free(str2);
++ return;
++ }
+ #ifdef IMAP_STORAGE
+ #define ENDL "\r\n"
+ #else
+ #define ENDL "\n"
+ #endif
+
+- /* One alloca for multiple fields */
+- len_passdata2 = strlen(vmu->fullname);
+- if (emailsubject && (tmplen = strlen(emailsubject)) > len_passdata2) {
+- len_passdata2 = tmplen;
+- }
+- if ((tmplen = strlen(fromstring)) > len_passdata2) {
+- len_passdata2 = tmplen;
+- }
+- len_passdata2 = len_passdata2 * 3 + 200;
+- passdata2 = alloca(len_passdata2);
+-
+ if (cidnum) {
+ strip_control(cidnum, enc_cidnum, sizeof(enc_cidnum));
+ }
+@@ -4071,14 +4085,16 @@
+ }
+ gethostname(host, sizeof(host) - 1);
+
+- if (strchr(srcemail, '@'))
++ if (strchr(srcemail, '@')) {
+ ast_copy_string(who, srcemail, sizeof(who));
+- else
++ } else {
+ snprintf(who, sizeof(who), "%s@%s", srcemail, host);
++ }
+
+ greeting_attachment = strrchr(ast_strdupa(attach), '/');
+- if (greeting_attachment)
++ if (greeting_attachment) {
+ *greeting_attachment++ = '\0';
++ }
+
+ snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
+ ast_strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm));
+@@ -4091,25 +4107,24 @@
+ struct ast_channel *ast;
+ if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Substitution/voicemail"))) {
+ char *ptr;
+- memset(passdata2, 0, len_passdata2);
+- prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, passdata2, len_passdata2, category, flag);
+- pbx_substitute_variables_helper(ast, fromstring, passdata2, len_passdata2);
+- len_passdata = strlen(passdata2) * 3 + 300;
+- passdata = alloca(len_passdata);
+- if (check_mime(passdata2)) {
++ prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category, flag);
++ ast_str_substitute_variables(&str1, 0, ast, fromstring);
++
++ if (check_mime(ast_str_buffer(str1))) {
+ int first_line = 1;
+- encode_mime_str(passdata2, passdata, len_passdata, strlen("From: "), strlen(who) + 3);
+- while ((ptr = strchr(passdata, ' '))) {
++ ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("From: "), strlen(who) + 3);
++ while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
+ *ptr = '\0';
+- fprintf(p, "%s %s" ENDL, first_line ? "From:" : "", passdata);
++ fprintf(p, "%s %s" ENDL, first_line ? "From:" : "", ast_str_buffer(str2));
+ first_line = 0;
+- passdata = ptr + 1;
++ /* Substring is smaller, so this will never grow */
++ ast_str_set(&str2, 0, "%s", ptr + 1);
+ }
+- fprintf(p, "%s %s <%s>" ENDL, first_line ? "From:" : "", passdata, who);
++ fprintf(p, "%s %s <%s>" ENDL, first_line ? "From:" : "", ast_str_buffer(str2), who);
+ } else {
+- fprintf(p, "From: %s <%s>" ENDL, quote(passdata2, passdata, len_passdata), who);
++ fprintf(p, "From: %s <%s>" ENDL, ast_str_quote(&str2, 0, ast_str_buffer(str1)), who);
+ }
+- ast_channel_free(ast);
++ ast = ast_channel_release(ast);
+ } else {
+ ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
+ }
+@@ -4120,46 +4135,41 @@
+ if (check_mime(vmu->fullname)) {
+ int first_line = 1;
+ char *ptr;
+- encode_mime_str(vmu->fullname, passdata2, len_passdata2, strlen("To: "), strlen(vmu->email) + 3);
+- while ((ptr = strchr(passdata2, ' '))) {
++ ast_str_encode_mime(&str2, 0, vmu->fullname, strlen("To: "), strlen(vmu->email) + 3);
++ while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
+ *ptr = '\0';
+- fprintf(p, "%s %s" ENDL, first_line ? "To:" : "", passdata2);
++ fprintf(p, "%s %s" ENDL, first_line ? "To:" : "", ast_str_buffer(str2));
+ first_line = 0;
+- passdata2 = ptr + 1;
++ /* Substring is smaller, so this will never grow */
++ ast_str_set(&str2, 0, "%s", ptr + 1);
+ }
+- fprintf(p, "%s %s <%s>" ENDL, first_line ? "To:" : "", passdata2, vmu->email);
++ fprintf(p, "%s %s <%s>" ENDL, first_line ? "To:" : "", ast_str_buffer(str2), vmu->email);
+ } else {
+- fprintf(p, "To: %s <%s>" ENDL, quote(vmu->fullname, passdata2, len_passdata2), vmu->email);
++ fprintf(p, "To: %s <%s>" ENDL, ast_str_quote(&str2, 0, vmu->fullname), vmu->email);
+ }
++
+ if (!ast_strlen_zero(emailsubject) || !ast_strlen_zero(vmu->emailsubject)) {
+ char *e_subj = !ast_strlen_zero(vmu->emailsubject) ? vmu->emailsubject : emailsubject;
+ struct ast_channel *ast;
+ if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Substitution/voicemail"))) {
+- int vmlen = strlen(e_subj) * 3 + 200;
+- /* Only allocate more space if the previous was not large enough */
+- if (vmlen > len_passdata) {
+- passdata = alloca(vmlen);
+- len_passdata = vmlen;
+- }
+-
+- memset(passdata, 0, len_passdata);
+- prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, passdata, len_passdata, category, flag);
+- pbx_substitute_variables_helper(ast, e_subj, passdata, len_passdata);
+- if (check_mime(passdata)) {
++ prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
++ ast_str_substitute_variables(&str1, 0, ast, e_subj);
++ if (check_mime(ast_str_buffer(str1))) {
+ int first_line = 1;
+ char *ptr;
+- encode_mime_str(passdata, passdata2, len_passdata2, strlen("Subject: "), 0);
+- while ((ptr = strchr(passdata2, ' '))) {
++ ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("Subject: "), 0);
++ while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
+ *ptr = '\0';
+- fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", passdata2);
++ fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
+ first_line = 0;
+- passdata2 = ptr + 1;
++ /* Substring is smaller, so this will never grow */
++ ast_str_set(&str2, 0, "%s", ptr + 1);
+ }
+- fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", passdata2);
++ fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
+ } else {
+- fprintf(p, "Subject: %s" ENDL, passdata);
++ fprintf(p, "Subject: %s" ENDL, ast_str_buffer(str1));
+ }
+- ast_channel_free(ast);
++ ast = ast_channel_release(ast);
+ } else {
+ ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
+ }
+@@ -4225,16 +4235,13 @@
+ char* e_body = vmu->emailbody ? vmu->emailbody : emailbody;
+ struct ast_channel *ast;
+ if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Substitution/voicemail"))) {
+- char *passdata;
+- int vmlen = strlen(e_body) * 3 + 200;
+- passdata = alloca(vmlen);
+- memset(passdata, 0, vmlen);
+- prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, passdata, vmlen, category, flag);
+- pbx_substitute_variables_helper(ast, e_body, passdata, vmlen);
+- fprintf(p, "%s" ENDL, passdata);
+- ast_channel_free(ast);
+- } else
++ prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
++ ast_str_substitute_variables(&str1, 0, ast, e_body);
++ fprintf(p, "%s" ENDL, ast_str_buffer(str1));
++ ast = ast_channel_release(ast);
++ } else {
+ ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
++ }
+ } else if (msgnum > -1) {
+ if (strcmp(vmu->mailbox, mailbox)) {
+ /* Forwarded type */
+@@ -4299,6 +4306,8 @@
+ add_email_attachment(p, vmu, format, attach, greeting_attachment, mailbox, bound, filename, 1, msgnum);
+ }
+ }
++ ast_free(str1);
++ ast_free(str2);
+ }
+
+ static int add_email_attachment(FILE *p, struct ast_vm_user *vmu, char *format, char *attach, char *greeting_attachment, char *mailbox, char *bound, char *filename, int last, int msgnum)
+@@ -4352,7 +4361,6 @@
+ }
+ return 0;
+ }
+-#undef ENDL
+
+ static int sendmail(char *srcemail, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, char *attach, char *attach2, char *format, int duration, int attach_user_voicemail, struct ast_channel *chan, const char *category, const char *flag)
+ {
+@@ -4384,6 +4392,7 @@
+
+ static int sendpage(char *srcemail, char *pager, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, int duration, struct ast_vm_user *vmu, const char *category, const char *flag)
+ {
++ char enc_cidnum[256], enc_cidname[256];
+ char date[256];
+ char host[MAXHOSTNAMELEN] = "";
+ char who[256];
+@@ -4392,49 +4401,106 @@
+ char tmp2[PATH_MAX];
+ struct ast_tm tm;
+ FILE *p;
++ struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16);
+
++ if (!str1 || !str2) {
++ ast_free(str1);
++ ast_free(str2);
++ return -1;
++ }
++
++ if (cidnum) {
++ strip_control(cidnum, enc_cidnum, sizeof(enc_cidnum));
++ }
++ if (cidname) {
++ strip_control(cidname, enc_cidname, sizeof(enc_cidname));
++ }
++
+ if ((p = vm_mkftemp(tmp)) == NULL) {
+ ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
++ ast_free(str1);
++ ast_free(str2);
+ return -1;
+ }
+ gethostname(host, sizeof(host)-1);
+- if (strchr(srcemail, '@'))
++ if (strchr(srcemail, '@')) {
+ ast_copy_string(who, srcemail, sizeof(who));
+- else
++ } else {
+ snprintf(who, sizeof(who), "%s@%s", srcemail, host);
++ }
+ snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
+ ast_strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm));
+ fprintf(p, "Date: %s\n", date);
+
+- if (*pagerfromstring) {
++ if (!ast_strlen_zero(pagerfromstring)) {
+ struct ast_channel *ast;
+ if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Substitution/voicemail"))) {
+- char *passdata;
+- int vmlen = strlen(fromstring)*3 + 200;
+- passdata = alloca(vmlen);
+- memset(passdata, 0, vmlen);
+- prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, passdata, vmlen, category, flag);
+- pbx_substitute_variables_helper(ast, pagerfromstring, passdata, vmlen);
+- fprintf(p, "From: %s <%s>\n", passdata, who);
+- ast_channel_free(ast);
+- } else
++ char *ptr;
++ prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category, flag);
++ ast_str_substitute_variables(&str1, 0, ast, pagerfromstring);
++
++ if (check_mime(ast_str_buffer(str1))) {
++ int first_line = 1;
++ ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("From: "), strlen(who) + 3);
++ while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
++ *ptr = '\0';
++ fprintf(p, "%s %s" ENDL, first_line ? "From:" : "", ast_str_buffer(str2));
++ first_line = 0;
++ /* Substring is smaller, so this will never grow */
++ ast_str_set(&str2, 0, "%s", ptr + 1);
++ }
++ fprintf(p, "%s %s <%s>" ENDL, first_line ? "From:" : "", ast_str_buffer(str2), who);
++ } else {
++ fprintf(p, "From: %s <%s>" ENDL, ast_str_quote(&str2, 0, ast_str_buffer(str1)), who);
++ }
++ ast = ast_channel_release(ast);
++ } else {
+ ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
+- } else
+- fprintf(p, "From: Asterisk PBX <%s>\n", who);
+- fprintf(p, "To: %s\n", pager);
+- if (pagersubject) {
++ }
++ } else {
++ fprintf(p, "From: Asterisk PBX <%s>" ENDL, who);
++ }
++
++ if (check_mime(vmu->fullname)) {
++ int first_line = 1;
++ char *ptr;
++ ast_str_encode_mime(&str2, 0, vmu->fullname, strlen("To: "), strlen(pager) + 3);
++ while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
++ *ptr = '\0';
++ fprintf(p, "%s %s" ENDL, first_line ? "To:" : "", ast_str_buffer(str2));
++ first_line = 0;
++ /* Substring is smaller, so this will never grow */
++ ast_str_set(&str2, 0, "%s", ptr + 1);
++ }
++ fprintf(p, "%s %s <%s>" ENDL, first_line ? "To:" : "", ast_str_buffer(str2), pager);
++ } else {
++ fprintf(p, "To: %s <%s>" ENDL, ast_str_quote(&str2, 0, vmu->fullname), pager);
++ }
++
++ if (!ast_strlen_zero(pagersubject)) {
+ struct ast_channel *ast;
+ if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Substitution/voicemail"))) {
+- char *passdata;
+- int vmlen = strlen(pagersubject) * 3 + 200;
+- passdata = alloca(vmlen);
+- memset(passdata, 0, vmlen);
+- prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, passdata, vmlen, category, flag);
+- pbx_substitute_variables_helper(ast, pagersubject, passdata, vmlen);
+- fprintf(p, "Subject: %s\n\n", passdata);
+- ast_channel_free(ast);
+- } else
++ prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
++ ast_str_substitute_variables(&str1, 0, ast, pagersubject);
++ if (check_mime(ast_str_buffer(str1))) {
++ int first_line = 1;
++ char *ptr;
++ ast_str_encode_mime(&str2, 0, ast_str_buffer(str1), strlen("Subject: "), 0);
++ while ((ptr = strchr(ast_str_buffer(str2), ' '))) {
++ *ptr = '\0';
++ fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
++ first_line = 0;
++ /* Substring is smaller, so this will never grow */
++ ast_str_set(&str2, 0, "%s", ptr + 1);
++ }
++ fprintf(p, "%s %s" ENDL, first_line ? "Subject:" : "", ast_str_buffer(str2));
++ } else {
++ fprintf(p, "Subject: %s" ENDL, ast_str_buffer(str1));
++ }
++ ast = ast_channel_release(ast);
++ } else {
+ ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
++ }
+ } else {
+ if (ast_strlen_zero(flag)) {
+ fprintf(p, "Subject: New VM\n\n");
+@@ -4447,26 +4513,27 @@
+ if (pagerbody) {
+ struct ast_channel *ast;
+ if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Substitution/voicemail"))) {
+- char *passdata;
+- int vmlen = strlen(pagerbody) * 3 + 200;
+- passdata = alloca(vmlen);
+- memset(passdata, 0, vmlen);
+- prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, passdata, vmlen, category, flag);
+- pbx_substitute_variables_helper(ast, pagerbody, passdata, vmlen);
+- fprintf(p, "%s\n", passdata);
+- ast_channel_free(ast);
+- } else
++ prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
++ ast_str_substitute_variables(&str1, 0, ast, pagerbody);
++ fprintf(p, "%s" ENDL, ast_str_buffer(str1));
++ ast = ast_channel_release(ast);
++ } else {
+ ast_log(AST_LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
++ }
+ } else {
+ fprintf(p, "New %s long %s msg in box %s\n"
+ "from %s, on %s", dur, flag, mailbox, (cidname ? cidname : (cidnum ? cidnum : "unknown")), date);
+ }
++
+ fclose(p);
+ snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
+ ast_safe_system(tmp2);
+ ast_debug(1, "Sent page to %s with command '%s'\n", pager, mailcmd);
++ ast_free(str1);
++ ast_free(str2);
+ return 0;
+ }
++#undef ENDL
+
+ /*!
+ * \brief Gets the current date and time, as formatted string.
+@@ -5037,8 +5104,11 @@
+ const char *alldtmf = "0123456789ABCD*#";
+ char flag[80];
+
+- ast_str_set(&tmp, 0, "%s", ext);
+- ext = ast_str_buffer(tmp);
++ if (!tmp) {
++ return -1;
++ }
++
++ ext = ast_strdupa(ext);
+ if ((context = strchr(ext, '@'))) {
+ *context++ = '\0';
+ tmpptr = strchr(context, '&');
+@@ -8894,7 +8964,7 @@
+ return 0;
+ }
+
+-static int vm_execmain(struct ast_channel *chan, void *data)
++static int vm_execmain(struct ast_channel *chan, const char *data)
+ {
+ /* XXX This is, admittedly, some pretty horrendous code. For some
+ reason it just seemed a lot easier to do with GOTO's. I feel
+@@ -9602,7 +9672,7 @@
+ return res;
+ }
+
+-static int vm_exec(struct ast_channel *chan, void *data)
++static int vm_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+ char *tmp;
+@@ -9734,7 +9804,7 @@
+ return 0;
+ }
+
+-static int vm_box_exists(struct ast_channel *chan, void *data)
++static int vm_box_exists(struct ast_channel *chan, const char *data)
+ {
+ struct ast_vm_user svm;
+ char *context, *box;
+@@ -9798,16 +9868,16 @@
+ .read = acf_mailbox_exists,
+ };
+
+-static int vmauthenticate(struct ast_channel *chan, void *data)
++static int vmauthenticate(struct ast_channel *chan, const char *data)
+ {
+- char *s = data, *user=NULL, *context=NULL, mailbox[AST_MAX_EXTENSION] = "";
++ char *s, *user=NULL, *context=NULL, mailbox[AST_MAX_EXTENSION] = "";
+ struct ast_vm_user vmus;
+ char *options = NULL;
+ int silent = 0, skipuser = 0;
+ int res = -1;
+
+- if (s) {
+- s = ast_strdupa(s);
++ if (data) {
++ s = ast_strdupa(data);
+ user = strsep(&s, ",");
+ options = strsep(&s, ",");
+ if (user) {
+@@ -10637,10 +10707,10 @@
+ if ((val = ast_variable_retrieve(cfg, "general", "smdienable")) && ast_true(val)) {
+ ast_debug(1, "Enabled SMDI voicemail notification\n");
+ if ((val = ast_variable_retrieve(cfg, "general", "smdiport"))) {
+- smdi_iface = ast_smdi_interface_find ? ast_smdi_interface_find(val) : NULL;
++ smdi_iface = ast_smdi_interface_find(val);
+ } else {
+ ast_debug(1, "No SMDI interface set, trying default (/dev/ttyS0)\n");
+- smdi_iface = ast_smdi_interface_find ? ast_smdi_interface_find("/dev/ttyS0") : NULL;
++ smdi_iface = ast_smdi_interface_find("/dev/ttyS0");
+ }
+ if (!smdi_iface) {
+ ast_log(AST_LOG_ERROR, "No valid SMDI interface specfied, disabling SMDI voicemail notification\n");
+@@ -11098,7 +11168,7 @@
+ res |= ast_register_application_xml(app3, vm_box_exists);
+ res |= ast_register_application_xml(app4, vmauthenticate);
+ res |= ast_custom_function_register(&mailbox_exists_acf);
+- res |= ast_manager_register("VoicemailUsersList", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, manager_list_voicemail_users, "List All Voicemail User Information");
++ res |= ast_manager_register_xml("VoicemailUsersList", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, manager_list_voicemail_users);
+ if (res)
+ return res;
+
+Index: apps/app_dial.c
+===================================================================
+--- a/apps/app_dial.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_dial.c (.../trunk) (revision 202568)
+@@ -54,7 +54,7 @@
+ #include "asterisk/utils.h"
+ #include "asterisk/app.h"
+ #include "asterisk/causes.h"
+-#include "asterisk/rtp.h"
++#include "asterisk/rtp_engine.h"
+ #include "asterisk/cdr.h"
+ #include "asterisk/manager.h"
+ #include "asterisk/privacy.h"
+@@ -109,11 +109,13 @@
+ <option name="D" argsep=":">
+ <argument name="called" />
+ <argument name="calling" />
++ <argument name="progress" />
+ <para>Send the specified DTMF strings <emphasis>after</emphasis> the called
+ party has answered, but before the call gets bridged. The
+ <replaceable>called</replaceable> DTMF string is sent to the called party, and the
+ <replaceable>calling</replaceable> DTMF string is sent to the calling party. Both arguments
+- can be used alone.</para>
++ can be used alone. If <replaceable>progress</replaceable> is specified, its DTMF is sent
++ immediately after receiving a PROGRESS message.</para>
+ </option>
+ <option name="e">
+ <para>Execute the <literal>h</literal> extension for peer after the call ends</para>
+@@ -131,6 +133,10 @@
+ <para>When the caller hangs up, transfer the called party
+ to the specified destination and continue execution at that location.</para>
+ </option>
++ <option name="F">
++ <para>Proceed with dialplan execution at the next priority in the current extension if the
++ source channel hangs up.</para>
++ </option>
+ <option name="g">
+ <para>Proceed with dialplan execution at the next priority in the current extension if the
+ destination channel hangs up.</para>
+@@ -155,6 +161,10 @@
+ <option name="i">
+ <para>Asterisk will ignore any forwarding requests it may receive on this dial attempt.</para>
+ </option>
++ <option name="I">
++ <para>Asterisk will ignore any connected line update requests or redirecting party update
++ requests it may receiveon this dial attempt.</para>
++ </option>
+ <option name="k">
+ <para>Allow the called party to enable parking of the call by sending
+ the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
+@@ -363,6 +373,9 @@
+ <para>Allow the calling party to enable recording of the call by sending
+ the DTMF sequence defined for one-touch automixmonitor in <filename>features.conf</filename>.</para>
+ </option>
++ <option name="z">
++ <para>On a call forward, cancel any dial timeout which has been set for this call.</para>
++ </option>
+ </optionlist>
+ </parameter>
+ <parameter name="URL">
+@@ -383,7 +396,6 @@
+ This application will report normal termination if the originating channel
+ hangs up, or if the call is bridged and either of the parties in the bridge
+ ends the call.</para>
+-
+ <para>If the <variable>OUTBOUND_GROUP</variable> variable is set, all peer channels created by this
+ application will be put into that group (as in Set(GROUP()=...).
+ If the <variable>OUTBOUND_GROUP_ONCE</variable> variable is set, all peer channels created by this
+@@ -453,8 +465,8 @@
+ </application>
+ ***/
+
+-static char *app = "Dial";
+-static char *rapp = "RetryDial";
++static const char app[] = "Dial";
++static const char rapp[] = "RetryDial";
+
+ enum {
+ OPT_ANNOUNCE = (1 << 0),
+@@ -465,12 +477,13 @@
+ OPT_GO_ON = (1 << 5),
+ OPT_CALLEE_HANGUP = (1 << 6),
+ OPT_CALLER_HANGUP = (1 << 7),
++ OPT_ORIGINAL_CLID = (1 << 8),
+ OPT_DURATION_LIMIT = (1 << 9),
+ OPT_MUSICBACK = (1 << 10),
+ OPT_CALLEE_MACRO = (1 << 11),
+ OPT_SCREEN_NOINTRO = (1 << 12),
+- OPT_SCREEN_NOCLID = (1 << 13),
+- OPT_ORIGINAL_CLID = (1 << 14),
++ OPT_SCREEN_NOCALLERID = (1 << 13),
++ OPT_IGNORE_CONNECTEDLINE = (1 << 14),
+ OPT_SCREENING = (1 << 15),
+ OPT_PRIVACY = (1 << 16),
+ OPT_RINGBACK = (1 << 17),
+@@ -491,9 +504,11 @@
+
+ #define DIAL_STILLGOING (1 << 31)
+ #define DIAL_NOFORWARDHTML ((uint64_t)1 << 32) /* flags are now 64 bits, so keep it up! */
+-#define OPT_CANCEL_ELSEWHERE ((uint64_t)1 << 33)
+-#define OPT_PEER_H ((uint64_t)1 << 34)
+-#define OPT_CALLEE_GO_ON ((uint64_t)1 << 35)
++#define DIAL_NOCONNECTEDLINE ((uint64_t)1 << 33)
++#define OPT_CANCEL_ELSEWHERE ((uint64_t)1 << 34)
++#define OPT_PEER_H ((uint64_t)1 << 35)
++#define OPT_CALLEE_GO_ON ((uint64_t)1 << 36)
++#define OPT_CANCEL_TIMEOUT ((uint64_t)1 << 37)
+
+ enum {
+ OPT_ARG_ANNOUNCE = 0,
+@@ -525,13 +540,14 @@
+ AST_APP_OPTION('h', OPT_CALLEE_HANGUP),
+ AST_APP_OPTION('H', OPT_CALLER_HANGUP),
+ AST_APP_OPTION('i', OPT_IGNORE_FORWARDING),
++ AST_APP_OPTION('I', OPT_IGNORE_CONNECTEDLINE),
+ AST_APP_OPTION('k', OPT_CALLEE_PARK),
+ AST_APP_OPTION('K', OPT_CALLER_PARK),
+ AST_APP_OPTION_ARG('L', OPT_DURATION_LIMIT, OPT_ARG_DURATION_LIMIT),
+ AST_APP_OPTION_ARG('m', OPT_MUSICBACK, OPT_ARG_MUSICBACK),
+ AST_APP_OPTION_ARG('M', OPT_CALLEE_MACRO, OPT_ARG_CALLEE_MACRO),
+ AST_APP_OPTION('n', OPT_SCREEN_NOINTRO),
+- AST_APP_OPTION('N', OPT_SCREEN_NOCLID),
++ AST_APP_OPTION('N', OPT_SCREEN_NOCALLERID),
+ AST_APP_OPTION('o', OPT_ORIGINAL_CLID),
+ AST_APP_OPTION_ARG('O', OPT_OPERMODE, OPT_ARG_OPERMODE),
+ AST_APP_OPTION('p', OPT_SCREENING),
+@@ -545,6 +561,7 @@
+ AST_APP_OPTION('W', OPT_CALLER_MONITOR),
+ AST_APP_OPTION('x', OPT_CALLEE_MIXMONITOR),
+ AST_APP_OPTION('X', OPT_CALLER_MIXMONITOR),
++ AST_APP_OPTION('z', OPT_CANCEL_TIMEOUT),
+ END_OPTIONS );
+
+ #define CAN_EARLY_BRIDGE(flags,chan,peer) (!ast_test_flag64(flags, OPT_CALLEE_HANGUP | \
+@@ -559,8 +576,10 @@
+ struct chanlist *next;
+ struct ast_channel *chan;
+ uint64_t flags;
++ struct ast_party_connected_line connected;
+ };
+
++static int detect_disconnect(struct ast_channel *chan, char code, struct ast_str *featurecode);
+
+ static void hanguptree(struct chanlist *outgoing, struct ast_channel *exception, int answered_elsewhere)
+ {
+@@ -575,6 +594,7 @@
+ /* This is for the channel drivers */
+ outgoing->chan->hangupcause = AST_CAUSE_ANSWERED_ELSEWHERE;
+ }
++ ast_party_connected_line_free(&outgoing->connected);
+ ast_hangup(outgoing->chan);
+ }
+ oo = outgoing;
+@@ -659,12 +679,17 @@
+ return 0;
+ }
+
+-
++/* do not call with chan lock held */
+ static const char *get_cid_name(char *name, int namelen, struct ast_channel *chan)
+ {
+- const char *context = S_OR(chan->macrocontext, chan->context);
+- const char *exten = S_OR(chan->macroexten, chan->exten);
++ const char *context;
++ const char *exten;
+
++ ast_channel_lock(chan);
++ context = ast_strdupa(S_OR(chan->macrocontext, chan->context));
++ exten = ast_strdupa(S_OR(chan->macroexten, chan->exten));
++ ast_channel_unlock(chan);
++
+ return ast_get_hint(NULL, 0, name, namelen, chan, context, exten) ? name : "";
+ }
+
+@@ -699,14 +724,18 @@
+ *
+ * XXX this code is highly suspicious, as it essentially overwrites
+ * the outgoing channel without properly deleting it.
++ *
++ * \todo eventually this function should be intergrated into and replaced by ast_call_forward()
+ */
+ static void do_forward(struct chanlist *o,
+- struct cause_args *num, struct ast_flags64 *peerflags, int single)
++ struct cause_args *num, struct ast_flags64 *peerflags, int single, int *to)
+ {
+ char tmpchan[256];
+ struct ast_channel *original = o->chan;
+ struct ast_channel *c = o->chan; /* the winner */
+ struct ast_channel *in = num->chan; /* the input channel */
++ struct ast_party_redirecting *apr = &o->chan->redirecting;
++ struct ast_party_connected_line *apc = &o->chan->connected;
+ char *stuff;
+ char *tech;
+ int cause;
+@@ -750,28 +779,42 @@
+ handle_cause(cause, num);
+ ast_hangup(original);
+ } else {
+- char *new_cid_num, *new_cid_name;
+- struct ast_channel *src;
++ if (single) {
++ ast_rtp_instance_early_bridge_make_compatible(c, in);
++ }
+
+- ast_rtp_make_compatible(c, in, single);
++ c->cdrflags = in->cdrflags;
++
++ ast_channel_set_redirecting(c, apr);
++ ast_channel_lock(c);
++ while (ast_channel_trylock(in)) {
++ CHANNEL_DEADLOCK_AVOIDANCE(c);
++ }
++ S_REPLACE(c->cid.cid_rdnis, ast_strdup(S_OR(original->cid.cid_rdnis, S_OR(in->macroexten, in->exten))));
++
++ c->cid.cid_tns = in->cid.cid_tns;
++
+ if (ast_test_flag64(o, OPT_FORCECLID)) {
+- new_cid_num = ast_strdup(S_OR(in->macroexten, in->exten));
+- new_cid_name = NULL; /* XXX no name ? */
+- src = c; /* XXX possible bug in previous code, which used 'winner' ? it may have changed */
++ S_REPLACE(c->cid.cid_num, ast_strdupa(S_OR(in->macroexten, in->exten)));
++ S_REPLACE(c->cid.cid_name, NULL);
++ ast_string_field_set(c, accountcode, c->accountcode);
+ } else {
+- new_cid_num = ast_strdup(in->cid.cid_num);
+- new_cid_name = ast_strdup(in->cid.cid_name);
+- src = in;
++ ast_party_caller_copy(&c->cid, &in->cid);
++ ast_string_field_set(c, accountcode, in->accountcode);
+ }
+- ast_string_field_set(c, accountcode, src->accountcode);
+- c->cdrflags = src->cdrflags;
+- S_REPLACE(c->cid.cid_num, new_cid_num);
+- S_REPLACE(c->cid.cid_name, new_cid_name);
++ ast_party_connected_line_copy(&c->connected, apc);
+
+- if (in->cid.cid_ani) { /* XXX or maybe unconditional ? */
+- S_REPLACE(c->cid.cid_ani, ast_strdup(in->cid.cid_ani));
++ S_REPLACE(in->cid.cid_rdnis, ast_strdup(c->cid.cid_rdnis));
++ ast_channel_update_redirecting(in, apr);
++
++ ast_clear_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE);
++ if (ast_test_flag64(peerflags, OPT_CANCEL_TIMEOUT)) {
++ *to = -1;
+ }
+- S_REPLACE(c->cid.cid_rdnis, ast_strdup(S_OR(in->macroexten, in->exten)));
++
++ ast_channel_unlock(in);
++ ast_channel_unlock(c);
++
+ if (ast_call(c, tmpchan, 0)) {
+ ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
+ ast_clear_flag64(o, DIAL_STILLGOING);
+@@ -780,11 +823,21 @@
+ c = o->chan = NULL;
+ num->nochan++;
+ } else {
++ ast_channel_lock(c);
++ while (ast_channel_trylock(in)) {
++ CHANNEL_DEADLOCK_AVOIDANCE(c);
++ }
+ senddialevent(in, c, stuff);
+- /* After calling, set callerid to extension */
+ if (!ast_test_flag64(peerflags, OPT_ORIGINAL_CLID)) {
+ char cidname[AST_MAX_EXTENSION] = "";
+- ast_set_callerid(c, S_OR(in->macroexten, in->exten), get_cid_name(cidname, sizeof(cidname), in), NULL);
++ const char *tmpexten;
++ tmpexten = ast_strdupa(S_OR(in->macroexten, in->exten));
++ ast_channel_unlock(in);
++ ast_channel_unlock(c);
++ ast_set_callerid(c, tmpexten, get_cid_name(cidname, sizeof(cidname), in), NULL);
++ } else {
++ ast_channel_unlock(in);
++ ast_channel_unlock(c);
+ }
+ /* Hangup the original channel now, in case we needed it */
+ ast_hangup(original);
+@@ -807,23 +860,37 @@
+ static struct ast_channel *wait_for_answer(struct ast_channel *in,
+ struct chanlist *outgoing, int *to, struct ast_flags64 *peerflags,
+ struct privacy_args *pa,
+- const struct cause_args *num_in, int *result)
++ const struct cause_args *num_in, int *result, char *dtmf_progress)
+ {
+ struct cause_args num = *num_in;
+ int prestart = num.busy + num.congestion + num.nochan;
+ int orig = *to;
+ struct ast_channel *peer = NULL;
+ /* single is set if only one destination is enabled */
+- int single = outgoing && !outgoing->next && !ast_test_flag64(outgoing, OPT_MUSICBACK | OPT_RINGBACK);
++ int single = outgoing && !outgoing->next;
+ #ifdef HAVE_EPOLL
+ struct chanlist *epollo;
+ #endif
++ struct ast_party_connected_line connected_caller;
++ struct ast_str *featurecode = ast_str_alloca(FEATURE_MAX_LEN + 1);
+
++ ast_party_connected_line_init(&connected_caller);
+ if (single) {
+ /* Turn off hold music, etc */
+- ast_deactivate_generator(in);
++ if (!ast_test_flag64(outgoing, OPT_MUSICBACK | OPT_RINGBACK))
++ ast_deactivate_generator(in);
++
+ /* If we are calling a single channel, make them compatible for in-band tone purpose */
+ ast_channel_make_compatible(outgoing->chan, in);
++
++ if (!ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE) && !ast_test_flag64(outgoing, DIAL_NOCONNECTEDLINE)) {
++ ast_channel_lock(outgoing->chan);
++ ast_connected_line_copy_from_caller(&connected_caller, &outgoing->chan->cid);
++ ast_channel_unlock(outgoing->chan);
++ connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
++ ast_channel_update_connected_line(in, &connected_caller);
++ ast_party_connected_line_free(&connected_caller);
++ }
+ }
+
+ #ifdef HAVE_EPOLL
+@@ -870,6 +937,20 @@
+ if (ast_test_flag64(o, DIAL_STILLGOING) && c->_state == AST_STATE_UP) {
+ if (!peer) {
+ ast_verb(3, "%s answered %s\n", c->name, in->name);
++ if (!single && !ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE)) {
++ if (o->connected.id.number) {
++ if (ast_channel_connected_line_macro(c, in, &o->connected, 1, 0)) {
++ ast_channel_update_connected_line(in, &o->connected);
++ }
++ } else if (!ast_test_flag64(o, DIAL_NOCONNECTEDLINE)) {
++ ast_channel_lock(c);
++ ast_connected_line_copy_from_caller(&connected_caller, &c->cid);
++ ast_channel_unlock(c);
++ connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
++ ast_channel_update_connected_line(in, &connected_caller);
++ ast_party_connected_line_free(&connected_caller);
++ }
++ }
+ peer = c;
+ ast_copy_flags64(peerflags, o,
+ OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
+@@ -887,7 +968,7 @@
+ continue;
+ /* here, o->chan == c == winner */
+ if (!ast_strlen_zero(c->call_forward)) {
+- do_forward(o, &num, peerflags, single);
++ do_forward(o, &num, peerflags, single, to);
+ continue;
+ }
+ f = ast_read(winner);
+@@ -908,6 +989,20 @@
+ /* This is our guy if someone answered. */
+ if (!peer) {
+ ast_verb(3, "%s answered %s\n", c->name, in->name);
++ if (!single && !ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE)) {
++ if (o->connected.id.number) {
++ if (ast_channel_connected_line_macro(c, in, &o->connected, 1, 0)) {
++ ast_channel_update_connected_line(in, &o->connected);
++ }
++ } else if (!ast_test_flag64(o, DIAL_NOCONNECTEDLINE)) {
++ ast_channel_lock(c);
++ ast_connected_line_copy_from_caller(&connected_caller, &c->cid);
++ ast_channel_unlock(c);
++ connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
++ ast_channel_update_connected_line(in, &connected_caller);
++ ast_party_connected_line_free(&connected_caller);
++ }
++ }
+ peer = c;
+ if (peer->cdr) {
+ peer->cdr->answer = ast_tvnow();
+@@ -963,6 +1058,10 @@
+ ast_channel_early_bridge(in, c);
+ if (!ast_test_flag64(outgoing, OPT_RINGBACK))
+ ast_indicate(in, AST_CONTROL_PROGRESS);
++ if(!ast_strlen_zero(dtmf_progress)) {
++ ast_verb(3, "Sending DTMF '%s' to the called party as result of receiving a PROGRESS message.\n", dtmf_progress);
++ ast_dtmf_stream(c, in, dtmf_progress, 250, 0);
++ }
+ break;
+ case AST_CONTROL_VIDUPDATE:
+ ast_verb(3, "%s requested a video update, passing it to %s\n", c->name, in->name);
+@@ -972,6 +1071,30 @@
+ ast_verb(3, "%s requested a source update, passing it to %s\n", c->name, in->name);
+ ast_indicate(in, AST_CONTROL_SRCUPDATE);
+ break;
++ case AST_CONTROL_CONNECTED_LINE:
++ if (ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE)) {
++ ast_verb(3, "Connected line update to %s prevented.\n", in->name);
++ } else if (!single) {
++ struct ast_party_connected_line connected;
++ ast_verb(3, "%s connected line has changed. Saving it until answer for %s\n", c->name, in->name);
++ ast_party_connected_line_set_init(&connected, &o->connected);
++ ast_connected_line_parse_data(f->data.ptr, f->datalen, &connected);
++ ast_party_connected_line_set(&o->connected, &connected);
++ ast_party_connected_line_free(&connected);
++ } else {
++ if (ast_channel_connected_line_macro(c, in, f, 1, 1)) {
++ ast_indicate_data(in, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen);
++ }
++ }
++ break;
++ case AST_CONTROL_REDIRECTING:
++ if (ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE)) {
++ ast_verb(3, "Redirecting update to %s prevented.\n", in->name);
++ } else {
++ ast_verb(3, "%s redirecting info has changed, passing it to %s\n", c->name, in->name);
++ ast_indicate_data(in, AST_CONTROL_REDIRECTING, f->data.ptr, f->datalen);
++ }
++ break;
+ case AST_CONTROL_PROCEEDING:
+ ast_verb(3, "%s is proceeding passing it to %s\n", c->name, in->name);
+ if (single && CAN_EARLY_BRIDGE(peerflags, in, c))
+@@ -1063,8 +1186,8 @@
+ }
+
+ if (ast_test_flag64(peerflags, OPT_CALLER_HANGUP) &&
+- (f->subclass == '*')) { /* hmm it it not guaranteed to be '*' anymore. */
+- ast_verb(3, "User hit %c to disconnect call.\n", f->subclass);
++ detect_disconnect(in, f->subclass, featurecode)) {
++ ast_verb(3, "User requested call disconnect.\n");
+ *to = 0;
+ strcpy(pa->status, "CANCEL");
+ ast_cdr_noanswer(in->cdr);
+@@ -1082,13 +1205,19 @@
+ if (ast_write(outgoing->chan, f))
+ ast_log(LOG_WARNING, "Unable to forward voice or dtmf\n");
+ }
+- if (single && (f->frametype == AST_FRAME_CONTROL) &&
+- ((f->subclass == AST_CONTROL_HOLD) ||
+- (f->subclass == AST_CONTROL_UNHOLD) ||
+- (f->subclass == AST_CONTROL_VIDUPDATE) ||
+- (f->subclass == AST_CONTROL_SRCUPDATE))) {
+- ast_verb(3, "%s requested special control %d, passing it to %s\n", in->name, f->subclass, outgoing->chan->name);
+- ast_indicate_data(outgoing->chan, f->subclass, f->data.ptr, f->datalen);
++ if (single && (f->frametype == AST_FRAME_CONTROL)) {
++ if ((f->subclass == AST_CONTROL_HOLD) ||
++ (f->subclass == AST_CONTROL_UNHOLD) ||
++ (f->subclass == AST_CONTROL_VIDUPDATE) ||
++ (f->subclass == AST_CONTROL_SRCUPDATE) ||
++ (f->subclass == AST_CONTROL_REDIRECTING)) {
++ ast_verb(3, "%s requested special control %d, passing it to %s\n", in->name, f->subclass, outgoing->chan->name);
++ ast_indicate_data(outgoing->chan, f->subclass, f->data.ptr, f->datalen);
++ } else if (f->subclass == AST_CONTROL_CONNECTED_LINE) {
++ if (ast_channel_connected_line_macro(in, outgoing->chan, f, 0, 1)) {
++ ast_indicate_data(outgoing->chan, f->subclass, f->data.ptr, f->datalen);
++ }
++ }
+ }
+ ast_frfree(f);
+ }
+@@ -1108,6 +1237,26 @@
+ return peer;
+ }
+
++static int detect_disconnect(struct ast_channel *chan, char code, struct ast_str *featurecode)
++{
++ struct ast_flags features = { AST_FEATURE_DISCONNECT }; /* only concerned with disconnect feature */
++ struct ast_call_feature feature = { 0, };
++ int res;
++
++ ast_str_append(&featurecode, 1, "%c", code);
++
++ res = ast_feature_detect(chan, &features, ast_str_buffer(featurecode), &feature);
++
++ if (res != AST_FEATURE_RETURN_STOREDIGITS) {
++ ast_str_reset(featurecode);
++ }
++ if (feature.feature_mask & AST_FEATURE_DISCONNECT) {
++ return 1;
++ }
++
++ return 0;
++}
++
+ static void replace_macro_delimiter(char *s)
+ {
+ for (; *s; s++)
+@@ -1316,7 +1465,7 @@
+ ast_autoservice_stop(chan);
+ if (ast_test_flag64(opts, OPT_PRIVACY) && (res2 >= '1' && res2 <= '5')) {
+ /* map keypresses to various things, the index is res2 - '1' */
+- static const char *_val[] = { "ALLOW", "DENY", "TORTURE", "KILL", "ALLOW" };
++ static const char * const _val[] = { "ALLOW", "DENY", "TORTURE", "KILL", "ALLOW" };
+ static const int _flag[] = { AST_PRIVACY_ALLOW, AST_PRIVACY_DENY, AST_PRIVACY_TORTURE, AST_PRIVACY_KILL, AST_PRIVACY_ALLOW};
+ int i = res2 - '1';
+ ast_verb(3, "--Set privacy database entry %s/%s to %s\n",
+@@ -1405,11 +1554,11 @@
+
+ ast_copy_string(pa->privcid, l, sizeof(pa->privcid));
+
+- if (strncmp(pa->privcid, "NOCALLERID", 10) != 0 && ast_test_flag64(opts, OPT_SCREEN_NOCLID)) {
+- /* if callerid is set and OPT_SCREEN_NOCLID is set also */
++ if (strncmp(pa->privcid, "NOCALLERID", 10) != 0 && ast_test_flag64(opts, OPT_SCREEN_NOCALLERID)) {
++ /* if callerid is set and OPT_SCREEN_NOCALLERID is set also */
+ ast_verb(3, "CallerID set (%s); N option set; Screening should be off\n", pa->privcid);
+ pa->privdb_val = AST_PRIVACY_ALLOW;
+- } else if (ast_test_flag64(opts, OPT_SCREEN_NOCLID) && strncmp(pa->privcid, "NOCALLERID", 10) == 0) {
++ } else if (ast_test_flag64(opts, OPT_SCREEN_NOCALLERID) && strncmp(pa->privcid, "NOCALLERID", 10) == 0) {
+ ast_verb(3, "CallerID blank; N option set; Screening should happen; dbval is %d\n", pa->privdb_val);
+ }
+
+@@ -1499,7 +1648,7 @@
+ bconfig->end_bridge_callback_data = originator;
+ }
+
+-static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags64 *peerflags, int *continue_exec)
++static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast_flags64 *peerflags, int *continue_exec)
+ {
+ int res = -1; /* default: error */
+ char *rest, *cur; /* scan the list of destinations */
+@@ -1513,7 +1662,7 @@
+
+ struct ast_bridge_config config = { { 0, } };
+ struct timeval calldurationlimit = { 0, };
+- char *dtmfcalled = NULL, *dtmfcalling = NULL;
++ char *dtmfcalled = NULL, *dtmfcalling = NULL, *dtmf_progress=NULL;
+ struct privacy_args pa = {
+ .sentringing = 0,
+ .privdb_val = 0,
+@@ -1564,12 +1713,11 @@
+ goto done;
+ }
+
+-
+ if (ast_test_flag64(&opts, OPT_OPERMODE)) {
+ opermode = ast_strlen_zero(opt_args[OPT_ARG_OPERMODE]) ? 1 : atoi(opt_args[OPT_ARG_OPERMODE]);
+ ast_verb(3, "Setting operator services mode to %d.\n", opermode);
+ }
+-
++
+ if (ast_test_flag64(&opts, OPT_DURATION_STOP) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_STOP])) {
+ calldurationlimit.tv_sec = atoi(opt_args[OPT_ARG_DURATION_STOP]);
+ if (!calldurationlimit.tv_sec) {
+@@ -1581,8 +1729,9 @@
+ }
+
+ if (ast_test_flag64(&opts, OPT_SENDDTMF) && !ast_strlen_zero(opt_args[OPT_ARG_SENDDTMF])) {
+- dtmfcalling = opt_args[OPT_ARG_SENDDTMF];
+- dtmfcalled = strsep(&dtmfcalling, ":");
++ dtmf_progress = opt_args[OPT_ARG_SENDDTMF];
++ dtmfcalled = strsep(&dtmf_progress, ":");
++ dtmfcalling = strsep(&dtmf_progress, ":");
+ }
+
+ if (ast_test_flag64(&opts, OPT_DURATION_LIMIT) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_LIMIT])) {
+@@ -1602,7 +1751,7 @@
+ res = -1; /* reset default */
+ }
+
+- if (ast_test_flag64(&opts, OPT_DTMF_EXIT)) {
++ if (ast_test_flag64(&opts, OPT_DTMF_EXIT) || ast_test_flag64(&opts, OPT_CALLER_HANGUP)) {
+ __ast_answer(chan, 0, 0);
+ }
+
+@@ -1619,7 +1768,7 @@
+ outbound_group = ast_strdupa(outbound_group);
+ }
+ ast_channel_unlock(chan);
+- ast_copy_flags64(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP | OPT_IGNORE_FORWARDING);
++ ast_copy_flags64(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP | OPT_IGNORE_FORWARDING | OPT_IGNORE_CONNECTEDLINE | OPT_CANCEL_TIMEOUT);
+
+ /* loop through the list of dial destinations */
+ rest = args.peers;
+@@ -1656,6 +1805,14 @@
+
+ ast_channel_lock(chan);
+ datastore = ast_channel_datastore_find(chan, &dialed_interface_info, NULL);
++ /* If the incoming channel has previously had connected line information
++ * set on it (perhaps through the CONNECTED_LINE dialplan function) then
++ * seed the calllist's connected line information with this previously
++ * acquired info
++ */
++ if (chan->connected.id.number) {
++ ast_party_connected_line_copy(&tmp->connected, &chan->connected);
++ }
+ ast_channel_unlock(chan);
+
+ if (datastore)
+@@ -1728,8 +1885,14 @@
+ }
+ pbx_builtin_setvar_helper(tc, "DIALEDPEERNUMBER", numsubst);
+
++ ast_channel_lock(tc);
++ while (ast_channel_trylock(chan)) {
++ CHANNEL_DEADLOCK_AVOIDANCE(tc);
++ }
+ /* Setup outgoing SDP to match incoming one */
+- ast_rtp_make_compatible(tc, chan, !outgoing && !rest);
++ if (!outgoing && !rest) {
++ ast_rtp_instance_early_bridge_make_compatible(tc, chan);
++ }
+
+ /* Inherit specially named variables from parent channel */
+ ast_channel_inherit_variables(chan, tc);
+@@ -1739,20 +1902,31 @@
+ tc->data = "(Outgoing Line)";
+ memset(&tc->whentohangup, 0, sizeof(tc->whentohangup));
+
+- S_REPLACE(tc->cid.cid_num, ast_strdup(chan->cid.cid_num));
+- S_REPLACE(tc->cid.cid_name, ast_strdup(chan->cid.cid_name));
+- S_REPLACE(tc->cid.cid_ani, ast_strdup(chan->cid.cid_ani));
++ /* If the new channel has no callerid, try to guess what it should be */
++ if (ast_strlen_zero(tc->cid.cid_num)) {
++ if (!ast_strlen_zero(chan->connected.id.number)) {
++ ast_set_callerid(tc, chan->connected.id.number, chan->connected.id.name, chan->connected.ani);
++ } else if (!ast_strlen_zero(chan->cid.cid_dnid)) {
++ ast_set_callerid(tc, chan->cid.cid_dnid, NULL, NULL);
++ } else if (!ast_strlen_zero(S_OR(chan->macroexten, chan->exten))) {
++ ast_set_callerid(tc, S_OR(chan->macroexten, chan->exten), NULL, NULL);
++ }
++ ast_set_flag64(tmp, DIAL_NOCONNECTEDLINE);
++ }
++
++ ast_connected_line_copy_from_caller(&tc->connected, &chan->cid);
++
+ S_REPLACE(tc->cid.cid_rdnis, ast_strdup(chan->cid.cid_rdnis));
+-
++ ast_party_redirecting_copy(&tc->redirecting, &chan->redirecting);
++
++ tc->cid.cid_tns = chan->cid.cid_tns;
++
+ ast_string_field_set(tc, accountcode, chan->accountcode);
+ tc->cdrflags = chan->cdrflags;
+ if (ast_strlen_zero(tc->musicclass))
+ ast_string_field_set(tc, musicclass, chan->musicclass);
+- /* Pass callingpres, type of number, tns, ADSI CPE, transfer capability */
+- tc->cid.cid_pres = chan->cid.cid_pres;
+- tc->cid.cid_ton = chan->cid.cid_ton;
+- tc->cid.cid_tns = chan->cid.cid_tns;
+- tc->cid.cid_ani2 = chan->cid.cid_ani2;
++
++ /* Pass ADSI CPE and transfer capability */
+ tc->adsicpe = chan->adsicpe;
+ tc->transfercapability = chan->transfercapability;
+
+@@ -1775,6 +1949,7 @@
+ else
+ ast_copy_string(tc->exten, chan->exten, sizeof(tc->exten));
+
++ ast_channel_unlock(tc);
+ res = ast_call(tc, numsubst, 0); /* Place the call, but don't wait on the answer */
+
+ /* Save the info in cdr's that we called them */
+@@ -1789,15 +1964,19 @@
+ if (tc->hangupcause) {
+ chan->hangupcause = tc->hangupcause;
+ }
++ ast_channel_unlock(chan);
+ ast_hangup(tc);
+ tc = NULL;
+ ast_free(tmp);
+ continue;
+ } else {
++ const char *tmpexten = ast_strdupa(S_OR(chan->macroexten, chan->exten));
+ senddialevent(chan, tc, numsubst);
+ ast_verb(3, "Called %s\n", numsubst);
+- if (!ast_test_flag64(peerflags, OPT_ORIGINAL_CLID))
+- ast_set_callerid(tc, S_OR(chan->macroexten, chan->exten), get_cid_name(cidname, sizeof(cidname), chan), NULL);
++ ast_channel_unlock(chan);
++ if (!ast_test_flag64(peerflags, OPT_ORIGINAL_CLID)) {
++ ast_set_callerid(tc, tmpexten, get_cid_name(cidname, sizeof(cidname), chan), NULL);
++ }
+ }
+ /* Put them in the list of outgoing thingies... We're ready now.
+ XXX If we're forcibly removed, these outgoing calls won't get
+@@ -1849,7 +2028,7 @@
+ }
+ }
+
+- peer = wait_for_answer(chan, outgoing, &to, peerflags, &pa, &num, &result);
++ peer = wait_for_answer(chan, outgoing, &to, peerflags, &pa, &num, &result, dtmf_progress);
+
+ /* The ast_channel_datastore_remove() function could fail here if the
+ * datastore was moved to another channel during a masquerade. If this is
+@@ -2206,9 +2385,18 @@
+ }
+ ast_set2_flag(peer, autoloopflag, AST_FLAG_IN_AUTOLOOP); /* set it back the way it was */
+ }
+- if (!ast_check_hangup(peer) && ast_test_flag64(&opts, OPT_CALLEE_GO_ON) && !ast_strlen_zero(opt_args[OPT_ARG_CALLEE_GO_ON])) {
+- replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_GO_ON]);
+- ast_parseable_goto(peer, opt_args[OPT_ARG_CALLEE_GO_ON]);
++ if (!ast_check_hangup(peer) && ast_test_flag64(&opts, OPT_CALLEE_GO_ON)) {
++ if(!ast_strlen_zero(opt_args[OPT_ARG_CALLEE_GO_ON])) {
++ replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_GO_ON]);
++ ast_parseable_goto(peer, opt_args[OPT_ARG_CALLEE_GO_ON]);
++ } else { /* F() */
++ int res;
++ res = ast_goto_if_exists(peer, chan->context, chan->exten, (chan->priority) + 1);
++ if (res == AST_PBX_GOTO_FAILED) {
++ ast_hangup(peer);
++ goto out;
++ }
++ }
+ ast_pbx_start(peer);
+ } else {
+ if (!ast_check_hangup(chan))
+@@ -2249,7 +2437,7 @@
+ return res;
+ }
+
+-static int dial_exec(struct ast_channel *chan, void *data)
++static int dial_exec(struct ast_channel *chan, const char *data)
+ {
+ struct ast_flags64 peerflags;
+
+@@ -2258,7 +2446,7 @@
+ return dial_exec_full(chan, data, &peerflags, NULL);
+ }
+
+-static int retrydial_exec(struct ast_channel *chan, void *data)
++static int retrydial_exec(struct ast_channel *chan, const char *data)
+ {
+ char *parse;
+ const char *context = NULL;
+Index: apps/app_nbscat.c
+===================================================================
+--- a/apps/app_nbscat.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_nbscat.c (.../trunk) (revision 202568)
+@@ -105,7 +105,7 @@
+
+ }
+
+-static int NBScat_exec(struct ast_channel *chan, void *data)
++static int NBScat_exec(struct ast_channel *chan, const char *data)
+ {
+ int res=0;
+ int fds[2];
+Index: apps/app_page.c
+===================================================================
+--- a/apps/app_page.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_page.c (.../trunk) (revision 202568)
+@@ -99,15 +99,15 @@
+ </see-also>
+ </application>
+ ***/
+-static const char *app_page= "Page";
++static const char * const app_page= "Page";
+
+-enum {
++enum page_opt_flags {
+ PAGE_DUPLEX = (1 << 0),
+ PAGE_QUIET = (1 << 1),
+ PAGE_RECORD = (1 << 2),
+ PAGE_SKIP = (1 << 3),
+ PAGE_IGNORE_FORWARDS = (1 << 4),
+-} page_opt_flags;
++};
+
+ AST_APP_OPTIONS(page_opts, {
+ AST_APP_OPTION('d', PAGE_DUPLEX),
+@@ -118,7 +118,7 @@
+ });
+
+
+-static int page_exec(struct ast_channel *chan, void *data)
++static int page_exec(struct ast_channel *chan, const char *data)
+ {
+ char *tech, *resource, *tmp;
+ char meetmeopts[88], originator[AST_CHANNEL_NAME], *opts[0];
+Index: apps/app_echo.c
+===================================================================
+--- a/apps/app_echo.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_echo.c (.../trunk) (revision 202568)
+@@ -46,9 +46,9 @@
+ </application>
+ ***/
+
+-static char *app = "Echo";
++static const char app[] = "Echo";
+
+-static int echo_exec(struct ast_channel *chan, void *data)
++static int echo_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = -1;
+ int format;
+Index: apps/app_waitforsilence.c
+===================================================================
+--- a/apps/app_waitforsilence.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_waitforsilence.c (.../trunk) (revision 202568)
+@@ -202,7 +202,7 @@
+ return res;
+ }
+
+-static int waitfor_exec(struct ast_channel *chan, void *data, int wait_for_silence)
++static int waitfor_exec(struct ast_channel *chan, const char *data, int wait_for_silence)
+ {
+ int res = 1;
+ int timereqd = 1000;
+@@ -232,12 +232,12 @@
+ return res;
+ }
+
+-static int waitforsilence_exec(struct ast_channel *chan, void *data)
++static int waitforsilence_exec(struct ast_channel *chan, const char *data)
+ {
+ return waitfor_exec(chan, data, 1);
+ }
+
+-static int waitfornoise_exec(struct ast_channel *chan, void *data)
++static int waitfornoise_exec(struct ast_channel *chan, const char *data)
+ {
+ return waitfor_exec(chan, data, 0);
+ }
+Index: apps/app_sayunixtime.c
+===================================================================
+--- a/apps/app_sayunixtime.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_sayunixtime.c (.../trunk) (revision 202568)
+@@ -89,7 +89,7 @@
+ static char *app_sayunixtime = "SayUnixTime";
+ static char *app_datetime = "DateTime";
+
+-static int sayunixtime_exec(struct ast_channel *chan, void *data)
++static int sayunixtime_exec(struct ast_channel *chan, const char *data)
+ {
+ AST_DECLARE_APP_ARGS(args,
+ AST_APP_ARG(timeval);
+Index: apps/app_readexten.c
+===================================================================
+--- a/apps/app_readexten.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_readexten.c (.../trunk) (revision 202568)
+@@ -111,11 +111,11 @@
+ </function>
+ ***/
+
+-enum {
++enum readexten_option_flags {
+ OPT_SKIP = (1 << 0),
+ OPT_INDICATION = (1 << 1),
+ OPT_NOANSWER = (1 << 2),
+-} readexten_option_flags;
++};
+
+ AST_APP_OPTIONS(readexten_app_options, {
+ AST_APP_OPTION('s', OPT_SKIP),
+@@ -125,7 +125,7 @@
+
+ static char *app = "ReadExten";
+
+-static int readexten_exec(struct ast_channel *chan, void *data)
++static int readexten_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+ char exten[256] = "";
+Index: apps/app_dahdiras.c
+===================================================================
+--- a/apps/app_dahdiras.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_dahdiras.c (.../trunk) (revision 202568)
+@@ -73,7 +73,7 @@
+
+ ***/
+
+-static char *app = "DAHDIRAS";
++static const char app[] = "DAHDIRAS";
+
+ #define PPP_MAX_ARGS 32
+ #define PPP_EXEC "/usr/sbin/pppd"
+@@ -187,7 +187,7 @@
+ ast_safe_fork_cleanup();
+ }
+
+-static int dahdiras_exec(struct ast_channel *chan, void *data)
++static int dahdiras_exec(struct ast_channel *chan, const char *data)
+ {
+ int res=-1;
+ char *args;
+Index: apps/app_disa.c
+===================================================================
+--- a/apps/app_disa.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_disa.c (.../trunk) (revision 202568)
+@@ -110,12 +110,12 @@
+ </see-also>
+ </application>
+ ***/
+-static char *app = "DISA";
++static const char app[] = "DISA";
+
+ enum {
+ NOANSWER_FLAG = (1 << 0),
+ POUND_TO_END_FLAG = (1 << 1),
+-} option_flags;
++};
+
+ AST_APP_OPTIONS(app_opts, {
+ AST_APP_OPTION('n', NOANSWER_FLAG),
+@@ -140,7 +140,7 @@
+ }
+ }
+
+-static int disa_exec(struct ast_channel *chan, void *data)
++static int disa_exec(struct ast_channel *chan, const char *data)
+ {
+ int i = 0, j, k = 0, did_ignore = 0, special_noanswer = 0;
+ int firstdigittimeout = (chan->pbx ? chan->pbx->rtimeoutms : 20000);
+Index: apps/app_userevent.c
+===================================================================
+--- a/apps/app_userevent.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_userevent.c (.../trunk) (revision 202568)
+@@ -56,7 +56,7 @@
+
+ static char *app = "UserEvent";
+
+-static int userevent_exec(struct ast_channel *chan, void *data)
++static int userevent_exec(struct ast_channel *chan, const char *data)
+ {
+ char *parse;
+ int x;
+Index: apps/app_chanisavail.c
+===================================================================
+--- a/apps/app_chanisavail.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_chanisavail.c (.../trunk) (revision 202568)
+@@ -41,7 +41,7 @@
+ #include "asterisk/app.h"
+ #include "asterisk/devicestate.h"
+
+-static char *app = "ChanIsAvail";
++static const char app[] = "ChanIsAvail";
+
+ /*** DOCUMENTATION
+ <application name="ChanIsAvail" language="en_US">
+@@ -92,7 +92,7 @@
+ </application>
+ ***/
+
+-static int chanavail_exec(struct ast_channel *chan, void *data)
++static int chanavail_exec(struct ast_channel *chan, const char *data)
+ {
+ int inuse=-1, option_state=0, string_compare=0, option_all_avail=0;
+ int status;
+Index: apps/app_system.c
+===================================================================
+--- a/apps/app_system.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_system.c (.../trunk) (revision 202568)
+@@ -100,7 +100,7 @@
+
+ static char *chanvar = "SYSTEMSTATUS";
+
+-static int system_exec_helper(struct ast_channel *chan, void *data, int failmode)
++static int system_exec_helper(struct ast_channel *chan, const char *data, int failmode)
+ {
+ int res = 0;
+ struct ast_str *buf = ast_str_thread_get(&buf_buf, 16);
+@@ -140,12 +140,12 @@
+ return res;
+ }
+
+-static int system_exec(struct ast_channel *chan, void *data)
++static int system_exec(struct ast_channel *chan, const char *data)
+ {
+ return system_exec_helper(chan, data, -1);
+ }
+
+-static int trysystem_exec(struct ast_channel *chan, void *data)
++static int trysystem_exec(struct ast_channel *chan, const char *data)
+ {
+ return system_exec_helper(chan, data, 0);
+ }
+Index: apps/app_transfer.c
+===================================================================
+--- a/apps/app_transfer.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_transfer.c (.../trunk) (revision 202568)
+@@ -72,9 +72,9 @@
+ </application>
+ ***/
+
+-static const char *app = "Transfer";
++static const char * const app = "Transfer";
+
+-static int transfer_exec(struct ast_channel *chan, void *data)
++static int transfer_exec(struct ast_channel *chan, const char *data)
+ {
+ int res;
+ int len;
+Index: apps/app_playback.c
+===================================================================
+--- a/apps/app_playback.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_playback.c (.../trunk) (revision 202568)
+@@ -90,8 +90,8 @@
+ * 'say load [new|old]' will enable the new or old method, or report status
+ */
+ static const void *say_api_buf[40];
+-static const char *say_old = "old";
+-static const char *say_new = "new";
++static const char * const say_old = "old";
++static const char * const say_new = "new";
+
+ static void save_say_mode(const void *arg)
+ {
+@@ -380,7 +380,7 @@
+ static char *__say_cli_init(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+ {
+ const char *old_mode = say_api_buf[0] ? say_new : say_old;
+- char *mode;
++ const char *mode;
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "say load [new|old]";
+@@ -415,7 +415,7 @@
+ AST_CLI_DEFINE(__say_cli_init, "Set or show the say mode"),
+ };
+
+-static int playback_exec(struct ast_channel *chan, void *data)
++static int playback_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+ int mres = 0;
+Index: apps/app_speech_utils.c
+===================================================================
+--- a/apps/app_speech_utils.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_speech_utils.c (.../trunk) (revision 202568)
+@@ -481,7 +481,7 @@
+
+
+ /*! \brief SpeechCreate() Dialplan Application */
+-static int speech_create(struct ast_channel *chan, void *data)
++static int speech_create(struct ast_channel *chan, const char *data)
+ {
+ struct ast_speech *speech = NULL;
+ struct ast_datastore *datastore = NULL;
+@@ -508,7 +508,7 @@
+ }
+
+ /*! \brief SpeechLoadGrammar(Grammar Name,Path) Dialplan Application */
+-static int speech_load(struct ast_channel *chan, void *vdata)
++static int speech_load(struct ast_channel *chan, const char *vdata)
+ {
+ int res = 0;
+ struct ast_speech *speech = find_speech(chan);
+@@ -534,7 +534,7 @@
+ }
+
+ /*! \brief SpeechUnloadGrammar(Grammar Name) Dialplan Application */
+-static int speech_unload(struct ast_channel *chan, void *data)
++static int speech_unload(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+ struct ast_speech *speech = find_speech(chan);
+@@ -549,7 +549,7 @@
+ }
+
+ /*! \brief SpeechDeactivateGrammar(Grammar Name) Dialplan Application */
+-static int speech_deactivate(struct ast_channel *chan, void *data)
++static int speech_deactivate(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+ struct ast_speech *speech = find_speech(chan);
+@@ -564,7 +564,7 @@
+ }
+
+ /*! \brief SpeechActivateGrammar(Grammar Name) Dialplan Application */
+-static int speech_activate(struct ast_channel *chan, void *data)
++static int speech_activate(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+ struct ast_speech *speech = find_speech(chan);
+@@ -579,7 +579,7 @@
+ }
+
+ /*! \brief SpeechStart() Dialplan Application */
+-static int speech_start(struct ast_channel *chan, void *data)
++static int speech_start(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+ struct ast_speech *speech = find_speech(chan);
+@@ -593,7 +593,7 @@
+ }
+
+ /*! \brief SpeechProcessingSound(Sound File) Dialplan Application */
+-static int speech_processing_sound(struct ast_channel *chan, void *data)
++static int speech_processing_sound(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+ struct ast_speech *speech = find_speech(chan);
+@@ -636,7 +636,7 @@
+ END_OPTIONS );
+
+ /*! \brief SpeechBackground(Sound File,Timeout) Dialplan Application */
+-static int speech_background(struct ast_channel *chan, void *data)
++static int speech_background(struct ast_channel *chan, const char *data)
+ {
+ unsigned int timeout = 0;
+ int res = 0, done = 0, started = 0, quieted = 0, max_dtmf_len = 0;
+@@ -888,7 +888,7 @@
+
+
+ /*! \brief SpeechDestroy() Dialplan Application */
+-static int speech_destroy(struct ast_channel *chan, void *data)
++static int speech_destroy(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+ struct ast_speech *speech = find_speech(chan);
+Index: apps/app_osplookup.c
+===================================================================
+--- a/apps/app_osplookup.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_osplookup.c (.../trunk) (revision 202568)
+@@ -39,6 +39,7 @@
+
+ #include <osp/osp.h>
+ #include <osp/osputils.h>
++#include <osp/ospb64.h>
+
+ #include "asterisk/paths.h"
+ #include "asterisk/lock.h"
+@@ -52,9 +53,162 @@
+ #include "asterisk/cli.h"
+ #include "asterisk/astosp.h"
+
++/*** DOCUMENTATION
++ <application name="OSPAuth" language="en_US">
++ <synopsis>
++ OSP Authentication.
++ </synopsis>
++ <syntax>
++ <parameter name="provider" />
++ <parameter name="options" />
++ </syntax>
++ <description>
++ <para>Authenticate a SIP INVITE by OSP and sets the variables:</para>
++ <variablelist>
++ <variable name="OSPINHANDLE">
++ <para>The inbound call transaction handle.</para>
++ </variable>
++ <variable name="OSPINTIMELIMIT">
++ <para>The inbound call duration limit in seconds.</para>
++ </variable>
++ </variablelist>
++ <para>This application sets the following channel variable upon completion:</para>
++ <variablelist>
++ <variable name="OSPAUTHSTATUS">
++ <para>The status of the OSP Auth attempt as a text string, one of</para>
++ <value name="SUCCESS" />
++ <value name="FAILED" />
++ <value name="ERROR" />
++ </variable>
++ </variablelist>
++ </description>
++ </application>
++ <application name="OSPLookup" language="en_US">
++ <synopsis>
++ Lookup destination by OSP.
++ </synopsis>
++ <syntax>
++ <parameter name="exten" required="true" />
++ <parameter name="provider" />
++ <parameter name="options">
++ <enumlist>
++ <enum name="h">
++ <para>generate H323 call id for the outbound call</para>
++ </enum>
++ <enum name="s">
++ <para>generate SIP call id for the outbound call.
++ Have not been implemented</para>
++ </enum>
++ <enum name="i">
++ <para>generate IAX call id for the outbound call.
++ Have not been implemented</para>
++ </enum>
++ </enumlist>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Looks up an extension via OSP and sets the variables, where <literal>n</literal> is the
++ number of the result beginning with <literal>1</literal>:</para>
++ <variablelist>
++ <variable name="OSPOUTHANDLE">
++ <para>The OSP Handle for anything remaining.</para>
++ </variable>
++ <variable name="OSPTECH">
++ <para>The technology to use for the call.</para>
++ </variable>
++ <variable name="OSPDEST">
++ <para>The destination to use for the call.</para>
++ </variable>
++ <variable name="OSPCALLED">
++ <para>The called number to use for the call.</para>
++ </variable>
++ <variable name="OSPCALLING">
++ <para>The calling number to use for the call.</para>
++ </variable>
++ <variable name="OSPDIALSTR">
++ <para>The dial command string.</para>
++ </variable>
++ <variable name="OSPOUTTOKEN">
++ <para>The actual OSP token as a string.</para>
++ </variable>
++ <variable name="OSPOUTTIMELIMIT">
++ <para>The outbound call duraction limit in seconds.</para>
++ </variable>
++ <variable name="OSPOUTCALLIDTYPES">
++ <para>The outbound call id types.</para>
++ </variable>
++ <variable name="OSPOUTCALLID">
++ <para>The outbound call id.</para>
++ </variable>
++ <variable name="OSPRESULTS">
++ <para>The number of OSP results total remaining.</para>
++ </variable>
++ </variablelist>
++ <variablelist>
++ <variable name="OSPLOOKUPSTATUS">
++ <para>This application sets the following channel variable upon completion:</para>
++ <value name="SUCCESS" />
++ <value name="FAILED" />
++ <value name="ERROR" />
++ </variable>
++ </variablelist>
++ </description>
++ </application>
++ <application name="OSPNext" language="en_US">
++ <synopsis>
++ Lookup next destination by OSP.
++ </synopsis>
++ <syntax>
++ <parameter name="cause" required="true" />
++ <parameter name="provider" />
++ <parameter name="options" />
++ </syntax>
++ <description>
++ <para>Looks up the next OSP Destination for <variable>OSPOUTHANDLE</variable>.</para>
++ <para>This application sets the following channel variable upon completion:</para>
++ <variablelist>
++ <variable name="OSPNEXTSTATUS">
++ <para>The status of the OSP Next attempt as a text string, one of</para>
++ <value name="SUCCESS" />
++ <value name="FAILED" />
++ <value name="ERROR" />
++ </variable>
++ </variablelist>
++ </description>
++ <see-also>
++ <ref type="application">OSPLookup</ref>
++ </see-also>
++ </application>
++ <application name="OSPFinish" language="en_US">
++ <synopsis>
++ Record OSP entry.
++ </synopsis>
++ <syntax>
++ <parameter name="status" />
++ <parameter name="options" />
++ </syntax>
++ <description>
++ <para>Records call state for <variable>OSPINHANDLE</variable>, according to status, which should
++ be one of <literal>BUSY</literal>, <literal>CONGESTION</literal>, <literal>ANSWER</literal>,
++ <literal>NOANSWER</literal>, or <literal>CHANUNAVAIL</literal> or coincidentally, just what the
++ Dial application stores in its <variable>DIALSTATUS</variable>.</para>
++ <para>This application sets the following channel variable upon completion:</para>
++ <variablelist>
++ <variable name="OSPFINISHSTATUS">
++ <para>The status of the OSP Finish attempt as a text string, one of</para>
++ <value name="SUCCESS" />
++ <value name="FAILED" />
++ <value name="ERROR" />
++ </variable>
++ </variablelist>
++ </description>
++ </application>
++ ***/
++
+ /* OSP Buffer Sizes */
+ #define OSP_INTSTR_SIZE ((unsigned int)16) /* OSP signed/unsigned int string buffer size */
+ #define OSP_NORSTR_SIZE ((unsigned int)256) /* OSP normal string buffer size */
++#define OSP_KEYSTR_SIZE ((unsigned int)1024) /* OSP certificate string buffer size */
+ #define OSP_TOKSTR_SIZE ((unsigned int)4096) /* OSP token string buffer size */
+ #define OSP_TECHSTR_SIZE ((unsigned int)32) /* OSP signed/unsigned int string buffer size */
+ #define OSP_UUID_SIZE ((unsigned int)16) /* UUID size */
+@@ -127,7 +281,7 @@
+ char privatekey[OSP_NORSTR_SIZE]; /* OSP private key file name */
+ char localcert[OSP_NORSTR_SIZE]; /* OSP local cert file name */
+ unsigned int cacount; /* Number of cacerts */
+- char cacerts[OSP_MAX_CERTS][OSP_NORSTR_SIZE]; /* Cacert file names */
++ char cacerts[OSP_MAX_CERTS][OSP_NORSTR_SIZE]; /* Cacert file names */
+ unsigned int spcount; /* Number of service points */
+ char srvpoints[OSP_MAX_SRVS][OSP_NORSTR_SIZE]; /* Service point URLs */
+ int maxconnections; /* Max number of connections */
+@@ -167,9 +321,15 @@
+ AST_MUTEX_DEFINE_STATIC(osplock); /* Lock of OSP provider list */
+ static int osp_initialized = 0; /* Init flag */
+ static int osp_hardware = 0; /* Hardware accelleration flag */
++static int osp_security = 0; /* Using security features flag */
+ static struct osp_provider* ospproviders = NULL; /* OSP provider list */
+ static unsigned int osp_tokenformat = TOKEN_ALGO_SIGNED; /* Token format supported */
+
++/* OSP default certificates */
++const char* B64PKey = "MIIBOgIBAAJBAK8t5l+PUbTC4lvwlNxV5lpl+2dwSZGW46dowTe6y133XyVEwNiiRma2YNk3xKs/TJ3Wl9Wpns2SYEAJsFfSTukCAwEAAQJAPz13vCm2GmZ8Zyp74usTxLCqSJZNyMRLHQWBM0g44Iuy4wE3vpi7Wq+xYuSOH2mu4OddnxswCP4QhaXVQavTAQIhAOBVCKXtppEw9UaOBL4vW0Ed/6EA/1D8hDW6St0h7EXJAiEAx+iRmZKhJD6VT84dtX5ZYNVk3j3dAcIOovpzUj9a0CECIEduTCapmZQ5xqAEsLXuVlxRtQgLTUD4ZxDElPn8x0MhAiBE2HlcND0+qDbvtwJQQOUzDgqg5xk3w8capboVdzAlQQIhAMC+lDL7+gDYkNAft5Mu+NObJmQs4Cr+DkDFsKqoxqrm";
++const char* B64LCert = "MIIBeTCCASMCEHqkOHVRRWr+1COq3CR/xsowDQYJKoZIhvcNAQEEBQAwOzElMCMGA1UEAxMcb3NwdGVzdHNlcnZlci50cmFuc25leHVzLmNvbTESMBAGA1UEChMJT1NQU2VydmVyMB4XDTA1MDYyMzAwMjkxOFoXDTA2MDYyNDAwMjkxOFowRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCvLeZfj1G0wuJb8JTcVeZaZftncEmRluOnaME3ustd918lRMDYokZmtmDZN8SrP0yd1pfVqZ7NkmBACbBX0k7pAgMBAAEwDQYJKoZIhvcNAQEEBQADQQDnV8QNFVVJx/+7IselU0wsepqMurivXZzuxOmTEmTVDzCJx1xhA8jd3vGAj7XDIYiPub1PV23eY5a2ARJuw5w9";
++const char* B64CACert = "MIIBYDCCAQoCAQEwDQYJKoZIhvcNAQEEBQAwOzElMCMGA1UEAxMcb3NwdGVzdHNlcnZlci50cmFuc25leHVzLmNvbTESMBAGA1UEChMJT1NQU2VydmVyMB4XDTAyMDIwNDE4MjU1MloXDTEyMDIwMzE4MjU1MlowOzElMCMGA1UEAxMcb3NwdGVzdHNlcnZlci50cmFuc25leHVzLmNvbTESMBAGA1UEChMJT1NQU2VydmVyMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAPGeGwV41EIhX0jEDFLRXQhDEr50OUQPq+f55VwQd0TQNts06BP29+UiNdRW3c3IRHdZcJdC1Cg68ME9cgeq0h8CAwEAATANBgkqhkiG9w0BAQQFAANBAGkzBSj1EnnmUxbaiG1N4xjIuLAWydun7o3bFk2tV8dBIhnuh445obYyk1EnQ27kI7eACCILBZqi2MHDOIMnoN0=";
++
+ /* OSP Client Wrapper APIs */
+
+ /*!
+@@ -190,7 +350,10 @@
+ OSPT_CERT cacerts[OSP_MAX_CERTS];
+ const OSPT_CERT* pcacerts[OSP_MAX_CERTS];
+ const char* psrvpoints[OSP_MAX_SRVS];
+- int t, i, j, error = OSPC_ERR_NO_ERROR;
++ unsigned char privatekeydata[OSP_KEYSTR_SIZE];
++ unsigned char localcertdata[OSP_KEYSTR_SIZE];
++ unsigned char cacertdata[OSP_KEYSTR_SIZE];
++ int i, t, error = OSPC_ERR_NO_ERROR;
+
+ if (!(p = ast_calloc(1, sizeof(*p)))) {
+ ast_log(LOG_ERROR, "Out of memory\n");
+@@ -213,30 +376,36 @@
+ v = ast_variable_browse(cfg, provider);
+ while(v) {
+ if (!strcasecmp(v->name, "privatekey")) {
+- if (v->value[0] == '/') {
+- ast_copy_string(p->privatekey, v->value, sizeof(p->privatekey));
+- } else {
+- snprintf(p->privatekey, sizeof(p->privatekey), "%s/%s", ast_config_AST_KEY_DIR, v->value);
++ if (osp_security) {
++ if (v->value[0] == '/') {
++ ast_copy_string(p->privatekey, v->value, sizeof(p->privatekey));
++ } else {
++ snprintf(p->privatekey, sizeof(p->privatekey), "%s/%s", ast_config_AST_KEY_DIR, v->value);
++ }
++ ast_debug(1, "OSP: privatekey '%s'\n", p->privatekey);
+ }
+- ast_debug(1, "OSP: privatekey '%s'\n", p->privatekey);
+ } else if (!strcasecmp(v->name, "localcert")) {
+- if (v->value[0] == '/') {
+- ast_copy_string(p->localcert, v->value, sizeof(p->localcert));
+- } else {
+- snprintf(p->localcert, sizeof(p->localcert), "%s/%s", ast_config_AST_KEY_DIR, v->value);
++ if (osp_security) {
++ if (v->value[0] == '/') {
++ ast_copy_string(p->localcert, v->value, sizeof(p->localcert));
++ } else {
++ snprintf(p->localcert, sizeof(p->localcert), "%s/%s", ast_config_AST_KEY_DIR, v->value);
++ }
++ ast_debug(1, "OSP: localcert '%s'\n", p->localcert);
+ }
+- ast_debug(1, "OSP: localcert '%s'\n", p->localcert);
+ } else if (!strcasecmp(v->name, "cacert")) {
+- if (p->cacount < OSP_MAX_CERTS) {
+- if (v->value[0] == '/') {
+- ast_copy_string(p->cacerts[p->cacount], v->value, sizeof(p->cacerts[0]));
++ if (osp_security) {
++ if (p->cacount < OSP_MAX_CERTS) {
++ if (v->value[0] == '/') {
++ ast_copy_string(p->cacerts[p->cacount], v->value, sizeof(p->cacerts[0]));
++ } else {
++ snprintf(p->cacerts[p->cacount], sizeof(p->cacerts[0]), "%s/%s", ast_config_AST_KEY_DIR, v->value);
++ }
++ ast_debug(1, "OSP: cacerts[%d]: '%s'\n", p->cacount, p->cacerts[p->cacount]);
++ p->cacount++;
+ } else {
+- snprintf(p->cacerts[p->cacount], sizeof(p->cacerts[0]), "%s/%s", ast_config_AST_KEY_DIR, v->value);
++ ast_log(LOG_WARNING, "OSP: Too many CA Certificates at line %d\n", v->lineno);
+ }
+- ast_debug(1, "OSP: cacert[%d]: '%s'\n", p->cacount, p->cacerts[p->cacount]);
+- p->cacount++;
+- } else {
+- ast_log(LOG_WARNING, "OSP: Too many CA Certificates at line %d\n", v->lineno);
+ }
+ } else if (!strcasecmp(v->name, "servicepoint")) {
+ if (p->spcount < OSP_MAX_SRVS) {
+@@ -307,96 +476,110 @@
+ v = v->next;
+ }
+
+- error = OSPPUtilLoadPEMPrivateKey((unsigned char*)p->privatekey, &privatekey);
+- if (error != OSPC_ERR_NO_ERROR) {
+- ast_log(LOG_WARNING, "OSP: Unable to load privatekey '%s', error '%d'\n", p->privatekey, error);
+- ast_free(p);
+- return 0;
++ if (p->cacount == 0) {
++ p->cacount = 1;
+ }
+
+- error = OSPPUtilLoadPEMCert((unsigned char*)p->localcert, &localcert);
+- if (error != OSPC_ERR_NO_ERROR) {
+- ast_log(LOG_WARNING, "OSP: Unable to load localcert '%s', error '%d'\n", p->localcert, error);
+- if (privatekey.PrivateKeyData) {
+- ast_free(privatekey.PrivateKeyData);
+- }
+- ast_free(p);
+- return 0;
++ for (i = 0; i < p->spcount; i++) {
++ psrvpoints[i] = p->srvpoints[i];
+ }
+
+- if (p->cacount < 1) {
+- snprintf(p->cacerts[p->cacount], sizeof(p->cacerts[0]), "%s/%s-cacert.pem", ast_config_AST_KEY_DIR, provider);
+- ast_debug(1, "OSP: cacert[%d]: '%s'\n", p->cacount, p->cacerts[p->cacount]);
+- p->cacount++;
+- }
+- for (i = 0; i < p->cacount; i++) {
+- error = OSPPUtilLoadPEMCert((unsigned char*)p->cacerts[i], &cacerts[i]);
+- if (error != OSPC_ERR_NO_ERROR) {
+- ast_log(LOG_WARNING, "OSP: Unable to load cacert '%s', error '%d'\n", p->cacerts[i], error);
+- for (j = 0; j < i; j++) {
+- if (cacerts[j].CertData) {
+- ast_free(cacerts[j].CertData);
++ if (osp_security) {
++ privatekey.PrivateKeyData = NULL;
++ privatekey.PrivateKeyLength = 0;
++
++ localcert.CertData = NULL;
++ localcert.CertDataLength = 0;
++
++ for (i = 0; i < p->cacount; i++) {
++ cacerts[i].CertData = NULL;
++ cacerts[i].CertDataLength = 0;
++ }
++
++ if ((error = OSPPUtilLoadPEMPrivateKey((unsigned char*)p->privatekey, &privatekey)) != OSPC_ERR_NO_ERROR) {
++ ast_log(LOG_WARNING, "OSP: Unable to load privatekey '%s', error '%d'\n", p->privatekey, error);
++ } else if ((error = OSPPUtilLoadPEMCert((unsigned char*)p->localcert, &localcert)) != OSPC_ERR_NO_ERROR) {
++ ast_log(LOG_WARNING, "OSP: Unable to load localcert '%s', error '%d'\n", p->localcert, error);
++ } else {
++ for (i = 0; i < p->cacount; i++) {
++ if ((error = OSPPUtilLoadPEMCert((unsigned char*)p->cacerts[i], &cacerts[i])) != OSPC_ERR_NO_ERROR) {
++ ast_log(LOG_WARNING, "OSP: Unable to load cacert '%s', error '%d'\n", p->cacerts[i], error);
++ break;
++ } else {
++ pcacerts[i] = &cacerts[i];
+ }
+ }
+- if (localcert.CertData) {
+- ast_free(localcert.CertData);
+- }
+- if (privatekey.PrivateKeyData) {
+- ast_free(privatekey.PrivateKeyData);
+- }
+- ast_free(p);
+- return 0;
+ }
+- pcacerts[i] = &cacerts[i];
+- }
++ } else {
++ privatekey.PrivateKeyData = privatekeydata;
++ privatekey.PrivateKeyLength = sizeof(privatekeydata);
+
+- for (i = 0; i < p->spcount; i++) {
+- psrvpoints[i] = p->srvpoints[i];
++ localcert.CertData = localcertdata;
++ localcert.CertDataLength = sizeof(localcertdata);
++
++ cacerts[0].CertData = cacertdata;
++ cacerts[0].CertDataLength = sizeof(cacertdata);
++ pcacerts[0] = &cacerts[0];
++
++ if ((error = OSPPBase64Decode(B64PKey, strlen(B64PKey), privatekey.PrivateKeyData, &privatekey.PrivateKeyLength)) != OSPC_ERR_NO_ERROR) {
++ ast_log(LOG_WARNING, "OSP: Unable to decode private key, error '%d'\n", error);
++ } else if ((error = OSPPBase64Decode(B64LCert, strlen(B64LCert), localcert.CertData, &localcert.CertDataLength)) != OSPC_ERR_NO_ERROR) {
++ ast_log(LOG_WARNING, "OSP: Unable to decode local cert, error '%d'\n", error);
++ } else if ((error = OSPPBase64Decode(B64CACert, strlen(B64CACert), cacerts[0].CertData, &cacerts[0].CertDataLength)) != OSPC_ERR_NO_ERROR) {
++ ast_log(LOG_WARNING, "OSP: Unable to decode cacert, error '%d'\n", error);
++ }
+ }
+
+- error = OSPPProviderNew(
+- p->spcount,
+- psrvpoints,
+- NULL,
+- OSP_AUDIT_URL,
+- &privatekey,
+- &localcert,
+- p->cacount,
+- pcacerts,
+- OSP_LOCAL_VALIDATION,
+- OSP_SSL_LIFETIME,
+- p->maxconnections,
+- OSP_HTTP_PERSISTENCE,
+- p->retrydelay,
+- p->retrylimit,
+- p->timeout,
+- OSP_CUSTOMER_ID,
+- OSP_DEVICE_ID,
+- &p->handle);
+- if (error != OSPC_ERR_NO_ERROR) {
+- ast_log(LOG_WARNING, "OSP: Unable to create provider '%s', error '%d'\n", provider, error);
+- ast_free(p);
+- res = -1;
+- } else {
+- ast_debug(1, "OSP: provider '%s'\n", provider);
+- ast_mutex_lock(&osplock);
+- p->next = ospproviders;
+- ospproviders = p;
+- ast_mutex_unlock(&osplock);
+- res = 1;
++ if (error == OSPC_ERR_NO_ERROR) {
++ error = OSPPProviderNew(
++ p->spcount,
++ psrvpoints,
++ NULL,
++ OSP_AUDIT_URL,
++ &privatekey,
++ &localcert,
++ p->cacount,
++ pcacerts,
++ OSP_LOCAL_VALIDATION,
++ OSP_SSL_LIFETIME,
++ p->maxconnections,
++ OSP_HTTP_PERSISTENCE,
++ p->retrydelay,
++ p->retrylimit,
++ p->timeout,
++ OSP_CUSTOMER_ID,
++ OSP_DEVICE_ID,
++ &p->handle);
++ if (error != OSPC_ERR_NO_ERROR) {
++ ast_log(LOG_WARNING, "OSP: Unable to create provider '%s', error '%d'\n", provider, error);
++ res = -1;
++ } else {
++ ast_debug(1, "OSP: provider '%s'\n", provider);
++ ast_mutex_lock(&osplock);
++ p->next = ospproviders;
++ ospproviders = p;
++ ast_mutex_unlock(&osplock);
++ res = 1;
++ }
+ }
+
+- for (i = 0; i < p->cacount; i++) {
+- if (cacerts[i].CertData) {
+- ast_free(cacerts[i].CertData);
++ if (osp_security) {
++ for (i = 0; i < p->cacount; i++) {
++ if (cacerts[i].CertData) {
++ ast_free(cacerts[i].CertData);
++ }
+ }
++ if (localcert.CertData) {
++ ast_free(localcert.CertData);
++ }
++ if (privatekey.PrivateKeyData) {
++ ast_free(privatekey.PrivateKeyData);
++ }
+ }
+- if (localcert.CertData) {
+- ast_free(localcert.CertData);
++
++ if (res != 1) {
++ ast_free(p);
+ }
+- if (privatekey.PrivateKeyData) {
+- ast_free(privatekey.PrivateKeyData);
+- }
+
+ return res;
+ }
+@@ -849,6 +1032,8 @@
+ * \param srcdev Source device of outbound call
+ * \param calling Calling number
+ * \param called Called number
++ * \param snetid Source network ID
++ * \param rnumber Routing number
+ * \param callidtypes Call ID types
+ * \param result Lookup results
+ * \return 1 Found , 0 No route, -1 Error
+@@ -858,6 +1043,8 @@
+ const char* srcdev,
+ const char* calling,
+ const char* called,
++ const char* snetid,
++ const char* rnumber,
+ unsigned int callidtypes,
+ struct osp_result* result)
+ {
+@@ -903,6 +1090,14 @@
+ return -1;
+ }
+
++ if (!ast_strlen_zero(snetid)) {
++ OSPPTransactionSetNetworkIds(result->outhandle, snetid, "");
++ }
++
++ if (!ast_strlen_zero(rnumber)) {
++ OSPPTransactionSetRoutingNumber(result->outhandle, rnumber);
++ }
++
+ callidnum = 0;
+ callids[0] = NULL;
+ for (i = 0; i < OSP_CALLID_MAXNUM; i++) {
+@@ -1253,8 +1448,8 @@
+ * \return 0 Success, -1 Failed
+ */
+ static int ospauth_exec(
+- struct ast_channel* chan,
+- void* data)
++ struct ast_channel *chan,
++ const char *data)
+ {
+ int res;
+ const char* provider = OSP_DEF_PROVIDER;
+@@ -1334,7 +1529,7 @@
+ */
+ static int osplookup_exec(
+ struct ast_channel* chan,
+- void* data)
++ const char * data)
+ {
+ int res, cres;
+ const char* provider = OSP_DEF_PROVIDER;
+@@ -1342,6 +1537,7 @@
+ struct ast_var_t* current;
+ const char* srcdev = "";
+ const char* snetid = "";
++ const char* rnumber = "";
+ char buffer[OSP_TOKSTR_SIZE];
+ unsigned int callidtypes = OSP_CALLID_UNDEFINED;
+ struct osp_result result;
+@@ -1401,6 +1597,8 @@
+ }
+ } else if (!strcasecmp(ast_var_name(current), "OSPINNETWORKID")) {
+ snetid = ast_var_value(current);
++ } else if (!strcasecmp(ast_var_name(current), "OSPROUTINGNUMBER")) {
++ rnumber = ast_var_value(current);
+ } else if (!strcasecmp(ast_var_name(current), "OSPPEERIP")) {
+ srcdev = ast_var_value(current);
+ }
+@@ -1408,13 +1606,14 @@
+ ast_debug(1, "OSPLookup: OSPINHANDLE '%d'\n", result.inhandle);
+ ast_debug(1, "OSPLookup: OSPINTIMELIMIT '%d'\n", result.intimelimit);
+ ast_debug(1, "OSPLookup: OSPINNETWORKID '%s'\n", snetid);
++ ast_debug(1, "OSPLookup: OSPROUTINGNUMBER '%s'\n", rnumber);
+ ast_debug(1, "OSPLookup: source device '%s'\n", srcdev);
+
+ if ((cres = ast_autoservice_start(chan)) < 0) {
+ return -1;
+ }
+
+- if ((res = osp_lookup(provider, srcdev, chan->cid.cid_num, args.exten, callidtypes, &result)) > 0) {
++ if ((res = osp_lookup(provider, srcdev, chan->cid.cid_num, args.exten, snetid, rnumber, callidtypes, &result)) > 0) {
+ status = AST_OSP_SUCCESS;
+ } else {
+ result.tech[0] = '\0';
+@@ -1445,6 +1644,8 @@
+ ast_debug(1, "OSPLookup: OSPCALLED '%s'\n", result.called);
+ pbx_builtin_setvar_helper(chan, "OSPCALLING", result.calling);
+ ast_debug(1, "OSPLookup: OSPCALLING '%s'\n", result.calling);
++ pbx_builtin_setvar_helper(chan, "OSPOUTNETWORKID", result.networkid);
++ ast_debug(1, "OSPLookup: OSPOUTNETWORKID '%s'\n", result.networkid);
+ pbx_builtin_setvar_helper(chan, "OSPOUTTOKEN", result.token);
+ ast_debug(1, "OSPLookup: OSPOUTTOKEN size '%zd'\n", strlen(result.token));
+ snprintf(buffer, sizeof(buffer), "%d", result.numresults);
+@@ -1502,7 +1703,7 @@
+ */
+ static int ospnext_exec(
+ struct ast_channel* chan,
+- void* data)
++ const char * data)
+ {
+ int res;
+ const char* provider = OSP_DEF_PROVIDER;
+@@ -1606,6 +1807,8 @@
+ ast_debug(1, "OSPNext: OSPCALLED'%s'\n", result.called);
+ pbx_builtin_setvar_helper(chan, "OSPCALLING", result.calling);
+ ast_debug(1, "OSPNext: OSPCALLING '%s'\n", result.calling);
++ pbx_builtin_setvar_helper(chan, "OSPOUTNETWORKID", result.networkid);
++ ast_debug(1, "OSPLookup: OSPOUTNETWORKID '%s'\n", result.networkid);
+ pbx_builtin_setvar_helper(chan, "OSPOUTTOKEN", result.token);
+ ast_debug(1, "OSPNext: OSPOUTTOKEN size '%zd'\n", strlen(result.token));
+ snprintf(buffer, sizeof(buffer), "%d", result.numresults);
+@@ -1656,7 +1859,7 @@
+ */
+ static int ospfinished_exec(
+ struct ast_channel* chan,
+- void* data)
++ const char * data)
+ {
+ int res = 1;
+ int cause = 0;
+@@ -1801,6 +2004,12 @@
+ }
+ ast_debug(1, "OSP: osp_hardware '%d'\n", osp_hardware);
+
++ t = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "securityfeatures");
++ if (t && ast_true(t)) {
++ osp_security = 1;
++ }
++ ast_debug(1, "OSP: osp_security '%d'\n", osp_security);
++
+ t = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "tokenformat");
+ if (t) {
+ if ((sscanf(t, "%d", &v) == 1) &&
+@@ -1854,6 +2063,7 @@
+ OSPPCleanup();
+
+ osp_tokenformat = TOKEN_ALGO_SIGNED;
++ osp_security = 0;
+ osp_hardware = 0;
+ osp_initialized = 0;
+ }
+@@ -1896,8 +2106,11 @@
+ tokenalgo = "Signed";
+ break;
+ }
+- ast_cli(a->fd, "OSP: %s %s %s\n",
+- osp_initialized ? "Initialized" : "Uninitialized", osp_hardware ? "Accelerated" : "Normal", tokenalgo);
++ ast_cli(a->fd, "OSP: %s/%s/%s/%s\n",
++ osp_initialized ? "Initialized" : "Uninitialized",
++ osp_hardware ? "Accelerated" : "Normal",
++ osp_security ? "Enabled" : "Disabled",
++ tokenalgo);
+ }
+
+ ast_mutex_lock(&osplock);
+@@ -1908,10 +2121,12 @@
+ ast_cli(a->fd, "\n");
+ }
+ ast_cli(a->fd, " == OSP Provider '%s' == \n", p->name);
+- ast_cli(a->fd, "Local Private Key: %s\n", p->privatekey);
+- ast_cli(a->fd, "Local Certificate: %s\n", p->localcert);
+- for (i = 0; i < p->cacount; i++) {
+- ast_cli(a->fd, "CA Certificate %d: %s\n", i + 1, p->cacerts[i]);
++ if (osp_security) {
++ ast_cli(a->fd, "Local Private Key: %s\n", p->privatekey);
++ ast_cli(a->fd, "Local Certificate: %s\n", p->localcert);
++ for (i = 0; i < p->cacount; i++) {
++ ast_cli(a->fd, "CA Certificate %d: %s\n", i + 1, p->cacerts[i]);
++ }
+ }
+ for (i = 0; i < p->spcount; i++) {
+ ast_cli(a->fd, "Service Point %d: %s\n", i + 1, p->srvpoints[i]);
+@@ -1940,63 +2155,17 @@
+ return CLI_SUCCESS;
+ }
+
+-static const char* app1= "OSPAuth";
+-static const char* synopsis1 = "OSP authentication";
+-static const char* descrip1 =
+-" OSPAuth([provider[,options]]): Authenticate a SIP INVITE by OSP and sets\n"
+-"the variables:\n"
+-" ${OSPINHANDLE}: The inbound call transaction handle\n"
+-" ${OSPINTIMELIMIT}: The inbound call duration limit in seconds\n"
+-"\n"
+-"This application sets the following channel variable upon completion:\n"
+-" OSPAUTHSTATUS The status of the OSP Auth attempt as a text string, one of\n"
+-" SUCCESS | FAILED | ERROR\n";
++/* OSPAuth() dialplan application */
++static const char app1[] = "OSPAuth";
+
+-static const char* app2= "OSPLookup";
+-static const char* synopsis2 = "Lookup destination by OSP";
+-static const char* descrip2 =
+-" OSPLookup(exten[,provider[,options]]): Looks up an extension via OSP and sets\n"
+-"the variables, where 'n' is the number of the result beginning with 1:\n"
+-" ${OSPOUTHANDLE}: The OSP Handle for anything remaining\n"
+-" ${OSPTECH}: The technology to use for the call\n"
+-" ${OSPDEST}: The destination to use for the call\n"
+-" ${OSPCALLED}: The called number to use for the call\n"
+-" ${OSPCALLING}: The calling number to use for the call\n"
+-" ${OSPDIALSTR}: The dial command string\n"
+-" ${OSPOUTTOKEN}: The actual OSP token as a string\n"
+-" ${OSPOUTTIMELIMIT}: The outbound call duration limit in seconds\n"
+-" ${OSPOUTCALLIDTYPES}: The outbound call id types\n"
+-" ${OSPOUTCALLID}: The outbound call id\n"
+-" ${OSPRESULTS}: The number of OSP results total remaining\n"
+-"\n"
+-"The option string may contain the following character:\n"
+-" 'h' -- generate H323 call id for the outbound call\n"
+-" 's' -- generate SIP call id for the outbound call. Have not been implemented\n"
+-" 'i' -- generate IAX call id for the outbound call. Have not been implemented\n"
+-"This application sets the following channel variable upon completion:\n"
+-" OSPLOOKUPSTATUS The status of the OSP Lookup attempt as a text string, one of\n"
+-" SUCCESS | FAILED | ERROR\n";
++/* OSPLookup() dialplan application */
++static const char app2[] = "OSPLookup";
+
+-static const char* app3 = "OSPNext";
+-static const char* synopsis3 = "Lookup next destination by OSP";
+-static const char* descrip3 =
+-" OSPNext(cause[,provider[,options]]): Looks up the next OSP Destination for ${OSPOUTHANDLE}\n"
+-"See OSPLookup for more information\n"
+-"\n"
+-"This application sets the following channel variable upon completion:\n"
+-" OSPNEXTSTATUS The status of the OSP Next attempt as a text string, one of\n"
+-" SUCCESS | FAILED | ERROR\n";
++/* OSPNext() dialplan application */
++static const char app3[] = "OSPNext";
+
+-static const char* app4 = "OSPFinish";
+-static const char* synopsis4 = "Record OSP entry";
+-static const char* descrip4 =
+-" OSPFinish([status[,options]]): Records call state for ${OSPINHANDLE}, according to\n"
+-"status, which should be one of BUSY, CONGESTION, ANSWER, NOANSWER, or CHANUNAVAIL\n"
+-"or coincidentally, just what the Dial application stores in its ${DIALSTATUS}.\n"
+-"\n"
+-"This application sets the following channel variable upon completion:\n"
+-" OSPFINISHSTATUS The status of the OSP Finish attempt as a text string, one of\n"
+-" SUCCESS | FAILED | ERROR \n";
++/* OSPFinish() dialplan application */
++static const char app4[] = "OSPFinish";
+
+ static struct ast_cli_entry cli_osp[] = {
+ AST_CLI_DEFINE(handle_cli_osp_show, "Displays OSF information")
+@@ -2010,10 +2179,10 @@
+ return AST_MODULE_LOAD_DECLINE;
+
+ ast_cli_register_multiple(cli_osp, sizeof(cli_osp) / sizeof(struct ast_cli_entry));
+- res = ast_register_application(app1, ospauth_exec, synopsis1, descrip1);
+- res |= ast_register_application(app2, osplookup_exec, synopsis2, descrip2);
+- res |= ast_register_application(app3, ospnext_exec, synopsis3, descrip3);
+- res |= ast_register_application(app4, ospfinished_exec, synopsis4, descrip4);
++ res = ast_register_application_xml(app1, ospauth_exec);
++ res |= ast_register_application_xml(app2, osplookup_exec);
++ res |= ast_register_application_xml(app3, ospnext_exec);
++ res |= ast_register_application_xml(app4, ospfinished_exec);
+
+ return res;
+ }
+Index: apps/app_sendtext.c
+===================================================================
+--- a/apps/app_sendtext.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_sendtext.c (.../trunk) (revision 202568)
+@@ -70,9 +70,9 @@
+ </application>
+ ***/
+
+-static const char *app = "SendText";
++static const char * const app = "SendText";
+
+-static int sendtext_exec(struct ast_channel *chan, void *data)
++static int sendtext_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+ char *status = "UNSUPPORTED";
+Index: apps/app_amd.c
+===================================================================
+--- a/apps/app_amd.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_amd.c (.../trunk) (revision 202568)
+@@ -124,7 +124,7 @@
+
+ ***/
+
+-static char *app = "AMD";
++static const char app[] = "AMD";
+
+ #define STATE_IN_WORD 1
+ #define STATE_IN_SILENCE 2
+@@ -143,7 +143,7 @@
+ /* Set to the lowest ms value provided in amd.conf or application parameters */
+ static int dfltMaxWaitTimeForFrame = 50;
+
+-static void isAnsweringMachine(struct ast_channel *chan, void *data)
++static void isAnsweringMachine(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+ struct ast_frame *f = NULL;
+@@ -404,7 +404,7 @@
+ }
+
+
+-static int amd_exec(struct ast_channel *chan, void *data)
++static int amd_exec(struct ast_channel *chan, const char *data)
+ {
+ isAnsweringMachine(chan, data);
+
+Index: apps/app_url.c
+===================================================================
+--- a/apps/app_url.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_url.c (.../trunk) (revision 202568)
+@@ -82,15 +82,15 @@
+
+ static char *app = "SendURL";
+
+-enum {
++enum option_flags {
+ OPTION_WAIT = (1 << 0),
+-} option_flags;
++};
+
+ AST_APP_OPTIONS(app_opts,{
+ AST_APP_OPTION('w', OPTION_WAIT),
+ });
+
+-static int sendurl_exec(struct ast_channel *chan, void *data)
++static int sendurl_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+ char *tmp;
+Index: apps/app_externalivr.c
+===================================================================
+--- a/apps/app_externalivr.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_externalivr.c (.../trunk) (revision 202568)
+@@ -48,34 +48,58 @@
+ #include "asterisk/tcptls.h"
+ #include "asterisk/astobj2.h"
+
+-static const char *app = "ExternalIVR";
++/*** DOCUMENTATION
++ <application name="ExternalIVR" language="en_US">
++ <synopsis>
++ Interfaces with an external IVR application.
++ </synopsis>
++ <syntax>
++ <parameter name="command|ivr://host" required="true" hasparams="true">
++ <argument name="arg1" />
++ <argument name="arg2" multiple="yes" />
++ </parameter>
++ <parameter name="options">
++ <optionlist>
++ <option name="n">
++ <para>Tells ExternalIVR() not to answer the channel.</para>
++ </option>
++ <option name="i">
++ <para>Tells ExternalIVR() not to send a hangup and exit when the
++ channel receives a hangup, instead it sends an <literal>I</literal>
++ informative message meaning that the external application MUST hang
++ up the call with an <literal>H</literal> command.</para>
++ </option>
++ <option name="d">
++ <para>Tells ExternalIVR() to run on a channel that has been hung up
++ and will not look for hangups. The external application must exit with
++ an <literal>E</literal> command.</para>
++ </option>
++ </optionlist>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Either forks a process to run given command or makes a socket to connect
++ to given host and starts a generator on the channel. The generator's play list
++ is controlled by the external application, which can add and clear entries via
++ simple commands issued over its stdout. The external application will receive
++ all DTMF events received on the channel, and notification if the channel is
++ hung up. The received on the channel, and notification if the channel is hung
++ up. The application will not be forcibly terminated when the channel is hung up.
++ See <filename>doc/externalivr.txt</filename> for a protocol specification.</para>
++ </description>
++ </application>
++ ***/
+
+-static const char *synopsis = "Interfaces with an external IVR application";
+-static const char *descrip =
+-" ExternalIVR(command|ivr://ivrhosti([,arg[,arg...]])[,options]): Either forks a process\n"
+-"to run given command or makes a socket to connect to given host and starts\n"
+-"a generator on the channel. The generator's play list is controlled by the\n"
+-"external application, which can add and clear entries via simple commands\n"
+-"issued over its stdout. The external application will receive all DTMF events\n"
+-"received on the channel, and notification if the channel is hung up. The\n"
+-"application will not be forcibly terminated when the channel is hung up.\n"
+-"See doc/externalivr.txt for a protocol specification.\n"
+-"The 'n' option tells ExternalIVR() not to answer the channel. \n"
+-"The 'i' option tells ExternalIVR() not to send a hangup and exit when the\n"
+-" channel receives a hangup, instead it sends an 'I' informative message\n"
+-" meaning that the external application MUST hang up the call with an H command\n"
+-"The 'd' option tells ExternalIVR() to run on a channel that has been hung up\n"
+-" and will not look for hangups. The external application must exit with\n"
+-" an 'E' command.\n";
++static const char app[] = "ExternalIVR";
+
+ /* XXX the parser in gcc 2.95 gets confused if you don't put a space between 'name' and the comma */
+ #define ast_chan_log(level, channel, format, ...) ast_log(level, "%s: " format, channel->name , ## __VA_ARGS__)
+
+-enum {
++enum options_flags {
+ noanswer = (1 << 0),
+ ignore_hangup = (1 << 1),
+ run_dead = (1 << 2),
+-} options_flags;
++};
+
+ AST_APP_OPTIONS(app_opts, {
+ AST_APP_OPTION('n', noanswer),
+@@ -311,7 +335,7 @@
+ return entry;
+ }
+
+-static int app_exec(struct ast_channel *chan, void *data)
++static int app_exec(struct ast_channel *chan, const char *data)
+ {
+ struct ast_flags flags = { 0, };
+ char *opts[0];
+@@ -800,7 +824,7 @@
+
+ static int load_module(void)
+ {
+- return ast_register_application(app, app_exec, synopsis, descrip);
++ return ast_register_application_xml(app, app_exec);
+ }
+
+ AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "External IVR Interface Application");
+Index: apps/app_directory.c
+===================================================================
+--- a/apps/app_directory.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_directory.c (.../trunk) (revision 202568)
+@@ -113,7 +113,7 @@
+ </application>
+
+ ***/
+-static char *app = "Directory";
++static const char app[] = "Directory";
+
+ /* For simplicity, I'm keeping the format compatible with the voicemail config,
+ but i'm open to suggestions for isolating it */
+@@ -128,7 +128,7 @@
+ OPT_LISTBYLASTNAME = (1 << 4),
+ OPT_LISTBYEITHER = OPT_LISTBYFIRSTNAME | OPT_LISTBYLASTNAME,
+ OPT_PAUSE = (1 << 5),
+-} directory_option_flags;
++};
+
+ enum {
+ OPT_ARG_FIRSTNAME = 0,
+@@ -714,7 +714,7 @@
+ return res;
+ }
+
+-static int directory_exec(struct ast_channel *chan, void *data)
++static int directory_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = 0, digit = 3;
+ struct ast_config *cfg, *ucfg;
+Index: apps/app_while.c
+===================================================================
+--- a/apps/app_while.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_while.c (.../trunk) (revision 202568)
+@@ -186,7 +186,7 @@
+ return res;
+ }
+
+-static int _while_exec(struct ast_channel *chan, void *data, int end)
++static int _while_exec(struct ast_channel *chan, const char *data, int end)
+ {
+ int res=0;
+ const char *while_pri = NULL;
+@@ -296,19 +296,19 @@
+ return res;
+ }
+
+-static int while_start_exec(struct ast_channel *chan, void *data) {
++static int while_start_exec(struct ast_channel *chan, const char *data) {
+ return _while_exec(chan, data, 0);
+ }
+
+-static int while_end_exec(struct ast_channel *chan, void *data) {
++static int while_end_exec(struct ast_channel *chan, const char *data) {
+ return _while_exec(chan, data, 1);
+ }
+
+-static int while_exit_exec(struct ast_channel *chan, void *data) {
++static int while_exit_exec(struct ast_channel *chan, const char *data) {
+ return _while_exec(chan, data, 2);
+ }
+
+-static int while_continue_exec(struct ast_channel *chan, void *data)
++static int while_continue_exec(struct ast_channel *chan, const char *data)
+ {
+ int x;
+ const char *prefix = "WHILE", *while_pri=NULL;
+Index: apps/app_dahdibarge.c
+===================================================================
+--- a/apps/app_dahdibarge.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_dahdibarge.c (.../trunk) (revision 202568)
+@@ -70,7 +70,7 @@
+ </description>
+ </application>
+ ***/
+-static char *app = "DAHDIBarge";
++static const char app[] = "DAHDIBarge";
+
+ #define CONF_SIZE 160
+
+@@ -258,7 +258,7 @@
+ return ret;
+ }
+
+-static int conf_exec(struct ast_channel *chan, void *data)
++static int conf_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = -1;
+ int retrycnt = 0;
+Index: apps/app_privacy.c
+===================================================================
+--- a/apps/app_privacy.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_privacy.c (.../trunk) (revision 202568)
+@@ -80,7 +80,7 @@
+
+ static char *app = "PrivacyManager";
+
+-static int privacy_exec (struct ast_channel *chan, void *data)
++static int privacy_exec(struct ast_channel *chan, const char *data)
+ {
+ int res=0;
+ int retries;
+Index: apps/app_record.c
+===================================================================
+--- a/apps/app_record.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_record.c (.../trunk) (revision 202568)
+@@ -129,7 +129,7 @@
+ AST_APP_OPTION('x', OPTION_IGNORE_TERMINATE),
+ });
+
+-static int record_exec(struct ast_channel *chan, void *data)
++static int record_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+ int count = 0;
+Index: apps/app_authenticate.c
+===================================================================
+--- a/apps/app_authenticate.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_authenticate.c (.../trunk) (revision 202568)
+@@ -43,7 +43,7 @@
+ OPT_DATABASE = (1 << 1),
+ OPT_MULTIPLE = (1 << 3),
+ OPT_REMOVE = (1 << 4),
+-} auth_option_flags;
++};
+
+ AST_APP_OPTIONS(auth_app_options, {
+ AST_APP_OPTION('a', OPT_ACCOUNT),
+@@ -53,7 +53,7 @@
+ });
+
+
+-static char *app = "Authenticate";
++static const char app[] = "Authenticate";
+ /*** DOCUMENTATION
+ <application name="Authenticate" language="en_US">
+ <synopsis>
+@@ -105,7 +105,7 @@
+ </application>
+ ***/
+
+-static int auth_exec(struct ast_channel *chan, void *data)
++static int auth_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = 0, retries, maxdigits;
+ char passwd[256], *prompt = "agent-pass", *argcopy = NULL;
+Index: apps/app_fax.c
+===================================================================
+--- a/apps/app_fax.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_fax.c (.../trunk) (revision 202568)
+@@ -141,8 +141,8 @@
+
+ ***/
+
+-static char *app_sndfax_name = "SendFAX";
+-static char *app_rcvfax_name = "ReceiveFAX";
++static const char app_sndfax_name[] = "SendFAX";
++static const char app_rcvfax_name[] = "ReceiveFAX";
+
+ #define MAX_SAMPLES 240
+
+@@ -351,7 +351,7 @@
+ return 0;
+ }
+
+-struct ast_generator generator = {
++static struct ast_generator generator = {
+ alloc: fax_generator_alloc,
+ generate: fax_generator_generate,
+ };
+@@ -374,7 +374,7 @@
+ struct timeval now, start, state_change;
+ enum ast_control_t38 t38control;
+
+-#if SPANDSP_RELEASE_DATE >= 20081012
++#if SPANDSP_RELEASE_DATE >= 20080725
+ /* for spandsp shaphots 0.0.6 and higher */
+ t30state = &fax.t30;
+ #else
+@@ -553,7 +553,7 @@
+ t30_state_t *t30state;
+ t38_core_state_t *t38state;
+
+-#if SPANDSP_RELEASE_DATE >= 20081012
++#if SPANDSP_RELEASE_DATE >= 20080725
+ /* for spandsp shaphots 0.0.6 and higher */
+ t30state = &t38.t30;
+ t38state = &t38.t38_fe.t38;
+@@ -705,11 +705,12 @@
+
+ /* === Application functions === */
+
+-static int sndfax_exec(struct ast_channel *chan, void *data)
++static int sndfax_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+ char *parse;
+ fax_session session;
++ char restore_digit_detect = 0;
+
+ AST_DECLARE_APP_ARGS(args,
+ AST_APP_ARG(file_name);
+@@ -744,16 +745,41 @@
+ session.chan = chan;
+ session.finished = 0;
+
++ /* get current digit detection mode, then disable digit detection if enabled */
++ {
++ int dummy = sizeof(restore_digit_detect);
++
++ ast_channel_queryoption(chan, AST_OPTION_DIGIT_DETECT, &restore_digit_detect, &dummy, 0);
++ }
++
++ if (restore_digit_detect) {
++ char new_digit_detect = 0;
++
++ ast_channel_setoption(chan, AST_OPTION_DIGIT_DETECT, &new_digit_detect, sizeof(new_digit_detect), 0);
++ }
++
++ /* disable FAX tone detection if enabled */
++ {
++ char new_fax_detect = 0;
++
++ ast_channel_setoption(chan, AST_OPTION_FAX_DETECT, &new_fax_detect, sizeof(new_fax_detect), 0);
++ }
++
+ res = transmit(&session);
+
++ if (restore_digit_detect) {
++ ast_channel_setoption(chan, AST_OPTION_DIGIT_DETECT, &restore_digit_detect, sizeof(restore_digit_detect), 0);
++ }
++
+ return res;
+ }
+
+-static int rcvfax_exec(struct ast_channel *chan, void *data)
++static int rcvfax_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+ char *parse;
+ fax_session session;
++ char restore_digit_detect = 0;
+
+ AST_DECLARE_APP_ARGS(args,
+ AST_APP_ARG(file_name);
+@@ -788,8 +814,32 @@
+ session.chan = chan;
+ session.finished = 0;
+
++ /* get current digit detection mode, then disable digit detection if enabled */
++ {
++ int dummy = sizeof(restore_digit_detect);
++
++ ast_channel_queryoption(chan, AST_OPTION_DIGIT_DETECT, &restore_digit_detect, &dummy, 0);
++ }
++
++ if (restore_digit_detect) {
++ char new_digit_detect = 0;
++
++ ast_channel_setoption(chan, AST_OPTION_DIGIT_DETECT, &new_digit_detect, sizeof(new_digit_detect), 0);
++ }
++
++ /* disable FAX tone detection if enabled */
++ {
++ char new_fax_detect = 0;
++
++ ast_channel_setoption(chan, AST_OPTION_FAX_DETECT, &new_fax_detect, sizeof(new_fax_detect), 0);
++ }
++
+ res = transmit(&session);
+
++ if (restore_digit_detect) {
++ ast_channel_setoption(chan, AST_OPTION_DIGIT_DETECT, &restore_digit_detect, sizeof(restore_digit_detect), 0);
++ }
++
+ return res;
+ }
+
+Index: apps/app_waituntil.c
+===================================================================
+--- a/apps/app_waituntil.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_waituntil.c (.../trunk) (revision 202568)
+@@ -67,7 +67,7 @@
+
+ static char *app = "WaitUntil";
+
+-static int waituntil_exec(struct ast_channel *chan, void *data)
++static int waituntil_exec(struct ast_channel *chan, const char *data)
+ {
+ int res;
+ double fraction;
+Index: apps/app_originate.c
+===================================================================
+--- a/apps/app_originate.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_originate.c (.../trunk) (revision 202568)
+@@ -89,7 +89,7 @@
+ </application>
+ ***/
+
+-static int originate_exec(struct ast_channel *chan, void *data)
++static int originate_exec(struct ast_channel *chan, const char *data)
+ {
+ AST_DECLARE_APP_ARGS(args,
+ AST_APP_ARG(tech_data);
+Index: apps/app_queue.c
+===================================================================
+--- a/apps/app_queue.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_queue.c (.../trunk) (revision 202568)
+@@ -94,6 +94,7 @@
+ #include "asterisk/strings.h"
+ #include "asterisk/global_datastores.h"
+ #include "asterisk/taskprocessor.h"
++#include "asterisk/callerid.h"
+
+ /*!
+ * \par Please read before modifying this file.
+@@ -141,6 +142,10 @@
+ <para>Ignore call forward requests from queue members and do nothing
+ when they are requested.</para>
+ </option>
++ <option name="I">
++ <para>Asterisk will ignore any connected line update requests or any redirecting party
++ update requests it may receive on this dial attempt.</para>
++ </option>
+ <option name="r">
+ <para>Ring instead of playing MOH. Periodic Announcements are still made, if applicable.</para>
+ </option>
+@@ -198,6 +203,11 @@
+ <parameter name="rule">
+ <para>Will cause the queue's defaultrule to be overridden by the rule specified.</para>
+ </parameter>
++ <parameter name="position">
++ <para>Attempt to enter the caller into the queue at the numerical position specified. <literal>1</literal>
++ would attempt to enter the caller at the head of the queue, and <literal>3</literal> would attempt to place
++ the caller third in the queue.</para>
++ </parameter>
+ </syntax>
+ <description>
+ <para>In addition to transferring the call, a call may be parked and then picked
+@@ -484,7 +494,160 @@
+ <para>Gets or sets queue members penalty.</para>
+ </description>
+ </function>
+-
++ <manager name="Queues" language="en_US">
++ <synopsis>
++ Queues.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ </syntax>
++ <description>
++ </description>
++ </manager>
++ <manager name="QueueStatus" language="en_US">
++ <synopsis>
++ Show queue status.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Queue" />
++ <parameter name="Member" />
++ </syntax>
++ <description>
++ </description>
++ </manager>
++ <manager name="QueueSummary" language="en_US">
++ <synopsis>
++ Show queue summary.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Queue" />
++ </syntax>
++ <description>
++ </description>
++ </manager>
++ <manager name="QueueAdd" language="en_US">
++ <synopsis>
++ Add interface to queue.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Queue" required="true" />
++ <parameter name="Interface" required="true" />
++ <parameter name="Penalty" />
++ <parameter name="Paused" />
++ <parameter name="MemberName" />
++ <parameter name="StateInterface" />
++ </syntax>
++ <description>
++ </description>
++ </manager>
++ <manager name="QueueRemove" language="en_US">
++ <synopsis>
++ Remove interface from queue.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Queue" required="true" />
++ <parameter name="Interface" required="true" />
++ </syntax>
++ <description>
++ </description>
++ </manager>
++ <manager name="QueuePause" language="en_US">
++ <synopsis>
++ Makes a queue member temporarily unavailable.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Interface" required="true" />
++ <parameter name="Paused" required="true" />
++ <parameter name="Queue" />
++ <parameter name="Reason" />
++ </syntax>
++ <description>
++ </description>
++ </manager>
++ <manager name="QueueLog" language="en_US">
++ <synopsis>
++ Adds custom entry in queue_log.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Queue" required="true" />
++ <parameter name="Event" required="true" />
++ <parameter name="Uniqueid" />
++ <parameter name="Interface" />
++ <parameter name="Message" />
++ </syntax>
++ <description>
++ </description>
++ </manager>
++ <manager name="QueuePenalty" language="en_US">
++ <synopsis>
++ Set the penalty for a queue member.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Interface" required="true" />
++ <parameter name="Penalty" required="true" />
++ <parameter name="Queue" />
++ </syntax>
++ <description>
++ </description>
++ </manager>
++ <manager name="QueueRule" language="en_US">
++ <synopsis>
++ Queue Rules.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Rule" />
++ </syntax>
++ <description>
++ </description>
++ </manager>
++ <manager name="QueueReload" language="en_US">
++ <synopsis>
++ Reload a queue, queues, or any sub-section of a queue or queues.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Queue" />
++ <parameter name="Members">
++ <enumlist>
++ <enum name="yes" />
++ <enum name="no" />
++ </enumlist>
++ </parameter>
++ <parameter name="Rules">
++ <enumlist>
++ <enum name="yes" />
++ <enum name="no" />
++ </enumlist>
++ </parameter>
++ <parameter name="Parameters">
++ <enumlist>
++ <enum name="yes" />
++ <enum name="no" />
++ </enumlist>
++ </parameter>
++ </syntax>
++ <description>
++ </description>
++ </manager>
++ <manager name="QueueReset" language="en_US">
++ <synopsis>
++ Reset queue statistics.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Queue" />
++ </syntax>
++ <description>
++ </description>
++ </manager>
+ ***/
+
+ enum {
+@@ -547,7 +710,7 @@
+ static char *app_ql = "QueueLog" ;
+
+ /*! \brief Persistent Members astdb family */
+-static const char *pm_family = "Queue/PersistentMembers";
++static const char * const pm_family = "Queue/PersistentMembers";
+ /* The maximum length of each persistent member queue database entry */
+ #define PM_MAX_LEN 8192
+
+@@ -583,7 +746,7 @@
+ QUEUE_CONTINUE = 7,
+ };
+
+-const struct {
++static const struct {
+ enum queue_result id;
+ char *text;
+ } queue_results[] = {
+@@ -625,6 +788,8 @@
+ time_t lastcall;
+ struct call_queue *lastqueue;
+ struct member *member;
++ unsigned int update_connectedline:1;
++ struct ast_party_connected_line connected;
+ };
+
+
+@@ -812,7 +977,7 @@
+ AST_LIST_ENTRY(rule_list) list;
+ };
+
+-AST_LIST_HEAD_STATIC(rule_lists, rule_list);
++static AST_LIST_HEAD_STATIC(rule_lists, rule_list);
+
+ static struct ao2_container *queues;
+
+@@ -1918,7 +2083,7 @@
+ ast_config_destroy(member_config);
+ }
+
+-static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *reason)
++static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *reason, int position)
+ {
+ struct call_queue *q;
+ struct queue_ent *cur, *prev = NULL;
+@@ -1959,6 +2124,17 @@
+ insert_entry(q, prev, qe, &pos);
+ inserted = 1;
+ }
++ /* <= is necessary for the position comparison because it may not be possible to enter
++ * at our desired position since higher-priority callers may have taken the position we want
++ */
++ if (!inserted && (qe->prio <= cur->prio) && position && (position <= pos + 1)) {
++ insert_entry(q, prev, qe, &pos);
++ /*pos is incremented inside insert_entry, so don't need to add 1 here*/
++ if (position < pos) {
++ ast_log(LOG_NOTICE, "Asked to be inserted at position %d but forced into position %d due to higher priority callers\n", position, pos);
++ }
++ inserted = 1;
++ }
+ cur->pos = ++pos;
+ prev = cur;
+ cur = cur->next;
+@@ -2219,12 +2395,13 @@
+ prev = NULL;
+ for (current = q->head; current; current = current->next) {
+ if (current == qe) {
++ char posstr[20];
+ q->count--;
+
+ /* Take us out of the queue */
+ manager_event(EVENT_FLAG_CALL, "Leave",
+- "Channel: %s\r\nQueue: %s\r\nCount: %d\r\nUniqueid: %s\r\n",
+- qe->chan->name, q->name, q->count, qe->chan->uniqueid);
++ "Channel: %s\r\nQueue: %s\r\nCount: %d\r\nPosition: %d\r\nUniqueid: %s\r\n",
++ qe->chan->name, q->name, q->count, qe->pos, qe->chan->uniqueid);
+ ast_debug(1, "Queue '%s' Leave, Channel '%s'\n", q->name, qe->chan->name );
+ /* Take us out of the queue */
+ if (prev)
+@@ -2234,6 +2411,8 @@
+ /* Free penalty rules */
+ while ((pr_iter = AST_LIST_REMOVE_HEAD(&qe->qe_rules, list)))
+ ast_free(pr_iter);
++ snprintf(posstr, sizeof(posstr), "%d", qe->pos);
++ pbx_builtin_setvar_helper(qe->chan, "QUEUEPOSITION", posstr);
+ } else {
+ /* Renumber the people after us in the queue based on a new count */
+ current->pos = ++pos;
+@@ -2378,7 +2557,7 @@
+ static char *vars2manager(struct ast_channel *chan, char *vars, size_t len)
+ {
+ struct ast_str *buf = ast_str_thread_get(&ast_str_thread_global_buf, len + 1);
+- char *tmp;
++ const char *tmp;
+
+ if (pbx_builtin_serialize_variables(chan, &buf)) {
+ int i, j;
+@@ -2492,23 +2671,41 @@
+ (*busies)++;
+ return 0;
+ }
+-
++
++ ast_channel_lock(tmp->chan);
++ while (ast_channel_trylock(qe->chan)) {
++ CHANNEL_DEADLOCK_AVOIDANCE(tmp->chan);
++ }
++
+ if (qe->cancel_answered_elsewhere) {
+ ast_set_flag(tmp->chan, AST_FLAG_ANSWERED_ELSEWHERE);
+ }
+ tmp->chan->appl = "AppQueue";
+ tmp->chan->data = "(Outgoing Line)";
+ memset(&tmp->chan->whentohangup, 0, sizeof(tmp->chan->whentohangup));
+- if (tmp->chan->cid.cid_num)
+- ast_free(tmp->chan->cid.cid_num);
+- tmp->chan->cid.cid_num = ast_strdup(qe->chan->cid.cid_num);
+- if (tmp->chan->cid.cid_name)
+- ast_free(tmp->chan->cid.cid_name);
+- tmp->chan->cid.cid_name = ast_strdup(qe->chan->cid.cid_name);
+- if (tmp->chan->cid.cid_ani)
+- ast_free(tmp->chan->cid.cid_ani);
+- tmp->chan->cid.cid_ani = ast_strdup(qe->chan->cid.cid_ani);
+
++ /* If the new channel has no callerid, try to guess what it should be */
++ if (ast_strlen_zero(tmp->chan->cid.cid_num)) {
++ if (!ast_strlen_zero(qe->chan->connected.id.number)) {
++ ast_set_callerid(tmp->chan, qe->chan->connected.id.number, qe->chan->connected.id.name, qe->chan->connected.ani);
++ tmp->chan->cid.cid_pres = qe->chan->connected.id.number_presentation;
++ } else if (!ast_strlen_zero(qe->chan->cid.cid_dnid)) {
++ ast_set_callerid(tmp->chan, qe->chan->cid.cid_dnid, NULL, NULL);
++ } else if (!ast_strlen_zero(S_OR(qe->chan->macroexten, qe->chan->exten))) {
++ ast_set_callerid(tmp->chan, S_OR(qe->chan->macroexten, qe->chan->exten), NULL, NULL);
++ }
++ tmp->update_connectedline = 0;
++ }
++
++ if (tmp->chan->cid.cid_rdnis)
++ ast_free(tmp->chan->cid.cid_rdnis);
++ tmp->chan->cid.cid_rdnis = ast_strdup(qe->chan->cid.cid_rdnis);
++ ast_party_redirecting_copy(&tmp->chan->redirecting, &qe->chan->redirecting);
++
++ tmp->chan->cid.cid_tns = qe->chan->cid.cid_tns;
++
++ ast_connected_line_copy_from_caller(&tmp->chan->connected, &qe->chan->cid);
++
+ /* Inherit specially named variables from parent channel */
+ ast_channel_inherit_variables(qe->chan, tmp->chan);
+
+@@ -2516,7 +2713,6 @@
+ tmp->chan->adsicpe = qe->chan->adsicpe;
+
+ /* Inherit context and extension */
+- ast_channel_lock(qe->chan);
+ macrocontext = pbx_builtin_getvar_helper(qe->chan, "MACRO_CONTEXT");
+ ast_string_field_set(tmp->chan, dialcontext, ast_strlen_zero(macrocontext) ? qe->chan->context : macrocontext);
+ macroexten = pbx_builtin_getvar_helper(qe->chan, "MACRO_EXTEN");
+@@ -2539,13 +2735,14 @@
+ strcpy(tmp->chan->cdr->accountcode, qe->chan->cdr->accountcode);
+ strcpy(tmp->chan->cdr->userfield, qe->chan->cdr->userfield);
+ }
+- ast_channel_unlock(qe->chan);
+
+ /* Place the call, but don't wait on the answer */
+ if ((res = ast_call(tmp->chan, location, 0))) {
+ /* Again, keep going even if there's an error */
+ ast_debug(1, "ast call on peer returned %d\n", res);
+ ast_verb(3, "Couldn't call %s\n", tmp->interface);
++ ast_channel_unlock(tmp->chan);
++ ast_channel_unlock(qe->chan);
+ do_hang(tmp);
+ (*busies)++;
+ update_status(qe->parent, tmp->member, ast_device_state(tmp->member->state_interface));
+@@ -2573,6 +2770,8 @@
+ qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
+ ast_verb(3, "Called %s\n", tmp->interface);
+ }
++ ast_channel_unlock(tmp->chan);
++ ast_channel_unlock(qe->chan);
+
+ update_status(qe->parent, tmp->member, ast_device_state(tmp->member->state_interface));
+ return 1;
+@@ -2802,8 +3001,10 @@
+ * \param[in] prebusies number of busy members calculated prior to calling wait_for_answer
+ * \param[in] caller_disconnect if the 'H' option is used when calling Queue(), this is used to detect if the caller pressed * to disconnect the call
+ * \param[in] forwardsallowed used to detect if we should allow call forwarding, based on the 'i' option to Queue()
++ *
++ * \todo eventually all call forward logic should be intergerated into and replaced by ast_call_forward()
+ */
+-static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed)
++static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed, int update_connectedline)
+ {
+ const char *queue = qe->parent->name;
+ struct callattempt *o, *start = NULL, *prev = NULL;
+@@ -2823,7 +3024,15 @@
+ #ifdef HAVE_EPOLL
+ struct callattempt *epollo;
+ #endif
++ struct ast_party_connected_line connected_caller;
++ char *inchan_name;
+
++ ast_party_connected_line_init(&connected_caller);
++
++ ast_channel_lock(qe->chan);
++ inchan_name = ast_strdupa(qe->chan->name);
++ ast_channel_unlock(qe->chan);
++
+ starttime = (long) time(NULL);
+ #ifdef HAVE_EPOLL
+ for (epollo = outgoing; epollo; epollo = epollo->q_next) {
+@@ -2873,9 +3082,32 @@
+ }
+ winner = ast_waitfor_n(watchers, pos, to);
+ for (o = start; o; o = o->call_next) {
++ /* We go with a static buffer here instead of using ast_strdupa. Using
++ * ast_strdupa in a loop like this one can cause a stack overflow
++ */
++ char ochan_name[AST_CHANNEL_NAME];
++ if (o->chan) {
++ ast_channel_lock(o->chan);
++ ast_copy_string(ochan_name, o->chan->name, sizeof(ochan_name));
++ ast_channel_unlock(o->chan);
++ }
+ if (o->stillgoing && (o->chan) && (o->chan->_state == AST_STATE_UP)) {
+ if (!peer) {
+- ast_verb(3, "%s answered %s\n", o->chan->name, in->name);
++ ast_verb(3, "%s answered %s\n", ochan_name, inchan_name);
++ if (update_connectedline) {
++ if (o->connected.id.number) {
++ if (ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) {
++ ast_channel_update_connected_line(in, &o->connected);
++ }
++ } else if (o->update_connectedline) {
++ ast_channel_lock(o->chan);
++ ast_connected_line_copy_from_caller(&connected_caller, &o->chan->cid);
++ ast_channel_unlock(o->chan);
++ connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
++ ast_channel_update_connected_line(in, &connected_caller);
++ ast_party_connected_line_free(&connected_caller);
++ }
++ }
+ peer = o;
+ }
+ } else if (o->chan && (o->chan == winner)) {
+@@ -2884,12 +3116,15 @@
+ ast_copy_string(membername, o->member->membername, sizeof(membername));
+
+ if (!ast_strlen_zero(o->chan->call_forward) && !forwardsallowed) {
+- ast_verb(3, "Forwarding %s to '%s' prevented.\n", in->name, o->chan->call_forward);
++ ast_verb(3, "Forwarding %s to '%s' prevented.\n", inchan_name, o->chan->call_forward);
+ numnochan++;
+ do_hang(o);
+ winner = NULL;
+ continue;
+ } else if (!ast_strlen_zero(o->chan->call_forward)) {
++ struct ast_party_redirecting *apr = &o->chan->redirecting;
++ struct ast_party_connected_line *apc = &o->chan->connected;
++ struct ast_channel *original = o->chan;
+ char tmpchan[256];
+ char *stuff;
+ char *tech;
+@@ -2904,7 +3139,7 @@
+ tech = "Local";
+ }
+ /* Before processing channel, go ahead and check for forwarding */
+- ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
++ ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n", inchan_name, tech, stuff, ochan_name);
+ /* Setup parameters */
+ o->chan = ast_request(tech, in->nativeformats, stuff, &status);
+ if (!o->chan) {
+@@ -2912,32 +3147,44 @@
+ o->stillgoing = 0;
+ numnochan++;
+ } else {
++ ast_channel_lock(o->chan);
++ while (ast_channel_trylock(in)) {
++ CHANNEL_DEADLOCK_AVOIDANCE(o->chan);
++ }
+ ast_channel_inherit_variables(in, o->chan);
+ ast_channel_datastore_inherit(in, o->chan);
+- if (o->chan->cid.cid_num)
+- ast_free(o->chan->cid.cid_num);
+- o->chan->cid.cid_num = ast_strdup(in->cid.cid_num);
+
+- if (o->chan->cid.cid_name)
+- ast_free(o->chan->cid.cid_name);
+- o->chan->cid.cid_name = ast_strdup(in->cid.cid_name);
+-
+ ast_string_field_set(o->chan, accountcode, in->accountcode);
+ o->chan->cdrflags = in->cdrflags;
+
+- if (in->cid.cid_ani) {
+- if (o->chan->cid.cid_ani)
+- ast_free(o->chan->cid.cid_ani);
+- o->chan->cid.cid_ani = ast_strdup(in->cid.cid_ani);
+- }
++ ast_channel_set_redirecting(o->chan, apr);
++
+ if (o->chan->cid.cid_rdnis)
+ ast_free(o->chan->cid.cid_rdnis);
+- o->chan->cid.cid_rdnis = ast_strdup(S_OR(in->macroexten, in->exten));
++ o->chan->cid.cid_rdnis = ast_strdup(S_OR(original->cid.cid_rdnis,S_OR(in->macroexten, in->exten)));
++
++ o->chan->cid.cid_tns = in->cid.cid_tns;
++
++ ast_party_caller_copy(&o->chan->cid, &in->cid);
++ ast_party_connected_line_copy(&o->chan->connected, apc);
++
++ ast_channel_update_redirecting(in, apr);
++ if (in->cid.cid_rdnis) {
++ ast_free(in->cid.cid_rdnis);
++ }
++ in->cid.cid_rdnis = ast_strdup(o->chan->cid.cid_rdnis);
++
++ update_connectedline = 1;
++
+ if (ast_call(o->chan, tmpchan, 0)) {
+ ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
++ ast_channel_unlock(o->chan);
+ do_hang(o);
+ numnochan++;
++ } else {
++ ast_channel_unlock(o->chan);
+ }
++ ast_channel_unlock(in);
+ }
+ /* Hangup the original channel now, in case we needed it */
+ ast_hangup(winner);
+@@ -2950,12 +3197,26 @@
+ case AST_CONTROL_ANSWER:
+ /* This is our guy if someone answered. */
+ if (!peer) {
+- ast_verb(3, "%s answered %s\n", o->chan->name, in->name);
++ ast_verb(3, "%s answered %s\n", ochan_name, inchan_name);
++ if (update_connectedline) {
++ if (o->connected.id.number) {
++ if (ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) {
++ ast_channel_update_connected_line(in, &o->connected);
++ }
++ } else if (o->update_connectedline) {
++ ast_channel_lock(o->chan);
++ ast_connected_line_copy_from_caller(&connected_caller, &o->chan->cid);
++ ast_channel_unlock(o->chan);
++ connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
++ ast_channel_update_connected_line(in, &connected_caller);
++ ast_party_connected_line_free(&connected_caller);
++ }
++ }
+ peer = o;
+ }
+ break;
+ case AST_CONTROL_BUSY:
+- ast_verb(3, "%s is busy\n", o->chan->name);
++ ast_verb(3, "%s is busy\n", ochan_name);
+ if (in->cdr)
+ ast_cdr_busy(in->cdr);
+ do_hang(o);
+@@ -2970,7 +3231,7 @@
+ numbusies++;
+ break;
+ case AST_CONTROL_CONGESTION:
+- ast_verb(3, "%s is circuit-busy\n", o->chan->name);
++ ast_verb(3, "%s is circuit-busy\n", ochan_name);
+ if (in->cdr)
+ ast_cdr_busy(in->cdr);
+ endtime = (long) time(NULL);
+@@ -2985,13 +3246,38 @@
+ numbusies++;
+ break;
+ case AST_CONTROL_RINGING:
+- ast_verb(3, "%s is ringing\n", o->chan->name);
++ ast_verb(3, "%s is ringing\n", ochan_name);
+ break;
+ case AST_CONTROL_OFFHOOK:
+ /* Ignore going off hook */
+ break;
++ case AST_CONTROL_CONNECTED_LINE:
++ if (!update_connectedline) {
++ ast_verb(3, "Connected line update to %s prevented.\n", inchan_name);
++ } else if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
++ struct ast_party_connected_line connected;
++ ast_verb(3, "%s connected line has changed. Saving it until answer for %s\n", ochan_name, inchan_name);
++ ast_party_connected_line_set_init(&connected, &o->connected);
++ ast_connected_line_parse_data(f->data.ptr, f->datalen, &connected);
++ ast_party_connected_line_set(&o->connected, &connected);
++ ast_party_connected_line_free(&connected);
++ } else {
++ if (ast_channel_connected_line_macro(o->chan, in, f, 1, 1)) {
++ ast_indicate_data(in, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen);
++ }
++ }
++ break;
++ case AST_CONTROL_REDIRECTING:
++ if (!update_connectedline) {
++ ast_verb(3, "Redirecting update to %s prevented\n", inchan_name);
++ } else {
++ ast_verb(3, "%s redirecting info has changed, passing it to %s\n", ochan_name, inchan_name);
++ ast_indicate_data(in, AST_CONTROL_REDIRECTING, f->data.ptr, f->datalen);
++ }
++ break;
+ default:
+ ast_debug(1, "Dunno what to do with control type %d\n", f->subclass);
++ break;
+ }
+ }
+ ast_frfree(f);
+@@ -3545,6 +3831,7 @@
+ char *p;
+ char vars[2048];
+ int forwardsallowed = 1;
++ int update_connectedline = 1;
+ int callcompletedinsl;
+ struct ao2_iterator memi;
+ struct ast_datastore *datastore, *transfer_ds;
+@@ -3610,6 +3897,9 @@
+ case 'i':
+ forwardsallowed = 0;
+ break;
++ case 'I':
++ update_connectedline = 0;
++ break;
+ case 'x':
+ ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_AUTOMIXMON);
+ break;
+@@ -3619,7 +3909,6 @@
+ case 'C':
+ qe->cancel_answered_elsewhere = 1;
+ break;
+-
+ }
+
+ /* if the calling channel has the ANSWERED_ELSEWHERE flag set, make sure this is inherited.
+@@ -3689,6 +3978,17 @@
+ }
+ }
+ AST_LIST_UNLOCK(dialed_interfaces);
++
++ ast_channel_lock(qe->chan);
++ /* If any pre-existing connected line information exists on this
++ * channel, like from the CONNECTED_LINE dialplan function, use this
++ * to seed the connected line information. It may, of course, be updated
++ * during the call
++ */
++ if (qe->chan->connected.id.number) {
++ ast_party_connected_line_copy(&tmp->connected, &qe->chan->connected);
++ }
++ ast_channel_unlock(qe->chan);
+
+ if (di) {
+ free(tmp);
+@@ -3720,6 +4020,7 @@
+ tmp->oldstatus = cur->status;
+ tmp->lastcall = cur->lastcall;
+ tmp->lastqueue = cur->lastqueue;
++ tmp->update_connectedline = 1;
+ ast_copy_string(tmp->interface, cur->interface, sizeof(tmp->interface));
+ /* Special case: If we ring everyone, go ahead and ring them, otherwise
+ just calculate their metric for the appropriate strategy */
+@@ -3760,7 +4061,7 @@
+ ring_one(qe, outgoing, &numbusies);
+ if (use_weight)
+ ao2_unlock(queues);
+- lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies, ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT), forwardsallowed);
++ lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies, ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT), forwardsallowed, update_connectedline);
+ /* The ast_channel_datastore_remove() function could fail here if the
+ * datastore was moved to another channel during a masquerade. If this is
+ * the case, don't free the datastore here because later, when the channel
+@@ -3955,18 +4256,16 @@
+ else
+ which = peer;
+ ast_channel_unlock(qe->chan);
+- if (ast_monitor_start) {
+- if (monitorfilename) {
+- ast_monitor_start(which, qe->parent->monfmt, monitorfilename, 1, X_REC_IN | X_REC_OUT);
+- } else if (qe->chan->cdr && ast_monitor_start) {
+- ast_monitor_start(which, qe->parent->monfmt, qe->chan->cdr->uniqueid, 1, X_REC_IN | X_REC_OUT);
+- } else if (ast_monitor_start) {
+- /* Last ditch effort -- no CDR, make up something */
+- snprintf(tmpid, sizeof(tmpid), "chan-%lx", ast_random());
+- ast_monitor_start(which, qe->parent->monfmt, tmpid, 1, X_REC_IN | X_REC_OUT);
+- }
++ if (monitorfilename) {
++ ast_monitor_start(which, qe->parent->monfmt, monitorfilename, 1, X_REC_IN | X_REC_OUT);
++ } else if (qe->chan->cdr) {
++ ast_monitor_start(which, qe->parent->monfmt, qe->chan->cdr->uniqueid, 1, X_REC_IN | X_REC_OUT);
++ } else {
++ /* Last ditch effort -- no CDR, make up something */
++ snprintf(tmpid, sizeof(tmpid), "chan-%lx", ast_random());
++ ast_monitor_start(which, qe->parent->monfmt, tmpid, 1, X_REC_IN | X_REC_OUT);
+ }
+- if (!ast_strlen_zero(monexec) && ast_monitor_setjoinfiles) {
++ if (!ast_strlen_zero(monexec)) {
+ ast_monitor_setjoinfiles(which, 1);
+ }
+ } else {
+@@ -4514,7 +4813,7 @@
+ }
+
+ /* \brief Sets members penalty, if queuename=NULL we set member penalty in all the queues. */
+-static int set_member_penalty(char *queuename, char *interface, int penalty)
++static int set_member_penalty(const char *queuename, const char *interface, int penalty)
+ {
+ int foundinterface = 0, foundqueue = 0;
+ struct call_queue *q;
+@@ -4691,7 +4990,7 @@
+ }
+
+ /*! \brief PauseQueueMember application */
+-static int pqm_exec(struct ast_channel *chan, void *data)
++static int pqm_exec(struct ast_channel *chan, const char *data)
+ {
+ char *parse;
+ AST_DECLARE_APP_ARGS(args,
+@@ -4727,7 +5026,7 @@
+ }
+
+ /*! \brief UnPauseQueueMember application */
+-static int upqm_exec(struct ast_channel *chan, void *data)
++static int upqm_exec(struct ast_channel *chan, const char *data)
+ {
+ char *parse;
+ AST_DECLARE_APP_ARGS(args,
+@@ -4763,7 +5062,7 @@
+ }
+
+ /*! \brief RemoveQueueMember application */
+-static int rqm_exec(struct ast_channel *chan, void *data)
++static int rqm_exec(struct ast_channel *chan, const char *data)
+ {
+ int res=-1;
+ char *parse, *temppos = NULL;
+@@ -4820,7 +5119,7 @@
+ }
+
+ /*! \brief AddQueueMember application */
+-static int aqm_exec(struct ast_channel *chan, void *data)
++static int aqm_exec(struct ast_channel *chan, const char *data)
+ {
+ int res=-1;
+ char *parse, *temppos = NULL;
+@@ -4883,7 +5182,7 @@
+ }
+
+ /*! \brief QueueLog application */
+-static int ql_exec(struct ast_channel *chan, void *data)
++static int ql_exec(struct ast_channel *chan, const char *data)
+ {
+ char *parse;
+
+@@ -4958,7 +5257,7 @@
+ * 6. Try 4 again unless some condition (such as an expiration time) causes us to
+ * exit the queue.
+ */
+-static int queue_exec(struct ast_channel *chan, void *data)
++static int queue_exec(struct ast_channel *chan, const char *data)
+ {
+ int res=-1;
+ int ringing=0;
+@@ -4974,6 +5273,7 @@
+ int noption = 0;
+ char *parse;
+ int makeannouncement = 0;
++ int position = 0;
+ AST_DECLARE_APP_ARGS(args,
+ AST_APP_ARG(queuename);
+ AST_APP_ARG(options);
+@@ -4984,12 +5284,13 @@
+ AST_APP_ARG(macro);
+ AST_APP_ARG(gosub);
+ AST_APP_ARG(rule);
++ AST_APP_ARG(position);
+ );
+ /* Our queue entry */
+ struct queue_ent qe;
+
+ if (ast_strlen_zero(data)) {
+- ast_log(LOG_WARNING, "Queue requires an argument: queuename[,options[,URL[,announceoverride[,timeout[,agi[,macro[,gosub[,rule]]]]]]]]\n");
++ ast_log(LOG_WARNING, "Queue requires an argument: queuename[,options[,URL[,announceoverride[,timeout[,agi[,macro[,gosub[,rule[,position]]]]]]]]]\n");
+ return -1;
+ }
+
+@@ -5055,6 +5356,14 @@
+ if (args.options && (strchr(args.options, 'c')))
+ qcontinue = 1;
+
++ if (args.position) {
++ position = atoi(args.position);
++ if (position < 0) {
++ ast_log(LOG_WARNING, "Invalid position '%s' given for call to queue '%s'. Assuming no preference for position\n", args.position, args.queuename);
++ position = 0;
++ }
++ }
++
+ ast_debug(1, "queue: %s, options: %s, url: %s, announce: %s, expires: %ld, priority: %d\n",
+ args.queuename, args.options, args.url, args.announceoverride, (long)qe.expire, prio);
+
+@@ -5067,7 +5376,7 @@
+ qe.last_periodic_announce_time = time(NULL);
+ qe.last_periodic_announce_sound = 0;
+ qe.valid_digits = 0;
+- if (join_queue(args.queuename, &qe, &reason)) {
++ if (join_queue(args.queuename, &qe, &reason, position)) {
+ ast_log(LOG_WARNING, "Unable to join queue '%s'\n", args.queuename);
+ set_queue_result(chan, reason);
+ return 0;
+@@ -5998,7 +6307,7 @@
+ * List the queues strategy, calls processed, members logged in,
+ * other queue statistics such as avg hold time.
+ */
+-static char *__queues_show(struct mansession *s, int fd, int argc, char **argv)
++static char *__queues_show(struct mansession *s, int fd, int argc, const char * const *argv)
+ {
+ struct call_queue *q;
+ struct ast_str *out = ast_str_alloca(240);
+@@ -6173,7 +6482,7 @@
+ */
+ static int manager_queues_show(struct mansession *s, const struct message *m)
+ {
+- char *a[] = { "queue", "show" };
++ static const char * const a[] = { "queue", "show" };
+
+ __queues_show(s, -1, 2, a);
+ astman_append(s, "\r\n\r\n"); /* Properly terminate Manager output */
+@@ -6609,7 +6918,7 @@
+
+ static char *handle_queue_add_member(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+ {
+- char *queuename, *interface, *membername = NULL, *state_interface = NULL;
++ const char *queuename, *interface, *membername = NULL, *state_interface = NULL;
+ int penalty;
+
+ switch ( cmd ) {
+@@ -6724,7 +7033,7 @@
+
+ static char *handle_queue_remove_member(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+ {
+- char *queuename, *interface;
++ const char *queuename, *interface;
+
+ switch (cmd) {
+ case CLI_INIT:
+@@ -6789,7 +7098,7 @@
+
+ static char *handle_queue_pause_member(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+ {
+- char *queuename, *interface, *reason;
++ const char *queuename, *interface, *reason;
+ int paused;
+
+ switch (cmd) {
+@@ -6863,7 +7172,7 @@
+
+ static char *handle_queue_set_member_penalty(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+ {
+- char *queuename = NULL, *interface;
++ const char *queuename = NULL, *interface;
+ int penalty = 0;
+
+ switch (cmd) {
+@@ -6925,7 +7234,7 @@
+
+ static char *handle_queue_rule_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+ {
+- char *rule;
++ const char *rule;
+ struct rule_list *rl_iter;
+ struct penalty_rule *pr_iter;
+ switch (cmd) {
+@@ -7152,17 +7461,17 @@
+ res |= ast_register_application_xml(app_pqm, pqm_exec);
+ res |= ast_register_application_xml(app_upqm, upqm_exec);
+ res |= ast_register_application_xml(app_ql, ql_exec);
+- res |= ast_manager_register("Queues", 0, manager_queues_show, "Queues");
+- res |= ast_manager_register("QueueStatus", 0, manager_queues_status, "Queue Status");
+- res |= ast_manager_register("QueueSummary", 0, manager_queues_summary, "Queue Summary");
+- res |= ast_manager_register("QueueAdd", EVENT_FLAG_AGENT, manager_add_queue_member, "Add interface to queue.");
+- res |= ast_manager_register("QueueRemove", EVENT_FLAG_AGENT, manager_remove_queue_member, "Remove interface from queue.");
+- res |= ast_manager_register("QueuePause", EVENT_FLAG_AGENT, manager_pause_queue_member, "Makes a queue member temporarily unavailable");
+- res |= ast_manager_register("QueueLog", EVENT_FLAG_AGENT, manager_queue_log_custom, "Adds custom entry in queue_log");
+- res |= ast_manager_register("QueuePenalty", EVENT_FLAG_AGENT, manager_queue_member_penalty, "Set the penalty for a queue member");
+- res |= ast_manager_register("QueueRule", 0, manager_queue_rule_show, "Queue Rules");
+- res |= ast_manager_register("QueueReload", 0, manager_queue_reload, "Reload a queue, queues, or any sub-section of a queue or queues");
+- res |= ast_manager_register("QueueReset", 0, manager_queue_reset, "Reset queue statistics");
++ res |= ast_manager_register_xml("Queues", 0, manager_queues_show);
++ res |= ast_manager_register_xml("QueueStatus", 0, manager_queues_status);
++ res |= ast_manager_register_xml("QueueSummary", 0, manager_queues_summary);
++ res |= ast_manager_register_xml("QueueAdd", EVENT_FLAG_AGENT, manager_add_queue_member);
++ res |= ast_manager_register_xml("QueueRemove", EVENT_FLAG_AGENT, manager_remove_queue_member);
++ res |= ast_manager_register_xml("QueuePause", EVENT_FLAG_AGENT, manager_pause_queue_member);
++ res |= ast_manager_register_xml("QueueLog", EVENT_FLAG_AGENT, manager_queue_log_custom);
++ res |= ast_manager_register_xml("QueuePenalty", EVENT_FLAG_AGENT, manager_queue_member_penalty);
++ res |= ast_manager_register_xml("QueueRule", 0, manager_queue_rule_show);
++ res |= ast_manager_register_xml("QueueReload", 0, manager_queue_reload);
++ res |= ast_manager_register_xml("QueueReset", 0, manager_queue_reset);
+ res |= ast_custom_function_register(&queuevar_function);
+ res |= ast_custom_function_register(&queuemembercount_function);
+ res |= ast_custom_function_register(&queuemembercount_dep);
+Index: apps/app_followme.c
+===================================================================
+--- a/apps/app_followme.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_followme.c (.../trunk) (revision 202568)
+@@ -275,18 +275,19 @@
+ }
+
+ /*! \brief Add a new number */
+-static struct number *create_followme_number(char *number, int timeout, int numorder)
++static struct number *create_followme_number(const char *number, int timeout, int numorder)
+ {
+ struct number *cur;
++ char *buf = ast_strdupa(number);
+ char *tmp;
+
+ if (!(cur = ast_calloc(1, sizeof(*cur))))
+ return NULL;
+
+ cur->timeout = timeout;
+- if ((tmp = strchr(number, ',')))
++ if ((tmp = strchr(buf, ',')))
+ *tmp = '\0';
+- ast_copy_string(cur->number, number, sizeof(cur->number));
++ ast_copy_string(cur->number, buf, sizeof(cur->number));
+ cur->order = numorder;
+ ast_debug(1, "Created a number, %s, order of , %d, with a timeout of %ld.\n", cur->number, cur->order, cur->timeout);
+
+@@ -996,7 +997,7 @@
+ bconfig->end_bridge_callback_data = originator;
+ }
+
+-static int app_exec(struct ast_channel *chan, void *data)
++static int app_exec(struct ast_channel *chan, const char *data)
+ {
+ struct fm_args targs = { 0, };
+ struct ast_bridge_config config;
+Index: apps/app_waitforring.c
+===================================================================
+--- a/apps/app_waitforring.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_waitforring.c (.../trunk) (revision 202568)
+@@ -53,7 +53,7 @@
+
+ static char *app = "WaitForRing";
+
+-static int waitforring_exec(struct ast_channel *chan, void *data)
++static int waitforring_exec(struct ast_channel *chan, const char *data)
+ {
+ struct ast_frame *f;
+ int res = 0;
+Index: apps/app_flash.c
+===================================================================
+--- a/apps/app_flash.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/apps/app_flash.c (.../trunk) (revision 202568)
+@@ -72,7 +72,7 @@
+ return j;
+ }
+
+-static int flash_exec(struct ast_channel *chan, void *data)
++static int flash_exec(struct ast_channel *chan, const char *data)
+ {
+ int res = -1;
+ int x;
+Index: doc/asterisk.sgml
+===================================================================
+--- a/doc/asterisk.sgml (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/doc/asterisk.sgml (.../trunk) (revision 202568)
+@@ -327,7 +327,7 @@
+ <refsect1>
+ <title>BUGS</title>
+ <para>
+- Bug reports and feature requests may be filed at http://bugs.digium.com
++ Bug reports and feature requests may be filed at https://issues.asterisk.org
+ </para>
+ </refsect1>
+ <refsect1>
+Index: doc/CODING-GUIDELINES
+===================================================================
+--- a/doc/CODING-GUIDELINES (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/doc/CODING-GUIDELINES (.../trunk) (revision 202568)
+@@ -22,7 +22,7 @@
+ Asterisk is published under a dual-licensing scheme by Digium.
+ To be accepted into the codebase, all non-trivial changes must be
+ licensed to Digium. For more information, see the electronic license
+-agreement on http://bugs.digium.com/.
++agreement on https://issues.asterisk.org/.
+
+ Patches should be in the form of a unified (-u) diff, made from a checkout
+ from subversion.
+@@ -114,7 +114,6 @@
+ is almost always necessary) write a short comment next to each #include to
+ explain why you need it.
+
+-
+ * Declaration of functions and variables
+ ----------------------------------------
+
+@@ -122,15 +121,47 @@
+ since it is harder to read and not portable to GCC 2.95 and others.
+
+ - Functions and variables that are not intended to be used outside the module
+- must be declared static.
++ must be declared static. If you are compiling on a Linux platform that has the
++ 'dwarves' package available, you can use the 'pglobal' tool from that package
++ to check for unintended global variables or functions being exposed in your
++ object files. Usage is very simple:
+
++ $ pglobal -vf <path to .o file>
++
+ - When reading integer numeric input with scanf (or variants), do _NOT_ use '%i'
+ unless you specifically want to allow non-base-10 input; '%d' is always a better
+ choice, since it will not silently turn numbers with leading zeros into base-8.
+
+-- Strings that are coming from input should not be used as a first argument to
+- a formatted *printf function.
++- Strings that are coming from input should not be used as the format argument to
++ any printf-style function.
+
++* Structure alignment and padding
++---------------------------------
++
++On many platforms, structure fields (in structures that are not marked 'packed')
++will be laid out by the compiler with gaps (padding) between them, in order to
++satisfy alignment requirements. As a simple example:
++
++struct foo {
++ int bar;
++ void *xyz;
++}
++
++On nearly every 64-bit platform, this will result in 4 bytes of dead space between
++'bar' and 'xyz', because pointers on 64-bit platforms must be aligned on 8-byte
++boundaries. Once you have your code written and tested, it may be worthwhile to review
++your structure definitions to look for problems of this nature. If you are on a Linux
++platform with the 'dwarves' package available, the 'pahole' tool from that package
++can be used to both check for padding issues of this type and also propose reorganized
++structure definitions to eliminate it. Usage is quite simple; for a structure named 'foo',
++the command would look something like this:
++
++$ pahole --reorganize --show_reorg_steps -C foo <path to module>
++
++The 'pahole' tool has many other modes available, including some that will list all the
++structures declared in the module and the amount of padding in each one that could possibly
++be recovered.
++
+ * Use the internal API
+ ----------------------
+
+Index: doc/asterisk.8
+===================================================================
+--- a/doc/asterisk.8 (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/doc/asterisk.8 (.../trunk) (revision 202568)
+@@ -176,7 +176,7 @@
+ \fBasterisk -rx "core show channels"\fR - Display channels on running server
+ .SH "BUGS"
+ .PP
+-Bug reports and feature requests may be filed at http://bugs.digium.com
++Bug reports and feature requests may be filed at https://issues.asterisk.org
+ .SH "SEE ALSO"
+ .PP
+ *CLI> \fBhelp\fR - Help on Asterisk CLI
+Index: doc/backtrace.txt
+===================================================================
+--- a/doc/backtrace.txt (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/doc/backtrace.txt (.../trunk) (revision 202568)
+@@ -1,6 +1,6 @@
+ This document is intended to provide information on how to obtain the
+ backtraces required on the asterisk bug tracker, available at
+-http://bugs.digium.com. The information is required by developers to
++https://issues.asterisk.org. The information is required by developers to
+ help fix problem with bugs of any kind. Backtraces provide information
+ about what was wrong when a program crashed; in our case,
+ Asterisk. There are two kind of backtraces (aka 'bt') which are
+Index: doc/janitor-projects.txt
+===================================================================
+--- a/doc/janitor-projects.txt (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/doc/janitor-projects.txt (.../trunk) (revision 202568)
+@@ -32,3 +32,5 @@
+ -- Audit all channel/res/app/etc. modules to ensure that they do not register any entrypoints with the Asterisk core until after they are ready to service requests; all config file reading/processing, structure allocation, etc. must be completed before Asterisk is made aware of any services the module offers.
+
+ -- Ensure that Realtime-enabled modules do not depend on the order of columns returned by the database lookup (example: outboundproxy and host settings in chan_sip).
++
++ -- Convert all usage of the signal(2) system API to the more portable sigaction(2) system API.
+Index: doc/lang/urdu.ods
+===================================================================
+Cannot display: file marked as a binary type.
+svn:mime-type = application/x-open-document-spreadsheet
+
+Property changes on: doc/lang/urdu.ods
+___________________________________________________________________
+Added: svn:mime-type
+ + application/x-open-document-spreadsheet
+
+Index: doc/appdocsxml.dtd
+===================================================================
+--- a/doc/appdocsxml.dtd (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/doc/appdocsxml.dtd (.../trunk) (revision 202568)
+@@ -1,4 +1,4 @@
+- <!ELEMENT docs (application|function|agi)*>
++ <!ELEMENT docs (application|function|agi|manager)*>
+ <!ATTLIST docs xmlns:xi CDATA #FIXED "http://www.w3.org/2001/XInclude">
+
+ <!ELEMENT xi:include (xi:fallback?) >
+@@ -23,6 +23,10 @@
+ <!ATTLIST agi name CDATA #REQUIRED>
+ <!ATTLIST agi language CDATA #REQUIRED>
+
++ <!ELEMENT manager (synopsis?,syntax?,description?,see-also?)>
++ <!ATTLIST manager name CDATA #REQUIRED>
++ <!ATTLIST manager language CDATA #REQUIRED>
++
+ <!ELEMENT see-also (ref|xi:include)*>
+
+ <!ELEMENT ref (#PCDATA)>
+Index: doc/datastores.txt
+===================================================================
+--- a/doc/datastores.txt (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/doc/datastores.txt (.../trunk) (revision 202568)
+@@ -19,8 +19,8 @@
+
+ * How do you create a data store?
+
+-1. Use ast_channel_datastore_alloc function to return a pre-allocated structure
+- Ex: datastore = ast_channel_datastore_alloc(&example_datastore, "uid");
++1. Use ast_datastore_alloc function to return a pre-allocated structure
++ Ex: datastore = ast_datastore_alloc(&example_datastore, "uid");
+ This function takes two arguments: (datastore info structure, uid)
+ 2. Attach data to pre-allocated structure.
+ Ex: datastore->data = mysillydata;
+@@ -36,7 +36,7 @@
+ }
+
+ struct ast_datastore *datastore = NULL;
+-datastore = ast_channel_datastore_alloc(&example_datastore, NULL);
++datastore = ast_datastore_alloc(&example_datastore, NULL);
+ datastore->data = mysillydata;
+ ast_channel_datastore_add(chan, datastore);
+
+Index: doc/manager_1_1.txt
+===================================================================
+--- a/doc/manager_1_1.txt (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/doc/manager_1_1.txt (.../trunk) (revision 202568)
+@@ -252,6 +252,35 @@
+ To list the information about a specific SKINNY line.
+ Variables:
+ Line: <line> Line to show information about.
++
++- Action: CoreSettings
++ Modules: manager.c
++ Purpose: To report core settings, like AMI and Asterisk version,
++ maxcalls and maxload settings.
++ * Integrated in SVN trunk as of May 4th, 2007
++ Example:
++ Response: Success
++ ActionID: 1681692777
++ AMIversion: 1.1
++ AsteriskVersion: SVN-oej-moremanager-r61756M
++ SystemName: EDVINA-node-a
++ CoreMaxCalls: 120
++ CoreMaxLoadAvg: 0.000000
++ CoreRunUser: edvina
++ CoreRunGroup: edvina
++
++- Action: CoreStatus
++ Modules: manager.c
++ Purpose: To report current PBX core status flags, like
++ number of concurrent calls, startup and reload time.
++ * Integrated in SVN trunk as of May 4th, 2007
++ Example:
++ Response: Success
++ ActionID: 1649760492
++ CoreStartupTime: 22:35:17
++ CoreReloadTime: 22:35:17
++ CoreCurrentCalls: 20
++
+
+ * NEW EVENTS
+ ------------
+@@ -294,34 +323,6 @@
+ SIPcallid: NTQzYWFiOWM4NmE0MWRkZjExMzU2YzQ3OWQwNzg3ZmI.
+ SIPfullcontact: sip:olle@127.0.0.1:49054
+
+-- Action: CoreSettings
+- Modules: manager.c
+- Purpose: To report core settings, like AMI and Asterisk version,
+- maxcalls and maxload settings.
+- * Integrated in SVN trunk as of May 4th, 2007
+- Example:
+- Response: Success
+- ActionID: 1681692777
+- AMIversion: 1.1
+- AsteriskVersion: SVN-oej-moremanager-r61756M
+- SystemName: EDVINA-node-a
+- CoreMaxCalls: 120
+- CoreMaxLoadAvg: 0.000000
+- CoreRunUser: edvina
+- CoreRunGroup: edvina
+-
+-- Action: CoreStatus
+- Modules: manager.c
+- Purpose: To report current PBX core status flags, like
+- number of concurrent calls, startup and reload time.
+- * Integrated in SVN trunk as of May 4th, 2007
+- Example:
+- Response: Success
+- ActionID: 1649760492
+- CoreStartupTime: 22:35:17
+- CoreReloadTime: 22:35:17
+- CoreCurrentCalls: 20
+-
+ - Event: NewAccountCode
+ Modules: cdr.c
+ Purpose: To report a change in account code for a live channel
+Index: doc/tex/asterisk.tex
+===================================================================
+--- a/doc/tex/asterisk.tex (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/doc/tex/asterisk.tex (.../trunk) (revision 202568)
+@@ -135,6 +135,9 @@
+ \chapter{Phone Provisioning}
+ \input{phoneprov.tex}
+
++\chapter{Calendaring}
++ \input{calendaring.tex}
++
+ \chapter{Development}
+ \section{Backtrace}
+ \input{backtrace.tex}
+Index: doc/tex/channelvariables.tex
+===================================================================
+--- a/doc/tex/channelvariables.tex (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/doc/tex/channelvariables.tex (.../trunk) (revision 202568)
+@@ -853,6 +853,10 @@
+ ${QUEUE_MIN_PENALTY} Minimum member penalty allowed to answer caller
+ ${QUEUESTATUS} Status of the call, one of:
+ (TIMEOUT | FULL | JOINEMPTY | LEAVEEMPTY | JOINUNAVAIL | LEAVEUNAVAIL)
++${QUEUEPOSITION} * When a caller is removed from a queue, his current position is logged
++ in this variable. If the value is 0, then this means that the caller was
++ serviced by a queue member. If non-zero, then this was the position in the
++ queue the caller was in when he left.
+ ${RECORDED_FILE} * Recorded file in record()
+ ${TALK_DETECTED} * Result from talkdetect()
+ ${TOUCH_MONITOR} The filename base to use with Touch Monitor (auto record)
+@@ -925,7 +929,9 @@
+ ${SIPFROMDOMAIN} Set SIP domain on outbound calls
+ ${SIPUSERAGENT} * SIP user agent (deprecated)
+ ${SIPURI} * SIP uri
+-${SIP_CODEC} Set the SIP codec for a call
++${SIP_CODEC} Set the SIP codec for an inbound call
++${SIP_CODEC_INBOUND} Set the SIP codec for an inbound call
++${SIP_CODEC_OUTBOUND} Set the SIP codec for an outbound call
+ ${SIP_URI_OPTIONS} * additional options to add to the URI for an outgoing call
+ ${RTPAUDIOQOS} RTCP QoS report for the audio of this call
+ ${RTPVIDEOQOS} RTCP QoS report for the video of this call
+@@ -999,3 +1005,11 @@
+ ${OSPOUTTIMELIMIT} Duration limit for out_bound call
+ ${OSPRESULTS} Number of remained destinations
+ \end{verbatim}
++
++\subsection{Connected line digit manipulation}
++\begin{verbatim}
++${CONNECTED_LINE_SEND_CALLEE_MACRO} Macro to call before sending a connected line update to the callee
++${CONNECTED_LINE_SEND_CALLEE_MACRO_ARGS} Arguments to pass to ${CONNECTED_LINE_SEND_CALLEE_MACRO}
++${CONNECTED_LINE_SEND_CALLER_MACRO} Macro to call before sending a connected line update to the caller
++${CONNECTED_LINE_SEND_CALLER_MACRO_ARGS} Arguments to pass to ${CONNECTED_LINE_SEND_CALLER_MACRO}
++\end{verbatim}
+Index: doc/tex/calendaring.tex
+===================================================================
+--- a/doc/tex/calendaring.tex (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/doc/tex/calendaring.tex (.../trunk) (revision 202568)
+@@ -0,0 +1,206 @@
++\section{Introduction}
++
++The Asterisk Calendaring API aims to be a generic interface for integrating
++Asterisk with various calendaring technologies. The goal is to be able to
++support reading and writing of calendar events as well as allowing notification
++of pending events through the Asterisk dialplan.
++
++There are three calendaring modules that ship with Asterisk that provide support
++for iCalendar, CalDAV, and Microsoft Exchange Server calendars. All three
++modules support event notification. Both CalDAV and Exchange support reading
++and writing calendars, while iCalendar is a read-only format.
++
++\section{Configuring Asterisk Calendaring}
++
++All asterisk calendaring modules are configured through calender.conf. Each
++calendar module can define its own set of required parameters in addition to the
++parameters available to all calendar types. An effort has been made to keep all
++options the same in all calendaring modules, but some options will diverge over
++time as features are added to each module.
++
++An example calendar.conf might look like:
++\begin{astlisting}
++\begin{verbatim}
++[calendar_joe]
++type = ical
++url = https://example.com/home/jdoe/Calendar
++user = jdoe
++secret = mysecret
++refresh = 15
++timeframe = 600
++autoreminder = 10
++channel = SIP/joe
++context = calendar_event_notify
++extension = s
++waittime = 30
++\end{verbatim}
++\end{astlisting}
++
++\subsection{Module-independent settings}
++
++The settings related to calendar event notification are handled by the core
++calendaring API. These settings are:
++\begin{description}
++\item[autoreminder] This allows the overriding of any alarms that may or may not
++be set for a calendar event. It is specified in minutes.
++\item[refresh] How often to refresh the calendar data; specified in minutes.
++\item[timeframe] How far into the future each calendar refresh should look. This
++is the amount of data that will be visible to queries from the dialplan. This
++setting should always be greater than or equal to the refresh setting or events
++may be missed. It is specified in minutes.
++\item[channel] The channel that should be used for making the notification
++attempt.
++\item[waittime] How long to wait, in seconds, for the channel to answer a notification
++attempt.
++\end{description}
++
++There are two ways to specify how to handle a notification. One option is
++providing a context and extension, while the other is providing an application
++and the arguments to that application. One (and only one) of these options
++should be provided.
++
++\begin{description}
++\item[context] The context of the extension to connect to the notification
++channel
++\item[extension] The extension to connect to the notification. Note that the
++priority will always be 1.
++\end{description}
++
++or
++
++\begin{description}
++\item[app] The dialplan application to execute upon the answer of a notification
++\item[appdata] The data to pass to the notification dialplan application
++\end{description}
++
++\subsection{Module-dependent settings}
++
++Connection-related options are specific to each module. Currently, all modules
++take a url, user, and secret for configuration and no other module-specific
++settings have been implemented. At this time, no support for HTTP redirects has
++been implemented, so it is important to specify the correct URL--paying attention
++to any trailing slashes that may be necessary.
++
++\section{Dialplan functions}
++\subsection{Read functions}
++
++The simplest dialplan query is the CALENDAR\_BUSY query. It takes a single
++option, the name of the calendar defined, and returns "1" for busy (including
++tentatively busy) and "0" for not busy.
++
++For more information about a calendar event, a combination of CALENDAR\_QUERY
++and CALENDAR\_QUERY\_RESULT is used. CALENDAR\_QUERY takes the calendar name
++and optionally a start and end time in "unix time" (seconds from unix epoch). It
++returns an id that can be passed to CALENDAR\_QUERY\_RESULT along with a field
++name to return the data in that field. If multiple events are returned in the
++query, the number of the event in the list can be specified as well. The available
++fields to return are:
++\begin{description}
++\item[summary] A short summary of the event
++\item[description] The full description of the event
++\item[organizer] Who organized the event
++\item[location] Where the event is located
++\item[calendar] The name of the calendar from calendar.conf
++\item[uid] The unique identifier associated with the event
++\item[start] The start of the event in seconds since Unix epoch
++\item[end] The end of the event in seconds since Unix epoch
++\item[busystate] The busy state 0=Free, 1=Tentative, 2=Busy
++\item[attendees] A comma separated list of attendees as stored in the event and
++may include prefixes such as "mailto:".
++\end{description}
++
++When an event notification is sent to the dial plan, the CALENDAR\_EVENT
++function may be used to return the information about the event that is causing
++the notification. The fields that can be returned are the same as those from
++CALENDAR\_QUERY\_RESULT.
++\subsection{Write functions}
++
++To write an event to a calendar, the CALENDAR\_WRITE function is used. This
++function takes a calendar name and also uses the same fields as
++CALENDAR\_QUERY\_RESULT. As a write function, it takes a set of comma-separated
++values that are in the same order as the specified fields. For example:
++\begin{astlisting}
++\begin{verbatim}
++CALENDAR_WRITE(mycalendar,summary,organizer,start,end,busystate)=
++ "My event","mailto:jdoe@example.com",228383580,228383640,1)
++\end{verbatim}
++\end{astlisting}
++
++\section{Dialplan Examples}
++\subsection{Office hours}
++A common business PBX scenario is would be executing dialplan logic based on
++when the business is open and the phones staffed. If the business is closed for
++holidays, it is sometimes desirable to play a message to the caller stating why
++the business is closed.
++
++The standard way to do this in asterisk has been doing a series of GotoIfTime
++statements or time-based include statements. Either way can be tedious and
++requires someone with access to edit asterisk config files.
++
++With calendaring, the adminstrator only needs to set up a calendar that contains
++the various holidays or even recurring events specifying the office hours. A
++custom greeting filename could even be contained in the description field for
++playback. For example:
++\begin{astlisting}
++\begin{verbatim}
++[incoming]
++exten => 5555551212,1,Answer
++exten => 5555551212,n,GotoIf(${CALENDAR_BUSY(officehours)}?closed:attendant,s,1)
++exten => 5555551212,n(closed),Set(id=${CALENDAR_QUERY(office,${EPOCH},${EPOCH})})
++exten => 5555551212,n,Set(soundfile=${CALENDAR_QUERY_RESULT(${id},description)})
++exten => 5555551212,n,Playback($[${ISNULL(soundfile)} ? generic-closed :: ${soundfile}])
++exten => 5555551212,n,Hangup
++\end{verbatim}
++\end{astlisting}
++
++\subsection{Meeting reminders}
++One useful application of Asterisk Calendaring is the ability to execute
++dialplan logic based on an event notification. Most calendaring technologies
++allow a user to set an alarm for an event. If these alarms are set on a calendar
++that Asterisk is monitoring and the calendar is set up for event notification
++via calendar.conf, then Asterisk will execute notify the specified channel at
++the time of the alarm. If an overrided notification time is set with the
++autoreminder setting, then the notification would happen at that time instead.
++
++The following example demonstrates the set up for a simple event notification
++that plays back a generic message followed by the time of the upcoming meeting.
++calendar.conf.
++\begin{astlisting}
++\begin{verbatim}
++[calendar_joe]
++type = ical
++url = https://example.com/home/jdoe/Calendar
++user = jdoe
++secret = mysecret
++refresh = 15
++timeframe = 600
++autoreminder = 10
++channel = SIP/joe
++context = calendar_event_notify
++extension = s
++waittime = 30
++\end{verbatim}
++\end{astlisting}
++
++\begin{astlisting}
++\begin{verbatim}
++[calendar_event_notify]
++exten => s,1,Answer
++exten => s,n,Playback(you-have-a-meeting-at)
++exten => s,n,SayUnixTime(${CALENDAR_EVENT(start)})
++exten => s,n,Hangup
++\end{verbatim}
++\end{astlisting}
++
++\subsection{Writing an event}
++Both CalDAV and Exchange calendar servers support creating new events. The
++following example demonstrates writing a log of a call to a calendar.
++\begin{astlisting}
++\begin{verbatim}
++[incoming]
++exten => 6000,1,Set(start=${EPOCH})
++exten => 6000,n,Dial(SIP/joe)
++exten => h,1,Set(end=${EPOCH})
++exten => h,n,Set(CALENDAR_WRITE(calendar_joe,summary,start,end)=Call from ${CALLERID(all)},${start},${end})
++\end{verbatim}
++\end{astlisting}
+
+Property changes on: doc/tex/calendaring.tex
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+
+Index: doc/tex/misdn.tex
+===================================================================
+--- a/doc/tex/misdn.tex (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/doc/tex/misdn.tex (.../trunk) (revision 202568)
+@@ -247,7 +247,7 @@
+ an '*', the rest is clear I think.
+
+ Please take a trace of the problem and open a report in the Asterisk issue
+-tracker at \url{http://bugs.digium.com} in the "channel drivers" project,
++tracker at \url{https://issues.asterisk.org} in the "channel drivers" project,
+ "chan\_misdn" category. Read the bug guidelines to make sure you
+ provide all the information needed.
+
+Index: doc/tex/backtrace.tex
+===================================================================
+--- a/doc/tex/backtrace.tex (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/doc/tex/backtrace.tex (.../trunk) (revision 202568)
+@@ -1,6 +1,6 @@
+ This document is intended to provide information on how to obtain the
+ backtraces required on the asterisk bug tracker, available at
+-\url{http://bugs.digium.com}. The information is required by developers to
++\url{https://issues.asterisk.org}. The information is required by developers to
+ help fix problem with bugs of any kind. Backtraces provide information
+ about what was wrong when a program crashed; in our case,
+ Asterisk. There are two kind of backtraces (aka 'bt') which are
+Index: doc/tex/mp3.tex
+===================================================================
+--- a/doc/tex/mp3.tex (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/doc/tex/mp3.tex (.../trunk) (revision 202568)
+@@ -7,5 +7,5 @@
+ However, if you still need to use mp3 as your music on hold format, a format
+ driver for reading MP3 audio files is available in the asterisk-addons SVN
+ repository on svn.digium.com or in the asterisk-addons release at
+-\url{http://downloads.digium.com/pub/telephony/asterisk/}.
++\url{http://downloads.asterisk.org/pub/telephony/asterisk/}.
+
+Index: UPGRADE.txt
+===================================================================
+--- a/UPGRADE.txt (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/UPGRADE.txt (.../trunk) (revision 202568)
+@@ -18,6 +18,17 @@
+ ===
+ ===========================================================
+
++From 1.6.2 to 1.6.3:
++
++* The usage of RTP inside of Asterisk has now become modularized. This means
++ the Asterisk RTP stack now exists as a loadable module, res_rtp_asterisk.
++ If you are not using autoload=yes in modules.conf you will need to ensure
++ it is set to load. If not, then any module which uses RTP (such as chan_sip)
++ will not be able to send or receive calls.
++* The app_dahdiscan.c file has been removed, but the dialplan app DAHDIScan still
++ remains. It now exists within app_chanspy.c and retains the exact same
++ functionality as before.
++
+ From 1.6.1 to 1.6.2:
+
+ * The res_indications module has been removed. Its functionality was important
+Index: CHANGES
+===================================================================
+--- a/CHANGES (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/CHANGES (.../trunk) (revision 202568)
+@@ -7,7 +7,170 @@
+ === and the other UPGRADE files for older releases.
+ ===
+ ======================================================================
++------------------------------------------------------------------------------
++--- Functionality changes from Asterisk 1.6.2 to Asterisk 1.6.3 -------------
++------------------------------------------------------------------------------
+
++SIP Changes
++-----------
++ * Added preferred_codec_only option in sip.conf. This feature limits the joint
++ codecs sent in response to an INVITE to the single most preferred codec.
++ * Added SIP_CODEC_OUTBOUND dialplan variable which can be used to set the codec
++ to be used for the outgoing call. It must be one of the codecs configured
++ for the device.
++ * Added tlsprivatekey option to sip.conf. This allows a separate .pem file
++ to be used for holding a private key. If tlsprivatekey is not specified,
++ tlscertfile is searched for both public and private key.
++ * Added tlsclientmethod option to sip.conf. This allows the protocol for
++ outbound client connections to be specified.
++ * The sendrpid parameter has been expanded to include the options
++ 'rpid' and 'pai'. Setting sendrpid to 'rpid' will cause Remote-Party-ID
++ header to be sent (equivalent to setting sendrpid=yes) and setting
++ sendrpid to 'pai' will cause P-Asserted-Identity header to be sent.
++ * The 'ignoresdpversion' behavior has been made automatic when the SDP received
++ is in response to a T.38 re-INVITE that Asterisk initiated. In this situation,
++ since the call will fail if Asterisk does not process the incoming SDP, Asterisk
++ will accept the SDP even if the SDP version number is not properly incremented,
++ but will generate a warning in the log indicating that the SIP peer that sent
++ the SDP should have the 'ignoresdpversion' option set.
++
++IAX2 Changes
++-----------
++ * Added rtsavesysname option into iax.conf to allow the systname to be saved
++ on realtime updates.
++
++Applications
++------------
++ * Added progress option to the app_dial D() option. When progress DTMF is
++ present, those values are sent immediatly upon receiving a PROGRESS message
++ regardless if the call has been answered or not.
++ * Added functionality to the app_dial F() option to continue with execution
++ at the current location when no parameters are provided.
++ * Added c() option to app_chanspy. This option allows custom DTMF to be set
++ to cycle through the next avaliable channel. By default this is still '*'.
++ * Added x() option to app_chanspy. This option allows DTMF to be set to
++ exit the application.
++
++Dialplan Functions
++------------------
++ * Added new dialplan functions CONNECTEDLINE and REDIRECTING which permits
++ setting various connected line and redirecting party information.
++ * The CHANNEL() function now supports the "name" option.
++ * For DAHDI channels, the CHANNEL() dialplan function now
++ supports changing the channel's buffer policy (for the current
++ call only), using this syntax:
++
++ exten => s,n,Set(CHANNEL(buffers)=6,full)
++
++ This would change the channel to the 'full' buffer policy and
++ 6 (six) buffers. Possible options for this setting are the same
++ as those in chan_dahdi.conf.
++ * For DAHDI channels, the CHANNEL() dialplan function now allows
++ the dialplan to request changes in the configuration of the active
++ echo canceller on the channel (if any), for the current call only.
++ The syntax is:
++
++ exten => s,n,Set(CHANNEL(echocan_mode)=off)
++
++ The possible values are:
++
++ on - normal mode (the echo canceller is actually reinitalized)
++ off - disabled
++ fax - FAX/data mode (NLP disabled if possible, otherwise completely
++ disabled)
++ voice - voice mode (returns from FAX mode, reverting the changes that
++ were made when FAX mode was requested)
++
++Queue changes
++-------------
++ * A new option, 'I' has been added to both app_queue and app_dial.
++ By setting this option, Asterisk will not update the caller with
++ connected line changes or redirecting party changes when they occur.
++
++mISDN channel driver (chan_misdn) changes
++----------------------------------------
++ * Added display_connected parameter to misdn.conf to put a display string
++ in the CONNECT message containing the connected name and/or number if
++ the presentation setting permits it.
++ * Added display_setup parameter to misdn.conf to put a display string
++ in the SETUP message containing the caller name and/or number if the
++ presentation setting permits it.
++ * Made misdn.conf parameters localdialplan and cpndialplan take a -1 to
++ indicate the dialplan settings are to be obtained from the asterisk
++ channel.
++ * Made misdn.conf parameter callerid accept the "name" <number> format
++ used by the rest of the system.
++ * Made use the nationalprefix and internationalprefix misdn.conf
++ parameters to prefix any received number from the ISDN link if that
++ number has the corresponding Type-Of-Number.
++ * Added the following new parameters: unknownprefix, netspecificprefix,
++ subscriberprefix, and abbreviatedprefix in misdn.conf to prefix any
++ received number from the ISDN link if that number has the corresponding
++ Type-Of-Number.
++ * Added new dialplan application misdn_command which permits controlling
++ the CCBS/CCNR functionality.
++ * Added new dialplan function mISDN_CC which permits retrieval of various
++ values from an active call completion record.
++ * For PTP, you should manually send the COLR of the redirected-to party
++ for an incomming redirected call if the incoming call could experience
++ further redirects. Just set the REDIRECTING(to-num,i) = ${EXTEN} and
++ set the REDIRECTING(to-pres) to the COLR. A call has been redirected
++ if the REDIRECTING(from-num) is not empty.
++ * For outgoing PTP redirected calls, you now need to use the inhibit(i)
++ option on all of the REDIRECTING statements before dialing the
++ redirected-to party. You still have to set the REDIRECTING(to-xxx,i)
++ and the REDIRECTING(from-xxx,i) values. The PTP call will update the
++ redirecting-to presentation (COLR) when it becomes available.
++ * Added outgoing_colp parameter to misdn.conf to filter outgoing COLP
++ information.
++
++thirdparty mISDN enhancements
++-----------------------------
++mISDN has been modified by Digium, Inc. to greatly expand facility message
++support to allow:
++ * Enhanced COLP support for call diversion and transfer.
++ * CCBS/CCNR support.
++
++The latest modified mISDN v1.1.x based version is available at:
++http://svn.digium.com/svn/thirdparty/mISDN/trunk
++http://svn.digium.com/svn/thirdparty/mISDNuser/trunk
++
++Tagged versions of the modified mISDN code are available under:
++http://svn.digium.com/svn/thirdparty/mISDN/tags
++http://svn.digium.com/svn/thirdparty/mISDNuser/tags
++
++Asterisk Manager Interface
++--------------------------
++ * The Hangup action now accepts a Cause header which may be used to
++ set the channel's hangup cause.
++ * sslprivatekey option added to manager.conf and http.conf. Adds the ability
++ to specify a separate .pem file to hold a private key. By default sslcert
++ is used to hold both the public and private key.
++ * Options in manager.conf and http.conf with the 'ssl' prefix have been replaced
++ for options containing the 'tls' prefix. For example, 'sslenable' is now
++ 'tlsenable'. This has been done in effort to keep ssl and tls options consistent
++ across all .conf files. All affected sample.conf files have been modified to
++ reflect this change. Previous options such as 'sslenable' still work,
++ but options with the 'tls' prefix are preferred.
++
++Logger
++------
++ * The rarely used 'event_log' and LOG_EVENT channel have been removed; the few
++ users of this channel in the tree have been converted to LOG_NOTICE or removed
++ (in cases where the same message was already generated to another channel).
++
++CDR
++---
++ * Multiple files and formats can now be specified in cdr_custom.conf.
++
++Calendaring for Asterisk
++------------------------
++ * A new set of modules were added supporing calendar integration with Asterisk.
++ Dialplan functions for reading from and writing to calendars are included,
++ as well as the ability to execute dialplan logic upon calendar event notifications.
++ iCalendar, CalDAV, and Exchange Server calendars are supported (Exchange support
++ only tested on Exchange Server 2003 with no support for forms-based authentication).
++
+ ------------------------------------------------------------------------------
+ --- Functionality changes from Asterisk 1.6.1 to Asterisk 1.6.2 -------------
+ ------------------------------------------------------------------------------
+@@ -77,6 +240,7 @@
+ and a 'full' buffer policy for a fax transmission, add:
+ faxbuffers=>6,full
+ The faxbuffers configuration will be in affect until the call is torn down.
++ * Added service message support for 4ESS/5ESS switches.
+
+ Dialplan Functions
+ ------------------
+Index: sounds/Makefile
+===================================================================
+--- a/sounds/Makefile (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/sounds/Makefile (.../trunk) (revision 202568)
+@@ -19,7 +19,7 @@
+ MOH_DIR:=$(DESTDIR)$(ASTDATADIR)/moh
+ CORE_SOUNDS_VERSION:=1.4.15
+ EXTRA_SOUNDS_VERSION:=1.4.9
+-SOUNDS_URL:=http://downloads.digium.com/pub/telephony/sounds/releases
++SOUNDS_URL:=http://downloads.asterisk.org/pub/telephony/sounds/releases
+ MCS:=$(subst -EN-,-en-,$(MENUSELECT_CORE_SOUNDS))
+ MCS:=$(subst -FR-,-fr-,$(MCS))
+ MCS:=$(subst -ES-,-es-,$(MCS))
+Index: Makefile
+===================================================================
+--- a/Makefile (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/Makefile (.../trunk) (revision 202568)
+@@ -307,7 +307,7 @@
+
+ ifneq ($(findstring darwin,$(OSARCH)),)
+ ASTCFLAGS+=-D__Darwin__
+- SOLINK=-dynamic -bundle -undefined suppress -force_flat_namespace
++ SOLINK=-bundle -undefined suppress -force_flat_namespace
+ else
+ # These are used for all but Darwin
+ SOLINK=-shared
+@@ -327,6 +327,10 @@
+ # comment to print directories during submakes
+ #PRINT_DIR=yes
+
++ifneq ($(INSIDE_EMACS),)
++PRINT_DIR=yes
++endif
++
+ SILENTMAKE:=$(MAKE) --quiet --no-print-directory
+ ifneq ($(PRINT_DIR)$(NOISY_BUILD),)
+ SUBMAKE:=$(MAKE)
+@@ -371,24 +375,24 @@
+ menuselect/menuselect --check-deps menuselect.makeopts $(GLOBAL_MAKEOPTS) $(USER_MAKEOPTS)
+
+ $(MOD_SUBDIRS_EMBED_LDSCRIPT):
+- @echo "EMBED_LDSCRIPTS+="`$(SILENTMAKE) -C $(@:-embed-ldscript=) SUBDIR=$(@:-embed-ldscript=) __embed_ldscript` >> makeopts.embed_rules
++ +@echo "EMBED_LDSCRIPTS+="`$(SILENTMAKE) -C $(@:-embed-ldscript=) SUBDIR=$(@:-embed-ldscript=) __embed_ldscript` >> makeopts.embed_rules
+
+ $(MOD_SUBDIRS_EMBED_LDFLAGS):
+- @echo "EMBED_LDFLAGS+="`$(SILENTMAKE) -C $(@:-embed-ldflags=) SUBDIR=$(@:-embed-ldflags=) __embed_ldflags` >> makeopts.embed_rules
++ +@echo "EMBED_LDFLAGS+="`$(SILENTMAKE) -C $(@:-embed-ldflags=) SUBDIR=$(@:-embed-ldflags=) __embed_ldflags` >> makeopts.embed_rules
+
+ $(MOD_SUBDIRS_EMBED_LIBS):
+- @echo "EMBED_LIBS+="`$(SILENTMAKE) -C $(@:-embed-libs=) SUBDIR=$(@:-embed-libs=) __embed_libs` >> makeopts.embed_rules
++ +@echo "EMBED_LIBS+="`$(SILENTMAKE) -C $(@:-embed-libs=) SUBDIR=$(@:-embed-libs=) __embed_libs` >> makeopts.embed_rules
+
+ $(MOD_SUBDIRS_MENUSELECT_TREE):
+- @$(SUBMAKE) -C $(@:-menuselect-tree=) SUBDIR=$(@:-menuselect-tree=) moduleinfo
+- @$(SUBMAKE) -C $(@:-menuselect-tree=) SUBDIR=$(@:-menuselect-tree=) makeopts
++ +@$(SUBMAKE) -C $(@:-menuselect-tree=) SUBDIR=$(@:-menuselect-tree=) moduleinfo
++ +@$(SUBMAKE) -C $(@:-menuselect-tree=) SUBDIR=$(@:-menuselect-tree=) makeopts
+
+ makeopts.embed_rules: menuselect.makeopts
+ @echo "Generating embedded module rules ..."
+ @rm -f $@
+- @$(SUBMAKE) $(MOD_SUBDIRS_EMBED_LDSCRIPT)
+- @$(SUBMAKE) $(MOD_SUBDIRS_EMBED_LDFLAGS)
+- @$(SUBMAKE) $(MOD_SUBDIRS_EMBED_LIBS)
++ +@$(SUBMAKE) $(MOD_SUBDIRS_EMBED_LDSCRIPT)
++ +@$(SUBMAKE) $(MOD_SUBDIRS_EMBED_LDFLAGS)
++ +@$(SUBMAKE) $(MOD_SUBDIRS_EMBED_LIBS)
+
+ $(SUBDIRS): main/version.c include/asterisk/version.h include/asterisk/build.h include/asterisk/buildopts.h defaults.h makeopts.embed_rules
+
+@@ -411,10 +415,10 @@
+ endif
+
+ $(MOD_SUBDIRS):
+- @ASTCFLAGS="$(MOD_SUBDIR_CFLAGS) $(ASTCFLAGS)" ASTLDFLAGS="$(ASTLDFLAGS)" $(SUBMAKE) --no-builtin-rules -C $@ SUBDIR=$@ all
++ +@ASTCFLAGS="$(MOD_SUBDIR_CFLAGS) $(ASTCFLAGS)" ASTLDFLAGS="$(ASTLDFLAGS)" $(SUBMAKE) --no-builtin-rules -C $@ SUBDIR=$@ all
+
+ $(OTHER_SUBDIRS):
+- @ASTCFLAGS="$(OTHER_SUBDIR_CFLAGS) $(ASTCFLAGS)" ASTLDFLAGS="$(ASTLDFLAGS)" $(SUBMAKE) --no-builtin-rules -C $@ SUBDIR=$@ all
++ +@ASTCFLAGS="$(OTHER_SUBDIR_CFLAGS) $(ASTCFLAGS)" ASTLDFLAGS="$(ASTLDFLAGS)" $(SUBMAKE) --no-builtin-rules -C $@ SUBDIR=$@ all
+
+ defaults.h: makeopts
+ @build_tools/make_defaults_h > $@.tmp
+@@ -442,10 +446,10 @@
+ @rm -f $@.tmp
+
+ $(SUBDIRS_CLEAN):
+- @$(SUBMAKE) -C $(@:-clean=) clean
++ +@$(SUBMAKE) -C $(@:-clean=) clean
+
+ $(SUBDIRS_DIST_CLEAN):
+- @$(SUBMAKE) -C $(@:-dist-clean=) dist-clean
++ +@$(SUBMAKE) -C $(@:-dist-clean=) dist-clean
+
+ clean: $(SUBDIRS_CLEAN) _clean
+
+@@ -559,8 +563,10 @@
+ chmod 755 $(DESTDIR)$(ASTSBINDIR)/safe_asterisk;\
+ fi
+ $(INSTALL) -d $(DESTDIR)$(ASTHEADERDIR)
++ $(INSTALL) -d $(DESTDIR)$(ASTHEADERDIR)/doxygen
+ $(INSTALL) -m 644 include/asterisk.h $(DESTDIR)$(includedir)
+ $(INSTALL) -m 644 include/asterisk/*.h $(DESTDIR)$(ASTHEADERDIR)
++ $(INSTALL) -m 644 include/asterisk/doxygen/*.h $(DESTDIR)$(ASTHEADERDIR)/doxygen
+ if [ -n "$(OLDHEADERS)" ]; then \
+ rm -f $(addprefix $(DESTDIR)$(ASTHEADERDIR)/,$(OLDHEADERS)) ;\
+ fi
+@@ -918,28 +924,28 @@
+ MAKE_MENUSELECT=CC="$(HOST_CC)" CXX="$(CXX)" LD="" AR="" RANLIB="" CFLAGS="" $(MAKE) -C menuselect CONFIGURE_SILENT="--silent"
+
+ menuselect/menuselect: menuselect/makeopts
+- $(MAKE_MENUSELECT) menuselect
++ +$(MAKE_MENUSELECT) menuselect
+
+ menuselect/cmenuselect: menuselect/makeopts
+- $(MAKE_MENUSELECT) cmenuselect
++ +$(MAKE_MENUSELECT) cmenuselect
+
+ menuselect/gmenuselect: menuselect/makeopts
+- $(MAKE_MENUSELECT) gmenuselect
++ +$(MAKE_MENUSELECT) gmenuselect
+
+ menuselect/nmenuselect: menuselect/makeopts
+- $(MAKE_MENUSELECT) nmenuselect
++ +$(MAKE_MENUSELECT) nmenuselect
+
+ menuselect/makeopts: makeopts
+- $(MAKE_MENUSELECT) makeopts
++ +$(MAKE_MENUSELECT) makeopts
+
+ menuselect-tree: $(foreach dir,$(filter-out main,$(MOD_SUBDIRS)),$(wildcard $(dir)/*.c) $(wildcard $(dir)/*.cc)) build_tools/cflags.xml build_tools/cflags-devmode.xml sounds/sounds.xml build_tools/embed_modules.xml configure
+ @echo "Generating input for menuselect ..."
+ @echo "<?xml version=\"1.0\"?>" > $@
+ @echo >> $@
+ @echo "<menu name=\"Asterisk Module and Build Option Selection\">" >> $@
+- @for dir in $(sort $(filter-out main,$(MOD_SUBDIRS))); do $(SILENTMAKE) -C $${dir} SUBDIR=$${dir} moduleinfo >> $@; done
++ +@for dir in $(sort $(filter-out main,$(MOD_SUBDIRS))); do $(SILENTMAKE) -C $${dir} SUBDIR=$${dir} moduleinfo >> $@; done
+ @cat build_tools/cflags.xml >> $@
+- @for dir in $(sort $(filter-out main,$(MOD_SUBDIRS))); do $(SILENTMAKE) -C $${dir} SUBDIR=$${dir} makeopts >> $@; done
++ +@for dir in $(sort $(filter-out main,$(MOD_SUBDIRS))); do $(SILENTMAKE) -C $${dir} SUBDIR=$${dir} makeopts >> $@; done
+ @if [ "${AST_DEVMODE}" = "yes" ]; then \
+ cat build_tools/cflags-devmode.xml >> $@; \
+ fi
+Index: autoconf/ast_gcc_attribute.m4
+===================================================================
+--- a/autoconf/ast_gcc_attribute.m4 (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/autoconf/ast_gcc_attribute.m4 (.../trunk) (revision 202568)
+@@ -1,16 +1,16 @@
+ # Helper function to check for gcc attributes.
+-# AST_GCC_ATTRIBUTE([attribute name], [attribute syntax])
++# AST_GCC_ATTRIBUTE([attribute name], [attribute syntax], [attribute scope])
+
+ AC_DEFUN([AST_GCC_ATTRIBUTE],
+ [
+ AC_MSG_CHECKING(for compiler 'attribute $1' support)
+ saved_CFLAGS="$CFLAGS"
+-CFLAGS="$CFLAGS -Werror"
++CFLAGS="$CFLAGS -Wall -Wno-unused -Werror"
+
+ if test "x$2" = "x"
+ then
+ AC_COMPILE_IFELSE(
+- AC_LANG_PROGRAM([void __attribute__(($1)) *test(void *muffin, ...) {}],
++ AC_LANG_PROGRAM([$3 void __attribute__(($1)) *test(void *muffin, ...) {return (void *) 0;}],
+ []),
+ AC_MSG_RESULT(yes)
+ AC_DEFINE_UNQUOTED([HAVE_ATTRIBUTE_$1], 1, [Define to 1 if your GCC C compiler supports the '$1' attribute.]),
+@@ -18,7 +18,7 @@
+ )
+ else
+ AC_COMPILE_IFELSE(
+- AC_LANG_PROGRAM([void __attribute__(($2)) *test(void *muffin, ...) {}],
++ AC_LANG_PROGRAM([$3 void __attribute__(($2)) *test(void *muffin, ...) {return (void *) 0;}],
+ []),
+ AC_MSG_RESULT(yes)
+ AC_DEFINE_UNQUOTED([HAVE_ATTRIBUTE_$1], 1, [Define to 1 if your GCC C compiler supports the '$1' attribute.]),
+Index: autoconf/ast_ext_lib.m4
+===================================================================
+--- a/autoconf/ast_ext_lib.m4 (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/autoconf/ast_ext_lib.m4 (.../trunk) (revision 202568)
+@@ -11,7 +11,7 @@
+ $1_DESCRIP="$2"
+ $1_OPTION="$3"
+ PBX_$1=0
+- AC_ARG_WITH([$3], AC_HELP_STRING([--with-$3=PATH],[use $2 files in PATH $4]),
++ AC_ARG_WITH([$3], AC_HELP_STRING([--with-$3=PATH],[use $2 files in PATH$4]),
+ [
+ case ${withval} in
+ n|no)
+Index: funcs/func_rand.c
+===================================================================
+--- a/funcs/func_rand.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/funcs/func_rand.c (.../trunk) (revision 202568)
+@@ -87,6 +87,7 @@
+ static struct ast_custom_function acf_rand = {
+ .name = "RAND",
+ .read = acf_rand_exec,
++ .read_max = 12,
+ };
+
+ static int unload_module(void)
+Index: funcs/func_base64.c
+===================================================================
+--- a/funcs/func_base64.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/funcs/func_base64.c (.../trunk) (revision 202568)
+@@ -29,6 +29,7 @@
+ #include "asterisk/module.h"
+ #include "asterisk/pbx.h" /* function register/unregister */
+ #include "asterisk/utils.h"
++#include "asterisk/strings.h"
+
+ /*** DOCUMENTATION
+ <function name="BASE64_ENCODE" language="en_US">
+@@ -59,40 +60,61 @@
+ </function>
+ ***/
+
+-static int base64_encode(struct ast_channel *chan, const char *cmd, char *data,
+- char *buf, size_t len)
++static int base64_helper(struct ast_channel *chan, const char *cmd, char *data,
++ char *buf, struct ast_str **str, ssize_t len)
+ {
+ if (ast_strlen_zero(data)) {
+- ast_log(LOG_WARNING, "Syntax: BASE64_ENCODE(<data>) - missing argument!\n");
++ ast_log(LOG_WARNING, "Syntax: %s(<data>) - missing argument!\n", cmd);
+ return -1;
+ }
+
+- ast_base64encode(buf, (unsigned char *) data, strlen(data), len);
++ if (cmd[7] == 'E') {
++ if (buf) {
++ ast_base64encode(buf, (unsigned char *) data, strlen(data), len);
++ } else {
++ if (len >= 0) {
++ ast_str_make_space(str, len ? len : ast_str_strlen(*str) + strlen(data) * 4 / 3 + 2);
++ }
++ ast_base64encode(ast_str_buffer(*str) + ast_str_strlen(*str), (unsigned char *) data, strlen(data), ast_str_size(*str) - ast_str_strlen(*str));
++ ast_str_update(*str);
++ }
++ } else {
++ if (buf) {
++ ast_base64decode((unsigned char *) buf, data, len);
++ } else {
++ if (len >= 0) {
++ ast_str_make_space(str, len ? len : ast_str_strlen(*str) + strlen(data) * 3 / 4 + 2);
++ }
++ ast_base64decode((unsigned char *) ast_str_buffer(*str) + ast_str_strlen(*str), data, ast_str_size(*str) - ast_str_strlen(*str));
++ ast_str_update(*str);
++ }
++ }
+
+ return 0;
+ }
+
+-static int base64_decode(struct ast_channel *chan, const char *cmd, char *data,
++static int base64_buf_helper(struct ast_channel *chan, const char *cmd, char *data,
+ char *buf, size_t len)
+ {
+- if (ast_strlen_zero(data)) {
+- ast_log(LOG_WARNING, "Syntax: BASE64_DECODE(<base_64 string>) - missing argument!\n");
+- return -1;
+- }
++ return base64_helper(chan, cmd, data, buf, NULL, len);
++}
+
+- ast_base64decode((unsigned char *) buf, data, len);
+-
+- return 0;
++static int base64_str_helper(struct ast_channel *chan, const char *cmd, char *data,
++ struct ast_str **buf, ssize_t len)
++{
++ return base64_helper(chan, cmd, data, NULL, buf, len);
+ }
+
+ static struct ast_custom_function base64_encode_function = {
+ .name = "BASE64_ENCODE",
+- .read = base64_encode,
++ .read = base64_buf_helper,
++ .read2 = base64_str_helper,
+ };
+
+ static struct ast_custom_function base64_decode_function = {
+ .name = "BASE64_DECODE",
+- .read = base64_decode,
++ .read = base64_buf_helper,
++ .read2 = base64_str_helper,
+ };
+
+ static int unload_module(void)
+Index: funcs/func_speex.c
+===================================================================
+--- a/funcs/func_speex.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/funcs/func_speex.c (.../trunk) (revision 202568)
+@@ -337,13 +337,15 @@
+ static struct ast_custom_function agc_function = {
+ .name = "AGC",
+ .write = speex_write,
+- .read = speex_read
++ .read = speex_read,
++ .read_max = 22,
+ };
+
+ static struct ast_custom_function denoise_function = {
+ .name = "DENOISE",
+ .write = speex_write,
+- .read = speex_read
++ .read = speex_read,
++ .read_max = 22,
+ };
+
+ static int unload_module(void)
+Index: funcs/func_module.c
+===================================================================
+--- a/funcs/func_module.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/funcs/func_module.c (.../trunk) (revision 202568)
+@@ -65,6 +65,7 @@
+ static struct ast_custom_function ifmodule_function = {
+ .name = "IFMODULE",
+ .read = ifmodule_read,
++ .read_max = 2,
+ };
+
+
+Index: funcs/func_md5.c
+===================================================================
+--- a/funcs/func_md5.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/funcs/func_md5.c (.../trunk) (revision 202568)
+@@ -64,6 +64,7 @@
+ static struct ast_custom_function md5_function = {
+ .name = "MD5",
+ .read = md5,
++ .read_max = 33,
+ };
+
+ static int unload_module(void)
+Index: funcs/func_env.c
+===================================================================
+--- a/funcs/func_env.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/funcs/func_env.c (.../trunk) (revision 202568)
+@@ -230,7 +230,8 @@
+
+ static struct ast_custom_function stat_function = {
+ .name = "STAT",
+- .read = stat_read
++ .read = stat_read,
++ .read_max = 12,
+ };
+
+ static struct ast_custom_function file_function = {
+Index: funcs/func_strings.c
+===================================================================
+--- a/funcs/func_strings.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/funcs/func_strings.c (.../trunk) (revision 202568)
+@@ -276,12 +276,83 @@
+ <para>Example: ${QUOTE(ab"c"de)} will return "abcde"</para>
+ </description>
+ </function>
++ <function name="SHIFT" language="en_US">
++ <synopsis>
++ Removes and returns the first item off of a variable containing delimited text
++ </synopsis>
++ <syntax>
++ <parameter name="varname" required="true" />
++ <parameter name="delimiter" required="false" default="," />
++ </syntax>
++ <description>
++ <para>Example:</para>
++ <para>exten => s,1,Set(array=one,two,three)</para>
++ <para>exten => s,n,While($["${SET(var=${SHIFT(array)})}" != ""])</para>
++ <para>exten => s,n,NoOp(var is ${var})</para>
++ <para>exten => s,n,EndWhile</para>
++ <para>This would iterate over each value in array, left to right, and
++ would result in NoOp(var is one), NoOp(var is two), and
++ NoOp(var is three) being executed.
++ </para>
++ </description>
++ </function>
++ <function name="POP" language="en_US">
++ <synopsis>
++ Removes and returns the last item off of a variable containing delimited text
++ </synopsis>
++ <syntax>
++ <parameter name="varname" required="true" />
++ <parameter name="delimiter" required="false" default="," />
++ </syntax>
++ <description>
++ <para>Example:</para>
++ <para>exten => s,1,Set(array=one,two,three)</para>
++ <para>exten => s,n,While($["${SET(var=${POP(array)})}" != ""])</para>
++ <para>exten => s,n,NoOp(var is ${var})</para>
++ <para>exten => s,n,EndWhile</para>
++ <para>This would iterate over each value in array, right to left, and
++ would result in NoOp(var is three), NoOp(var is two), and
++ NoOp(var is one) being executed.
++ </para>
++ </description>
++ </function>
++ <function name="PUSH" language="en_US">
++ <synopsis>
++ Appends one or more values to the end of a variable containing delimited text
++ </synopsis>
++ <syntax>
++ <parameter name="varname" required="true" />
++ <parameter name="delimiter" required="false" default="," />
++ </syntax>
++ <description>
++ <para>Example: Set(PUSH(array)=one,two,three) would append one,
++ two, and three to the end of the values stored in the variable
++ "array".
++ </para>
++ </description>
++ </function>
++ <function name="UNSHIFT" language="en_US">
++ <synopsis>
++ Inserts one or more values to the beginning of a variable containing delimited text
++ </synopsis>
++ <syntax>
++ <parameter name="varname" required="true" />
++ <parameter name="delimiter" required="false" default="," />
++ </syntax>
++ <description>
++ <para>Example: Set(UNSHIFT(array)=one,two,three) would insert one,
++ two, and three before the values stored in the variable
++ "array".
++ </para>
++ </description>
++ </function>
+ ***/
+
+-static int function_fieldqty(struct ast_channel *chan, const char *cmd,
+- char *parse, char *buf, size_t len)
++static int function_fieldqty_helper(struct ast_channel *chan, const char *cmd,
++ char *parse, char *buf, struct ast_str **sbuf, ssize_t len)
+ {
+- char *varsubst, varval[8192], *varval2 = varval;
++ char *varsubst;
++ struct ast_str *str = ast_str_create(16);
+ int fieldcount = 0;
+ AST_DECLARE_APP_ARGS(args,
+ AST_APP_ARG(varname);
+@@ -290,6 +361,10 @@
+ char delim[2] = "";
+ size_t delim_used;
+
++ if (!str) {
++ return -1;
++ }
++
+ AST_STANDARD_APP_ARGS(args, parse);
+ if (args.delim) {
+ ast_get_encoded_char(args.delim, delim, &delim_used);
+@@ -297,27 +372,47 @@
+ varsubst = alloca(strlen(args.varname) + 4);
+
+ sprintf(varsubst, "${%s}", args.varname);
+- pbx_substitute_variables_helper(chan, varsubst, varval, sizeof(varval) - 1);
+- if (ast_strlen_zero(varval2))
++ ast_str_substitute_variables(&str, 0, chan, varsubst);
++ if (ast_str_strlen(str) == 0) {
+ fieldcount = 0;
+- else {
+- while (strsep(&varval2, delim))
++ } else {
++ char *varval = ast_str_buffer(str);
++ while (strsep(&varval, delim)) {
+ fieldcount++;
++ }
+ }
+ } else {
+ fieldcount = 1;
+ }
+- snprintf(buf, len, "%d", fieldcount);
++ if (sbuf) {
++ ast_str_set(sbuf, len, "%d", fieldcount);
++ } else {
++ snprintf(buf, len, "%d", fieldcount);
++ }
+
++ ast_free(str);
+ return 0;
+ }
+
++static int function_fieldqty(struct ast_channel *chan, const char *cmd,
++ char *parse, char *buf, size_t len)
++{
++ return function_fieldqty_helper(chan, cmd, parse, buf, NULL, len);
++}
++
++static int function_fieldqty_str(struct ast_channel *chan, const char *cmd,
++ char *parse, struct ast_str **buf, ssize_t len)
++{
++ return function_fieldqty_helper(chan, cmd, parse, NULL, buf, len);
++}
++
+ static struct ast_custom_function fieldqty_function = {
+ .name = "FIELDQTY",
+ .read = function_fieldqty,
++ .read2 = function_fieldqty_str,
+ };
+
+-static int listfilter(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
++static int listfilter(struct ast_channel *chan, const char *cmd, char *parse, char *buf, struct ast_str **bufstr, ssize_t len)
+ {
+ AST_DECLARE_APP_ARGS(args,
+ AST_APP_ARG(listname);
+@@ -327,11 +422,18 @@
+ const char *orig_list, *ptr;
+ const char *begin, *cur, *next;
+ int dlen, flen, first = 1;
+- struct ast_str *result = ast_str_thread_get(&result_buf, 16);
++ struct ast_str *result, **result_ptr = &result;
+ char *delim;
+
+ AST_STANDARD_APP_ARGS(args, parse);
+
++ if (buf) {
++ result = ast_str_thread_get(&result_buf, 16);
++ } else {
++ /* Place the result directly into the output buffer */
++ result_ptr = bufstr;
++ }
++
+ if (args.argc < 3) {
+ ast_log(LOG_ERROR, "Usage: LISTFILTER(<listname>,<delimiter>,<fieldvalue>)\n");
+ return -1;
+@@ -351,7 +453,11 @@
+
+ /* If the string isn't there, just copy out the string and be done with it. */
+ if (!(ptr = strstr(orig_list, args.fieldvalue))) {
+- ast_copy_string(buf, orig_list, len);
++ if (buf) {
++ ast_copy_string(buf, orig_list, len);
++ } else {
++ ast_str_set(result_ptr, len, "%s", orig_list);
++ }
+ if (chan) {
+ ast_channel_unlock(chan);
+ }
+@@ -371,7 +477,9 @@
+
+ ast_str_reset(result);
+ /* Enough space for any result */
+- ast_str_make_space(&result, strlen(orig_list) + 1);
++ if (len > -1) {
++ ast_str_make_space(result_ptr, len ? len : strlen(orig_list) + 1);
++ }
+
+ begin = orig_list;
+ next = strstr(begin, delim);
+@@ -391,10 +499,10 @@
+ } else {
+ /* Copy field to output */
+ if (!first) {
+- ast_str_append(&result, 0, "%s", delim);
++ ast_str_append(result_ptr, len, "%s", delim);
+ }
+
+- ast_str_append_substr(&result, 0, begin, cur - begin + 1);
++ ast_str_append_substr(result_ptr, len, begin, cur - begin + 1);
+ first = 0;
+ begin = cur + dlen;
+ }
+@@ -403,14 +511,27 @@
+ ast_channel_unlock(chan);
+ }
+
+- ast_copy_string(buf, ast_str_buffer(result), len);
++ if (buf) {
++ ast_copy_string(buf, ast_str_buffer(result), len);
++ }
+
+ return 0;
+ }
+
++static int listfilter_read(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
++{
++ return listfilter(chan, cmd, parse, buf, NULL, len);
++}
++
++static int listfilter_read2(struct ast_channel *chan, const char *cmd, char *parse, struct ast_str **buf, ssize_t len)
++{
++ return listfilter(chan, cmd, parse, NULL, buf, len);
++}
++
+ static struct ast_custom_function listfilter_function = {
+ .name = "LISTFILTER",
+- .read = listfilter,
++ .read = listfilter_read,
++ .read2 = listfilter_read2,
+ };
+
+ static int filter(struct ast_channel *chan, const char *cmd, char *parse, char *buf,
+@@ -538,7 +659,7 @@
+ AST_LIST_TRAVERSE_SAFE_END
+ }
+
+-static int exec_clearhash(struct ast_channel *chan, void *data)
++static int exec_clearhash(struct ast_channel *chan, const char *data)
+ {
+ char prefix[80];
+ snprintf(prefix, sizeof(prefix), HASH_PREFIX, data ? (char *)data : "null");
+@@ -614,16 +735,15 @@
+ static int hashkeys_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
+ {
+ struct ast_var_t *newvar;
+- int plen;
+- char prefix[80];
+- snprintf(prefix, sizeof(prefix), HASH_PREFIX, data);
+- plen = strlen(prefix);
++ struct ast_str *prefix = ast_str_alloca(80);
+
++ ast_str_set(&prefix, -1, HASH_PREFIX, data);
+ memset(buf, 0, len);
++
+ AST_LIST_TRAVERSE(&chan->varshead, newvar, entries) {
+- if (strncasecmp(prefix, ast_var_name(newvar), plen) == 0) {
++ if (strncasecmp(ast_str_buffer(prefix), ast_var_name(newvar), ast_str_strlen(prefix)) == 0) {
+ /* Copy everything after the prefix */
+- strncat(buf, ast_var_name(newvar) + plen, len - strlen(buf) - 1);
++ strncat(buf, ast_var_name(newvar) + ast_str_strlen(prefix), len - strlen(buf) - 1);
+ /* Trim the trailing ~ */
+ buf[strlen(buf) - 1] = ',';
+ }
+@@ -633,6 +753,29 @@
+ return 0;
+ }
+
++static int hashkeys_read2(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
++{
++ struct ast_var_t *newvar;
++ struct ast_str *prefix = ast_str_alloca(80);
++ char *tmp;
++
++ ast_str_set(&prefix, -1, HASH_PREFIX, data);
++
++ AST_LIST_TRAVERSE(&chan->varshead, newvar, entries) {
++ if (strncasecmp(ast_str_buffer(prefix), ast_var_name(newvar), ast_str_strlen(prefix)) == 0) {
++ /* Copy everything after the prefix */
++ ast_str_append(buf, len, "%s", ast_var_name(newvar) + ast_str_strlen(prefix));
++ /* Trim the trailing ~ */
++ tmp = ast_str_buffer(*buf);
++ tmp[ast_str_strlen(*buf) - 1] = ',';
++ }
++ }
++ /* Trim the trailing comma */
++ tmp = ast_str_buffer(*buf);
++ tmp[ast_str_strlen(*buf) - 1] = '\0';
++ return 0;
++}
++
+ static int hash_write(struct ast_channel *chan, const char *cmd, char *var, const char *value)
+ {
+ char varname[256];
+@@ -708,6 +851,7 @@
+ static struct ast_custom_function hashkeys_function = {
+ .name = "HASHKEYS",
+ .read = hashkeys_read,
++ .read2 = hashkeys_read2,
+ };
+
+ static struct ast_custom_function array_function = {
+@@ -759,6 +903,7 @@
+ static struct ast_custom_function len_function = {
+ .name = "LEN",
+ .read = len,
++ .read_max = 12,
+ };
+
+ static int acf_strftime(struct ast_channel *chan, const char *cmd, char *parse,
+@@ -850,9 +995,23 @@
+ return 0;
+ }
+
++static int function_eval2(struct ast_channel *chan, const char *cmd, char *data,
++ struct ast_str **buf, ssize_t buflen)
++{
++ if (ast_strlen_zero(data)) {
++ ast_log(LOG_WARNING, "EVAL requires an argument: EVAL(<string>)\n");
++ return -1;
++ }
++
++ ast_str_substitute_variables(buf, buflen, chan, data);
++
++ return 0;
++}
++
+ static struct ast_custom_function eval_function = {
+ .name = "EVAL",
+ .read = function_eval,
++ .read2 = function_eval2,
+ };
+
+ static int keypadhash(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
+@@ -904,9 +1063,24 @@
+ return 0;
+ }
+
++static int string_toupper2(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t buflen)
++{
++ char *bufptr, *dataptr = data;
++
++ if (buflen > -1) {
++ ast_str_make_space(buf, buflen > 0 ? buflen : strlen(data) + 1);
++ }
++ bufptr = ast_str_buffer(*buf);
++ while ((bufptr < ast_str_buffer(*buf) + ast_str_size(*buf) - 1) && (*bufptr++ = toupper(*dataptr++)));
++ ast_str_update(*buf);
++
++ return 0;
++}
++
+ static struct ast_custom_function toupper_function = {
+ .name = "TOUPPER",
+ .read = string_toupper,
++ .read2 = string_toupper2,
+ };
+
+ static int string_tolower(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
+@@ -918,11 +1092,160 @@
+ return 0;
+ }
+
++static int string_tolower2(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t buflen)
++{
++ char *bufptr, *dataptr = data;
++
++ if (buflen > -1) {
++ ast_str_make_space(buf, buflen > 0 ? buflen : strlen(data) + 1);
++ }
++ bufptr = ast_str_buffer(*buf);
++ while ((bufptr < ast_str_buffer(*buf) + ast_str_size(*buf) - 1) && (*bufptr++ = tolower(*dataptr++)));
++ ast_str_update(*buf);
++
++ return 0;
++}
++
+ static struct ast_custom_function tolower_function = {
+ .name = "TOLOWER",
+ .read = string_tolower,
++ .read2 = string_tolower2,
+ };
+
++static int array_remove(struct ast_channel *chan, const char *cmd, char *var, char *buf, size_t len, int beginning)
++{
++ const char *tmp;
++ char *after, *before;
++ char *(*search_func)(const char *s, int c) = beginning ? strchr : strrchr;
++ AST_DECLARE_APP_ARGS(args,
++ AST_APP_ARG(var);
++ AST_APP_ARG(delimiter);
++ );
++
++ if (!chan) {
++ ast_log(LOG_WARNING, "%s requires a channel\n", cmd);
++ return -1;
++ }
++
++ AST_STANDARD_APP_ARGS(args, var);
++
++ if (ast_strlen_zero(args.var)) {
++ ast_log(LOG_WARNING, "%s requires a channel variable name\n", cmd);
++ return -1;
++ }
++
++ if (args.delimiter && strlen(args.delimiter) != 1) {
++ ast_log(LOG_WARNING, "%s delimeters should be a single character\n", cmd);
++ return -1;
++ }
++
++ ast_channel_lock(chan);
++ if (ast_strlen_zero(tmp = pbx_builtin_getvar_helper(chan, args.var))) {
++ ast_channel_unlock(chan);
++ return 0;
++ }
++
++ before = ast_strdupa(tmp);
++ ast_channel_unlock(chan);
++
++ /* Only one entry in array */
++ if (!(after = search_func(before, S_OR(args.delimiter, ",")[0]))) {
++ ast_copy_string(buf, before, len);
++ pbx_builtin_setvar_helper(chan, args.var, "");
++ } else {
++ *after++ = '\0';
++ ast_copy_string(buf, beginning ? before : after, len);
++ pbx_builtin_setvar_helper(chan, args.var, beginning ? after : before);
++ }
++
++ return 0;
++
++}
++
++static int shift(struct ast_channel *chan, const char *cmd, char *var, char *buf, size_t len)
++{
++ return array_remove(chan, cmd, var, buf, len, 1);
++}
++static struct ast_custom_function shift_function = {
++ .name = "SHIFT",
++ .read = shift,
++};
++
++static int pop(struct ast_channel *chan, const char *cmd, char *var, char *buf, size_t len)
++{
++ return array_remove(chan, cmd, var, buf, len, 0);
++}
++
++static struct ast_custom_function pop_function = {
++ .name = "POP",
++ .read = pop,
++};
++
++static int array_insert(struct ast_channel *chan, const char *cmd, char *var, const char *val, int beginning)
++{
++ const char *tmp;
++ struct ast_str *buf;
++ AST_DECLARE_APP_ARGS(args,
++ AST_APP_ARG(var);
++ AST_APP_ARG(delimiter);
++ );
++
++ if (!chan) {
++ ast_log(LOG_WARNING, "%s requires a channel\n", cmd);
++ return -1;
++ }
++
++ AST_STANDARD_APP_ARGS(args, var);
++
++ if (ast_strlen_zero(args.var) || ast_strlen_zero(val)) {
++ ast_log(LOG_WARNING, "%s requires a variable, and at least one value\n", cmd);
++ return -1;
++ }
++
++ if (args.delimiter && strlen(args.delimiter) != 1) {
++ ast_log(LOG_WARNING, "%s delimeters should be a single character\n", cmd);
++ return -1;
++ }
++
++ if (!(buf = ast_str_create(32))) {
++ ast_log(LOG_ERROR, "Unable to allocate memory for buffer!\n");
++ return -1;
++ }
++
++ ast_channel_lock(chan);
++ if (!(tmp = pbx_builtin_getvar_helper(chan, args.var))) {
++ ast_str_set(&buf, 0, "%s", val);
++ } else {
++ ast_str_append(&buf, 0, "%s%s%s", beginning ? val : tmp, S_OR(args.delimiter, ","), beginning ? tmp : val);
++ }
++ ast_channel_unlock(chan);
++
++ pbx_builtin_setvar_helper(chan, args.var, ast_str_buffer(buf));
++ ast_free(buf);
++
++ return 0;
++}
++
++static int push(struct ast_channel *chan, const char *cmd, char *var, const char *val)
++{
++ return array_insert(chan, cmd, var, val, 0);
++}
++
++static struct ast_custom_function push_function = {
++ .name = "PUSH",
++ .write = push,
++};
++
++static int unshift(struct ast_channel *chan, const char *cmd, char *var, const char *val)
++{
++ return array_insert(chan, cmd, var, val, 1);
++}
++
++static struct ast_custom_function unshift_function = {
++ .name = "UNSHIFT",
++ .write = unshift,
++};
++
+ static int unload_module(void)
+ {
+ int res = 0;
+@@ -943,6 +1266,10 @@
+ res |= ast_unregister_application(app_clearhash);
+ res |= ast_custom_function_unregister(&toupper_function);
+ res |= ast_custom_function_unregister(&tolower_function);
++ res |= ast_custom_function_unregister(&shift_function);
++ res |= ast_custom_function_unregister(&pop_function);
++ res |= ast_custom_function_unregister(&push_function);
++ res |= ast_custom_function_unregister(&unshift_function);
+
+ return res;
+ }
+@@ -967,6 +1294,10 @@
+ res |= ast_register_application_xml(app_clearhash, exec_clearhash);
+ res |= ast_custom_function_register(&toupper_function);
+ res |= ast_custom_function_register(&tolower_function);
++ res |= ast_custom_function_register(&shift_function);
++ res |= ast_custom_function_register(&pop_function);
++ res |= ast_custom_function_register(&push_function);
++ res |= ast_custom_function_register(&unshift_function);
+
+ return res;
+ }
+Index: funcs/func_sysinfo.c
+===================================================================
+--- a/funcs/func_sysinfo.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/funcs/func_sysinfo.c (.../trunk) (revision 202568)
+@@ -36,6 +36,57 @@
+ #include "asterisk/module.h"
+ #include "asterisk/pbx.h"
+
++/*** DOCUMENTATION
++ <function name="SYSINFO" language="en_US">
++ <synopsis>
++ Returns system information specified by parameter.
++ </synopsis>
++ <syntax>
++ <parameter name="parameter" required="true">
++ <enumlist>
++ <enum name="loadavg">
++ <para>System load average from past minute.</para>
++ </enum>
++ <enum name="numcalls">
++ <para>Number of active calls currently in progress.</para>
++ </enum>
++ <enum name="uptime">
++ <para>System uptime in hours.</para>
++ <note><para>This parameter is dependant upon operating system.</para></note>
++ </enum>
++ <enum name="totalram">
++ <para>Total usable main memory size in KiB.</para>
++ <note><para>This parameter is dependant upon operating system.</para></note>
++ </enum>
++ <enum name="freeram">
++ <para>Available memory size in KiB.</para>
++ <note><para>This parameter is dependant upon operating system.</para></note>
++ </enum>
++ <enum name="bufferram">
++ <para>Memory used by buffers in KiB.</para>
++ <note><para>This parameter is dependant upon operating system.</para></note>
++ </enum>
++ <enum name="totalswap">
++ <para>Total swap space still available in KiB.</para>
++ <note><para>This parameter is dependant upon operating system.</para></note>
++ </enum>
++ <enum name="freeswap">
++ <para>Free swap space still available in KiB.</para>
++ <note><para>This parameter is dependant upon operating system.</para></note>
++ </enum>
++ <enum name="numprocs">
++ <para>Number of current processes.</para>
++ <note><para>This parameter is dependant upon operating system.</para></note>
++ </enum>
++ </enumlist>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Returns information from a given parameter.</para>
++ </description>
++ </function>
++ ***/
++
+ static int sysinfo_helper(struct ast_channel *chan, const char *cmd, char *data,
+ char *buf, size_t len)
+ {
+@@ -83,23 +134,8 @@
+
+ static struct ast_custom_function sysinfo_function = {
+ .name = "SYSINFO",
+- .synopsis = "Returns system information specified by parameter.",
+- .syntax = "SYSINFO(<parameter>)",
+ .read = sysinfo_helper,
+- .desc =
+-"Returns information from a given parameter\n"
+-" Options:\n"
+-" loadavg - system load average from past minute\n"
+-" numcalls - number of active calls currently in progress\n"
+-#if defined(HAVE_SYSINFO)
+-" uptime - system uptime in hours\n"
+-" totalram - total usable main memory size in KiB\n"
+-" freeram - available memory size in KiB\n"
+-" bufferram - memory used by buffers in KiB\n"
+-" totalswap - total swap space size in KiB\n"
+-" freeswap - free swap space still available in KiB\n"
+-" numprocs - number of current processes\n",
+-#endif /* HAVE_SYSINFO */
++ .read_max = 22,
+ };
+
+ static int unload_module(void)
+Index: funcs/func_vmcount.c
+===================================================================
+--- a/funcs/func_vmcount.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/funcs/func_vmcount.c (.../trunk) (revision 202568)
+@@ -94,9 +94,10 @@
+ return 0;
+ }
+
+-struct ast_custom_function acf_vmcount = {
++static struct ast_custom_function acf_vmcount = {
+ .name = "VMCOUNT",
+ .read = acf_vmcount_exec,
++ .read_max = 12,
+ };
+
+ static int unload_module(void)
+Index: funcs/func_sha1.c
+===================================================================
+--- a/funcs/func_sha1.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/funcs/func_sha1.c (.../trunk) (revision 202568)
+@@ -74,6 +74,7 @@
+ static struct ast_custom_function sha1_function = {
+ .name = "SHA1",
+ .read = sha1,
++ .read_max = 42,
+ };
+
+ static int unload_module(void)
+Index: funcs/func_logic.c
+===================================================================
+--- a/funcs/func_logic.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/funcs/func_logic.c (.../trunk) (revision 202568)
+@@ -223,41 +223,73 @@
+ return 0;
+ }
+
+-static int acf_import(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
++static int set2(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **str, ssize_t len)
+ {
++ if (len > -1) {
++ ast_str_make_space(str, len == 0 ? strlen(data) : len);
++ }
++ return set(chan, cmd, data, ast_str_buffer(*str), ast_str_size(*str));
++}
++
++static int import_helper(struct ast_channel *chan, const char *cmd, char *data, char *buf, struct ast_str **str, ssize_t len)
++{
+ AST_DECLARE_APP_ARGS(args,
+ AST_APP_ARG(channel);
+ AST_APP_ARG(varname);
+ );
+ AST_STANDARD_APP_ARGS(args, data);
+- buf[0] = 0;
++ if (buf) {
++ *buf = '\0';
++ }
++
+ if (!ast_strlen_zero(args.varname)) {
+- struct ast_channel *chan2 = ast_get_channel_by_name_locked(args.channel);
+- if (chan2) {
++ struct ast_channel *chan2;
++
++ if ((chan2 = ast_channel_get_by_name(args.channel))) {
+ char *s = alloca(strlen(args.varname) + 4);
+ if (s) {
+ sprintf(s, "${%s}", args.varname);
+- pbx_substitute_variables_helper(chan2, s, buf, len);
++ ast_channel_lock(chan2);
++ if (buf) {
++ pbx_substitute_variables_helper(chan2, s, buf, len);
++ } else {
++ ast_str_substitute_variables(str, len, chan2, s);
++ }
++ ast_channel_unlock(chan2);
+ }
+- ast_channel_unlock(chan2);
++ chan2 = ast_channel_unref(chan2);
+ }
+ }
++
+ return 0;
+ }
+
++static int import_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
++{
++ return import_helper(chan, cmd, data, buf, NULL, len);
++}
++
++static int import_read2(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **str, ssize_t len)
++{
++ return import_helper(chan, cmd, data, NULL, str, len);
++}
++
+ static struct ast_custom_function isnull_function = {
+ .name = "ISNULL",
+ .read = isnull,
++ .read_max = 2,
+ };
+
+ static struct ast_custom_function set_function = {
+ .name = "SET",
+ .read = set,
++ .read2 = set2,
+ };
+
+ static struct ast_custom_function exists_function = {
+ .name = "EXISTS",
+ .read = exists,
++ .read_max = 2,
+ };
+
+ static struct ast_custom_function if_function = {
+@@ -272,7 +304,8 @@
+
+ static struct ast_custom_function import_function = {
+ .name = "IMPORT",
+- .read = acf_import,
++ .read = import_read,
++ .read2 = import_read2,
+ };
+
+ static int unload_module(void)
+Index: funcs/func_enum.c
+===================================================================
+--- a/funcs/func_enum.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/funcs/func_enum.c (.../trunk) (revision 202568)
+@@ -216,7 +216,7 @@
+ return 0;
+ }
+
+-unsigned int enum_datastore_id;
++static unsigned int enum_datastore_id;
+
+ struct enum_result_datastore {
+ struct enum_context *context;
+@@ -243,7 +243,7 @@
+ erds_destroy(erds);
+ }
+
+-const struct ast_datastore_info enum_result_datastore_info = {
++static const struct ast_datastore_info enum_result_datastore_info = {
+ .type = "ENUMQUERY",
+ .destroy = erds_destroy_cb,
+ };
+Index: funcs/func_groupcount.c
+===================================================================
+--- a/funcs/func_groupcount.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/funcs/func_groupcount.c (.../trunk) (revision 202568)
+@@ -134,6 +134,7 @@
+ static struct ast_custom_function group_count_function = {
+ .name = "GROUP_COUNT",
+ .read = group_count_function_read,
++ .read_max = 12,
+ };
+
+ static int group_match_count_function_read(struct ast_channel *chan,
+@@ -159,6 +160,7 @@
+ static struct ast_custom_function group_match_count_function = {
+ .name = "GROUP_MATCH_COUNT",
+ .read = group_match_count_function_read,
++ .read_max = 12,
+ .write = NULL,
+ };
+
+Index: funcs/func_odbc.c
+===================================================================
+--- a/funcs/func_odbc.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/funcs/func_odbc.c (.../trunk) (revision 202568)
+@@ -99,10 +99,10 @@
+
+ static char *config = "func_odbc.conf";
+
+-enum {
++enum odbc_option_flags {
+ OPT_ESCAPECOMMAS = (1 << 0),
+ OPT_MULTIROW = (1 << 1),
+-} odbc_option_flags;
++};
+
+ struct acf_odbc_query {
+ AST_RWLIST_ENTRY(acf_odbc_query) list;
+@@ -118,7 +118,7 @@
+
+ static void odbc_datastore_free(void *data);
+
+-struct ast_datastore_info odbc_info = {
++static struct ast_datastore_info odbc_info = {
+ .type = "FUNC_ODBC",
+ .destroy = odbc_datastore_free,
+ };
+@@ -135,7 +135,7 @@
+ char names[0];
+ };
+
+-AST_RWLIST_HEAD_STATIC(queries, acf_odbc_query);
++static AST_RWLIST_HEAD_STATIC(queries, acf_odbc_query);
+
+ static int resultcount = 0;
+
+@@ -257,7 +257,7 @@
+ if (chan)
+ ast_autoservice_stop(chan);
+ if (bogus_chan) {
+- ast_channel_free(chan);
++ ast_channel_release(chan);
+ } else {
+ pbx_builtin_setvar_helper(chan, "ODBCSTATUS", status);
+ }
+@@ -367,7 +367,7 @@
+ if (chan)
+ ast_autoservice_stop(chan);
+ if (bogus_chan)
+- ast_channel_free(chan);
++ ast_channel_release(chan);
+
+ return 0;
+ }
+@@ -473,7 +473,7 @@
+ ast_autoservice_stop(chan);
+ }
+ if (bogus_chan) {
+- ast_channel_free(chan);
++ ast_channel_release(chan);
+ }
+ return -1;
+ }
+@@ -490,7 +490,7 @@
+ ast_autoservice_stop(chan);
+ }
+ if (bogus_chan) {
+- ast_channel_free(chan);
++ ast_channel_release(chan);
+ }
+ return -1;
+ }
+@@ -517,7 +517,7 @@
+ if (chan)
+ ast_autoservice_stop(chan);
+ if (bogus_chan)
+- ast_channel_free(chan);
++ ast_channel_release(chan);
+ return res1;
+ }
+
+@@ -561,7 +561,7 @@
+ if (chan)
+ ast_autoservice_stop(chan);
+ if (bogus_chan)
+- ast_channel_free(chan);
++ ast_channel_release(chan);
+ return -1;
+ }
+ resultset = tmp;
+@@ -657,7 +657,7 @@
+ if (chan)
+ ast_autoservice_stop(chan);
+ if (bogus_chan)
+- ast_channel_free(chan);
++ ast_channel_release(chan);
+ return -1;
+ }
+ odbc_store->data = resultset;
+@@ -670,7 +670,7 @@
+ if (chan)
+ ast_autoservice_stop(chan);
+ if (bogus_chan)
+- ast_channel_free(chan);
++ ast_channel_release(chan);
+ return 0;
+ }
+
+@@ -732,7 +732,7 @@
+
+ static char *app_odbcfinish = "ODBCFinish";
+
+-static int exec_odbcfinish(struct ast_channel *chan, void *data)
++static int exec_odbcfinish(struct ast_channel *chan, const char *data)
+ {
+ struct ast_datastore *store = ast_channel_datastore_find(chan, &odbc_info, data);
+ if (!store) /* Already freed; no big deal. */
+@@ -1060,7 +1060,7 @@
+ }
+
+ ast_str_substitute_variables(&sql, 0, chan, query->sql_read);
+- ast_channel_free(chan);
++ chan = ast_channel_release(chan);
+
+ if (a->argc == 5 && !strcmp(a->argv[4], "exec")) {
+ /* Execute the query */
+@@ -1273,7 +1273,7 @@
+ pbx_builtin_pushvar_helper(chan, "VALUE", S_OR(a->argv[4], ""));
+ ast_str_substitute_variables(&sql, 0, chan, query->sql_write);
+ ast_debug(1, "SQL is %s\n", ast_str_buffer(sql));
+- ast_channel_free(chan);
++ chan = ast_channel_release(chan);
+
+ if (a->argc == 6 && !strcmp(a->argv[5], "exec")) {
+ /* Execute the query */
+Index: funcs/func_aes.c
+===================================================================
+--- a/funcs/func_aes.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/funcs/func_aes.c (.../trunk) (revision 202568)
+@@ -31,6 +31,7 @@
+ #include "asterisk/pbx.h"
+ #include "asterisk/app.h"
+ #include "asterisk/aes.h"
++#include "asterisk/strings.h"
+
+ #define AES_BLOCK_SIZE 16
+
+@@ -71,15 +72,15 @@
+
+
+ static int aes_helper(struct ast_channel *chan, const char *cmd, char *data,
+- char *buf, size_t len)
++ char *buf, struct ast_str **str, ssize_t maxlen)
+ {
+ unsigned char curblock[AES_BLOCK_SIZE] = { 0, };
+- char *tmp;
++ char *tmp = NULL;
+ char *tmpP;
+ int data_len, encrypt;
++ int keylen, len, tmplen, elen = 0;
+ ast_aes_encrypt_key ecx; /* AES 128 Encryption context */
+ ast_aes_decrypt_key dcx;
+-
+ AST_DECLARE_APP_ARGS(args,
+ AST_APP_ARG(key);
+ AST_APP_ARG(data);
+@@ -92,22 +93,37 @@
+ return -1;
+ }
+
+- if (strlen(args.key) != AES_BLOCK_SIZE) { /* key must be of 16 characters in length, 128 bits */
+- ast_log(LOG_WARNING, "Syntax: %s(<key>,<data>) - <key> parameter must be exactly 16 characters!\n", cmd);
++ if ((keylen = strlen(args.key)) != AES_BLOCK_SIZE) { /* key must be of 16 characters in length, 128 bits */
++ ast_log(LOG_WARNING, "Syntax: %s(<key>,<data>) - <key> parameter must be exactly 16 characters%s!\n", cmd, keylen < 16 ? " - padding" : "");
+ return -1;
+ }
+
+- ast_aes_encrypt_key((unsigned char *) args.key, &ecx); /* encryption: plaintext -> encryptedtext -> base64 */
+- ast_aes_decrypt_key((unsigned char *) args.key, &dcx); /* decryption: base64 -> encryptedtext -> plaintext */
+- tmp = ast_calloc(1, len); /* requires a tmp buffer for the base64 decode */
++ if (buf) {
++ len = maxlen;
++ } else if (maxlen == -1) {
++ len = ast_str_size(*str);
++ } else if (maxlen > 0) {
++ len = maxlen;
++ } else {
++ len = INT_MAX;
++ }
++ ast_debug(3, "len=%d\n", len);
++
++ encrypt = strcmp("AES_DECRYPT", cmd); /* -1 if encrypting, 0 if decrypting */
++ /* Round up the buffer to an even multiple of 16, plus 1 */
++ tmplen = (strlen(args.data) / 16 + 1) * 16 + 1;
++ tmp = ast_calloc(1, tmplen);
+ tmpP = tmp;
+- encrypt = strcmp("AES_DECRYPT", cmd); /* -1 if encrypting, 0 if decrypting */
+
+ if (encrypt) { /* if decrypting first decode src to base64 */
+- ast_copy_string(tmp, args.data, len);
++ /* encryption: plaintext -> encryptedtext -> base64 */
++ ast_aes_encrypt_key((unsigned char *) args.key, &ecx);
++ strcpy(tmp, args.data);
+ data_len = strlen(tmp);
+ } else {
+- data_len = ast_base64decode((unsigned char *) tmp, args.data, len);
++ /* decryption: base64 -> encryptedtext -> plaintext */
++ ast_aes_decrypt_key((unsigned char *) args.key, &dcx);
++ data_len = ast_base64decode((unsigned char *) tmp, args.data, tmplen);
+ }
+
+ if (data_len >= len) { /* make sure to not go over buffer len */
+@@ -116,8 +132,11 @@
+ }
+
+ while (data_len > 0) {
++ /* Tricky operation. We first copy the data into curblock, then
++ * the data is encrypted or decrypted and put back into the original
++ * buffer. */
+ memset(curblock, 0, AES_BLOCK_SIZE);
+- memcpy(curblock, tmpP, (data_len < AES_BLOCK_SIZE) ? data_len : AES_BLOCK_SIZE);
++ memcpy(curblock, tmpP, AES_BLOCK_SIZE);
+ if (encrypt) {
+ ast_aes_encrypt(curblock, (unsigned char *) tmpP, &ecx);
+ } else {
+@@ -125,26 +144,53 @@
+ }
+ tmpP += AES_BLOCK_SIZE;
+ data_len -= AES_BLOCK_SIZE;
++ elen += AES_BLOCK_SIZE;
+ }
+
+ if (encrypt) { /* if encrypting encode result to base64 */
+- ast_base64encode(buf, (unsigned char *) tmp, strlen(tmp), len);
++ if (buf) {
++ ast_base64encode(buf, (unsigned char *) tmp, elen, len);
++ } else {
++ if (maxlen >= 0) {
++ ast_str_make_space(str, maxlen ? maxlen : elen * 4 / 3 + 2);
++ }
++ ast_base64encode(ast_str_buffer(*str), (unsigned char *) tmp, elen, ast_str_size(*str));
++ ast_str_update(*str);
++ }
+ } else {
+- memcpy(buf, tmp, len);
++ if (buf) {
++ memcpy(buf, tmp, len);
++ } else {
++ ast_str_set(str, maxlen, "%s", tmp);
++ }
+ }
+ ast_free(tmp);
+
+ return 0;
+ }
+
++static int aes_buf_helper(struct ast_channel *chan, const char *cmd, char *data,
++ char *buf, size_t maxlen)
++{
++ return aes_helper(chan, cmd, data, buf, NULL, maxlen);
++}
++
++static int aes_str_helper(struct ast_channel *chan, const char *cmd, char *data,
++ struct ast_str **buf, ssize_t maxlen)
++{
++ return aes_helper(chan, cmd, data, NULL, buf, maxlen);
++}
++
+ static struct ast_custom_function aes_encrypt_function = {
+ .name = "AES_ENCRYPT",
+- .read = aes_helper,
++ .read = aes_buf_helper,
++ .read2 = aes_str_helper,
+ };
+
+ static struct ast_custom_function aes_decrypt_function = {
+ .name = "AES_DECRYPT",
+- .read = aes_helper,
++ .read = aes_buf_helper,
++ .read2 = aes_str_helper,
+ };
+
+ static int unload_module(void)
+Index: funcs/func_dialplan.c
+===================================================================
+--- a/funcs/func_dialplan.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/funcs/func_dialplan.c (.../trunk) (revision 202568)
+@@ -105,6 +105,7 @@
+ static struct ast_custom_function isexten_function = {
+ .name = "DIALPLAN_EXISTS",
+ .read = isexten_function_read,
++ .read_max = 2,
+ };
+
+ static int unload_module(void)
+Index: funcs/func_db.c
+===================================================================
+--- a/funcs/func_db.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/funcs/func_db.c (.../trunk) (revision 202568)
+@@ -201,6 +201,7 @@
+ static struct ast_custom_function db_exists_function = {
+ .name = "DB_EXISTS",
+ .read = function_db_exists,
++ .read_max = 2,
+ };
+
+ static int function_db_delete(struct ast_channel *chan, const char *cmd,
+Index: funcs/func_timeout.c
+===================================================================
+--- a/funcs/func_timeout.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/funcs/func_timeout.c (.../trunk) (revision 202568)
+@@ -191,6 +191,7 @@
+ static struct ast_custom_function timeout_function = {
+ .name = "TIMEOUT",
+ .read = timeout_read,
++ .read_max = 22,
+ .write = timeout_write,
+ };
+
+Index: funcs/func_lock.c
+===================================================================
+--- a/funcs/func_lock.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/funcs/func_lock.c (.../trunk) (revision 202568)
+@@ -84,7 +84,7 @@
+
+
+
+-AST_LIST_HEAD_STATIC(locklist, lock_frame);
++static AST_LIST_HEAD_STATIC(locklist, lock_frame);
+
+ static void lock_free(void *data);
+ static int unloading = 0;
+@@ -324,16 +324,19 @@
+ static struct ast_custom_function lock_function = {
+ .name = "LOCK",
+ .read = lock_read,
++ .read_max = 2,
+ };
+
+ static struct ast_custom_function trylock_function = {
+ .name = "TRYLOCK",
+ .read = trylock_read,
++ .read_max = 2,
+ };
+
+ static struct ast_custom_function unlock_function = {
+ .name = "UNLOCK",
+ .read = unlock_read,
++ .read_max = 2,
+ };
+
+ static int unload_module(void)
+Index: funcs/func_math.c
+===================================================================
+--- a/funcs/func_math.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/funcs/func_math.c (.../trunk) (revision 202568)
+@@ -1,9 +1,10 @@
+ /*
+ * Asterisk -- An open source telephony toolkit.
+ *
+- * Copyright (C) 2004 - 2006, Andy Powell
++ * Copyright (C) 2004 - 2006, Andy Powell
+ *
+ * Updated by Mark Spencer <markster@digium.com>
++ * Updated by Nir Simionovich <nirs@greenfieldtech.net>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+@@ -22,6 +23,7 @@
+ *
+ * \author Andy Powell
+ * \author Mark Spencer <markster@digium.com>
++ * \author Nir Simionovich <nirs@greenfieldtech.net>
+ *
+ * \ingroup functions
+ */
+@@ -66,6 +68,40 @@
+ <para>Example: Set(i=${MATH(123%16,int)}) - sets var i=11</para>
+ </description>
+ </function>
++ <function name="INC" language="en_US">
++ <synopsis>
++ Increments the value of a variable, while returning the updated value to the dialplan
++ </synopsis>
++ <syntax>
++ <parameter name="variable" required="true">
++ <para>
++ The variable name to be manipulated, without the braces.
++ </para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Increments the value of a variable, while returning the updated value to the dialplan</para>
++ <para>Example: INC(MyVAR) - Increments MyVar</para>
++ <para>Note: INC(${MyVAR}) - Is wrong, as INC expects the variable name, not its value</para>
++ </description>
++ </function>
++ <function name="DEC" language="en_US">
++ <synopsis>
++ Decrements the value of a variable, while returning the updated value to the dialplan
++ </synopsis>
++ <syntax>
++ <parameter name="variable" required="true">
++ <para>
++ The variable name to be manipulated, without the braces.
++ </para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Decrements the value of a variable, while returning the updated value to the dialplan</para>
++ <para>Example: DEC(MyVAR) - Increments MyVar</para>
++ <para>Note: DEC(${MyVAR}) - Is wrong, as INC expects the variable name, not its value</para>
++ </description>
++ </function>
+ ***/
+
+ enum TypeOfFunctions {
+@@ -333,19 +369,107 @@
+ return 0;
+ }
+
++static int crement_function_read(struct ast_channel *chan, const char *cmd,
++ char *data, char *buf, size_t len)
++{
++ int ret = -1;
++ int int_value = 0;
++ int modify_orig = 0;
++ const char *var;
++ char endchar = 0, returnvar[12]; /* If you need a variable longer than 11 digits - something is way wrong */
++
++ if (ast_strlen_zero(data)) {
++ ast_log(LOG_WARNING, "Syntax: %s(<data>) - missing argument!\n", cmd);
++ return -1;
++ }
++
++ ast_channel_lock(chan);
++
++ if (!(var = pbx_builtin_getvar_helper(chan, data))) {
++ ast_log(LOG_NOTICE, "Failed to obtain variable %s, bailing out\n", data);
++ ast_channel_unlock(chan);
++ return -1;
++ }
++
++ if (ast_strlen_zero(var)) {
++ ast_log(LOG_NOTICE, "Variable %s doesn't exist - are you sure you wrote it corrrectly?\n", data);
++ ast_channel_unlock(chan);
++ return -1;
++ }
++
++ if (sscanf(var, "%d%c", &int_value, &endchar) == 0 || endchar != 0) {
++ ast_log(LOG_NOTICE, "The content of ${%s} is not a numeric value - bailing out!\n", data);
++ ast_channel_unlock(chan);
++ return -1;
++ }
++
++ /* now we'll actually do something useful */
++ if (!strcasecmp(cmd, "INC")) { /* Increment variable */
++ int_value++;
++ modify_orig = 1;
++ } else if (!strcasecmp(cmd, "DEC")) { /* Decrement variable */
++ int_value--;
++ modify_orig = 1;
++ }
++
++ ast_log(LOG_NOTICE, "The value is now: %d\n", int_value);
++
++ if (snprintf(returnvar, sizeof(returnvar), "%d", int_value) > 0) {
++ pbx_builtin_setvar_helper(chan, data, returnvar);
++ if (modify_orig) {
++ ast_copy_string(buf, returnvar, len);
++ }
++ ret = 0;
++ } else {
++ pbx_builtin_setvar_helper(chan, data, "0");
++ if (modify_orig) {
++ ast_copy_string(buf, "0", len);
++ }
++ ast_log(LOG_NOTICE, "Variable %s refused to be %sREMENTED, setting value to 0", data, cmd);
++ ret = 0;
++ }
++
++ ast_channel_unlock(chan);
++
++ return ret;
++}
++
++
+ static struct ast_custom_function math_function = {
+ .name = "MATH",
+ .read = math
+ };
+
++static struct ast_custom_function increment_function = {
++ .name = "INC",
++ .read = crement_function_read,
++};
++
++static struct ast_custom_function decrement_function = {
++ .name = "DEC",
++ .read = crement_function_read,
++};
++
+ static int unload_module(void)
+ {
+- return ast_custom_function_unregister(&math_function);
++ int res = 0;
++
++ res |= ast_custom_function_unregister(&math_function);
++ res |= ast_custom_function_unregister(&increment_function);
++ res |= ast_custom_function_unregister(&decrement_function);
++
++ return res;
+ }
+
+ static int load_module(void)
+ {
+- return ast_custom_function_register(&math_function);
++ int res = 0;
++
++ res |= ast_custom_function_register(&math_function);
++ res |= ast_custom_function_register(&increment_function);
++ res |= ast_custom_function_register(&decrement_function);
++
++ return res;
+ }
+
+ AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Mathematical dialplan function");
+Index: funcs/func_cut.c
+===================================================================
+--- a/funcs/func_cut.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/funcs/func_cut.c (.../trunk) (revision 202568)
+@@ -77,9 +77,6 @@
+ </function>
+ ***/
+
+-/* Maximum length of any variable */
+-#define MAXRESULT 1024
+-
+ struct sortable_keys {
+ char *key;
+ float value;
+@@ -151,99 +148,86 @@
+ return 0;
+ }
+
+-static int cut_internal(struct ast_channel *chan, char *data, char *buffer, size_t buflen)
++static int cut_internal(struct ast_channel *chan, char *data, struct ast_str **buf, ssize_t buflen)
+ {
+- char *parse;
++ char *parse, ds[2], *var_expr;
+ size_t delim_consumed;
++ struct ast_str *var_value;
+ AST_DECLARE_APP_ARGS(args,
+ AST_APP_ARG(varname);
+ AST_APP_ARG(delimiter);
+ AST_APP_ARG(field);
+ );
+
+- *buffer = '\0';
+-
+ parse = ast_strdupa(data);
+
+ AST_STANDARD_APP_ARGS(args, parse);
+
+- /* Check and parse arguments */
++ /* Check arguments */
+ if (args.argc < 3) {
+ return ERROR_NOARG;
+- } else {
+- char d, ds[2] = "";
+- char *tmp = alloca(strlen(args.varname) + 4);
+- char varvalue[MAXRESULT], *tmp2=varvalue;
++ } else if (!(var_expr = alloca(strlen(args.varname) + 4))) {
++ return ERROR_NOMEM;
++ }
+
+- if (tmp) {
+- snprintf(tmp, strlen(args.varname) + 4, "${%s}", args.varname);
+- } else {
+- return ERROR_NOMEM;
+- }
++ /* Get the value of the variable named in the 1st argument */
++ snprintf(var_expr, strlen(args.varname) + 4, "${%s}", args.varname);
++ var_value = ast_str_create(16);
++ ast_str_substitute_variables(&var_value, 0, chan, var_expr);
+
+- if (ast_get_encoded_char(args.delimiter, ds, &delim_consumed))
+- ast_copy_string(ds, "-", sizeof(ds));
++ /* Copy delimiter from 2nd argument to ds[] possibly decoding backslash escapes */
++ if (ast_get_encoded_char(args.delimiter, ds, &delim_consumed)) {
++ ast_copy_string(ds, "-", sizeof(ds));
++ }
++ ds[1] = '\0';
+
+- /* String form of the delimiter, for use with strsep(3) */
+- d = *ds;
++ if (ast_str_strlen(var_value)) {
++ int curfieldnum = 1;
++ char *curfieldptr = ast_str_buffer(var_value);
++ int out_field_count = 0;
+
+- pbx_substitute_variables_helper(chan, tmp, tmp2, MAXRESULT - 1);
++ while (curfieldptr != NULL && args.field != NULL) {
++ char *next_range = strsep(&(args.field), "&");
++ int start_field, stop_field;
++ char trashchar;
+
+- if (tmp2) {
+- int curfieldnum = 1, firstfield = 1;
+- while (tmp2 != NULL && args.field != NULL) {
+- char *nextgroup = strsep(&(args.field), "&");
+- int num1 = 0, num2 = MAXRESULT;
+- char trashchar;
++ if (sscanf(next_range, "%d-%d", &start_field, &stop_field) == 2) {
++ /* range with both start and end */
++ } else if (sscanf(next_range, "-%d", &stop_field) == 1) {
++ /* range with end only */
++ start_field = 1;
++ } else if ((sscanf(next_range, "%d%c", &start_field, &trashchar) == 2) && (trashchar == '-')) {
++ /* range with start only */
++ stop_field = INT_MAX;
++ } else if (sscanf(next_range, "%d", &start_field) == 1) {
++ /* single number */
++ stop_field = start_field;
++ } else {
++ /* invalid field spec */
++ ast_free(var_value);
++ return ERROR_USAGE;
++ }
+
+- if (sscanf(nextgroup, "%d-%d", &num1, &num2) == 2) {
+- /* range with both start and end */
+- } else if (sscanf(nextgroup, "-%d", &num2) == 1) {
+- /* range with end */
+- num1 = 0;
+- } else if ((sscanf(nextgroup, "%d%c", &num1, &trashchar) == 2) && (trashchar == '-')) {
+- /* range with start */
+- num2 = MAXRESULT;
+- } else if (sscanf(nextgroup, "%d", &num1) == 1) {
+- /* single number */
+- num2 = num1;
+- } else {
+- return ERROR_USAGE;
+- }
++ /* Get to start, if not there already */
++ while (curfieldptr != NULL && curfieldnum < start_field) {
++ strsep(&curfieldptr, ds);
++ curfieldnum++;
++ }
+
+- /* Get to start, if any */
+- if (num1 > 0) {
+- while (tmp2 != (char *)NULL + 1 && curfieldnum < num1) {
+- tmp2 = strchr(tmp2, d) + 1;
+- curfieldnum++;
+- }
+- }
++ /* Most frequent problem is the expectation of reordering fields */
++ if (curfieldnum > start_field) {
++ ast_log(LOG_WARNING, "We're already past the field you wanted?\n");
++ }
+
+- /* Most frequent problem is the expectation of reordering fields */
+- if ((num1 > 0) && (curfieldnum > num1))
+- ast_log(LOG_WARNING, "We're already past the field you wanted?\n");
+-
+- /* Re-null tmp2 if we added 1 to NULL */
+- if (tmp2 == (char *)NULL + 1)
+- tmp2 = NULL;
+-
+- /* Output fields until we either run out of fields or num2 is reached */
+- while (tmp2 != NULL && curfieldnum <= num2) {
+- char *tmp3 = strsep(&tmp2, ds);
+- int curlen = strlen(buffer);
+-
+- if (firstfield) {
+- snprintf(buffer, buflen, "%s", tmp3);
+- firstfield = 0;
+- } else {
+- snprintf(buffer + curlen, buflen - curlen, "%c%s", d, tmp3);
+- }
+-
+- curfieldnum++;
+- }
++ /* Output fields until we either run out of fields or stop_field is reached */
++ while (curfieldptr != NULL && curfieldnum <= stop_field) {
++ char *field_value = strsep(&curfieldptr, ds);
++ ast_str_append(buf, buflen, "%s%s", out_field_count++ ? ds : "", field_value);
++ curfieldnum++;
+ }
+ }
+ }
++ ast_free(var_value);
+ return 0;
+ }
+
+@@ -271,7 +255,33 @@
+ static int acf_cut_exec(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
+ {
+ int ret = -1;
++ struct ast_str *str = ast_str_create(16);
+
++ switch (cut_internal(chan, data, &str, len)) {
++ case ERROR_NOARG:
++ ast_log(LOG_ERROR, "Syntax: CUT(<varname>,<char-delim>,<range-spec>) - missing argument!\n");
++ break;
++ case ERROR_NOMEM:
++ ast_log(LOG_ERROR, "Out of memory\n");
++ break;
++ case ERROR_USAGE:
++ ast_log(LOG_ERROR, "Usage: CUT(<varname>,<char-delim>,<range-spec>)\n");
++ break;
++ case 0:
++ ret = 0;
++ ast_copy_string(buf, ast_str_buffer(str), len);
++ break;
++ default:
++ ast_log(LOG_ERROR, "Unknown internal error\n");
++ }
++ ast_free(str);
++ return ret;
++}
++
++static int acf_cut_exec2(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
++{
++ int ret = -1;
++
+ switch (cut_internal(chan, data, buf, len)) {
+ case ERROR_NOARG:
+ ast_log(LOG_ERROR, "Syntax: CUT(<varname>,<char-delim>,<range-spec>) - missing argument!\n");
+@@ -292,14 +302,15 @@
+ return ret;
+ }
+
+-struct ast_custom_function acf_sort = {
++static struct ast_custom_function acf_sort = {
+ .name = "SORT",
+ .read = acf_sort_exec,
+ };
+
+-struct ast_custom_function acf_cut = {
++static struct ast_custom_function acf_cut = {
+ .name = "CUT",
+ .read = acf_cut_exec,
++ .read2 = acf_cut_exec2,
+ };
+
+ static int unload_module(void)
+Index: funcs/func_redirecting.c
+===================================================================
+--- a/funcs/func_redirecting.c (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/funcs/func_redirecting.c (.../trunk) (revision 202568)
+@@ -0,0 +1,482 @@
++/*
++ * Asterisk -- An open source telephony toolkit.
++ *
++ * Copyright (C) 2008 Digium, Inc.
++ *
++ * Richard Mudgett <rmudgett@digium.com>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * 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.
++ */
++
++/*!
++ * \file
++ * \brief Redirecting data dialplan function
++ * \ingroup functions
++ *
++ * \author Richard Mudgett <rmudgett@digium.com>
++ *
++ * See Also:
++ * \arg \ref AstCREDITS
++ */
++
++
++#include "asterisk.h"
++
++ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
++
++/* ------------------------------------------------------------------- */
++
++
++#include <stdlib.h>
++#include <stdio.h>
++#include <string.h>
++#include <sys/types.h>
++
++#include "asterisk/module.h"
++#include "asterisk/channel.h"
++#include "asterisk/pbx.h"
++#include "asterisk/logger.h"
++#include "asterisk/utils.h"
++#include "asterisk/app.h"
++#include "asterisk/options.h"
++#include "asterisk/callerid.h"
++
++/*
++ * Do not document the REDIRECTING(pres) datatype.
++ * It has turned out that the from-pres and to-pres values must be kept
++ * separate. They represent two different parties and there is a case when
++ * they are active at the same time. The plain pres option will simply
++ * live on as a historical relic.
++ */
++/*** DOCUMENTATION
++ <function name="REDIRECTING" language="en_US">
++ <synopsis>
++ Gets or sets Redirecting data on the channel.
++ </synopsis>
++ <syntax>
++ <parameter name="datatype" required="true">
++ <para>The allowable datatypes are:</para>
++ <enumlist>
++ <enum name = "from-all" />
++ <enum name = "from-num" />
++ <enum name = "from-name" />
++ <enum name = "from-ton" />
++ <enum name = "from-pres" />
++ <enum name = "to-all" />
++ <enum name = "to-num" />
++ <enum name = "to-name" />
++ <enum name = "to-ton" />
++ <enum name = "to-pres" />
++ <enum name = "reason" />
++ <enum name = "count" />
++ </enumlist>
++ </parameter>
++ <parameter name="i">
++ <para>If set, this will prevent the channel from sending out protocol
++ messages because of the value being set</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Gets or sets Redirecting data on the channel. The allowable values
++ for the <replaceable>reason</replaceable> field are the following:</para>
++ <enumlist>
++ <enum name = "unknown"><para>Unknown</para></enum>
++ <enum name = "cfb"><para>Call Forwarding Busy</para></enum>
++ <enum name = "cfnr"><para>Call Forwarding No Reply</para></enum>
++ <enum name = "unavailable"><para>Callee is Unavailable</para></enum>
++ <enum name = "time_of_day"><para>Time of Day</para></enum>
++ <enum name = "dnd"><para>Do Not Disturb</para></enum>
++ <enum name = "deflection"><para>Call Deflection</para></enum>
++ <enum name = "follow_me"><para>Follow Me</para></enum>
++ <enum name = "out_of_order"><para>Called DTE Out-Of-Order</para></enum>
++ <enum name = "away"><para>Callee is Away</para></enum>
++ <enum name = "cf_dte"><para>Call Forwarding By The Called DTE</para></enum>
++ <enum name = "cfu"><para>Call Forwarding Unconditional</para></enum>
++ </enumlist>
++ </description>
++ </function>
++ ***/
++
++enum ID_FIELD_STATUS {
++ ID_FIELD_VALID,
++ ID_FIELD_INVALID,
++ ID_FIELD_UNKNOWN
++};
++
++
++
++
++/* ******************************************************************* */
++/*!
++ * \internal
++ * \brief Read values from the party id struct.
++ *
++ * \param buf Buffer to fill with read value.
++ * \param len Length of the buffer
++ * \param data Remaining function datatype string
++ *
++ * \retval ID_FIELD_VALID on success.
++ * \retval ID_FIELD_UNKNOWN on unknown field name.
++ */
++static enum ID_FIELD_STATUS redirecting_id_read(char *buf, size_t len, char *data, const struct ast_party_id *id)
++{
++ enum ID_FIELD_STATUS status;
++
++ status = ID_FIELD_VALID;
++
++ if (!strncasecmp("all", data, 3)) {
++ snprintf(buf, len, "\"%s\" <%s>",
++ S_OR(id->name, ""),
++ S_OR(id->number, ""));
++ } else if (!strncasecmp("name", data, 4)) {
++ if (id->name) {
++ ast_copy_string(buf, id->name, len);
++ }
++ } else if (!strncasecmp("num", data, 3)) {
++ if (id->number) {
++ ast_copy_string(buf, id->number, len);
++ }
++ } else if (!strncasecmp("ton", data, 3)) {
++ snprintf(buf, len, "%d", id->number_type);
++ } else if (!strncasecmp("pres", data, 4)) {
++ ast_copy_string(buf, ast_named_caller_presentation(id->number_presentation), len);
++ } else {
++ status = ID_FIELD_UNKNOWN;
++ }
++
++ return status;
++}
++
++
++
++
++/* ******************************************************************* */
++/*!
++ * \internal
++ * \brief Read values from the redirecting information struct.
++ *
++ * \param chan Asterisk channel to read
++ * \param cmd Not used
++ * \param data Redirecting function datatype string
++ * \param buf Buffer to fill with read value.
++ * \param len Length of the buffer
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++static int redirecting_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
++{
++ /* Ensure that the buffer is empty */
++ *buf = 0;
++
++ if (!chan)
++ return -1;
++
++ ast_channel_lock(chan);
++
++ if (!strncasecmp("from-", data, 5)) {
++ struct ast_party_id from_id;
++
++ from_id = chan->redirecting.from;
++ from_id.number = chan->cid.cid_rdnis;
++ switch (redirecting_id_read(buf, len, data + 5, &from_id)) {
++ case ID_FIELD_VALID:
++ case ID_FIELD_INVALID:
++ break;
++
++ default:
++ ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
++ break;
++ }
++ } else if (!strncasecmp("to-", data, 3)) {
++ switch (redirecting_id_read(buf, len, data + 3, &chan->redirecting.to)) {
++ case ID_FIELD_VALID:
++ case ID_FIELD_INVALID:
++ break;
++
++ default:
++ ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
++ break;
++ }
++ } else if (!strncasecmp("pres", data, 4)) {
++ ast_copy_string(buf, ast_named_caller_presentation(chan->redirecting.from.number_presentation), len);
++ } else if (!strncasecmp("reason", data, 6)) {
++ ast_copy_string(buf, ast_redirecting_reason_name(chan->redirecting.reason), len);
++ } else if (!strncasecmp("count", data, 5)) {
++ snprintf(buf, len, "%d", chan->redirecting.count);
++ } else {
++ ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
++ }
++
++ ast_channel_unlock(chan);
++
++ return 0;
++}
++
++
++
++
++/* ******************************************************************* */
++/*!
++ * \internal
++ * \brief Write new values to the party id struct
++ *
++ * \param id Party ID struct to write values
++ * \param data Remaining function datatype string
++ * \param value Value to assign to the party id.
++ *
++ * \retval ID_FIELD_VALID on success.
++ * \retval ID_FIELD_INVALID on error with field value.
++ * \retval ID_FIELD_UNKNOWN on unknown field name.
++ */
++static enum ID_FIELD_STATUS redirecting_id_write(struct ast_party_id *id, char *data, const char *value)
++{
++ char *val;
++ enum ID_FIELD_STATUS status;
++
++ status = ID_FIELD_VALID;
++
++ if (!strncasecmp("all", data, 3)) {
++ char name[256];
++ char num[256];
++
++ ast_callerid_split(value, name, sizeof(name), num, sizeof(num));
++ if (!(id->name = ast_strdup(name))) {
++ return ID_FIELD_INVALID;
++ }
++ if (!(id->number = ast_strdup(num))) {
++ return ID_FIELD_INVALID;
++ }
++ } else if (!strncasecmp("name", data, 4)) {
++ id->name = ast_strdup(value);
++ ast_trim_blanks(id->name);
++ } else if (!strncasecmp("num", data, 3)) {
++ id->number = ast_strdup(value);
++ ast_trim_blanks(id->number);
++ } else if (!strncasecmp("ton", data, 3)) {
++ val = ast_strdupa(value);
++ ast_trim_blanks(val);
++
++ if (('0' <= val[0]) && (val[0] <= '9')) {
++ id->number_type = atoi(val);
++ } else {
++ ast_log(LOG_ERROR, "Unknown redirecting type of number '%s', value unchanged\n", val);
++ status = ID_FIELD_INVALID;
++ }
++ } else if (!strncasecmp("pres", data, 4)) {
++ int pres;
++
++ val = ast_strdupa(value);
++ ast_trim_blanks(val);
++
++ if (('0' <= val[0]) && (val[0] <= '9')) {
++ pres = atoi(val);
++ } else {
++ pres = ast_parse_caller_presentation(val);
++ }
++
++ if (pres < 0) {
++ ast_log(LOG_ERROR, "Unknown redirecting number presentation '%s', value unchanged\n", val);
++ status = ID_FIELD_INVALID;
++ } else {
++ id->number_presentation = pres;
++ }
++ } else {
++ status = ID_FIELD_UNKNOWN;
++ }
++
++ return status;
++}
++
++
++
++
++/* ******************************************************************* */
++/*!
++ * \internal
++ * \brief Write new values to the redirecting information struct.
++ *
++ * \param chan Asterisk channel to update
++ * \param cmd Not used
++ * \param data Redirecting function datatype string
++ * \param value Value to assign to the redirecting information struct.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++static int redirecting_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
++{
++ struct ast_party_redirecting redirecting;
++ char *val;
++ char *option;
++ void (*set_it)(struct ast_channel *chan, const struct ast_party_redirecting *redirecting);
++
++ if (!value || !chan) {
++ return -1;
++ }
++
++ /* Determine if the update indication inhibit option is present */
++ option = strchr(data, ',');
++ if (option) {
++ option = ast_skip_blanks(option + 1);
++ switch (*option) {
++ case 'i':
++ set_it = ast_channel_set_redirecting;
++ break;
++
++ default:
++ ast_log(LOG_ERROR, "Unknown redirecting option '%s'.\n", option);
++ return 0;
++ }
++ }
++ else {
++ set_it = ast_channel_update_redirecting;
++ }
++
++ ast_channel_lock(chan);
++ ast_party_redirecting_set_init(&redirecting, &chan->redirecting);
++ ast_channel_unlock(chan);
++
++ value = ast_skip_blanks(value);
++
++ if (!strncasecmp("from-", data, 5)) {
++ switch (redirecting_id_write(&redirecting.from, data + 5, value)) {
++ case ID_FIELD_VALID:
++ set_it(chan, &redirecting);
++ ast_party_redirecting_free(&redirecting);
++ break;
++
++ case ID_FIELD_INVALID:
++ break;
++
++ default:
++ ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
++ break;
++ }
++ } else if (!strncasecmp("to-", data, 3)) {
++ switch (redirecting_id_write(&redirecting.to, data + 3, value)) {
++ case ID_FIELD_VALID:
++ set_it(chan, &redirecting);
++ ast_party_redirecting_free(&redirecting);
++ break;
++
++ case ID_FIELD_INVALID:
++ break;
++
++ default:
++ ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
++ break;
++ }
++ } else if (!strncasecmp("pres", data, 4)) {
++ int pres;
++
++ val = ast_strdupa(value);
++ ast_trim_blanks(val);
++
++ if (('0' <= val[0]) && (val[0] <= '9')) {
++ pres = atoi(val);
++ } else {
++ pres = ast_parse_caller_presentation(val);
++ }
++
++ if (pres < 0) {
++ ast_log(LOG_ERROR, "Unknown redirecting number presentation '%s', value unchanged\n", val);
++ } else {
++ redirecting.from.number_presentation = pres;
++ redirecting.to.number_presentation = pres;
++ set_it(chan, &redirecting);
++ }
++ } else if (!strncasecmp("reason", data, 6)) {
++ int reason;
++
++ val = ast_strdupa(value);
++ ast_trim_blanks(val);
++
++ if (('0' <= val[0]) && (val[0] <= '9')) {
++ reason = atoi(val);
++ } else {
++ reason = ast_redirecting_reason_parse(val);
++ }
++
++ if (reason < 0) {
++ ast_log(LOG_ERROR, "Unknown redirecting reason '%s', value unchanged\n", val);
++ } else {
++ redirecting.reason = reason;
++ set_it(chan, &redirecting);
++ }
++ } else if (!strncasecmp("count", data, 5)) {
++ val = ast_strdupa(value);
++ ast_trim_blanks(val);
++
++ if (('0' <= val[0]) && (val[0] <= '9')) {
++ redirecting.count = atoi(val);
++ set_it(chan, &redirecting);
++ } else {
++ ast_log(LOG_ERROR, "Unknown redirecting count '%s', value unchanged\n", val);
++ }
++ } else {
++ ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
++ }
++
++ return 0;
++}
++
++
++
++
++static struct ast_custom_function redirecting_function = {
++ .name = "REDIRECTING",
++ .read = redirecting_read,
++ .write = redirecting_write,
++};
++
++
++
++
++/* ******************************************************************* */
++/*!
++ * \internal
++ * \brief Unload the function module
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++static int unload_module(void)
++{
++ return ast_custom_function_unregister(&redirecting_function);
++}
++
++
++
++
++/* ******************************************************************* */
++/*!
++ * \internal
++ * \brief Load and initialize the function module.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++static int load_module(void)
++{
++ return ast_custom_function_register(&redirecting_function)
++ ? AST_MODULE_LOAD_DECLINE
++ : AST_MODULE_LOAD_SUCCESS;
++}
++
++
++
++
++AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Redirecting data dialplan function");
++
++
++/* ------------------------------------------------------------------- */
++/* end func_redirecting.c */
+
+Property changes on: funcs/func_redirecting.c
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+
+Index: funcs/func_global.c
+===================================================================
+--- a/funcs/func_global.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/funcs/func_global.c (.../trunk) (revision 202568)
+@@ -134,6 +134,7 @@
+ AST_APP_ARG(var);
+ AST_APP_ARG(chan);
+ );
++ struct ast_channel *c_ref = NULL;
+
+ if (ast_strlen_zero(data)) {
+ ast_log(LOG_WARNING, "SHARED() requires an argument: SHARED(<var>[,<chan>])\n");
+@@ -145,15 +146,20 @@
+ if (!ast_strlen_zero(args.chan)) {
+ char *prefix = alloca(strlen(args.chan) + 2);
+ sprintf(prefix, "%s-", args.chan);
+- if (!(chan = ast_get_channel_by_name_locked(args.chan)) && !(chan = ast_get_channel_by_name_prefix_locked(prefix, strlen(prefix)))) {
++ if (!(c_ref = ast_channel_get_by_name(args.chan)) && !(c_ref = ast_channel_get_by_name_prefix(prefix, strlen(prefix)))) {
+ ast_log(LOG_ERROR, "Channel '%s' not found! Variable '%s' will be blank.\n", args.chan, args.var);
+ return -1;
+ }
+- } else
+- ast_channel_lock(chan);
++ chan = c_ref;
++ }
+
++ ast_channel_lock(chan);
++
+ if (!(varstore = ast_channel_datastore_find(chan, &shared_variable_info, NULL))) {
+ ast_channel_unlock(chan);
++ if (c_ref) {
++ c_ref = ast_channel_unref(c_ref);
++ }
+ return -1;
+ }
+
+@@ -170,6 +176,10 @@
+
+ ast_channel_unlock(chan);
+
++ if (c_ref) {
++ c_ref = ast_channel_unref(c_ref);
++ }
++
+ return 0;
+ }
+
+@@ -182,6 +192,7 @@
+ AST_APP_ARG(var);
+ AST_APP_ARG(chan);
+ );
++ struct ast_channel *c_ref = NULL;
+
+ if (ast_strlen_zero(data)) {
+ ast_log(LOG_WARNING, "SHARED() requires an argument: SHARED(<var>[,<chan>])\n");
+@@ -193,17 +204,22 @@
+ if (!ast_strlen_zero(args.chan)) {
+ char *prefix = alloca(strlen(args.chan) + 2);
+ sprintf(prefix, "%s-", args.chan);
+- if (!(chan = ast_get_channel_by_name_locked(args.chan)) && !(chan = ast_get_channel_by_name_prefix_locked(prefix, strlen(prefix)))) {
++ if (!(c_ref = ast_channel_get_by_name(args.chan)) && !(c_ref = ast_channel_get_by_name_prefix(prefix, strlen(prefix)))) {
+ ast_log(LOG_ERROR, "Channel '%s' not found! Variable '%s' not set to '%s'.\n", args.chan, args.var, value);
+ return -1;
+ }
+- } else
+- ast_channel_lock(chan);
++ chan = c_ref;
++ }
+
++ ast_channel_lock(chan);
++
+ if (!(varstore = ast_channel_datastore_find(chan, &shared_variable_info, NULL))) {
+ if (!(varstore = ast_datastore_alloc(&shared_variable_info, NULL))) {
+ ast_log(LOG_ERROR, "Unable to allocate new datastore. Shared variable not set.\n");
+ ast_channel_unlock(chan);
++ if (c_ref) {
++ c_ref = ast_channel_unref(c_ref);
++ }
+ return -1;
+ }
+
+@@ -211,6 +227,9 @@
+ ast_log(LOG_ERROR, "Unable to allocate variable structure. Shared variable not set.\n");
+ ast_datastore_free(varstore);
+ ast_channel_unlock(chan);
++ if (c_ref) {
++ c_ref = ast_channel_unref(c_ref);
++ }
+ return -1;
+ }
+
+@@ -241,6 +260,10 @@
+
+ ast_channel_unlock(chan);
+
++ if (c_ref) {
++ c_ref = ast_channel_unref(c_ref);
++ }
++
+ return 0;
+ }
+
+Index: funcs/func_extstate.c
+===================================================================
+--- a/funcs/func_extstate.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/funcs/func_extstate.c (.../trunk) (revision 202568)
+@@ -122,6 +122,7 @@
+ static struct ast_custom_function extstate_function = {
+ .name = "EXTENSION_STATE",
+ .read = extstate_read,
++ .read_max = 12,
+ };
+
+ static int unload_module(void)
+Index: funcs/func_realtime.c
+===================================================================
+--- a/funcs/func_realtime.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/funcs/func_realtime.c (.../trunk) (revision 202568)
+@@ -410,29 +410,29 @@
+ return 0;
+ }
+
+-struct ast_custom_function realtime_function = {
++static struct ast_custom_function realtime_function = {
+ .name = "REALTIME",
+ .read = function_realtime_read,
+ .write = function_realtime_write,
+ };
+
+-struct ast_custom_function realtimefield_function = {
++static struct ast_custom_function realtimefield_function = {
+ .name = "REALTIME_FIELD",
+ .read = realtimefield_read,
+ .write = function_realtime_write,
+ };
+
+-struct ast_custom_function realtimehash_function = {
++static struct ast_custom_function realtimehash_function = {
+ .name = "REALTIME_HASH",
+ .read = realtimefield_read,
+ };
+
+-struct ast_custom_function realtime_store_function = {
++static struct ast_custom_function realtime_store_function = {
+ .name = "REALTIME_STORE",
+ .write = function_realtime_store,
+ };
+
+-struct ast_custom_function realtime_destroy_function = {
++static struct ast_custom_function realtime_destroy_function = {
+ .name = "REALTIME_DESTROY",
+ .read = function_realtime_readdestroy,
+ };
+Index: funcs/func_curl.c
+===================================================================
+--- a/funcs/func_curl.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/funcs/func_curl.c (.../trunk) (revision 202568)
+@@ -276,7 +276,7 @@
+ return 0;
+ }
+
+-static int acf_curlopt_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
++static int acf_curlopt_helper(struct ast_channel *chan, const char *cmd, char *data, char *buf, struct ast_str **bufstr, ssize_t len)
+ {
+ struct ast_datastore *store;
+ struct global_curl_info *list[2] = { &global_curl_info, NULL };
+@@ -303,38 +303,78 @@
+ AST_LIST_TRAVERSE(list[i], cur, list) {
+ if (cur->key == key) {
+ if (ot == OT_BOOLEAN || ot == OT_INTEGER) {
+- snprintf(buf, len, "%ld", (long)cur->value);
++ if (buf) {
++ snprintf(buf, len, "%ld", (long) cur->value);
++ } else {
++ ast_str_set(bufstr, len, "%ld", (long) cur->value);
++ }
+ } else if (ot == OT_INTEGER_MS) {
+- if ((long)cur->value % 1000 == 0) {
+- snprintf(buf, len, "%ld", (long)cur->value / 1000);
++ if ((long) cur->value % 1000 == 0) {
++ if (buf) {
++ snprintf(buf, len, "%ld", (long)cur->value / 1000);
++ } else {
++ ast_str_set(bufstr, len, "%ld", (long) cur->value / 1000);
++ }
+ } else {
+- snprintf(buf, len, "%.3f", (double)((long)cur->value) / 1000.0);
++ if (buf) {
++ snprintf(buf, len, "%.3f", (double) ((long) cur->value) / 1000.0);
++ } else {
++ ast_str_set(bufstr, len, "%.3f", (double) ((long) cur->value) / 1000.0);
++ }
+ }
+ } else if (ot == OT_STRING) {
+ ast_debug(1, "Found entry %p, with key %d and value %p\n", cur, cur->key, cur->value);
+- ast_copy_string(buf, cur->value, len);
++ if (buf) {
++ ast_copy_string(buf, cur->value, len);
++ } else {
++ ast_str_set(bufstr, 0, "%s", (char *) cur->value);
++ }
+ } else if (key == CURLOPT_PROXYTYPE) {
+ if (0) {
+ #if CURLVERSION_ATLEAST(7,15,2)
+ } else if ((long)cur->value == CURLPROXY_SOCKS4) {
+- ast_copy_string(buf, "socks4", len);
++ if (buf) {
++ ast_copy_string(buf, "socks4", len);
++ } else {
++ ast_str_set(bufstr, 0, "socks4");
++ }
+ #endif
+ #if CURLVERSION_ATLEAST(7,18,0)
+ } else if ((long)cur->value == CURLPROXY_SOCKS4A) {
+- ast_copy_string(buf, "socks4a", len);
++ if (buf) {
++ ast_copy_string(buf, "socks4a", len);
++ } else {
++ ast_str_set(bufstr, 0, "socks4a");
++ }
+ #endif
+ } else if ((long)cur->value == CURLPROXY_SOCKS5) {
+- ast_copy_string(buf, "socks5", len);
++ if (buf) {
++ ast_copy_string(buf, "socks5", len);
++ } else {
++ ast_str_set(bufstr, 0, "socks5");
++ }
+ #if CURLVERSION_ATLEAST(7,18,0)
+ } else if ((long)cur->value == CURLPROXY_SOCKS5_HOSTNAME) {
+- ast_copy_string(buf, "socks5hostname", len);
++ if (buf) {
++ ast_copy_string(buf, "socks5hostname", len);
++ } else {
++ ast_str_set(bufstr, 0, "socks5hostname");
++ }
+ #endif
+ #if CURLVERSION_ATLEAST(7,10,0)
+ } else if ((long)cur->value == CURLPROXY_HTTP) {
+- ast_copy_string(buf, "http", len);
++ if (buf) {
++ ast_copy_string(buf, "http", len);
++ } else {
++ ast_str_set(bufstr, 0, "http");
++ }
+ #endif
+ } else {
+- ast_copy_string(buf, "unknown", len);
++ if (buf) {
++ ast_copy_string(buf, "unknown", len);
++ } else {
++ ast_str_set(bufstr, 0, "unknown");
++ }
+ }
+ }
+ break;
+@@ -349,6 +389,16 @@
+ return cur ? 0 : -1;
+ }
+
++static int acf_curlopt_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
++{
++ return acf_curlopt_helper(chan, cmd, data, buf, NULL, len);
++}
++
++static int acf_curlopt_read2(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
++{
++ return acf_curlopt_helper(chan, cmd, data, NULL, buf, len);
++}
++
+ static size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
+ {
+ register int realsize = size * nmemb;
+@@ -363,7 +413,7 @@
+ return realsize;
+ }
+
+-static const char *global_useragent = "asterisk-libcurl-agent/1.0";
++static const char * const global_useragent = "asterisk-libcurl-agent/1.0";
+
+ static int curl_instance_init(void *data)
+ {
+@@ -391,7 +441,7 @@
+
+ AST_THREADSTORAGE_CUSTOM(curl_instance, curl_instance_init, curl_instance_cleanup);
+
+-static int acf_curl_exec(struct ast_channel *chan, const char *cmd, char *info, char *buf, size_t len)
++static int acf_curl_helper(struct ast_channel *chan, const char *cmd, char *info, char *buf, struct ast_str **input_str, ssize_t len)
+ {
+ struct ast_str *str = ast_str_create(16);
+ int ret = -1;
+@@ -405,15 +455,17 @@
+ int hashcompat = 0;
+ AST_LIST_HEAD(global_curl_info, curl_settings) *list = NULL;
+
+- *buf = '\0';
+-
++ if (buf) {
++ *buf = '\0';
++ }
++
+ if (ast_strlen_zero(info)) {
+ ast_log(LOG_WARNING, "CURL requires an argument (URL)\n");
+ ast_free(str);
+ return -1;
+ }
+
+- AST_STANDARD_APP_ARGS(args, info);
++ AST_STANDARD_APP_ARGS(args, info);
+
+ if (chan) {
+ ast_autoservice_start(chan);
+@@ -483,11 +535,19 @@
+ rowcount++;
+ }
+ pbx_builtin_setvar_helper(chan, "~ODBCFIELDS~", ast_str_buffer(fields));
+- ast_copy_string(buf, ast_str_buffer(values), len);
++ if (buf) {
++ ast_copy_string(buf, ast_str_buffer(values), len);
++ } else {
++ ast_str_set(input_str, len, "%s", ast_str_buffer(values));
++ }
+ ast_free(fields);
+ ast_free(values);
+ } else {
+- ast_copy_string(buf, ast_str_buffer(str), len);
++ if (buf) {
++ ast_copy_string(buf, ast_str_buffer(str), len);
++ } else {
++ ast_str_set(input_str, len, "%s", ast_str_buffer(str));
++ }
+ }
+ ret = 0;
+ }
+@@ -495,11 +555,21 @@
+
+ if (chan)
+ ast_autoservice_stop(chan);
+-
++
+ return ret;
+ }
+
+-struct ast_custom_function acf_curl = {
++static int acf_curl_exec(struct ast_channel *chan, const char *cmd, char *info, char *buf, size_t len)
++{
++ return acf_curl_helper(chan, cmd, info, buf, NULL, len);
++}
++
++static int acf_curl2_exec(struct ast_channel *chan, const char *cmd, char *info, struct ast_str **buf, ssize_t len)
++{
++ return acf_curl_helper(chan, cmd, info, NULL, buf, len);
++}
++
++static struct ast_custom_function acf_curl = {
+ .name = "CURL",
+ .synopsis = "Retrieves the contents of a URL",
+ .syntax = "CURL(url[,post-data])",
+@@ -507,9 +577,10 @@
+ " url - URL to retrieve\n"
+ " post-data - Optional data to send as a POST (GET is default action)\n",
+ .read = acf_curl_exec,
++ .read2 = acf_curl2_exec,
+ };
+
+-struct ast_custom_function acf_curlopt = {
++static struct ast_custom_function acf_curlopt = {
+ .name = "CURLOPT",
+ .synopsis = "Set options for use with the CURL() function",
+ .syntax = "CURLOPT(<option>)",
+@@ -532,6 +603,7 @@
+ " hashcompat - Result data will be compatible for use with HASH()\n"
+ "",
+ .read = acf_curlopt_read,
++ .read2 = acf_curlopt_read2,
+ .write = acf_curlopt_write,
+ };
+
+Index: funcs/func_blacklist.c
+===================================================================
+--- a/funcs/func_blacklist.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/funcs/func_blacklist.c (.../trunk) (revision 202568)
+@@ -70,9 +70,26 @@
+ return 0;
+ }
+
++static int blacklist_read2(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **str, ssize_t len)
++{
++ /* 2 bytes is a single integer, plus terminating null */
++ if (ast_str_size(*str) - ast_str_strlen(*str) < 2) {
++ if (len > ast_str_size(*str) || len == 0) {
++ ast_str_make_space(str, len ? len : ast_str_strlen(*str) + 2);
++ }
++ }
++ if (ast_str_size(*str) - ast_str_strlen(*str) >= 2) {
++ int res = blacklist_read(chan, cmd, data, ast_str_buffer(*str) + ast_str_strlen(*str), 2);
++ ast_str_update(*str);
++ return res;
++ }
++ return -1;
++}
++
+ static struct ast_custom_function blacklist_function = {
+ .name = "BLACKLIST",
+ .read = blacklist_read,
++ .read2 = blacklist_read2,
+ };
+
+ static int unload_module(void)
+Index: funcs/func_cdr.c
+===================================================================
+--- a/funcs/func_cdr.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/funcs/func_cdr.c (.../trunk) (revision 202568)
+@@ -163,12 +163,12 @@
+ </function>
+ ***/
+
+-enum {
++enum cdr_option_flags {
+ OPT_RECURSIVE = (1 << 0),
+ OPT_UNPARSED = (1 << 1),
+ OPT_LAST = (1 << 2),
+ OPT_SKIPLOCKED = (1 << 3),
+-} cdr_option_flags;
++};
+
+ AST_APP_OPTIONS(cdr_func_options, {
+ AST_APP_OPTION('l', OPT_LAST),
+Index: funcs/func_channel.c
+===================================================================
+--- a/funcs/func_channel.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/funcs/func_channel.c (.../trunk) (revision 202568)
+@@ -83,6 +83,9 @@
+ <enum name="musicclass">
+ <para>R/W class (from musiconhold.conf) for hold music.</para>
+ </enum>
++ <enum name="name">
++ <para>The name of the channel</para>
++ </enum>
+ <enum name="parkinglot">
+ <para>R/W parkinglot for parking.</para>
+ </enum>
+@@ -224,7 +227,7 @@
+ ast_channel_unlock(chan); \
+ } while (0)
+
+-char *transfercapability_table[0x20] = {
++static const char * const transfercapability_table[0x20] = {
+ "SPEECH", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
+ "DIGITAL", "RESTRICTED_DIGITAL", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
+ "3K1AUDIO", "DIGITAL_W_TONES", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
+@@ -260,7 +263,9 @@
+ locked_copy_string(chan, buf, chan->language, len);
+ else if (!strcasecmp(data, "musicclass"))
+ locked_copy_string(chan, buf, chan->musicclass, len);
+- else if (!strcasecmp(data, "parkinglot"))
++ else if (!strcasecmp(data, "name")) {
++ locked_copy_string(chan, buf, chan->name, len);
++ } else if (!strcasecmp(data, "parkinglot"))
+ locked_copy_string(chan, buf, chan->parkinglot, len);
+ else if (!strcasecmp(data, "state"))
+ locked_copy_string(chan, buf, ast_state2str(chan->_state), len);
+@@ -358,7 +363,8 @@
+ regex_t re;
+ int res;
+ size_t buflen = 0;
+-
++ struct ast_channel_iterator *iter;
++
+ buf[0] = '\0';
+
+ if (!ast_strlen_zero(data)) {
+@@ -369,7 +375,15 @@
+ }
+ }
+
+- for (c = ast_channel_walk_locked(NULL); c; ast_channel_unlock(c), c = ast_channel_walk_locked(c)) {
++ if (!(iter = ast_channel_iterator_all_new(0))) {
++ if (!ast_strlen_zero(data)) {
++ regfree(&re);
++ }
++ return -1;
++ }
++
++ while ((c = ast_channel_iterator_next(iter))) {
++ ast_channel_lock(c);
+ if (ast_strlen_zero(data) || regexec(&re, c->name, 0, NULL, 0) == 0) {
+ size_t namelen = strlen(c->name);
+ if (buflen + namelen + (ast_strlen_zero(buf) ? 0 : 1) + 1 < maxlen) {
+@@ -383,8 +397,12 @@
+ ast_log(LOG_WARNING, "Number of channels exceeds the available buffer space. Output will be truncated!\n");
+ }
+ }
++ ast_channel_unlock(c);
++ c = ast_channel_unref(c);
+ }
+
++ ast_channel_iterator_destroy(iter);
++
+ if (!ast_strlen_zero(data)) {
+ regfree(&re);
+ }
+Index: funcs/func_connectedline.c
+===================================================================
+--- a/funcs/func_connectedline.c (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/funcs/func_connectedline.c (.../trunk) (revision 202568)
+@@ -0,0 +1,237 @@
++/*
++ * Asterisk -- An open source telephony toolkit.
++ *
++ * Copyright (C) 2007, Gareth Palmer
++ *
++ * Gareth Palmer <gareth@acsdata.co.nz>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * 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.
++ */
++
++/*! \file
++ *
++ * \brief Connected Line dialplan function
++ *
++ * \ingroup functions
++ */
++
++#include "asterisk.h"
++
++ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
++
++#include <stdlib.h>
++#include <stdio.h>
++#include <string.h>
++#include <sys/types.h>
++
++#include "asterisk/module.h"
++#include "asterisk/channel.h"
++#include "asterisk/pbx.h"
++#include "asterisk/logger.h"
++#include "asterisk/utils.h"
++#include "asterisk/app.h"
++#include "asterisk/options.h"
++#include "asterisk/callerid.h"
++
++/*
++ * Do not document the CONNECTEDLINE(source) datatype.
++ * It has turned out to not be needed. The source value is really .
++ * only useful as a possible tracing aid.
++ */
++/*** DOCUMENTATION
++ <function name="CONNECTEDLINE" language="en_US">
++ <synopsis>
++ Gets or sets Connected Line data on the channel.
++ </synopsis>
++ <syntax>
++ <parameter name="datatype" required="true">
++ <para>The allowable datatypes are:</para>
++ <enumlist>
++ <enum name = "all" />
++ <enum name = "num" />
++ <enum name = "name" />
++ <enum name = "ton" />
++ <enum name = "pres" />
++ </enumlist>
++ </parameter>
++ <parameter name="i">
++ <para>If set, this will prevent the channel from sending out protocol
++ messages because of the value being set</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Gets or sets Connected Line data on the channel.</para>
++ </description>
++ </function>
++ ***/
++
++static int connectedline_read(struct ast_channel *chan, const char *cmd, char *data,
++ char *buf, size_t len)
++{
++ /* Ensure that the buffer is empty */
++ *buf = 0;
++
++ if (!chan)
++ return -1;
++
++ ast_channel_lock(chan);
++
++ if (!strncasecmp("all", data, 3)) {
++ snprintf(buf, len, "\"%s\" <%s>",
++ S_OR(chan->connected.id.name, ""),
++ S_OR(chan->connected.id.number, ""));
++ } else if (!strncasecmp("name", data, 4)) {
++ if (chan->connected.id.name) {
++ ast_copy_string(buf, chan->connected.id.name, len);
++ }
++ } else if (!strncasecmp("num", data, 3)) {
++ if (chan->connected.id.number) {
++ ast_copy_string(buf, chan->connected.id.number, len);
++ }
++ } else if (!strncasecmp("ton", data, 3)) {
++ snprintf(buf, len, "%d", chan->connected.id.number_type);
++ } else if (!strncasecmp("pres", data, 4)) {
++ ast_copy_string(buf, ast_named_caller_presentation(chan->connected.id.number_presentation), len);
++ } else if (!strncasecmp("source", data, 6)) {
++ ast_copy_string(buf, ast_connected_line_source_name(chan->connected.source), len);
++ } else {
++ ast_log(LOG_ERROR, "Unknown connectedline data type '%s'.\n", data);
++ }
++
++ ast_channel_unlock(chan);
++
++ return 0;
++}
++
++static int connectedline_write(struct ast_channel *chan, const char *cmd, char *data,
++ const char *value)
++{
++ struct ast_party_connected_line connected;
++ char *val;
++ char *option;
++ void (*set_it)(struct ast_channel *chan, const struct ast_party_connected_line *connected);
++
++ if (!value || !chan) {
++ return -1;
++ }
++
++ /* Determine if the update indication inhibit option is present */
++ option = strchr(data, ',');
++ if (option) {
++ option = ast_skip_blanks(option + 1);
++ switch (*option) {
++ case 'i':
++ set_it = ast_channel_set_connected_line;
++ break;
++
++ default:
++ ast_log(LOG_ERROR, "Unknown connectedline option '%s'.\n", option);
++ return 0;
++ }
++ }
++ else {
++ set_it = ast_channel_update_connected_line;
++ }
++
++ ast_channel_lock(chan);
++ ast_party_connected_line_set_init(&connected, &chan->connected);
++ ast_channel_unlock(chan);
++
++ value = ast_skip_blanks(value);
++
++ if (!strncasecmp("all", data, 3)) {
++ char name[256];
++ char num[256];
++
++ ast_callerid_split(value, name, sizeof(name), num, sizeof(num));
++ connected.id.name = name;
++ connected.id.number = num;
++ set_it(chan, &connected);
++ } else if (!strncasecmp("name", data, 4)) {
++ connected.id.name = ast_strdupa(value);
++ ast_trim_blanks(connected.id.name);
++ set_it(chan, &connected);
++ } else if (!strncasecmp("num", data, 3)) {
++ connected.id.number = ast_strdupa(value);
++ ast_trim_blanks(connected.id.number);
++ set_it(chan, &connected);
++ } else if (!strncasecmp("ton", data, 3)) {
++ val = ast_strdupa(value);
++ ast_trim_blanks(val);
++
++ if (('0' <= val[0]) && (val[0] <= '9')) {
++ connected.id.number_type = atoi(val);
++ set_it(chan, &connected);
++ } else {
++ ast_log(LOG_ERROR, "Unknown connectedline type of number '%s', value unchanged\n", val);
++ }
++ } else if (!strncasecmp("pres", data, 4)) {
++ int pres;
++
++ val = ast_strdupa(value);
++ ast_trim_blanks(val);
++
++ if (('0' <= val[0]) && (val[0] <= '9')) {
++ pres = atoi(val);
++ } else {
++ pres = ast_parse_caller_presentation(val);
++ }
++
++ if (pres < 0) {
++ ast_log(LOG_ERROR, "Unknown connectedline number presentation '%s', value unchanged\n", val);
++ } else {
++ connected.id.number_presentation = pres;
++ set_it(chan, &connected);
++ }
++ } else if (!strncasecmp("source", data, 6)) {
++ int source;
++
++ val = ast_strdupa(value);
++ ast_trim_blanks(val);
++
++ if (('0' <= val[0]) && (val[0] <= '9')) {
++ source = atoi(val);
++ } else {
++ source = ast_connected_line_source_parse(val);
++ }
++
++ if (source < 0) {
++ ast_log(LOG_ERROR, "Unknown connectedline source '%s', value unchanged\n", val);
++ } else {
++ connected.source = source;
++ set_it(chan, &connected);
++ }
++ } else {
++ ast_log(LOG_ERROR, "Unknown connectedline data type '%s'.\n", data);
++ }
++
++ return 0;
++}
++
++static struct ast_custom_function connectedline_function = {
++ .name = "CONNECTEDLINE",
++ .read = connectedline_read,
++ .write = connectedline_write,
++};
++
++static int unload_module(void)
++{
++ return ast_custom_function_unregister(&connectedline_function);
++}
++
++static int load_module(void)
++{
++ return ast_custom_function_register(&connectedline_function)
++ ? AST_MODULE_LOAD_DECLINE
++ : AST_MODULE_LOAD_SUCCESS;
++}
++
++AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Connected Line dialplan function");
+
+Property changes on: funcs/func_connectedline.c
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+
+Index: funcs/func_callerid.c
+===================================================================
+--- a/funcs/func_callerid.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/funcs/func_callerid.c (.../trunk) (revision 202568)
+@@ -274,12 +274,14 @@
+ static struct ast_custom_function callerid_function = {
+ .name = "CALLERID",
+ .read = callerid_read,
++ .read_max = 256,
+ .write = callerid_write,
+ };
+
+ static struct ast_custom_function callerpres_function = {
+ .name = "CALLERPRES",
+ .read = callerpres_read,
++ .read_max = 50,
+ .write = callerpres_write,
+ };
+
+Index: funcs/func_devstate.c
+===================================================================
+--- a/funcs/func_devstate.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/funcs/func_devstate.c (.../trunk) (revision 202568)
+@@ -255,8 +255,8 @@
+ return NULL;
+ case CLI_GENERATE:
+ {
+- static char * const cmds[] = { "UNKNOWN", "NOT_INUSE", "INUSE", "BUSY",
+- "UNAVAILABLE", "RINGING", "RINGINUSE", "ONHOLD", NULL };
++ static const char * const cmds[] = { "UNKNOWN", "NOT_INUSE", "INUSE", "BUSY",
++ "UNAVAILABLE", "RINGING", "RINGINUSE", "ONHOLD", NULL };
+
+ if (a->pos == e->args + 1)
+ return ast_cli_complete(a->word, cmds, a->n);
+Index: include/asterisk/rtp.h
+===================================================================
+--- a/include/asterisk/rtp.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/rtp.h (.../trunk) (revision 202568)
+@@ -1,433 +0,0 @@
+-/*
+- * Asterisk -- An open source telephony toolkit.
+- *
+- * Copyright (C) 1999 - 2006, Digium, Inc.
+- *
+- * Mark Spencer <markster@digium.com>
+- *
+- * See http://www.asterisk.org for more information about
+- * the Asterisk project. Please do not directly contact
+- * any of the maintainers of this project for assistance;
+- * the project provides a web site, mailing lists and IRC
+- * channels for your use.
+- *
+- * 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.
+- */
+-
+-/*!
+- * \file rtp.h
+- * \brief Supports RTP and RTCP with Symmetric RTP support for NAT traversal.
+- *
+- * RTP is defined in RFC 3550.
+- */
+-
+-#ifndef _ASTERISK_RTP_H
+-#define _ASTERISK_RTP_H
+-
+-#include "asterisk/network.h"
+-
+-#include "asterisk/frame.h"
+-#include "asterisk/io.h"
+-#include "asterisk/sched.h"
+-#include "asterisk/channel.h"
+-#include "asterisk/linkedlists.h"
+-
+-#if defined(__cplusplus) || defined(c_plusplus)
+-extern "C" {
+-#endif
+-
+-/* Codes for RTP-specific data - not defined by our AST_FORMAT codes */
+-/*! DTMF (RFC2833) */
+-#define AST_RTP_DTMF (1 << 0)
+-/*! 'Comfort Noise' (RFC3389) */
+-#define AST_RTP_CN (1 << 1)
+-/*! DTMF (Cisco Proprietary) */
+-#define AST_RTP_CISCO_DTMF (1 << 2)
+-/*! Maximum RTP-specific code */
+-#define AST_RTP_MAX AST_RTP_CISCO_DTMF
+-
+-/*! Maxmum number of payload defintions for a RTP session */
+-#define MAX_RTP_PT 256
+-
+-/*! T.140 Redundancy Maxium number of generations */
+-#define RED_MAX_GENERATION 5
+-
+-#define FLAG_3389_WARNING (1 << 0)
+-
+-enum ast_rtp_options {
+- AST_RTP_OPT_G726_NONSTANDARD = (1 << 0),
+-};
+-
+-enum ast_rtp_get_result {
+- /*! Failed to find the RTP structure */
+- AST_RTP_GET_FAILED = 0,
+- /*! RTP structure exists but true native bridge can not occur so try partial */
+- AST_RTP_TRY_PARTIAL,
+- /*! RTP structure exists and native bridge can occur */
+- AST_RTP_TRY_NATIVE,
+-};
+-
+-/*! \brief Variables used in ast_rtcp_get function */
+-enum ast_rtp_qos_vars {
+- AST_RTP_TXCOUNT,
+- AST_RTP_RXCOUNT,
+- AST_RTP_TXJITTER,
+- AST_RTP_RXJITTER,
+- AST_RTP_RXPLOSS,
+- AST_RTP_TXPLOSS,
+- AST_RTP_RTT
+-};
+-
+-struct ast_rtp;
+-/*! T.140 Redundancy structure*/
+-struct rtp_red;
+-
+-/*! \brief The value of each payload format mapping: */
+-struct rtpPayloadType {
+- int isAstFormat; /*!< whether the following code is an AST_FORMAT */
+- int code;
+-};
+-
+-/*! \brief This is the structure that binds a channel (SIP/Jingle/H.323) to the RTP subsystem
+-*/
+-struct ast_rtp_protocol {
+- /*! Get RTP struct, or NULL if unwilling to transfer */
+- enum ast_rtp_get_result (* const get_rtp_info)(struct ast_channel *chan, struct ast_rtp **rtp);
+- /*! Get RTP struct, or NULL if unwilling to transfer */
+- enum ast_rtp_get_result (* const get_vrtp_info)(struct ast_channel *chan, struct ast_rtp **rtp);
+- /*! Get RTP struct, or NULL if unwilling to transfer */
+- enum ast_rtp_get_result (* const get_trtp_info)(struct ast_channel *chan, struct ast_rtp **rtp);
+- /*! Set RTP peer */
+- int (* const set_rtp_peer)(struct ast_channel *chan, struct ast_rtp *peer, struct ast_rtp *vpeer, struct ast_rtp *tpeer, int codecs, int nat_active);
+- int (* const get_codec)(struct ast_channel *chan);
+- const char * const type;
+- AST_LIST_ENTRY(ast_rtp_protocol) list;
+-};
+-
+-enum ast_rtp_quality_type {
+- RTPQOS_SUMMARY = 0,
+- RTPQOS_JITTER,
+- RTPQOS_LOSS,
+- RTPQOS_RTT
+-};
+-
+-/*! \brief RTCP quality report storage */
+-struct ast_rtp_quality {
+- unsigned int local_ssrc; /*!< Our SSRC */
+- unsigned int local_lostpackets; /*!< Our lost packets */
+- double local_jitter; /*!< Our calculated jitter */
+- unsigned int local_count; /*!< Number of received packets */
+- unsigned int remote_ssrc; /*!< Their SSRC */
+- unsigned int remote_lostpackets; /*!< Their lost packets */
+- double remote_jitter; /*!< Their reported jitter */
+- unsigned int remote_count; /*!< Number of transmitted packets */
+- double rtt; /*!< Round trip time */
+-};
+-
+-/*! RTP callback structure */
+-typedef int (*ast_rtp_callback)(struct ast_rtp *rtp, struct ast_frame *f, void *data);
+-
+-/*!
+- * \brief Get the amount of space required to hold an RTP session
+- * \return number of bytes required
+- */
+-size_t ast_rtp_alloc_size(void);
+-
+-/*!
+- * \brief Initializate a RTP session.
+- *
+- * \param sched
+- * \param io
+- * \param rtcpenable
+- * \param callbackmode
+- * \return A representation (structure) of an RTP session.
+- */
+-struct ast_rtp *ast_rtp_new(struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode);
+-
+-/*!
+- * \brief Initializate a RTP session using an in_addr structure.
+- *
+- * This fuction gets called by ast_rtp_new().
+- *
+- * \param sched
+- * \param io
+- * \param rtcpenable
+- * \param callbackmode
+- * \param in
+- * \return A representation (structure) of an RTP session.
+- */
+-struct ast_rtp *ast_rtp_new_with_bindaddr(struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode, struct in_addr in);
+-
+-void ast_rtp_set_peer(struct ast_rtp *rtp, struct sockaddr_in *them);
+-
+-/*!
+- * \since 1.4.26
+- * \brief set potential alternate source for RTP media
+- *
+- * This function may be used to give the RTP stack a hint that there is a potential
+- * second source of media. One case where this is used is when the SIP stack receives
+- * a REINVITE to which it will be replying with a 491. In such a scenario, the IP and
+- * port information in the SDP of that REINVITE lets us know that we may receive media
+- * from that source/those sources even though the SIP transaction was unable to be completed
+- * successfully
+- *
+- * \param rtp The RTP structure we wish to set up an alternate host/port on
+- * \param alt The address information for the alternate media source
+- * \retval void
+- */
+-void ast_rtp_set_alt_peer(struct ast_rtp *rtp, struct sockaddr_in *alt);
+-
+-/* Copies from rtp to them and returns 1 if there was a change or 0 if it was already the same */
+-int ast_rtp_get_peer(struct ast_rtp *rtp, struct sockaddr_in *them);
+-
+-void ast_rtp_get_us(struct ast_rtp *rtp, struct sockaddr_in *us);
+-
+-struct ast_rtp *ast_rtp_get_bridged(struct ast_rtp *rtp);
+-
+-/*! Destroy RTP session */
+-void ast_rtp_destroy(struct ast_rtp *rtp);
+-
+-void ast_rtp_reset(struct ast_rtp *rtp);
+-
+-/*! Stop RTP session, do not destroy structure */
+-void ast_rtp_stop(struct ast_rtp *rtp);
+-
+-void ast_rtp_set_callback(struct ast_rtp *rtp, ast_rtp_callback callback);
+-
+-void ast_rtp_set_data(struct ast_rtp *rtp, void *data);
+-
+-int ast_rtp_write(struct ast_rtp *rtp, struct ast_frame *f);
+-
+-struct ast_frame *ast_rtp_read(struct ast_rtp *rtp);
+-
+-struct ast_frame *ast_rtcp_read(struct ast_rtp *rtp);
+-
+-int ast_rtp_fd(struct ast_rtp *rtp);
+-
+-int ast_rtcp_fd(struct ast_rtp *rtp);
+-
+-int ast_rtp_senddigit_begin(struct ast_rtp *rtp, char digit);
+-
+-int ast_rtp_senddigit_end(struct ast_rtp *rtp, char digit);
+-
+-int ast_rtp_sendcng(struct ast_rtp *rtp, int level);
+-
+-int ast_rtp_setqos(struct ast_rtp *rtp, int tos, int cos, char *desc);
+-
+-void ast_rtp_new_source(struct ast_rtp *rtp);
+-
+-/*! \brief Setting RTP payload types from lines in a SDP description: */
+-void ast_rtp_pt_clear(struct ast_rtp* rtp);
+-/*! \brief Set payload types to defaults */
+-void ast_rtp_pt_default(struct ast_rtp* rtp);
+-
+-/*! \brief Copy payload types between RTP structures */
+-void ast_rtp_pt_copy(struct ast_rtp *dest, struct ast_rtp *src);
+-
+-/*! \brief Activate payload type */
+-void ast_rtp_set_m_type(struct ast_rtp* rtp, int pt);
+-
+-/*! \brief clear payload type */
+-void ast_rtp_unset_m_type(struct ast_rtp* rtp, int pt);
+-
+-/*! \brief Set payload type to a known MIME media type for a codec
+- *
+- * \param rtp RTP structure to modify
+- * \param pt Payload type entry to modify
+- * \param mimeType top-level MIME type of media stream (typically "audio", "video", "text", etc.)
+- * \param mimeSubtype MIME subtype of media stream (typically a codec name)
+- * \param options Zero or more flags from the ast_rtp_options enum
+- *
+- * This function 'fills in' an entry in the list of possible formats for
+- * a media stream associated with an RTP structure.
+- *
+- * \retval 0 on success
+- * \retval -1 if the payload type is out of range
+- * \retval -2 if the mimeType/mimeSubtype combination was not found
+- */
+-int ast_rtp_set_rtpmap_type(struct ast_rtp* rtp, int pt,
+- char *mimeType, char *mimeSubtype,
+- enum ast_rtp_options options);
+-
+-/*! \brief Set payload type to a known MIME media type for a codec with a specific sample rate
+- *
+- * \param rtp RTP structure to modify
+- * \param pt Payload type entry to modify
+- * \param mimeType top-level MIME type of media stream (typically "audio", "video", "text", etc.)
+- * \param mimeSubtype MIME subtype of media stream (typically a codec name)
+- * \param options Zero or more flags from the ast_rtp_options enum
+- * \param sample_rate The sample rate of the media stream
+- *
+- * This function 'fills in' an entry in the list of possible formats for
+- * a media stream associated with an RTP structure.
+- *
+- * \retval 0 on success
+- * \retval -1 if the payload type is out of range
+- * \retval -2 if the mimeType/mimeSubtype combination was not found
+- */
+-int ast_rtp_set_rtpmap_type_rate(struct ast_rtp* rtp, int pt,
+- char *mimeType, char *mimeSubtype,
+- enum ast_rtp_options options,
+- unsigned int sample_rate);
+-
+-/*! \brief Mapping between RTP payload format codes and Asterisk codes: */
+-struct rtpPayloadType ast_rtp_lookup_pt(struct ast_rtp* rtp, int pt);
+-int ast_rtp_lookup_code(struct ast_rtp* rtp, int isAstFormat, int code);
+-
+-void ast_rtp_get_current_formats(struct ast_rtp* rtp,
+- int* astFormats, int* nonAstFormats);
+-
+-/*! \brief Mapping an Asterisk code into a MIME subtype (string): */
+-const char *ast_rtp_lookup_mime_subtype(int isAstFormat, int code,
+- enum ast_rtp_options options);
+-
+-/*! \brief Get the sample rate associated with known RTP payload types
+- *
+- * \param isAstFormat True if the value in the 'code' parameter is an AST_FORMAT value
+- * \param code Format code, either from AST_FORMAT list or from AST_RTP list
+- *
+- * \return the sample rate if the format was found, zero if it was not found
+- */
+-unsigned int ast_rtp_lookup_sample_rate(int isAstFormat, int code);
+-
+-/*! \brief Build a string of MIME subtype names from a capability list */
+-char *ast_rtp_lookup_mime_multiple(char *buf, size_t size, const int capability,
+- const int isAstFormat, enum ast_rtp_options options);
+-
+-void ast_rtp_setnat(struct ast_rtp *rtp, int nat);
+-
+-int ast_rtp_getnat(struct ast_rtp *rtp);
+-
+-/*! \brief Indicate whether this RTP session is carrying DTMF or not */
+-void ast_rtp_setdtmf(struct ast_rtp *rtp, int dtmf);
+-
+-/*! \brief Compensate for devices that send RFC2833 packets all at once */
+-void ast_rtp_setdtmfcompensate(struct ast_rtp *rtp, int compensate);
+-
+-/*! \brief Enable STUN capability */
+-void ast_rtp_setstun(struct ast_rtp *rtp, int stun_enable);
+-
+-/*! \brief Generic STUN request
+- * send a generic stun request to the server specified.
+- * \param s the socket used to send the request
+- * \param dst the address of the STUN server
+- * \param username if non null, add the username in the request
+- * \param answer if non null, the function waits for a response and
+- * puts here the externally visible address.
+- * \return 0 on success, other values on error.
+- * The interface it may change in the future.
+- */
+-int ast_stun_request(int s, struct sockaddr_in *dst,
+- const char *username, struct sockaddr_in *answer);
+-
+-/*! \brief Send STUN request for an RTP socket
+- * Deprecated, this is just a wrapper for ast_rtp_stun_request()
+- */
+-void ast_rtp_stun_request(struct ast_rtp *rtp, struct sockaddr_in *suggestion, const char *username);
+-
+-/*! \brief The RTP bridge.
+- \arg \ref AstRTPbridge
+-*/
+-int ast_rtp_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms);
+-
+-/*! \brief Register an RTP channel client */
+-int ast_rtp_proto_register(struct ast_rtp_protocol *proto);
+-
+-/*! \brief Unregister an RTP channel client */
+-void ast_rtp_proto_unregister(struct ast_rtp_protocol *proto);
+-
+-int ast_rtp_make_compatible(struct ast_channel *dest, struct ast_channel *src, int media);
+-
+-/*! \brief If possible, create an early bridge directly between the devices without
+- having to send a re-invite later */
+-int ast_rtp_early_bridge(struct ast_channel *c0, struct ast_channel *c1);
+-
+-/*! \brief Get QOS stats on a RTP channel
+- * \since 1.6.1
+- */
+-int ast_rtp_get_qos(struct ast_rtp *rtp, const char *qos, char *buf, unsigned int buflen);
+-
+-/*! \brief Return RTP and RTCP QoS values
+- * \since 1.6.1
+- */
+-unsigned int ast_rtp_get_qosvalue(struct ast_rtp *rtp, enum ast_rtp_qos_vars value);
+-
+-/*! \brief Set RTPAUDIOQOS(...) variables on a channel when it is being hung up
+- * \since 1.6.1
+- */
+-void ast_rtp_set_vars(struct ast_channel *chan, struct ast_rtp *rtp);
+-
+-/*! \brief Return RTCP quality string
+- *
+- * \param rtp An rtp structure to get qos information about.
+- *
+- * \param qual An (optional) rtp quality structure that will be
+- * filled with the quality information described in
+- * the ast_rtp_quality structure. This structure is
+- * not dependent on any qtype, so a call for any
+- * type of information would yield the same results
+- * because ast_rtp_quality is not a data type
+- * specific to any qos type.
+- *
+- * \param qtype The quality type you'd like, default should be
+- * RTPQOS_SUMMARY which returns basic information
+- * about the call. The return from RTPQOS_SUMMARY
+- * is basically ast_rtp_quality in a string. The
+- * other types are RTPQOS_JITTER, RTPQOS_LOSS and
+- * RTPQOS_RTT which will return more specific
+- * statistics.
+- * \version 1.6.1 added qtype parameter
+- */
+-char *ast_rtp_get_quality(struct ast_rtp *rtp, struct ast_rtp_quality *qual, enum ast_rtp_quality_type qtype);
+-/*! \brief Send an H.261 fast update request. Some devices need this rather than the XML message in SIP */
+-int ast_rtcp_send_h261fur(void *data);
+-
+-void ast_rtp_init(void); /*! Initialize RTP subsystem */
+-int ast_rtp_reload(void); /*! reload rtp configuration */
+-void ast_rtp_new_init(struct ast_rtp *rtp);
+-
+-/*! \brief Set codec preference */
+-void ast_rtp_codec_setpref(struct ast_rtp *rtp, struct ast_codec_pref *prefs);
+-
+-/*! \brief Get codec preference */
+-struct ast_codec_pref *ast_rtp_codec_getpref(struct ast_rtp *rtp);
+-
+-/*! \brief get format from predefined dynamic payload format */
+-int ast_rtp_codec_getformat(int pt);
+-
+-/*! \brief Set rtp timeout */
+-void ast_rtp_set_rtptimeout(struct ast_rtp *rtp, int timeout);
+-/*! \brief Set rtp hold timeout */
+-void ast_rtp_set_rtpholdtimeout(struct ast_rtp *rtp, int timeout);
+-/*! \brief set RTP keepalive interval */
+-void ast_rtp_set_rtpkeepalive(struct ast_rtp *rtp, int period);
+-/*! \brief Get RTP keepalive interval */
+-int ast_rtp_get_rtpkeepalive(struct ast_rtp *rtp);
+-/*! \brief Get rtp hold timeout */
+-int ast_rtp_get_rtpholdtimeout(struct ast_rtp *rtp);
+-/*! \brief Get rtp timeout */
+-int ast_rtp_get_rtptimeout(struct ast_rtp *rtp);
+-/* \brief Put RTP timeout timers on hold during another transaction, like T.38 */
+-void ast_rtp_set_rtptimers_onhold(struct ast_rtp *rtp);
+-
+-/*! \brief Initalize t.140 redudancy
+- * \param ti time between each t140red frame is sent
+- * \param red_pt payloadtype for RTP packet
+- * \param pt payloadtype numbers for each generation including primary data
+- * \param num_gen number of redundant generations, primary data excluded
+- * \since 1.6.1
+- */
+-int rtp_red_init(struct ast_rtp *rtp, int ti, int *pt, int num_gen);
+-
+-/*! \brief Buffer t.140 data */
+-void red_buffer_t140(struct ast_rtp *rtp, struct ast_frame *f);
+-
+-
+-
+-#if defined(__cplusplus) || defined(c_plusplus)
+-}
+-#endif
+-
+-#endif /* _ASTERISK_RTP_H */
+Index: include/asterisk/rtp_engine.h
+===================================================================
+--- a/include/asterisk/rtp_engine.h (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/include/asterisk/rtp_engine.h (.../trunk) (revision 202568)
+@@ -0,0 +1,1640 @@
++/*
++ * Asterisk -- An open source telephony toolkit.
++ *
++ * Copyright (C) 1999 - 2009, Digium, Inc.
++ *
++ * Mark Spencer <markster@digium.com>
++ * Joshua Colp <jcolp@digium.com>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * 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.
++ */
++
++/*! \file
++ * \brief Pluggable RTP Architecture
++ * \author Joshua Colp <jcolp@digium.com>
++ * \ref AstRTPEngine
++ */
++
++/*!
++ * \page AstRTPEngine Asterisk RTP Engine API
++ *
++ * The purpose of this API is to provide a way for multiple RTP stacks to be used inside
++ * of Asterisk without any module that uses RTP knowing any different. To the module each RTP
++ * stack behaves the same.
++ *
++ * An RTP session is called an instance and is made up of a combination of codec information,
++ * RTP engine, RTP properties, and address information. An engine name may be passed in to explicitly
++ * choose an RTP stack to be used but a default one will be used if none is provided. An address to use
++ * for RTP may also be provided but the underlying RTP engine may choose a different address depending on
++ * it's configuration.
++ *
++ * An RTP engine is the layer between the RTP engine core and the RTP stack itself. The RTP engine core provides
++ * a set of callbacks to do various things (such as write audio out) that the RTP engine has to have implemented.
++ *
++ * Glue is what binds an RTP instance to a channel. It is used to retrieve RTP instance information when
++ * performing remote or local bridging and is used to have the channel driver tell the remote side to change
++ * destination of the RTP stream.
++ *
++ * Statistics from an RTP instance can be retrieved using the ast_rtp_instance_get_stats API call. This essentially
++ * asks the RTP engine in use to fill in a structure with the requested values. It is not required for an RTP engine
++ * to support all statistic values.
++ *
++ * Properties allow behavior of the RTP engine and RTP engine core to be changed. For example, there is a property named
++ * AST_RTP_PROPERTY_NAT which is used to tell the RTP engine to enable symmetric RTP if it supports it. It is not required
++ * for an RTP engine to support all properties.
++ *
++ * Codec information is stored using a separate data structure which has it's own set of API calls to add/remove/retrieve
++ * information. They are used by the module after an RTP instance is created so that payload information is available for
++ * the RTP engine.
++ */
++
++#ifndef _ASTERISK_RTP_ENGINE_H
++#define _ASTERISK_RTP_ENGINE_H
++
++#if defined(__cplusplus) || defined(c_plusplus)
++extern "C" {
++#endif
++
++#include "asterisk/astobj2.h"
++
++/* Maximum number of payloads supported */
++#define AST_RTP_MAX_PT 256
++
++/* Maximum number of generations */
++#define AST_RED_MAX_GENERATION 5
++
++struct ast_rtp_instance;
++struct ast_rtp_glue;
++
++/*! RTP Properties that can be set on an RTP instance */
++enum ast_rtp_property {
++ /*! Enable symmetric RTP support */
++ AST_RTP_PROPERTY_NAT = 0,
++ /*! RTP instance will be carrying DTMF (using RFC2833) */
++ AST_RTP_PROPERTY_DTMF,
++ /*! Expect unreliable DTMF from remote party */
++ AST_RTP_PROPERTY_DTMF_COMPENSATE,
++ /*! Enable STUN support */
++ AST_RTP_PROPERTY_STUN,
++ /*! Enable RTCP support */
++ AST_RTP_PROPERTY_RTCP,
++ /*! Maximum number of RTP properties supported */
++ AST_RTP_PROPERTY_MAX,
++};
++
++/*! Additional RTP options */
++enum ast_rtp_options {
++ /*! Remote side is using non-standard G.726 */
++ AST_RTP_OPT_G726_NONSTANDARD = (1 << 0),
++};
++
++/*! RTP DTMF Modes */
++enum ast_rtp_dtmf_mode {
++ /*! No DTMF is being carried over the RTP stream */
++ AST_RTP_DTMF_MODE_NONE = 0,
++ /*! DTMF is being carried out of band using RFC2833 */
++ AST_RTP_DTMF_MODE_RFC2833,
++ /*! DTMF is being carried inband over the RTP stream */
++ AST_RTP_DTMF_MODE_INBAND,
++};
++
++/*! Result codes when RTP glue is queried for information */
++enum ast_rtp_glue_result {
++ /*! No remote or local bridging is permitted */
++ AST_RTP_GLUE_RESULT_FORBID = 0,
++ /*! Move RTP stream to be remote between devices directly */
++ AST_RTP_GLUE_RESULT_REMOTE,
++ /*! Perform RTP engine level bridging if possible */
++ AST_RTP_GLUE_RESULT_LOCAL,
++};
++
++/*! Field statistics that can be retrieved from an RTP instance */
++enum ast_rtp_instance_stat_field {
++ /*! Retrieve quality information */
++ AST_RTP_INSTANCE_STAT_FIELD_QUALITY = 0,
++ /*! Retrieve quality information about jitter */
++ AST_RTP_INSTANCE_STAT_FIELD_QUALITY_JITTER,
++ /*! Retrieve quality information about packet loss */
++ AST_RTP_INSTANCE_STAT_FIELD_QUALITY_LOSS,
++ /*! Retrieve quality information about round trip time */
++ AST_RTP_INSTANCE_STAT_FIELD_QUALITY_RTT,
++};
++
++/*! Statistics that can be retrieved from an RTP instance */
++enum ast_rtp_instance_stat {
++ /*! Retrieve all statistics */
++ AST_RTP_INSTANCE_STAT_ALL = 0,
++ /*! Retrieve number of packets transmitted */
++ AST_RTP_INSTANCE_STAT_TXCOUNT,
++ /*! Retrieve number of packets received */
++ AST_RTP_INSTANCE_STAT_RXCOUNT,
++ /*! Retrieve ALL statistics relating to packet loss */
++ AST_RTP_INSTANCE_STAT_COMBINED_LOSS,
++ /*! Retrieve number of packets lost for transmitting */
++ AST_RTP_INSTANCE_STAT_TXPLOSS,
++ /*! Retrieve number of packets lost for receiving */
++ AST_RTP_INSTANCE_STAT_RXPLOSS,
++ /*! Retrieve maximum number of packets lost on remote side */
++ AST_RTP_INSTANCE_STAT_REMOTE_MAXRXPLOSS,
++ /*! Retrieve minimum number of packets lost on remote side */
++ AST_RTP_INSTANCE_STAT_REMOTE_MINRXPLOSS,
++ /*! Retrieve average number of packets lost on remote side */
++ AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVRXPLOSS,
++ /*! Retrieve standard deviation of packets lost on remote side */
++ AST_RTP_INSTANCE_STAT_REMOTE_STDEVRXPLOSS,
++ /*! Retrieve maximum number of packets lost on local side */
++ AST_RTP_INSTANCE_STAT_LOCAL_MAXRXPLOSS,
++ /*! Retrieve minimum number of packets lost on local side */
++ AST_RTP_INSTANCE_STAT_LOCAL_MINRXPLOSS,
++ /*! Retrieve average number of packets lost on local side */
++ AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVRXPLOSS,
++ /*! Retrieve standard deviation of packets lost on local side */
++ AST_RTP_INSTANCE_STAT_LOCAL_STDEVRXPLOSS,
++ /*! Retrieve ALL statistics relating to jitter */
++ AST_RTP_INSTANCE_STAT_COMBINED_JITTER,
++ /*! Retrieve jitter on transmitted packets */
++ AST_RTP_INSTANCE_STAT_TXJITTER,
++ /*! Retrieve jitter on received packets */
++ AST_RTP_INSTANCE_STAT_RXJITTER,
++ /*! Retrieve maximum jitter on remote side */
++ AST_RTP_INSTANCE_STAT_REMOTE_MAXJITTER,
++ /*! Retrieve minimum jitter on remote side */
++ AST_RTP_INSTANCE_STAT_REMOTE_MINJITTER,
++ /*! Retrieve average jitter on remote side */
++ AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVJITTER,
++ /*! Retrieve standard deviation jitter on remote side */
++ AST_RTP_INSTANCE_STAT_REMOTE_STDEVJITTER,
++ /*! Retrieve maximum jitter on local side */
++ AST_RTP_INSTANCE_STAT_LOCAL_MAXJITTER,
++ /*! Retrieve minimum jitter on local side */
++ AST_RTP_INSTANCE_STAT_LOCAL_MINJITTER,
++ /*! Retrieve average jitter on local side */
++ AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVJITTER,
++ /*! Retrieve standard deviation jitter on local side */
++ AST_RTP_INSTANCE_STAT_LOCAL_STDEVJITTER,
++ /*! Retrieve ALL statistics relating to round trip time */
++ AST_RTP_INSTANCE_STAT_COMBINED_RTT,
++ /*! Retrieve round trip time */
++ AST_RTP_INSTANCE_STAT_RTT,
++ /*! Retrieve maximum round trip time */
++ AST_RTP_INSTANCE_STAT_MAX_RTT,
++ /*! Retrieve minimum round trip time */
++ AST_RTP_INSTANCE_STAT_MIN_RTT,
++ /*! Retrieve average round trip time */
++ AST_RTP_INSTANCE_STAT_NORMDEVRTT,
++ /*! Retrieve standard deviation round trip time */
++ AST_RTP_INSTANCE_STAT_STDEVRTT,
++ /*! Retrieve local SSRC */
++ AST_RTP_INSTANCE_STAT_LOCAL_SSRC,
++ /*! Retrieve remote SSRC */
++ AST_RTP_INSTANCE_STAT_REMOTE_SSRC,
++};
++
++/* Codes for RTP-specific data - not defined by our AST_FORMAT codes */
++/*! DTMF (RFC2833) */
++#define AST_RTP_DTMF (1 << 0)
++/*! 'Comfort Noise' (RFC3389) */
++#define AST_RTP_CN (1 << 1)
++/*! DTMF (Cisco Proprietary) */
++#define AST_RTP_CISCO_DTMF (1 << 2)
++/*! Maximum RTP-specific code */
++#define AST_RTP_MAX AST_RTP_CISCO_DTMF
++
++/*! Structure that represents a payload */
++struct ast_rtp_payload_type {
++ /*! Is this an Asterisk value */
++ int asterisk_format;
++ /*! Actual internal value of the payload */
++ int code;
++};
++
++/*! Structure that represents statistics from an RTP instance */
++struct ast_rtp_instance_stats {
++ /*! Number of packets transmitted */
++ unsigned int txcount;
++ /*! Number of packets received */
++ unsigned int rxcount;
++ /*! Jitter on transmitted packets */
++ unsigned int txjitter;
++ /*! Jitter on received packets */
++ unsigned int rxjitter;
++ /*! Maximum jitter on remote side */
++ double remote_maxjitter;
++ /*! Minimum jitter on remote side */
++ double remote_minjitter;
++ /*! Average jitter on remote side */
++ double remote_normdevjitter;
++ /*! Standard deviation jitter on remote side */
++ double remote_stdevjitter;
++ /*! Maximum jitter on local side */
++ double local_maxjitter;
++ /*! Minimum jitter on local side */
++ double local_minjitter;
++ /*! Average jitter on local side */
++ double local_normdevjitter;
++ /*! Standard deviation jitter on local side */
++ double local_stdevjitter;
++ /*! Number of transmitted packets lost */
++ unsigned int txploss;
++ /*! Number of received packets lost */
++ unsigned int rxploss;
++ /*! Maximum number of packets lost on remote side */
++ double remote_maxrxploss;
++ /*! Minimum number of packets lost on remote side */
++ double remote_minrxploss;
++ /*! Average number of packets lost on remote side */
++ double remote_normdevrxploss;
++ /*! Standard deviation packets lost on remote side */
++ double remote_stdevrxploss;
++ /*! Maximum number of packets lost on local side */
++ double local_maxrxploss;
++ /*! Minimum number of packets lost on local side */
++ double local_minrxploss;
++ /*! Average number of packets lost on local side */
++ double local_normdevrxploss;
++ /*! Standard deviation packets lost on local side */
++ double local_stdevrxploss;
++ /*! Total round trip time */
++ unsigned int rtt;
++ /*! Maximum round trip time */
++ double maxrtt;
++ /*! Minimum round trip time */
++ double minrtt;
++ /*! Average round trip time */
++ double normdevrtt;
++ /*! Standard deviation round trip time */
++ double stdevrtt;
++ /*! Our SSRC */
++ unsigned int local_ssrc;
++ /*! Their SSRC */
++ unsigned int remote_ssrc;
++};
++
++#define AST_RTP_STAT_SET(current_stat, combined, placement, value) \
++if (stat == current_stat || stat == AST_RTP_INSTANCE_STAT_ALL || (combined >= 0 && combined == current_stat)) { \
++placement = value; \
++if (stat == current_stat) { \
++return 0; \
++} \
++}
++
++#define AST_RTP_STAT_TERMINATOR(combined) \
++if (stat == combined) { \
++return 0; \
++}
++
++/*! Structure that represents an RTP stack (engine) */
++struct ast_rtp_engine {
++ /*! Name of the RTP engine, used when explicitly requested */
++ const char *name;
++ /*! Module this RTP engine came from, used for reference counting */
++ struct ast_module *mod;
++ /*! Callback for setting up a new RTP instance */
++ int (*new)(struct ast_rtp_instance *instance, struct sched_context *sched, struct sockaddr_in *sin, void *data);
++ /*! Callback for destroying an RTP instance */
++ int (*destroy)(struct ast_rtp_instance *instance);
++ /*! Callback for writing out a frame */
++ int (*write)(struct ast_rtp_instance *instance, struct ast_frame *frame);
++ /*! Callback for stopping the RTP instance */
++ void (*stop)(struct ast_rtp_instance *instance);
++ /*! Callback for starting RFC2833 DTMF transmission */
++ int (*dtmf_begin)(struct ast_rtp_instance *instance, char digit);
++ /*! Callback for stopping RFC2833 DTMF transmission */
++ int (*dtmf_end)(struct ast_rtp_instance *instance, char digit);
++ /*! Callback to indicate that a new source of media has come in */
++ void (*new_source)(struct ast_rtp_instance *instance);
++ /*! Callback for setting an extended RTP property */
++ int (*extended_prop_set)(struct ast_rtp_instance *instance, int property, void *value);
++ /*! Callback for getting an extended RTP property */
++ void *(*extended_prop_get)(struct ast_rtp_instance *instance, int property);
++ /*! Callback for setting an RTP property */
++ void (*prop_set)(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value);
++ /*! Callback for setting a payload */
++ void (*payload_set)(struct ast_rtp_instance *instance, int payload, int astformat, int format);
++ /*! Callback for setting packetization preferences */
++ void (*packetization_set)(struct ast_rtp_instance *instance, struct ast_codec_pref *pref);
++ /*! Callback for setting the remote address that RTP is to be sent to */
++ void (*remote_address_set)(struct ast_rtp_instance *instance, struct sockaddr_in *sin);
++ /*! Callback for setting an alternate remote address */
++ void (*alt_remote_address_set)(struct ast_rtp_instance *instance, struct sockaddr_in *sin);
++ /*! Callback for changing DTMF mode */
++ int (*dtmf_mode_set)(struct ast_rtp_instance *instance, enum ast_rtp_dtmf_mode dtmf_mode);
++ /*! Callback for retrieving statistics */
++ int (*get_stat)(struct ast_rtp_instance *instance, struct ast_rtp_instance_stats *stats, enum ast_rtp_instance_stat stat);
++ /*! Callback for setting QoS values */
++ int (*qos)(struct ast_rtp_instance *instance, int tos, int cos, const char *desc);
++ /*! Callback for retrieving a file descriptor to poll on, not always required */
++ int (*fd)(struct ast_rtp_instance *instance, int rtcp);
++ /*! Callback for initializing RED support */
++ int (*red_init)(struct ast_rtp_instance *instance, int buffer_time, int *payloads, int generations);
++ /*! Callback for buffering a frame using RED */
++ int (*red_buffer)(struct ast_rtp_instance *instance, struct ast_frame *frame);
++ /*! Callback for reading a frame from the RTP engine */
++ struct ast_frame *(*read)(struct ast_rtp_instance *instance, int rtcp);
++ /*! Callback to locally bridge two RTP instances */
++ int (*local_bridge)(struct ast_rtp_instance *instance0, struct ast_rtp_instance *instance1);
++ /*! Callback to set the read format */
++ int (*set_read_format)(struct ast_rtp_instance *instance, int format);
++ /*! Callback to set the write format */
++ int (*set_write_format)(struct ast_rtp_instance *instance, int format);
++ /*! Callback to make two instances compatible */
++ int (*make_compatible)(struct ast_channel *chan0, struct ast_rtp_instance *instance0, struct ast_channel *chan1, struct ast_rtp_instance *instance1);
++ /*! Callback to see if two instances are compatible with DTMF */
++ int (*dtmf_compatible)(struct ast_channel *chan0, struct ast_rtp_instance *instance0, struct ast_channel *chan1, struct ast_rtp_instance *instance1);
++ /*! Callback to indicate that packets will now flow */
++ int (*activate)(struct ast_rtp_instance *instance);
++ /*! Callback to request that the RTP engine send a STUN BIND request */
++ void (*stun_request)(struct ast_rtp_instance *instance, struct sockaddr_in *suggestion, const char *username);
++ /*! Callback to get the transcodeable formats supported */
++ int (*available_formats)(struct ast_rtp_instance *instance, int to_endpoint, int to_asterisk);
++ /*! Linked list information */
++ AST_RWLIST_ENTRY(ast_rtp_engine) entry;
++};
++
++/*! Structure that represents codec and packetization information */
++struct ast_rtp_codecs {
++ /*! Codec packetization preferences */
++ struct ast_codec_pref pref;
++ /*! Payloads present */
++ struct ast_rtp_payload_type payloads[AST_RTP_MAX_PT];
++};
++
++/*! Structure that represents the glue that binds an RTP instance to a channel */
++struct ast_rtp_glue {
++ /*! Name of the channel driver that this glue is responsible for */
++ const char *type;
++ /*! Module that the RTP glue came from */
++ struct ast_module *mod;
++ /*!
++ * \brief Callback for retrieving the RTP instance carrying audio
++ * \note This function increases the reference count on the returned RTP instance.
++ */
++ enum ast_rtp_glue_result (*get_rtp_info)(struct ast_channel *chan, struct ast_rtp_instance **instance);
++ /*!
++ * \brief Callback for retrieving the RTP instance carrying video
++ * \note This function increases the reference count on the returned RTP instance.
++ */
++ enum ast_rtp_glue_result (*get_vrtp_info)(struct ast_channel *chan, struct ast_rtp_instance **instance);
++ /*!
++ * \brief Callback for retrieving the RTP instance carrying text
++ * \note This function increases the reference count on the returned RTP instance.
++ */
++ enum ast_rtp_glue_result (*get_trtp_info)(struct ast_channel *chan, struct ast_rtp_instance **instance);
++ /*! Callback for updating the destination that the remote side should send RTP to */
++ int (*update_peer)(struct ast_channel *chan, struct ast_rtp_instance *instance, struct ast_rtp_instance *vinstance, struct ast_rtp_instance *tinstance, int codecs, int nat_active);
++ /*! Callback for retrieving codecs that the channel can do */
++ int (*get_codec)(struct ast_channel *chan);
++ /*! Linked list information */
++ AST_RWLIST_ENTRY(ast_rtp_glue) entry;
++};
++
++#define ast_rtp_engine_register(engine) ast_rtp_engine_register2(engine, ast_module_info->self)
++
++/*!
++ * \brief Register an RTP engine
++ *
++ * \param engine Structure of the RTP engine to register
++ * \param module Module that the RTP engine is part of
++ *
++ * \retval 0 success
++ * \retval -1 failure
++ *
++ * Example usage:
++ *
++ * \code
++ * ast_rtp_engine_register2(&example_rtp_engine, NULL);
++ * \endcode
++ *
++ * This registers the RTP engine declared as example_rtp_engine with the RTP engine core, but does not
++ * associate a module with it.
++ *
++ * \note It is recommended that you use the ast_rtp_engine_register macro so that the module is
++ * associated with the RTP engine and use counting is performed.
++ *
++ * \since 1.6.3
++ */
++int ast_rtp_engine_register2(struct ast_rtp_engine *engine, struct ast_module *module);
++
++/*!
++ * \brief Unregister an RTP engine
++ *
++ * \param engine Structure of the RTP engine to unregister
++ *
++ * \retval 0 success
++ * \retval -1 failure
++ *
++ * Example usage:
++ *
++ * \code
++ * ast_rtp_engine_unregister(&example_rtp_engine);
++ * \endcode
++ *
++ * This unregisters the RTP engine declared as example_rtp_engine from the RTP engine core. If a module
++ * reference was provided when it was registered then this will only be called once the RTP engine is no longer in use.
++ *
++ * \since 1.6.3
++ */
++int ast_rtp_engine_unregister(struct ast_rtp_engine *engine);
++
++#define ast_rtp_glue_register(glue) ast_rtp_glue_register2(glue, ast_module_info->self)
++
++/*!
++ * \brief Register RTP glue
++ *
++ * \param glue The glue to register
++ * \param module Module that the RTP glue is part of
++ *
++ * \retval 0 success
++ * \retval -1 failure
++ *
++ * Example usage:
++ *
++ * \code
++ * ast_rtp_glue_register2(&example_rtp_glue, NULL);
++ * \endcode
++ *
++ * This registers the RTP glue declared as example_rtp_glue with the RTP engine core, but does not
++ * associate a module with it.
++ *
++ * \note It is recommended that you use the ast_rtp_glue_register macro so that the module is
++ * associated with the RTP glue and use counting is performed.
++ *
++ * \since 1.6.3
++ */
++int ast_rtp_glue_register2(struct ast_rtp_glue *glue, struct ast_module *module);
++
++/*!
++ * \brief Unregister RTP glue
++ *
++ * \param glue The glue to unregister
++ *
++ * \retval 0 success
++ * \retval -1 failure
++ *
++ * Example usage:
++ *
++ * \code
++ * ast_rtp_glue_unregister(&example_rtp_glue);
++ * \endcode
++ *
++ * This unregisters the RTP glue declared as example_rtp_gkue from the RTP engine core. If a module
++ * reference was provided when it was registered then this will only be called once the RTP engine is no longer in use.
++ *
++ * \since 1.6.3
++ */
++int ast_rtp_glue_unregister(struct ast_rtp_glue *glue);
++
++/*!
++ * \brief Create a new RTP instance
++ *
++ * \param engine_name Name of the engine to use for the RTP instance
++ * \param sched Scheduler context that the RTP engine may want to use
++ * \param sin Address we want to bind to
++ * \param data Unique data for the engine
++ *
++ * \retval non-NULL success
++ * \retval NULL failure
++ *
++ * Example usage:
++ *
++ * \code
++ * struct ast_rtp_instance *instance = NULL;
++ * instance = ast_rtp_instance_new(NULL, sched, &sin, NULL);
++ * \endcode
++ *
++ * This creates a new RTP instance using the default engine and asks the RTP engine to bind to the address given
++ * in the sin structure.
++ *
++ * \note The RTP engine does not have to use the address provided when creating an RTP instance. It may choose to use
++ * another depending on it's own configuration.
++ *
++ * \since 1.6.3
++ */
++struct ast_rtp_instance *ast_rtp_instance_new(const char *engine_name, struct sched_context *sched, struct sockaddr_in *sin, void *data);
++
++/*!
++ * \brief Destroy an RTP instance
++ *
++ * \param instance The RTP instance to destroy
++ *
++ * \retval 0 success
++ * \retval -1 failure
++ *
++ * Example usage:
++ *
++ * \code
++ * ast_rtp_instance_destroy(instance);
++ * \endcode
++ *
++ * This destroys the RTP instance pointed to by instance. Once this function returns instance no longer points to valid
++ * memory and may not be used again.
++ *
++ * \since 1.6.3
++ */
++int ast_rtp_instance_destroy(struct ast_rtp_instance *instance);
++
++/*!
++ * \brief Set the data portion of an RTP instance
++ *
++ * \param instance The RTP instance to manipulate
++ * \param data Pointer to data
++ *
++ * Example usage:
++ *
++ * \code
++ * ast_rtp_instance_set_data(instance, blob);
++ * \endcode
++ *
++ * This sets the data pointer on the RTP instance pointed to by 'instance' to
++ * blob.
++ *
++ * \since 1.6.3
++ */
++void ast_rtp_instance_set_data(struct ast_rtp_instance *instance, void *data);
++
++/*!
++ * \brief Get the data portion of an RTP instance
++ *
++ * \param instance The RTP instance we want the data portion from
++ *
++ * Example usage:
++ *
++ * \code
++ * struct *blob = ast_rtp_instance_get_data(instance);
++ ( \endcode
++ *
++ * This gets the data pointer on the RTP instance pointed to by 'instance'.
++ *
++ * \since 1.6.3
++ */
++void *ast_rtp_instance_get_data(struct ast_rtp_instance *instance);
++
++/*!
++ * \brief Send a frame out over RTP
++ *
++ * \param instance The RTP instance to send frame out on
++ *
++ * \retval 0 success
++ * \retval -1 failure
++ *
++ * Example usage:
++ *
++ * \code
++ * ast_rtp_instance_write(instance, frame);
++ * \endcode
++ *
++ * This gives the frame pointed to by frame to the RTP engine being used for the instance
++ * and asks that it be transmitted to the current remote address set on the RTP instance.
++ *
++ * \since 1.6.3
++ */
++int ast_rtp_instance_write(struct ast_rtp_instance *instance, struct ast_frame *frame);
++
++/*!
++ * \brief Receive a frame over RTP
++ *
++ * \param instance The RTP instance to receive frame on
++ * \param rtcp Whether to read in RTCP or not
++ *
++ * \retval non-NULL success
++ * \retval NULL failure
++ *
++ * Example usage:
++ *
++ * \code
++ * struct ast_frame *frame;
++ * frame = ast_rtp_instance_read(instance, 0);
++ * \endcode
++ *
++ * This asks the RTP engine to read in RTP from the instance and return it as an Asterisk frame.
++ *
++ * \since 1.6.3
++ */
++struct ast_frame *ast_rtp_instance_read(struct ast_rtp_instance *instance, int rtcp);
++
++/*!
++ * \brief Set the address of the remote endpoint that we are sending RTP to
++ *
++ * \param instance The RTP instance to change the address on
++ * \param address Address to set it to
++ *
++ * \retval 0 success
++ * \retval -1 failure
++ *
++ * Example usage:
++ *
++ * \code
++ * ast_rtp_instance_set_remote_address(instance, &sin);
++ * \endcode
++ *
++ * This changes the remote address that RTP will be sent to on instance to the address given in the sin
++ * structure.
++ *
++ * \since 1.6.3
++ */
++int ast_rtp_instance_set_remote_address(struct ast_rtp_instance *instance, struct sockaddr_in *address);
++
++/*!
++ * \brief Set the address of an an alternate RTP address to receive from
++ *
++ * \param instance The RTP instance to change the address on
++ * \param address Address to set it to
++ *
++ * \retval 0 success
++ * \retval -1 failure
++ *
++ * Example usage:
++ *
++ * \code
++ * ast_rtp_instance_set_alt_remote_address(instance, &sin);
++ * \endcode
++ *
++ * This changes the alternate remote address that RTP will be sent to on instance to the address given in the sin
++ * structure.
++ *
++ * \since 1.6.3
++ */
++int ast_rtp_instance_set_alt_remote_address(struct ast_rtp_instance *instance, struct sockaddr_in *address);
++
++/*!
++ * \brief Set the address that we are expecting to receive RTP on
++ *
++ * \param instance The RTP instance to change the address on
++ * \param address Address to set it to
++ *
++ * \retval 0 success
++ * \retval -1 failure
++ *
++ * Example usage:
++ *
++ * \code
++ * ast_rtp_instance_set_local_address(instance, &sin);
++ * \endcode
++ *
++ * This changes the local address that RTP is expected on to the address given in the sin
++ * structure.
++ *
++ * \since 1.6.3
++ */
++int ast_rtp_instance_set_local_address(struct ast_rtp_instance *instance, struct sockaddr_in *address);
++
++/*!
++ * \brief Get the local address that we are expecting RTP on
++ *
++ * \param instance The RTP instance to get the address from
++ * \param address The variable to store the address in
++ *
++ * \retval 0 success
++ * \retval -1 failure
++ *
++ * Example usage:
++ *
++ * \code
++ * struct sockaddr_in sin;
++ * ast_rtp_instance_get_local_address(instance, &sin);
++ * \endcode
++ *
++ * This gets the local address that we are expecting RTP on and stores it in the 'sin' structure.
++ *
++ * \since 1.6.3
++ */
++int ast_rtp_instance_get_local_address(struct ast_rtp_instance *instance, struct sockaddr_in *address);
++
++/*!
++ * \brief Get the address of the remote endpoint that we are sending RTP to
++ *
++ * \param instance The instance that we want to get the remote address for
++ * \param address A structure to put the address into
++ *
++ * \retval 0 success
++ * \retval -1 failure
++ *
++ * Example usage:
++ *
++ * \code
++ * struct sockaddr_in sin;
++ * ast_rtp_instance_get_remote_address(instance, &sin);
++ * \endcode
++ *
++ * This retrieves the current remote address set on the instance pointed to by instance and puts the value
++ * into the sin structure.
++ *
++ * \since 1.6.3
++ */
++int ast_rtp_instance_get_remote_address(struct ast_rtp_instance *instance, struct sockaddr_in *address);
++
++/*!
++ * \brief Set the value of an RTP instance extended property
++ *
++ * \param instance The RTP instance to set the extended property on
++ * \param property The extended property to set
++ * \param value The value to set the extended property to
++ *
++ * \since 1.6.3
++ */
++void ast_rtp_instance_set_extended_prop(struct ast_rtp_instance *instance, int property, void *value);
++
++/*!
++ * \brief Get the value of an RTP instance extended property
++ *
++ * \param instance The RTP instance to get the extended property on
++ * \param property The extended property to get
++ *
++ * \since 1.6.3
++ */
++void *ast_rtp_instance_get_extended_prop(struct ast_rtp_instance *instance, int property);
++
++/*!
++ * \brief Set the value of an RTP instance property
++ *
++ * \param instance The RTP instance to set the property on
++ * \param property The property to modify
++ * \param value The value to set the property to
++ *
++ * Example usage:
++ *
++ * \code
++ * ast_rtp_instance_set_prop(instance, AST_RTP_PROPERTY_NAT, 1);
++ * \endcode
++ *
++ * This enables the AST_RTP_PROPERTY_NAT property on the instance pointed to by instance.
++ *
++ * \since 1.6.3
++ */
++void ast_rtp_instance_set_prop(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value);
++
++/*!
++ * \brief Get the value of an RTP instance property
++ *
++ * \param instance The RTP instance to get the property from
++ * \param property The property to get
++ *
++ * \retval Current value of the property
++ *
++ * Example usage:
++ *
++ * \code
++ * ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT);
++ * \endcode
++ *
++ * This returns the current value of the NAT property on the instance pointed to by instance.
++ *
++ * \since 1.6.3
++ */
++int ast_rtp_instance_get_prop(struct ast_rtp_instance *instance, enum ast_rtp_property property);
++
++/*!
++ * \brief Get the codecs structure of an RTP instance
++ *
++ * \param instance The RTP instance to get the codecs structure from
++ *
++ * Example usage:
++ *
++ * \code
++ * struct ast_rtp_codecs *codecs = ast_rtp_instance_get_codecs(instance);
++ * \endcode
++ *
++ * This gets the codecs structure on the RTP instance pointed to by 'instance'.
++ *
++ * \since 1.6.3
++ */
++struct ast_rtp_codecs *ast_rtp_instance_get_codecs(struct ast_rtp_instance *instance);
++
++/*!
++ * \brief Clear payload information from an RTP instance
++ *
++ * \param codecs The codecs structure that payloads will be cleared from
++ * \param instance Optionally the instance that the codecs structure belongs to
++ *
++ * Example usage:
++ *
++ * \code
++ * struct ast_rtp_codecs codecs;
++ * ast_rtp_codecs_payloads_clear(&codecs, NULL);
++ * \endcode
++ *
++ * This clears the codecs structure and puts it into a pristine state.
++ *
++ * \since 1.6.3
++ */
++void ast_rtp_codecs_payloads_clear(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance);
++
++/*!
++ * \brief Set payload information on an RTP instance to the default
++ *
++ * \param codecs The codecs structure to set defaults on
++ * \param instance Optionally the instance that the codecs structure belongs to
++ *
++ * Example usage:
++ *
++ * \code
++ * struct ast_rtp_codecs codecs;
++ * ast_rtp_codecs_payloads_default(&codecs, NULL);
++ * \endcode
++ *
++ * This sets the default payloads on the codecs structure.
++ *
++ * \since 1.6.3
++ */
++void ast_rtp_codecs_payloads_default(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance);
++
++/*!
++ * \brief Copy payload information from one RTP instance to another
++ *
++ * \param src The source codecs structure
++ * \param dst The destination codecs structure that the values from src will be copied to
++ * \param instance Optionally the instance that the dst codecs structure belongs to
++ *
++ * Example usage:
++ *
++ * \code
++ * ast_rtp_codecs_payloads_copy(&codecs0, &codecs1, NULL);
++ * \endcode
++ *
++ * This copies the payloads from the codecs0 structure to the codecs1 structure, overwriting any current values.
++ *
++ * \since 1.6.3
++ */
++void ast_rtp_codecs_payloads_copy(struct ast_rtp_codecs *src, struct ast_rtp_codecs *dest, struct ast_rtp_instance *instance);
++
++/*!
++ * \brief Record payload information that was seen in an m= SDP line
++ *
++ * \param codecs The codecs structure to muck with
++ * \param instance Optionally the instance that the codecs structure belongs to
++ * \param payload Numerical payload that was seen in the m= SDP line
++ *
++ * Example usage:
++ *
++ * \code
++ * ast_rtp_codecs_payloads_set_m_type(&codecs, NULL, 0);
++ * \endcode
++ *
++ * This records that the numerical payload '0' was seen in the codecs structure.
++ *
++ * \since 1.6.3
++ */
++void ast_rtp_codecs_payloads_set_m_type(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload);
++
++/*!
++ * \brief Record payload information that was seen in an a=rtpmap: SDP line
++ *
++ * \param codecs The codecs structure to muck with
++ * \param instance Optionally the instance that the codecs structure belongs to
++ * \param payload Numerical payload that was seen in the a=rtpmap: SDP line
++ * \param mimetype The string mime type that was seen
++ * \param mimesubtype The strin mime sub type that was seen
++ * \param options Optional options that may change the behavior of this specific payload
++ *
++ * \retval 0 success
++ * \retval -1 failure
++ *
++ * Example usage:
++ *
++ * \code
++ * ast_rtp_codecs_payloads_set_rtpmap_type(&codecs, NULL, 0, "audio", "PCMU", 0);
++ * \endcode
++ *
++ * This records that the numerical payload '0' was seen with mime type 'audio' and sub mime type 'PCMU' in the codecs structure.
++ *
++ * \since 1.6.3
++ */
++int ast_rtp_codecs_payloads_set_rtpmap_type(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload, char *mimetype, char *mimesubtype, enum ast_rtp_options options);
++
++/*!
++ * \brief Set payload type to a known MIME media type for a codec with a specific sample rate
++ *
++ * \param rtp RTP structure to modify
++ * \param instance Optionally the instance that the codecs structure belongs to
++ * \param pt Payload type entry to modify
++ * \param mimetype top-level MIME type of media stream (typically "audio", "video", "text", etc.)
++ * \param mimesubtype MIME subtype of media stream (typically a codec name)
++ * \param options Zero or more flags from the ast_rtp_options enum
++ * \param sample_rate The sample rate of the media stream
++ *
++ * This function 'fills in' an entry in the list of possible formats for
++ * a media stream associated with an RTP structure.
++ *
++ * \retval 0 on success
++ * \retval -1 if the payload type is out of range
++ * \retval -2 if the mimeType/mimeSubtype combination was not found
++ *
++ * \since 1.6.3
++ */
++int ast_rtp_codecs_payloads_set_rtpmap_type_rate(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int pt,
++ char *mimetype, char *mimesubtype,
++ enum ast_rtp_options options,
++ unsigned int sample_rate);
++
++/*!
++ * \brief Remove payload information
++ *
++ * \param codecs The codecs structure to muck with
++ * \param instance Optionally the instance that the codecs structure belongs to
++ * \param payload Numerical payload to unset
++ *
++ * Example usage:
++ *
++ * \code
++ * ast_rtp_codecs_payloads_unset(&codecs, NULL, 0);
++ * \endcode
++ *
++ * This clears the payload '0' from the codecs structure. It will be as if it was never set.
++ *
++ * \since 1.6.3
++ */
++void ast_rtp_codecs_payloads_unset(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload);
++
++/*!
++ * \brief Retrieve payload information by payload
++ *
++ * \param codecs Codecs structure to look in
++ * \param payload Numerical payload to look up
++ *
++ * \retval Payload information
++ *
++ * Example usage:
++ *
++ * \code
++ * struct ast_rtp_payload_type payload_type;
++ * payload_type = ast_rtp_codecs_payload_lookup(&codecs, 0);
++ * \endcode
++ *
++ * This looks up the information for payload '0' from the codecs structure.
++ *
++ * \since 1.6.3
++ */
++struct ast_rtp_payload_type ast_rtp_codecs_payload_lookup(struct ast_rtp_codecs *codecs, int payload);
++
++/*!
++ * \brief Get the sample rate associated with known RTP payload types
++ *
++ * \param asterisk_format True if the value in the 'code' parameter is an AST_FORMAT value
++ * \param code Format code, either from AST_FORMAT list or from AST_RTP list
++ *
++ * \return the sample rate if the format was found, zero if it was not found
++ *
++ * \since 1.6.3
++ */
++unsigned int ast_rtp_lookup_sample_rate2(int asterisk_format, int code);
++
++/*!
++ * \brief Retrieve all formats that were found
++ *
++ * \param codecs Codecs structure to look in
++ * \param astFormats An integer to put the Asterisk formats in
++ * \param nonastformats An integer to put the non-Asterisk formats in
++ *
++ * Example usage:
++ *
++ * \code
++ * int astformats, nonastformats;
++ * ast_rtp_codecs_payload_Formats(&codecs, &astformats, &nonastformats);
++ * \endcode
++ *
++ * This retrieves all the formats known about in the codecs structure and puts the Asterisk ones in the integer
++ * pointed to by astformats and the non-Asterisk ones in the integer pointed to by nonastformats.
++ *
++ * \since 1.6.3
++ */
++void ast_rtp_codecs_payload_formats(struct ast_rtp_codecs *codecs, int *astformats, int *nonastformats);
++
++/*!
++ * \brief Retrieve a payload based on whether it is an Asterisk format and the code
++ *
++ * \param codecs Codecs structure to look in
++ * \param asterisk_format Non-zero if the given code is an Asterisk format value
++ * \param code The format to look for
++ *
++ * \retval Numerical payload
++ *
++ * Example usage:
++ *
++ * \code
++ * int payload = ast_rtp_codecs_payload_code(&codecs, 1, AST_FORMAT_ULAW);
++ * \endcode
++ *
++ * This looks for the numerical payload for ULAW in the codecs structure.
++ *
++ * \since 1.6.3
++ */
++int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, const int asterisk_format, const int code);
++
++/*!
++ * \brief Retrieve mime subtype information on a payload
++ *
++ * \param asterisk_format Non-zero if the given code is an Asterisk format value
++ * \param code Format to look up
++ * \param options Additional options that may change the result
++ *
++ * \retval Mime subtype success
++ * \retval NULL failure
++ *
++ * Example usage:
++ *
++ * \code
++ * const char *subtype = ast_rtp_lookup_mime_subtype2(1, AST_FORMAT_ULAW, 0);
++ * \endcode
++ *
++ * This looks up the mime subtype for the ULAW format.
++ *
++ * \since 1.6.3
++ */
++const char *ast_rtp_lookup_mime_subtype2(const int asterisk_format, const int code, enum ast_rtp_options options);
++
++/*!
++ * \brief Convert formats into a string and put them into a buffer
++ *
++ * \param buf Buffer to put the mime output into
++ * \param capability Formats that we are looking up
++ * \param asterisk_format Non-zero if the given capability are Asterisk format capabilities
++ * \param options Additional options that may change the result
++ *
++ * \retval non-NULL success
++ * \retval NULL failure
++ *
++ * Example usage:
++ *
++ * \code
++ * char buf[256] = "";
++ * char *mime = ast_rtp_lookup_mime_multiple2(&buf, sizeof(buf), AST_FORMAT_ULAW | AST_FORMAT_ALAW, 1, 0);
++ * \endcode
++ *
++ * This returns the mime values for ULAW and ALAW in the buffer pointed to by buf.
++ *
++ * \since 1.6.3
++ */
++char *ast_rtp_lookup_mime_multiple2(struct ast_str *buf, const int capability, const int asterisk_format, enum ast_rtp_options options);
++
++/*!
++ * \brief Set codec packetization preferences
++ *
++ * \param codecs Codecs structure to muck with
++ * \param instance Optionally the instance that the codecs structure belongs to
++ * \param prefs Codec packetization preferences
++ *
++ * Example usage:
++ *
++ * \code
++ * ast_rtp_codecs_packetization_set(&codecs, NULL, &prefs);
++ * \endcode
++ *
++ * This sets the packetization preferences pointed to by prefs on the codecs structure pointed to by codecs.
++ *
++ * \since 1.6.3
++ */
++void ast_rtp_codecs_packetization_set(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, struct ast_codec_pref *prefs);
++
++/*!
++ * \brief Begin sending a DTMF digit
++ *
++ * \param instance The RTP instance to send the DTMF on
++ * \param digit What DTMF digit to send
++ *
++ * \retval 0 success
++ * \retval -1 failure
++ *
++ * Example usage:
++ *
++ * \code
++ * ast_rtp_instance_dtmf_begin(instance, '1');
++ * \endcode
++ *
++ * This starts sending the DTMF '1' on the RTP instance pointed to by instance. It will
++ * continue being sent until it is ended.
++ *
++ * \since 1.6.3
++ */
++int ast_rtp_instance_dtmf_begin(struct ast_rtp_instance *instance, char digit);
++
++/*!
++ * \brief Stop sending a DTMF digit
++ *
++ * \param instance The RTP instance to stop the DTMF on
++ * \param digit What DTMF digit to stop
++ *
++ * \retval 0 success
++ * \retval -1 failure
++ *
++ * Example usage:
++ *
++ * \code
++ * ast_rtp_instance_dtmf_end(instance, '1');
++ * \endcode
++ *
++ * This stops sending the DTMF '1' on the RTP instance pointed to by instance.
++ *
++ * \since 1.6.3
++ */
++int ast_rtp_instance_dtmf_end(struct ast_rtp_instance *instance, char digit);
++
++/*!
++ * \brief Set the DTMF mode that should be used
++ *
++ * \param instance the RTP instance to set DTMF mode on
++ * \param dtmf_mode The DTMF mode that is in use
++ *
++ * \retval 0 success
++ * \retval -1 failure
++ *
++ * Example usage:
++ *
++ * \code
++ * ast_rtp_instance_dtmf_mode_set(instance, AST_RTP_DTMF_MODE_RFC2833);
++ * \endcode
++ *
++ * This sets the RTP instance to use RFC2833 for DTMF transmission and receiving.
++ *
++ * \since 1.6.3
++ */
++int ast_rtp_instance_dtmf_mode_set(struct ast_rtp_instance *instance, enum ast_rtp_dtmf_mode dtmf_mode);
++
++/*!
++ * \brief Get the DTMF mode of an RTP instance
++ *
++ * \param instance The RTP instance to get the DTMF mode of
++ *
++ * \retval DTMF mode
++ *
++ * Example usage:
++ *
++ * \code
++ * enum ast_rtp_dtmf_mode dtmf_mode = ast_rtp_instance_dtmf_mode_get(instance);
++ * \endcode
++ *
++ * This gets the DTMF mode set on the RTP instance pointed to by 'instance'.
++ *
++ * \since 1.6.3
++ */
++enum ast_rtp_dtmf_mode ast_rtp_instance_dtmf_mode_get(struct ast_rtp_instance *instance);
++
++/*!
++ * \brief Indicate a new source of audio has dropped in
++ *
++ * \param instance Instance that the new media source is feeding into
++ *
++ * Example usage:
++ *
++ * \code
++ * ast_rtp_instance_new_source(instance);
++ * \endcode
++ *
++ * This indicates that a new source of media is feeding the instance pointed to by
++ * instance.
++ *
++ * \since 1.6.3
++ */
++void ast_rtp_instance_new_source(struct ast_rtp_instance *instance);
++
++/*!
++ * \brief Set QoS parameters on an RTP session
++ *
++ * \param instance Instance to set the QoS parameters on
++ * \param tos Terms of service value
++ * \param cos Class of service value
++ * \param desc What is setting the QoS values
++ *
++ * \retval 0 success
++ * \retval -1 failure
++ *
++ * Example usage:
++ *
++ * \code
++ * ast_rtp_instance_set_qos(instance, 0, 0, "Example");
++ * \endcode
++ *
++ * This sets the TOS and COS values to 0 on the instance pointed to by instance.
++ *
++ * \since 1.6.3
++ */
++int ast_rtp_instance_set_qos(struct ast_rtp_instance *instance, int tos, int cos, const char *desc);
++
++/*!
++ * \brief Stop an RTP instance
++ *
++ * \param instance Instance that media is no longer going to at this time
++ *
++ * Example usage:
++ *
++ * \code
++ * ast_rtp_instance_stop(instance);
++ * \endcode
++ *
++ * This tells the RTP engine being used for the instance pointed to by instance
++ * that media is no longer going to it at this time, but may in the future.
++ *
++ * \since 1.6.3
++ */
++void ast_rtp_instance_stop(struct ast_rtp_instance *instance);
++
++/*!
++ * \brief Get the file descriptor for an RTP session (or RTCP)
++ *
++ * \param instance Instance to get the file descriptor for
++ * \param rtcp Whether to retrieve the file descriptor for RTCP or not
++ *
++ * \retval fd success
++ * \retval -1 failure
++ *
++ * Example usage:
++ *
++ * \code
++ * int rtp_fd = ast_rtp_instance_fd(instance, 0);
++ * \endcode
++ *
++ * This retrieves the file descriptor for the socket carrying media on the instance
++ * pointed to by instance.
++ *
++ * \since 1.6.3
++ */
++int ast_rtp_instance_fd(struct ast_rtp_instance *instance, int rtcp);
++
++/*!
++ * \brief Get the RTP glue that binds a channel to the RTP engine
++ *
++ * \param type Name of the glue we want
++ *
++ * \retval non-NULL success
++ * \retval NULL failure
++ *
++ * Example usage:
++ *
++ * \code
++ * struct ast_rtp_glue *glue = ast_rtp_instance_get_glue("Example");
++ * \endcode
++ *
++ * This retrieves the RTP glue that has the name 'Example'.
++ *
++ * \since 1.6.3
++ */
++struct ast_rtp_glue *ast_rtp_instance_get_glue(const char *type);
++
++/*!
++ * \brief Bridge two channels that use RTP instances
++ *
++ * \param c0 First channel part of the bridge
++ * \param c1 Second channel part of the bridge
++ * \param flags Bridging flags
++ * \param fo If a frame needs to be passed up it is stored here
++ * \param rc Channel that passed the above frame up
++ * \param timeoutms How long the channels should be bridged for
++ *
++ * \retval Bridge result
++ *
++ * \note This should only be used by channel drivers in their technology declaration.
++ *
++ * \since 1.6.3
++ */
++enum ast_bridge_result ast_rtp_instance_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms);
++
++/*!
++ * \brief Get the other RTP instance that an instance is bridged to
++ *
++ * \param instance The RTP instance that we want
++ *
++ * \retval non-NULL success
++ * \retval NULL failure
++ *
++ * Example usage:
++ *
++ * \code
++ * struct ast_rtp_instance *bridged = ast_rtp_instance_get_bridged(instance0);
++ * \endcode
++ *
++ * This gets the RTP instance that instance0 is bridged to.
++ *
++ * \since 1.6.3
++ */
++struct ast_rtp_instance *ast_rtp_instance_get_bridged(struct ast_rtp_instance *instance);
++
++/*!
++ * \brief Make two channels compatible for early bridging
++ *
++ * \param c0 First channel part of the bridge
++ * \param c1 Second channel part of the bridge
++ *
++ * \since 1.6.3
++ */
++void ast_rtp_instance_early_bridge_make_compatible(struct ast_channel *c0, struct ast_channel *c1);
++
++/*!
++ * \brief Early bridge two channels that use RTP instances
++ *
++ * \param c0 First channel part of the bridge
++ * \param c1 Second channel part of the bridge
++ *
++ * \retval 0 success
++ * \retval -1 failure
++ *
++ * \note This should only be used by channel drivers in their technology declaration.
++ *
++ * \since 1.6.3
++ */
++int ast_rtp_instance_early_bridge(struct ast_channel *c0, struct ast_channel *c1);
++
++/*!
++ * \brief Initialize RED support on an RTP instance
++ *
++ * \param instance The instance to initialize RED support on
++ * \param buffer_time How long to buffer before sending
++ * \param payloads Payload values
++ * \param generations Number of generations
++ *
++ * \retval 0 success
++ * \retval -1 failure
++ *
++ * \since 1.6.3
++ */
++int ast_rtp_red_init(struct ast_rtp_instance *instance, int buffer_time, int *payloads, int generations);
++
++/*!
++ * \brief Buffer a frame in an RTP instance for RED
++ *
++ * \param instance The instance to buffer the frame on
++ * \param frame Frame that we want to buffer
++ *
++ * \retval 0 success
++ * \retval -1 failure
++ *
++ * \since 1.6.3
++ */
++int ast_rtp_red_buffer(struct ast_rtp_instance *instance, struct ast_frame *frame);
++
++/*!
++ * \brief Retrieve statistics about an RTP instance
++ *
++ * \param instance Instance to get statistics on
++ * \param stats Structure to put results into
++ * \param stat What statistic(s) to retrieve
++ *
++ * \retval 0 success
++ * \retval -1 failure
++ *
++ * Example usage:
++ *
++ * \code
++ * struct ast_rtp_instance_stats stats;
++ * ast_rtp_instance_get_stats(instance, &stats, AST_RTP_INSTANCE_STAT_ALL);
++ * \endcode
++ *
++ * This retrieves all statistics the underlying RTP engine supports and puts the values into the
++ * stats structure.
++ *
++ * \since 1.6.3
++ */
++int ast_rtp_instance_get_stats(struct ast_rtp_instance *instance, struct ast_rtp_instance_stats *stats, enum ast_rtp_instance_stat stat);
++
++/*!
++ * \brief Set standard statistics from an RTP instance on a channel
++ *
++ * \param chan Channel to set the statistics on
++ * \param instance The RTP instance that statistics will be retrieved from
++ *
++ * Example usage:
++ *
++ * \code
++ * ast_rtp_instance_set_stats_vars(chan, rtp);
++ * \endcode
++ *
++ * This retrieves standard statistics from the RTP instance rtp and sets it on the channel pointed to
++ * by chan.
++ *
++ * \since 1.6.3
++ */
++void ast_rtp_instance_set_stats_vars(struct ast_channel *chan, struct ast_rtp_instance *instance);
++
++/*!
++ * \brief Retrieve quality statistics about an RTP instance
++ *
++ * \param instance Instance to get statistics on
++ * \param field What quality statistic to retrieve
++ * \param buf What buffer to put the result into
++ * \param size Size of the above buffer
++ *
++ * \retval non-NULL success
++ * \retval NULL failure
++ *
++ * Example usage:
++ *
++ * \code
++ * char quality[AST_MAX_USER_FIELD];
++ * ast_rtp_instance_get_quality(instance, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, &buf, sizeof(buf));
++ * \endcode
++ *
++ * This retrieves general quality statistics and places a text representation into the buf pointed to by buf.
++ *
++ * \since 1.6.3
++ */
++char *ast_rtp_instance_get_quality(struct ast_rtp_instance *instance, enum ast_rtp_instance_stat_field field, char *buf, size_t size);
++
++/*!
++ * \brief Request that the underlying RTP engine provide audio frames in a specific format
++ *
++ * \param instance The RTP instance to change read format on
++ * \param format Format that frames are wanted in
++ *
++ * \retval 0 success
++ * \retval -1 failure
++ *
++ * Example usage:
++ *
++ * \code
++ * ast_rtp_instance_set_read_format(instance, AST_FORMAT_ULAW);
++ * \endcode
++ *
++ * This requests that the RTP engine provide audio frames in the ULAW format.
++ *
++ * \since 1.6.3
++ */
++int ast_rtp_instance_set_read_format(struct ast_rtp_instance *instance, int format);
++
++/*!
++ * \brief Tell underlying RTP engine that audio frames will be provided in a specific format
++ *
++ * \param instance The RTP instance to change write format on
++ * \param format Format that frames will be provided in
++ *
++ * \retval 0 success
++ * \retval -1 failure
++ *
++ * Example usage:
++ *
++ * \code
++ * ast_rtp_instance_set_write_format(instance, AST_FORMAT_ULAW);
++ * \endcode
++ *
++ * This tells the underlying RTP engine that audio frames will be provided to it in ULAW format.
++ *
++ * \since 1.6.3
++ */
++int ast_rtp_instance_set_write_format(struct ast_rtp_instance *instance, int format);
++
++/*!
++ * \brief Request that the underlying RTP engine make two RTP instances compatible with eachother
++ *
++ * \param chan Our own Asterisk channel
++ * \param instance The first RTP instance
++ * \param peer The peer Asterisk channel
++ *
++ * \retval 0 success
++ * \retval -1 failure
++ *
++ * Example usage:
++ *
++ * \code
++ * ast_rtp_instance_make_compatible(instance, peer);
++ * \endcode
++ *
++ * This makes the RTP instance for 'peer' compatible with 'instance' and vice versa.
++ *
++ * \since 1.6.3
++ */
++int ast_rtp_instance_make_compatible(struct ast_channel *chan, struct ast_rtp_instance *instance, struct ast_channel *peer);
++
++/*! \brief Request the formats that can be transcoded
++ *
++ * \param instance The RTP instance
++ * \param to_endpoint Formats being sent/received towards the endpoint
++ * \param to_asterisk Formats being sent/received towards Asterisk
++ *
++ * \retval supported formats
++ *
++ * Example usage:
++ *
++ * \code
++ * ast_rtp_instance_available_formats(instance, AST_FORMAT_ULAW, AST_FORMAT_SLINEAR);
++ * \endcode
++ *
++ * This sees if it is possible to have ulaw communicated to the endpoint but signed linear received into Asterisk.
++ *
++ * \since 1.6.3
++ */
++int ast_rtp_instance_available_formats(struct ast_rtp_instance *instance, int to_endpoint, int to_asterisk);
++
++/*!
++ * \brief Indicate to the RTP engine that packets are now expected to be sent/received on the RTP instance
++ *
++ * \param instance The RTP instance
++ *
++ * \retval 0 success
++ * \retval -1 failure
++ *
++ * Example usage:
++ *
++ * \code
++ * ast_rtp_instance_activate(instance);
++ * \endcode
++ *
++ * This tells the underlying RTP engine of instance that packets will now flow.
++ *
++ * \since 1.6.3
++ */
++int ast_rtp_instance_activate(struct ast_rtp_instance *instance);
++
++/*!
++ * \brief Request that the underlying RTP engine send a STUN BIND request
++ *
++ * \param instance The RTP instance
++ * \param suggestion The suggested destination
++ * \param username Optionally a username for the request
++ *
++ * Example usage:
++ *
++ * \code
++ * ast_rtp_instance_stun_request(instance, NULL, NULL);
++ * \endcode
++ *
++ * This requests that the RTP engine send a STUN BIND request on the session pointed to by
++ * 'instance'.
++ *
++ * \since 1.6.3
++ */
++void ast_rtp_instance_stun_request(struct ast_rtp_instance *instance, struct sockaddr_in *suggestion, const char *username);
++
++/*!
++ * \brief Set the RTP timeout value
++ *
++ * \param instance The RTP instance
++ * \param timeout Value to set the timeout to
++ *
++ * Example usage:
++ *
++ * \code
++ * ast_rtp_instance_set_timeout(instance, 5000);
++ * \endcode
++ *
++ * This sets the RTP timeout value on 'instance' to be 5000.
++ *
++ * \since 1.6.3
++ */
++void ast_rtp_instance_set_timeout(struct ast_rtp_instance *instance, int timeout);
++
++/*!
++ * \brief Set the RTP timeout value for when the instance is on hold
++ *
++ * \param instance The RTP instance
++ * \param timeout Value to set the timeout to
++ *
++ * Example usage:
++ *
++ * \code
++ * ast_rtp_instance_set_hold_timeout(instance, 5000);
++ * \endcode
++ *
++ * This sets the RTP hold timeout value on 'instance' to be 5000.
++ *
++ * \since 1.6.3
++ */
++void ast_rtp_instance_set_hold_timeout(struct ast_rtp_instance *instance, int timeout);
++
++/*!
++ * \brief Get the RTP timeout value
++ *
++ * \param instance The RTP instance
++ *
++ * \retval timeout value
++ *
++ * Example usage:
++ *
++ * \code
++ * int timeout = ast_rtp_instance_get_timeout(instance);
++ * \endcode
++ *
++ * This gets the RTP timeout value for the RTP instance pointed to by 'instance'.
++ *
++ * \since 1.6.3
++ */
++int ast_rtp_instance_get_timeout(struct ast_rtp_instance *instance);
++
++/*!
++ * \brief Get the RTP timeout value for when an RTP instance is on hold
++ *
++ * \param instance The RTP instance
++ *
++ * \retval timeout value
++ *
++ * Example usage:
++ *
++ * \code
++ * int timeout = ast_rtp_instance_get_hold_timeout(instance);
++ * \endcode
++ *
++ * This gets the RTP hold timeout value for the RTP instance pointed to by 'instance'.
++ *
++ * \since 1.6.3
++ */
++int ast_rtp_instance_get_hold_timeout(struct ast_rtp_instance *instance);
++
++#if defined(__cplusplus) || defined(c_plusplus)
++}
++#endif
++
++#endif /* _ASTERISK_RTP_ENGINE_H */
+
+Property changes on: include/asterisk/rtp_engine.h
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+
+Index: include/asterisk/utils.h
+===================================================================
+--- a/include/asterisk/utils.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/utils.h (.../trunk) (revision 202568)
+@@ -32,8 +32,9 @@
+ #include "asterisk/time.h"
+ #include "asterisk/logger.h"
+ #include "asterisk/localtime.h"
++#include "asterisk/stringfields.h"
+
+-/*!
++/*!
+ \note \verbatim
+ Note:
+ It is very important to use only unsigned variables to hold
+@@ -214,9 +215,9 @@
+ struct hostent *ast_gethostbyname(const char *host, struct ast_hostent *hp);
+
+ /*! \brief Produces MD5 hash based on input string */
+-void ast_md5_hash(char *output, char *input);
++void ast_md5_hash(char *output, const char *input);
+ /*! \brief Produces SHA1 hash based on input string */
+-void ast_sha1_hash(char *output, char *input);
++void ast_sha1_hash(char *output, const char *input);
+
+ int ast_base64encode_full(char *dst, const unsigned char *src, int srclen, int max, int linebreaks);
+
+@@ -646,6 +647,33 @@
+
+ #define ARRAY_LEN(a) (sizeof(a) / sizeof(0[a]))
+
++
++/* Definition for Digest authorization */
++struct ast_http_digest {
++ AST_DECLARE_STRING_FIELDS(
++ AST_STRING_FIELD(username);
++ AST_STRING_FIELD(nonce);
++ AST_STRING_FIELD(uri);
++ AST_STRING_FIELD(realm);
++ AST_STRING_FIELD(domain);
++ AST_STRING_FIELD(response);
++ AST_STRING_FIELD(cnonce);
++ AST_STRING_FIELD(opaque);
++ AST_STRING_FIELD(nc);
++ );
++ int qop; /* Flag set to 1, if we send/recv qop="quth" */
++};
++
++/*!
++ *\brief Parse digest authorization header.
++ *\return Returns -1 if we have no auth or something wrong with digest.
++ *\note This function may be used for Digest request and responce header.
++ * request arg is set to nonzero, if we parse Digest Request.
++ * pedantic arg can be set to nonzero if we need to do addition Digest check.
++ */
++int ast_parse_digest(const char *digest, struct ast_http_digest *d, int request, int pedantic);
++
++
+ #ifdef AST_DEVMODE
+ #define ast_assert(a) _ast_assert(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+ static void force_inline _ast_assert(int condition, const char *condition_str,
+Index: include/asterisk/channel.h
+===================================================================
+--- a/include/asterisk/channel.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/channel.h (.../trunk) (revision 202568)
+@@ -102,7 +102,7 @@
+ can create a native bridge without sending media through the
+ core.
+
+- Native briding can be disabled by a number of reasons,
++ Native bridging can be disabled by a number of reasons,
+ like DTMF being needed by the core or codecs being incompatible
+ so a transcoding module is needed.
+
+@@ -124,6 +124,7 @@
+ #define _ASTERISK_CHANNEL_H
+
+ #include "asterisk/abstract_jb.h"
++#include "asterisk/astobj2.h"
+
+ #include "asterisk/poll-compat.h"
+
+@@ -183,45 +184,174 @@
+ void (*digit)(struct ast_channel *chan, char digit);
+ };
+
+-/*! \brief Structure for all kinds of caller ID identifications.
++/*!
++ * \brief Structure for all kinds of caller ID identifications.
+ * \note All string fields here are malloc'ed, so they need to be
+ * freed when the structure is deleted.
+ * Also, NULL and "" must be considered equivalent.
+ *
+- * SIP and IAX2 has utf8 encoded Unicode caller ID names.
++ * \note SIP and IAX2 has utf8 encoded Unicode caller ID names.
+ * In some cases, we also have an alternative (RPID) E.164 number that can be used
+- * as caller ID on numeric E.164 phone networks (DAHDI or SIP/IAX2 to pstn gateway).
++ * as caller ID on numeric E.164 phone networks (DAHDI or SIP/IAX2 to PSTN gateway).
+ *
+ * \todo Implement settings for transliteration between UTF8 caller ID names in
+ * to Ascii Caller ID's (DAHDI). Östen Åsklund might be transliterated into
+- * Osten Asklund or Oesten Aasklund depending upon language and person...
+- * We need automatic routines for incoming calls and static settings for
+- * our own accounts.
++ * Osten Asklund or Oesten Aasklund depending upon language and person...
++ * We need automatic routines for incoming calls and static settings for
++ * our own accounts.
+ */
+ struct ast_callerid {
+- char *cid_dnid; /*!< Malloc'd Dialed Number Identifier */
+- char *cid_num; /*!< Malloc'd Caller Number */
+- char *cid_name; /*!< Malloc'd Caller Name (ASCII) */
+- char *cid_ani; /*!< Malloc'd ANI */
+- char *cid_rdnis; /*!< Malloc'd RDNIS */
+- int cid_pres; /*!< Callerid presentation/screening */
+- int cid_ani2; /*!< Callerid ANI 2 (Info digits) */
+- int cid_ton; /*!< Callerid Type of Number */
+- int cid_tns; /*!< Callerid Transit Network Select */
++ /*!
++ * \brief Malloc'd Dialed Number Identifier
++ * (Field will eventually move to struct ast_channel.dialed.number)
++ */
++ char *cid_dnid;
++
++ /*!
++ * \brief Malloc'd Caller Number
++ * (Field will eventually move to struct ast_channel.caller.id.number)
++ */
++ char *cid_num;
++
++ /*!
++ * \brief Malloc'd Caller Name (ASCII)
++ * (Field will eventually move to struct ast_channel.caller.id.name)
++ */
++ char *cid_name;
++
++ /*!
++ * \brief Malloc'd Automatic Number Identification (ANI)
++ * (Field will eventually move to struct ast_channel.caller.ani)
++ */
++ char *cid_ani;
++
++ /*!
++ * \brief Malloc'd Redirecting Directory Number Information Service (RDNIS)
++ * (Field will eventually move to struct ast_channel.redirecting.from.number)
++ */
++ char *cid_rdnis;
++
++ /*!
++ * \brief Callerid Q.931 encoded number presentation/screening fields
++ * (Field will eventually move to struct ast_channel.caller.id.number_presentation)
++ */
++ int cid_pres;
++
++ /*!
++ * \brief Callerid ANI 2 (Info digits)
++ * (Field will eventually move to struct ast_channel.caller.ani2)
++ */
++ int cid_ani2;
++
++ /*!
++ * \brief Callerid Q.931 encoded type-of-number/numbering-plan fields
++ * \note Currently this value is mostly just passed around the system.
++ * The H.323 interfaces set the value from received messages and uses the value for sent messages.
++ * The DAHDI PRI interfaces set the value from received messages but does not use it for sent messages.
++ * You can read it and set it but only H.323 uses it.
++ * (Field will eventually move to struct ast_channel.caller.id.number_type)
++ */
++ int cid_ton;
++
++ /*!
++ * \brief Callerid Transit Network Select
++ * \note Currently this value is just passed around the system.
++ * You can read it and set it but it is never used for anything.
++ * (Field will eventually move to struct ast_channel.dialed.transit_network_select)
++ */
++ int cid_tns;
+ };
+
+-/*! \brief
+- Structure to describe a channel "technology", ie a channel driver
+- See for examples:
+- \arg chan_iax2.c - The Inter-Asterisk exchange protocol
+- \arg chan_sip.c - The SIP channel driver
+- \arg chan_dahdi.c - PSTN connectivity (TDM, PRI, T1/E1, FXO, FXS)
++/*!
++ * \since 1.6.3
++ * \brief Information needed to identify an endpoint in a call.
++ * \note All string fields here are malloc'ed, so they need to be
++ * freed when the structure is deleted.
++ * \note NULL and "" must be considered equivalent.
++ */
++struct ast_party_id {
++ /*! \brief Subscriber phone number (Malloced) */
++ char *number;
+
+- If you develop your own channel driver, this is where you
+- tell the PBX at registration of your driver what properties
+- this driver supports and where different callbacks are
+- implemented.
+-*/
++ /*! \brief Subscriber name (Malloced) */
++ char *name;
++
++ /*! \brief Q.931 encoded type-of-number/numbering-plan fields */
++ int number_type;
++
++ /*! \brief Q.931 encoded number presentation/screening fields */
++ int number_presentation;
++};
++
++/*!
++ * \since 1.6.3
++ * \brief Connected Line/Party information.
++ * \note All string fields here are malloc'ed, so they need to be
++ * freed when the structure is deleted.
++ * \note NULL and "" must be considered equivalent.
++ */
++struct ast_party_connected_line {
++ struct ast_party_id id; /*! \brief Connected party ID */
++
++ /*!
++ * \brief Automatic Number Identification (ANI) (Malloced)
++ * \note Not really part of connected line data but needed to
++ * save the corresponding caller id value.
++ */
++ char *ani;
++
++ /*!
++ * \brief Automatic Number Identification 2 (Info Digits)
++ * \note Not really part of connected line data but needed to
++ * save the corresponding caller id value.
++ */
++ int ani2;
++
++ /*!
++ * \brief Information about the source of an update.
++ * \note enum AST_CONNECTED_LINE_UPDATE_SOURCE values
++ * for Normal-Answer and Call-transfer.
++ */
++ int source;
++};
++
++/*!
++ * \since 1.6.3
++ * \brief Redirecting Line information.
++ * RDNIS (Redirecting Directory Number Information Service)
++ * Where a call diversion or transfer was invoked.
++ * \note All string fields here are malloc'ed, so they need to be
++ * freed when the structure is deleted.
++ * \note NULL and "" must be considered equivalent.
++ */
++struct ast_party_redirecting {
++ /*! \brief Who is redirecting the call (Sent to the party the call is redirected toward) */
++ struct ast_party_id from;
++
++ /*! \brief Call is redirecting to a new party (Sent to the caller) */
++ struct ast_party_id to;
++
++ /*! \brief Number of times the call was redirected */
++ int count;
++
++ /*! \brief enum AST_REDIRECTING_REASON value for redirection */
++ int reason;
++};
++
++/*!
++ * \brief
++ * Structure to describe a channel "technology", ie a channel driver
++ * See for examples:
++ * \arg chan_iax2.c - The Inter-Asterisk exchange protocol
++ * \arg chan_sip.c - The SIP channel driver
++ * \arg chan_dahdi.c - PSTN connectivity (TDM, PRI, T1/E1, FXO, FXS)
++ *
++ * \details
++ * If you develop your own channel driver, this is where you
++ * tell the PBX at registration of your driver what properties
++ * this driver supports and where different callbacks are
++ * implemented.
++ */
+ struct ast_channel_tech {
+ const char * const type;
+ const char * const description;
+@@ -250,7 +380,7 @@
+ int (* const send_digit_end)(struct ast_channel *chan, char digit, unsigned int duration);
+
+ /*! \brief Call a given phone number (address, etc), but don't
+- take longer than timeout seconds to do so. */
++ * take longer than timeout seconds to do so. */
+ int (* const call)(struct ast_channel *chan, char *addr, int timeout);
+
+ /*! \brief Hangup (and possibly destroy) the channel */
+@@ -381,9 +511,60 @@
+ T38_STATE_NEGOTIATED, /*!< T38 established */
+ };
+
+-/*! \brief Main Channel structure associated with a channel.
+- * This is the side of it mostly used by the pbx and call management.
++/*!
++ * \page AstChannel ast_channel locking and reference tracking
+ *
++ * \par Creating Channels
++ * A channel is allocated using the ast_channel_alloc() function. When created, it is
++ * automatically inserted into the main channels hash table that keeps track of all
++ * active channels in the system. The hash key is based on the channel name. Because
++ * of this, if you want to change the name, you _must_ use ast_change_name(), not change
++ * the name field directly. When ast_channel_alloc() returns a channel pointer, you now
++ * hold a reference to that channel. In most cases this reference is given to ast_pbx_run().
++ *
++ * \par Channel Locking
++ * There is a lock associated with every ast_channel. It is allocated internally via astobj2.
++ * To lock or unlock a channel, you must use the ast_channel_lock() wrappers.
++ *
++ * Previously, before ast_channel was converted to astobj2, the channel lock was used in some
++ * additional ways that are no longer necessary. Before, the only way to ensure that a channel
++ * did not disappear out from under you if you were working with a channel outside of the channel
++ * thread that owns it, was to hold the channel lock. Now, that is no longer necessary.
++ * You simply must hold a reference to the channel to ensure it does not go away.
++ *
++ * The channel must be locked if you need to ensure that data that you reading from the channel
++ * does not change while you access it. Further, you must hold the channel lock if you are
++ * making a non-atomic change to channel data.
++ *
++ * \par Channel References
++ * There are multiple ways to get a reference to a channel. The first is that you hold a reference
++ * to a channel after creating it. The other ways involve using the channel search or the channel
++ * traversal APIs. These functions are the ast_channel_get_*() functions or ast_channel_iterator_*()
++ * functions. Once a reference is retrieved by one of these methods, you know that the channel will
++ * not go away. So, the channel should only get locked as needed for data access or modification.
++ * But, make sure that the reference gets released when you are done with it!
++ *
++ * There are different things you can do when you are done with a reference to a channel. The first
++ * is to simply release the reference using ast_channel_unref(). The other option is to call
++ * ast_channel_release(). This function is generally used where ast_channel_free() was used in
++ * the past. The release function releases a reference as well as ensures that the channel is no
++ * longer in the global channels container. That way, the channel will get destroyed as soon as any
++ * other pending references get released.
++ *
++ * \par Exceptions to the rules
++ * Even though ast_channel is reference counted, there are some places where pointers to an ast_channel
++ * get stored, but the reference count does not reflect it. The reason is mostly historical.
++ * The only places where this happens should be places where because of how the code works, we
++ * _know_ that the pointer to the channel will get removed before the channel goes away. The main
++ * example of this is in channel drivers. Channel drivers generally store a pointer to their owner
++ * ast_channel in their technology specific pvt struct. In this case, the channel drivers _know_
++ * that this pointer to the channel will be removed in time, because the channel's hangup callback
++ * gets called before the channel goes away.
++ */
++
++/*!
++ * \brief Main Channel structure associated with a channel.
++ *
+ * \note XXX It is important to remember to increment .cleancount each time
+ * this structure is changed. XXX
+ *
+@@ -395,7 +576,6 @@
+ * and 8-byte fields causes 4 bytes of padding to be added before many
+ * 8-byte fields.
+ */
+-
+ struct ast_channel {
+ const struct ast_channel_tech *tech; /*!< Technology (point to channel driver) */
+ void *tech_pvt; /*!< Private data used by the technology driver */
+@@ -403,8 +583,8 @@
+ void *generatordata; /*!< Current generator data if there is any */
+ struct ast_generator *generator; /*!< Current active data generator */
+ struct ast_channel *_bridge; /*!< Who are we bridged to, if we're bridged.
+- Who is proxying for us, if we are proxied (i.e. chan_agent).
+- Do not access directly, use ast_bridged_channel(chan) */
++ * Who is proxying for us, if we are proxied (i.e. chan_agent).
++ * Do not access directly, use ast_bridged_channel(chan) */
+ struct ast_channel *masq; /*!< Channel that will masquerade as us */
+ struct ast_channel *masqr; /*!< Who we are masquerading as */
+ const char *blockproc; /*!< Procedure causing blocking */
+@@ -421,7 +601,7 @@
+ struct ast_audiohook_list *audiohooks;
+ struct ast_cdr *cdr; /*!< Call Detail Record */
+ struct ast_tone_zone *zone; /*!< Tone zone as set in indications.conf or
+- in the CHANNEL dialplan function */
++ * in the CHANNEL dialplan function */
+ struct ast_channel_monitor *monitor; /*!< Channel monitoring */
+ #ifdef HAVE_EPOLL
+ struct ast_epoll_data *epfd_data[AST_MAX_FDS];
+@@ -440,8 +620,29 @@
+
+ struct timeval whentohangup; /*!< Non-zero, set to actual time when channel is to be hung up */
+ pthread_t blocker; /*!< If anyone is blocking, this is them */
+- ast_mutex_t lock_dont_use; /*!< Lock a channel for some operations. See ast_channel_lock() */
+- struct ast_callerid cid; /*!< Caller ID, name, presentation etc */
++
++ /*!
++ * \brief Channel Caller ID information.
++ * \note The caller id information is the caller id of this
++ * channel when it is used to initiate a call.
++ */
++ struct ast_callerid cid;
++
++ /*!
++ * \brief Channel Connected Line ID information.
++ * \note The connected line information identifies the channel
++ * connected/bridged to this channel.
++ */
++ struct ast_party_connected_line connected;
++
++ /*!
++ * \brief Redirecting/Diversion information
++ * \note Until struct ast_channel.cid.cid_rdnis is replaced
++ * with ast_channel.redirecting.from.number, the
++ * ast_channel.redirecting.from.number field is not used.
++ */
++ struct ast_party_redirecting redirecting;
++
+ struct ast_frame dtmff; /*!< DTMF frame */
+ struct varshead varshead; /*!< A linked list for channel variables. See \ref AstChanVar */
+ ast_group_t callgroup; /*!< Call group for call pickups */
+@@ -451,16 +652,17 @@
+ struct ast_jb jb; /*!< The jitterbuffer state */
+ struct timeval dtmf_tv; /*!< The time that an in process digit began, or the last digit ended */
+ AST_LIST_HEAD_NOLOCK(datastores, ast_datastore) datastores; /*!< Data stores on the channel */
++ AST_LIST_HEAD_NOLOCK(autochans, ast_autochan) autochans; /*!< Autochans on the channel */
+
+ unsigned long insmpl; /*!< Track the read/written samples for monitor use */
+ unsigned long outsmpl; /*!< Track the read/written samples for monitor use */
+
+ int fds[AST_MAX_FDS]; /*!< File descriptors for channel -- Drivers will poll on
+- these file descriptors, so at least one must be non -1.
+- See \arg \ref AstFileDesc */
++ * these file descriptors, so at least one must be non -1.
++ * See \arg \ref AstFileDesc */
+ int cdrflags; /*!< Call Detail Record Flags */
+ int _softhangup; /*!< Whether or not we have been hung up... Do not set this value
+- directly, use ast_softhangup() */
++ * directly, use ast_softhangup() */
+ int fdno; /*!< Which fd had an event detected on */
+ int streamid; /*!< For streaming playback, the schedule ID */
+ int vstreamid; /*!< For streaming video playback, the schedule ID */
+@@ -473,9 +675,9 @@
+ int amaflags; /*!< Set BEFORE PBX is started to determine AMA flags */
+ enum ast_channel_adsicpe adsicpe; /*!< Whether or not ADSI is detected on CPE */
+ unsigned int fin; /*!< Frames in counters. The high bit is a debug mask, so
+- the counter is only in the remaining bits */
++ * the counter is only in the remaining bits */
+ unsigned int fout; /*!< Frames out counters. The high bit is a debug mask, so
+- the counter is only in the remaining bits */
++ * the counter is only in the remaining bits */
+ int hangupcause; /*!< Why is the channel hanged up. See causes.h */
+ unsigned int flags; /*!< channel flags of AST_FLAG_ type */
+ int alertpipe[2];
+@@ -490,15 +692,10 @@
+ #endif
+ int visible_indication; /*!< Indication currently playing on the channel */
+
+- unsigned short transfercapability; /*!< ISDN Transfer Capbility - AST_FLAG_DIGITAL is not enough */
++ unsigned short transfercapability; /*!< ISDN Transfer Capability - AST_FLAG_DIGITAL is not enough */
+
+- union {
+- char unused_old_dtmfq[AST_MAX_EXTENSION]; /*!< (deprecated, use readq instead) Any/all queued DTMF characters */
+- struct {
+- struct ast_bridge *bridge; /*!< Bridge this channel is participating in */
+- struct ast_timer *timer; /*!< timer object that provided timingfd */
+- };
+- };
++ struct ast_bridge *bridge; /*!< Bridge this channel is participating in */
++ struct ast_timer *timer; /*!< timer object that provided timingfd */
+
+ char context[AST_MAX_CONTEXT]; /*!< Dialplan: Current extension context */
+ char exten[AST_MAX_EXTENSION]; /*!< Dialplan: Current extension number */
+@@ -509,17 +706,21 @@
+
+ /*! \brief ast_channel_tech Properties */
+ enum {
+- /*! \brief Channels have this property if they can accept input with jitter;
+- * i.e. most VoIP channels */
++ /*!
++ * \brief Channels have this property if they can accept input with jitter;
++ * i.e. most VoIP channels
++ */
+ AST_CHAN_TP_WANTSJITTER = (1 << 0),
+- /*! \brief Channels have this property if they can create jitter;
+- * i.e. most VoIP channels */
++ /*!
++ * \brief Channels have this property if they can create jitter;
++ * i.e. most VoIP channels
++ */
+ AST_CHAN_TP_CREATESJITTER = (1 << 1),
+ };
+
+ /*! \brief ast_channel flags */
+ enum {
+- /*! Queue incoming dtmf, to be released when this flag is turned off */
++ /*! Queue incoming DTMF, to be released when this flag is turned off */
+ AST_FLAG_DEFER_DTMF = (1 << 1),
+ /*! write should be interrupt generator */
+ AST_FLAG_WRITE_INT = (1 << 2),
+@@ -550,7 +751,7 @@
+ * to instead only generate END frames. */
+ AST_FLAG_END_DTMF_ONLY = (1 << 14),
+ /*! Flag to show channels that this call is hangup due to the fact that the call
+- was indeed anwered, but in another channel */
++ was indeed answered, but in another channel */
+ AST_FLAG_ANSWERED_ELSEWHERE = (1 << 15),
+ /*! This flag indicates that on a masquerade, an active stream should not
+ * be carried over */
+@@ -584,7 +785,7 @@
+ struct ast_flags features_callee;
+ struct timeval start_time;
+ struct timeval nexteventts;
+- struct timeval partialfeature_timer;
++ struct timeval feature_start_time;
+ long feature_timer;
+ long timelimit;
+ long play_warning;
+@@ -592,7 +793,6 @@
+ const char *warning_sound;
+ const char *end_sound;
+ const char *start_sound;
+- int firstpass;
+ unsigned int flags;
+ void (* end_bridge_callback)(void *); /*!< A callback that is called after a bridge attempt */
+ void *end_bridge_callback_data; /*!< Data passed to the callback */
+@@ -676,7 +876,6 @@
+ * \retval 0 success
+ * \retval non-zero failure
+ */
+-
+ int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore);
+
+ /*!
+@@ -726,19 +925,26 @@
+ __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
+
+ /*!
+- * \brief Queue an outgoing frame
++ * \brief Queue one or more frames to a channel's frame queue
+ *
+- * \note The channel does not need to be locked before calling this function.
++ * \param chan the channel to queue the frame(s) on
++ * \param f the frame(s) to queue. Note that the frame(s) will be duplicated
++ * by this function. It is the responsibility of the caller to handle
++ * freeing the memory associated with the frame(s) being passed if
++ * necessary.
++ *
++ * \retval 0 success
++ * \retval non-zero failure
+ */
+ int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f);
+
+ /*!
+- * \brief Queue an outgoing frame to the head of the frame queue
++ * \brief Queue one or more frames to the head of a channel's frame queue
+ *
+- * \param chan the channel to queue the frame on
+- * \param f the frame to queue. Note that this frame will be duplicated by
+- * this function. It is the responsibility of the caller to handle
+- * freeing the memory associated with the frame being passed if
++ * \param chan the channel to queue the frame(s) on
++ * \param f the frame(s) to queue. Note that the frame(s) will be duplicated
++ * by this function. It is the responsibility of the caller to handle
++ * freeing the memory associated with the frame(s) being passed if
+ * necessary.
+ *
+ * \retval 0 success
+@@ -788,6 +994,7 @@
+ * \retval 0 success
+ * \retval non-zero failure
+ *
++ * \details
+ * The supplied payload data is copied into the frame, so the caller's copy
+ * is not modified nor freed, and the resulting frame will retain a copy of
+ * the data even if the caller frees their local copy.
+@@ -807,12 +1014,26 @@
+ /*!
+ * \brief Change channel name
+ *
+- * \note The channel must be locked before calling this function.
++ * \pre The channel must be locked before calling this function.
++ *
++ * \param chan the channel to change the name of
++ * \param newname the name to change to
++ *
++ * \return nothing
+ */
+-void ast_change_name(struct ast_channel *chan, char *newname);
++void ast_change_name(struct ast_channel *chan, const char *newname);
+
+-/*! \brief Free a channel structure */
+-void ast_channel_free(struct ast_channel *);
++/*!
++ * \brief Unlink and release reference to a channel
++ *
++ * This function will unlink the channel from the global channels container
++ * if it is still there and also release the current reference to the channel.
++ *
++ * \return NULL, convenient for clearing invalid pointers
++ *
++ * \since 1.6.3
++ */
++struct ast_channel *ast_channel_release(struct ast_channel *chan);
+
+ /*!
+ * \brief Requests a channel
+@@ -822,6 +1043,7 @@
+ * \param data data to pass to the channel requester
+ * \param status status
+ *
++ * \details
+ * Request a channel of a given type, with data as optional information used
+ * by the low level module
+ *
+@@ -864,66 +1086,76 @@
+ */
+ struct ast_channel *__ast_request_and_dial(const char *type, int format, void *data,
+ int timeout, int *reason, const char *cid_num, const char *cid_name, struct outgoing_helper *oh);
++
+ /*!
+-* \brief Forwards a call to a new channel specified by the original channel's call_forward str. If possible, the new forwarded channel is created and returned while the original one is terminated.
+-* \param caller in channel that requested orig
+-* \param orig channel being replaced by the call forward channel
+-* \param timeout maximum amount of time to wait for setup of new forward channel
+-* \param format requested channel format
+-* \param oh outgoing helper used with original channel
+-* \param outstate reason why unsuccessful (if uncuccessful)
+-* \return Returns the forwarded call's ast_channel on success or NULL on failure
+-*/
++ * \brief Forwards a call to a new channel specified by the original channel's call_forward str. If possible, the new forwarded channel is created and returned while the original one is terminated.
++ * \param caller in channel that requested orig
++ * \param orig channel being replaced by the call forward channel
++ * \param timeout maximum amount of time to wait for setup of new forward channel
++ * \param format requested channel format
++ * \param oh outgoing helper used with original channel
++ * \param outstate reason why unsuccessful (if uncuccessful)
++ * \return Returns the forwarded call's ast_channel on success or NULL on failure
++ */
+ struct ast_channel *ast_call_forward(struct ast_channel *caller, struct ast_channel *orig, int *timeout, int format, struct outgoing_helper *oh, int *outstate);
+
+-/*!\brief Register a channel technology (a new channel driver)
++/*!
++ * \brief Register a channel technology (a new channel driver)
+ * Called by a channel module to register the kind of channels it supports.
+ * \param tech Structure defining channel technology or "type"
+ * \return Returns 0 on success, -1 on failure.
+ */
+ int ast_channel_register(const struct ast_channel_tech *tech);
+
+-/*! \brief Unregister a channel technology
++/*!
++ * \brief Unregister a channel technology
+ * \param tech Structure defining channel technology or "type" that was previously registered
+ * \return No return value.
+ */
+ void ast_channel_unregister(const struct ast_channel_tech *tech);
+
+-/*! \brief Get a channel technology structure by name
++/*!
++ * \brief Get a channel technology structure by name
+ * \param name name of technology to find
+ * \return a pointer to the structure, or NULL if no matching technology found
+ */
+ const struct ast_channel_tech *ast_get_channel_tech(const char *name);
+
+ #ifdef CHANNEL_TRACE
+-/*! \brief Update the context backtrace if tracing is enabled
++/*!
++ * \brief Update the context backtrace if tracing is enabled
+ * \return Returns 0 on success, -1 on failure
+ */
+ int ast_channel_trace_update(struct ast_channel *chan);
+
+-/*! \brief Enable context tracing in the channel
++/*!
++ * \brief Enable context tracing in the channel
+ * \return Returns 0 on success, -1 on failure
+ */
+ int ast_channel_trace_enable(struct ast_channel *chan);
+
+-/*! \brief Disable context tracing in the channel.
++/*!
++ * \brief Disable context tracing in the channel.
+ * \note Does not remove current trace entries
+ * \return Returns 0 on success, -1 on failure
+ */
+ int ast_channel_trace_disable(struct ast_channel *chan);
+
+-/*! \brief Whether or not context tracing is enabled
++/*!
++ * \brief Whether or not context tracing is enabled
+ * \return Returns -1 when the trace is enabled. 0 if not.
+ */
+ int ast_channel_trace_is_enabled(struct ast_channel *chan);
+
+-/*! \brief Put the channel backtrace in a string
++/*!
++ * \brief Put the channel backtrace in a string
+ * \return Returns the amount of lines in the backtrace. -1 on error.
+ */
+ int ast_channel_trace_serialize(struct ast_channel *chan, struct ast_str **out);
+ #endif
+
+-/*! \brief Hang up a channel
++/*!
++ * \brief Hang up a channel
+ * \note This function performs a hard hangup on a channel. Unlike the soft-hangup, this function
+ * performs all stream stopping, etc, on the channel that needs to end.
+ * chan is no longer valid after this call.
+@@ -938,6 +1170,7 @@
+ * \param chan channel to be soft-hung-up
+ * \param cause Ast hangupcause for hangup
+ *
++ * \details
+ * Call the protocol layer, but don't destroy the channel structure
+ * (use this if you are trying to
+ * safely hangup a channel managed by another thread.
+@@ -948,9 +1181,11 @@
+ */
+ int ast_softhangup(struct ast_channel *chan, int cause);
+
+-/*! \brief Softly hangup up a channel (no channel lock)
++/*!
++ * \brief Softly hangup up a channel (no channel lock)
+ * \param chan channel to be soft-hung-up
+- * \param cause Ast hangupcause for hangup (see cause.h) */
++ * \param cause Ast hangupcause for hangup (see cause.h)
++ */
+ int ast_softhangup_nolock(struct ast_channel *chan, int cause);
+
+ /*! \brief Check to see if a channel is needing hang up
+@@ -960,11 +1195,14 @@
+ */
+ int ast_check_hangup(struct ast_channel *chan);
+
++int ast_check_hangup_locked(struct ast_channel *chan);
++
+ /*!
+ * \brief Compare a offset with the settings of when to hang a channel up
+ * \param chan channel on which to check for hang up
+ * \param offset offset in seconds from current time
+ * \return 1, 0, or -1
++ * \details
+ * This function compares a offset from current time with the absolute time
+ * out on a channel (when to hang up). If the absolute time out on a channel
+ * is earlier than current time plus the offset, it returns 1, if the two
+@@ -987,11 +1225,13 @@
+ */
+ int ast_channel_cmpwhentohangup_tv(struct ast_channel *chan, struct timeval offset);
+
+-/*! \brief Set when to hang a channel up
++/*!
++ * \brief Set when to hang a channel up
+ *
+ * \param chan channel on which to check for hang up
+ * \param offset offset in seconds relative to the current time of when to hang up
+ *
++ * \details
+ * This function sets the absolute time out on a channel (when to hang up).
+ *
+ * \note This function does not require that the channel is locked before
+@@ -1003,7 +1243,8 @@
+ */
+ void ast_channel_setwhentohangup(struct ast_channel *chan, time_t offset) __attribute__((deprecated));
+
+-/*! \brief Set when to hang a channel up
++/*!
++ * \brief Set when to hang a channel up
+ *
+ * \param chan channel on which to check for hang up
+ * \param offset offset in seconds and useconds relative to the current time of when to hang up
+@@ -1023,6 +1264,7 @@
+ *
+ * \param chan channel to answer
+ *
++ * \details
+ * This function answers a channel and handles all necessary call
+ * setup functions.
+ *
+@@ -1083,18 +1325,21 @@
+ */
+ int __ast_answer(struct ast_channel *chan, unsigned int delay, int cdr_answer);
+
+-/*! \brief Make a call
++/*!
++ * \brief Make a call
+ * \param chan which channel to make the call on
+ * \param addr destination of the call
+ * \param timeout time to wait on for connect
++ * \details
+ * Place a call, take no longer than timeout ms.
+- \return Returns -1 on failure, 0 on not enough time
+- (does not automatically stop ringing), and
+- the number of seconds the connect took otherwise.
+- */
++ * \return -1 on failure, 0 on not enough time
++ * (does not automatically stop ringing), and
++ * the number of seconds the connect took otherwise.
++ */
+ int ast_call(struct ast_channel *chan, char *addr, int timeout);
+
+-/*! \brief Indicates condition of channel
++/*!
++ * \brief Indicates condition of channel
+ * \note Indicate a condition such as AST_CONTROL_BUSY, AST_CONTROL_RINGING, or AST_CONTROL_CONGESTION on a channel
+ * \param chan channel to change the indication
+ * \param condition which condition to indicate on the channel
+@@ -1102,7 +1347,8 @@
+ */
+ int ast_indicate(struct ast_channel *chan, int condition);
+
+-/*! \brief Indicates condition of channel, with payload
++/*!
++ * \brief Indicates condition of channel, with payload
+ * \note Indicate a condition such as AST_CONTROL_HOLD with payload being music on hold class
+ * \param chan channel to change the indication
+ * \param condition which condition to indicate on the channel
+@@ -1114,33 +1360,43 @@
+
+ /* Misc stuff ------------------------------------------------ */
+
+-/*! \brief Wait for input on a channel
++/*!
++ * \brief Wait for input on a channel
+ * \param chan channel to wait on
+ * \param ms length of time to wait on the channel
++ * \details
+ * Wait for input on a channel for a given # of milliseconds (<0 for indefinite).
+- \return Returns < 0 on failure, 0 if nothing ever arrived, and the # of ms remaining otherwise */
++ * \retval < 0 on failure
++ * \retval 0 if nothing ever arrived
++ * \retval the # of ms remaining otherwise
++ */
+ int ast_waitfor(struct ast_channel *chan, int ms);
+
+-/*! \brief Wait for a specified amount of time, looking for hangups
++/*!
++ * \brief Wait for a specified amount of time, looking for hangups
+ * \param chan channel to wait for
+ * \param ms length of time in milliseconds to sleep
++ * \details
+ * Waits for a specified amount of time, servicing the channel as required.
+ * \return returns -1 on hangup, otherwise 0.
+ */
+ int ast_safe_sleep(struct ast_channel *chan, int ms);
+
+-/*! \brief Wait for a specified amount of time, looking for hangups and a condition argument
++/*!
++ * \brief Wait for a specified amount of time, looking for hangups and a condition argument
+ * \param chan channel to wait for
+ * \param ms length of time in milliseconds to sleep
+ * \param cond a function pointer for testing continue condition
+ * \param data argument to be passed to the condition test function
+ * \return returns -1 on hangup, otherwise 0.
++ * \details
+ * Waits for a specified amount of time, servicing the channel as required. If cond
+ * returns 0, this function returns.
+ */
+ int ast_safe_sleep_conditional(struct ast_channel *chan, int ms, int (*cond)(void*), void *data );
+
+-/*! \brief Waits for activity on a group of channels
++/*!
++ * \brief Waits for activity on a group of channels
+ * \param chan an array of pointers to channels
+ * \param n number of channels that are to be waited upon
+ * \param fds an array of fds to wait upon
+@@ -1148,44 +1404,55 @@
+ * \param exception exception flag
+ * \param outfd fd that had activity on it
+ * \param ms how long the wait was
++ * \details
+ * Big momma function here. Wait for activity on any of the n channels, or any of the nfds
+- file descriptors.
+- \return Returns the channel with activity, or NULL on error or if an FD
+- came first. If the FD came first, it will be returned in outfd, otherwise, outfd
+- will be -1 */
++ * file descriptors.
++ * \return Returns the channel with activity, or NULL on error or if an FD
++ * came first. If the FD came first, it will be returned in outfd, otherwise, outfd
++ * will be -1
++ */
+ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **chan, int n,
+ int *fds, int nfds, int *exception, int *outfd, int *ms);
+
+-/*! \brief Waits for input on a group of channels
+- Wait for input on an array of channels for a given # of milliseconds.
+- \return Return channel with activity, or NULL if none has activity.
+- \param chan an array of pointers to channels
+- \param n number of channels that are to be waited upon
+- \param ms time "ms" is modified in-place, if applicable */
++/*!
++ * \brief Waits for input on a group of channels
++ * Wait for input on an array of channels for a given # of milliseconds.
++ * \return Return channel with activity, or NULL if none has activity.
++ * \param chan an array of pointers to channels
++ * \param n number of channels that are to be waited upon
++ * \param ms time "ms" is modified in-place, if applicable
++ */
+ struct ast_channel *ast_waitfor_n(struct ast_channel **chan, int n, int *ms);
+
+-/*! \brief Waits for input on an fd
+- This version works on fd's only. Be careful with it. */
++/*!
++ * \brief Waits for input on an fd
++ * \note This version works on fd's only. Be careful with it.
++ */
+ int ast_waitfor_n_fd(int *fds, int n, int *ms, int *exception);
+
+
+-/*! \brief Reads a frame
++/*!
++ * \brief Reads a frame
+ * \param chan channel to read a frame from
+ * \return Returns a frame, or NULL on error. If it returns NULL, you
+- best just stop reading frames and assume the channel has been
+- disconnected. */
++ * best just stop reading frames and assume the channel has been
++ * disconnected.
++ */
+ struct ast_frame *ast_read(struct ast_channel *chan);
+
+-/*! \brief Reads a frame, returning AST_FRAME_NULL frame if audio.
+- \param chan channel to read a frame from
+- \return Returns a frame, or NULL on error. If it returns NULL, you
+- best just stop reading frames and assume the channel has been
+- disconnected.
+- \note Audio is replaced with AST_FRAME_NULL to avoid
+- transcode when the resulting audio is not necessary. */
++/*!
++ * \brief Reads a frame, returning AST_FRAME_NULL frame if audio.
++ * \param chan channel to read a frame from
++ * \return Returns a frame, or NULL on error. If it returns NULL, you
++ * best just stop reading frames and assume the channel has been
++ * disconnected.
++ * \note Audio is replaced with AST_FRAME_NULL to avoid
++ * transcode when the resulting audio is not necessary.
++ */
+ struct ast_frame *ast_read_noaudio(struct ast_channel *chan);
+
+-/*! \brief Write a frame to a channel
++/*!
++ * \brief Write a frame to a channel
+ * This function writes the given frame to the indicated channel.
+ * \param chan destination channel of the frame
+ * \param frame frame that will be written
+@@ -1193,7 +1460,8 @@
+ */
+ int ast_write(struct ast_channel *chan, struct ast_frame *frame);
+
+-/*! \brief Write video frame to a channel
++/*!
++ * \brief Write video frame to a channel
+ * This function writes the given frame to the indicated channel.
+ * \param chan destination channel of the frame
+ * \param frame frame that will be written
+@@ -1201,7 +1469,8 @@
+ */
+ int ast_write_video(struct ast_channel *chan, struct ast_frame *frame);
+
+-/*! \brief Write text frame to a channel
++/*!
++ * \brief Write text frame to a channel
+ * This function writes the given frame to the indicated channel.
+ * \param chan destination channel of the frame
+ * \param frame frame that will be written
+@@ -1212,7 +1481,8 @@
+ /*! \brief Send empty audio to prime a channel driver */
+ int ast_prod(struct ast_channel *chan);
+
+-/*! \brief Sets read format on channel chan
++/*!
++ * \brief Sets read format on channel chan
+ * Set read format for channel to whichever component of "format" is best.
+ * \param chan channel to change
+ * \param format format to change to
+@@ -1220,7 +1490,8 @@
+ */
+ int ast_set_read_format(struct ast_channel *chan, int format);
+
+-/*! \brief Sets write format on channel chan
++/*!
++ * \brief Sets write format on channel chan
+ * Set write format for channel to whichever component of "format" is best.
+ * \param chan channel to change
+ * \param format new format for writing
+@@ -1234,6 +1505,7 @@
+ * \param chan channel to act upon
+ * \param text string of text to send on the channel
+ *
++ * \details
+ * Write text to a display on a channel
+ *
+ * \note The channel does not need to be locked before calling this function.
+@@ -1243,34 +1515,35 @@
+ */
+ int ast_sendtext(struct ast_channel *chan, const char *text);
+
+-/*! \brief Receives a text character from a channel
++/*!
++ * \brief Receives a text character from a channel
+ * \param chan channel to act upon
+ * \param timeout timeout in milliseconds (0 for infinite wait)
++ * \details
+ * Read a char of text from a channel
+- * Returns 0 on success, -1 on failure
++ * \return 0 on success, -1 on failure
+ */
+ int ast_recvchar(struct ast_channel *chan, int timeout);
+
+-/*! \brief Send a DTMF digit to a channel
+- * Send a DTMF digit to a channel.
++/*!
++ * \brief Send a DTMF digit to a channel.
+ * \param chan channel to act upon
+ * \param digit the DTMF digit to send, encoded in ASCII
+ * \param duration the duration of the digit ending in ms
+- * \return Returns 0 on success, -1 on failure
++ * \return 0 on success, -1 on failure
+ */
+ int ast_senddigit(struct ast_channel *chan, char digit, unsigned int duration);
+
+-/*! \brief Send a DTMF digit to a channel
+- * Send a DTMF digit to a channel.
++/*!
++ * \brief Send a DTMF digit to a channel.
+ * \param chan channel to act upon
+ * \param digit the DTMF digit to send, encoded in ASCII
+- * \return Returns 0 on success, -1 on failure
++ * \return 0 on success, -1 on failure
+ */
+ int ast_senddigit_begin(struct ast_channel *chan, char digit);
+
+-/*! \brief Send a DTMF digit to a channel
+-
+- * Send a DTMF digit to a channel.
++/*!
++ * \brief Send a DTMF digit to a channel.
+ * \param chan channel to act upon
+ * \param digit the DTMF digit to send, encoded in ASCII
+ * \param duration the duration of the digit ending in ms
+@@ -1278,7 +1551,8 @@
+ */
+ int ast_senddigit_end(struct ast_channel *chan, char digit, unsigned int duration);
+
+-/*! \brief Receives a text string from a channel
++/*!
++ * \brief Receives a text string from a channel
+ * Read a string of text from a channel
+ * \param chan channel to act upon
+ * \param timeout timeout in milliseconds (0 for infinite wait)
+@@ -1286,69 +1560,41 @@
+ */
+ char *ast_recvtext(struct ast_channel *chan, int timeout);
+
+-/*! \brief Browse channels in use
+- * Browse the channels currently in use
+- * \param prev where you want to start in the channel list
+- * \return Returns the next channel in the list, NULL on end.
+- * If it returns a channel, that channel *has been locked*!
+- */
+-struct ast_channel *ast_channel_walk_locked(const struct ast_channel *prev);
+-
+-/*! \brief Get channel by name or uniqueid (locks channel) */
+-struct ast_channel *ast_get_channel_by_name_locked(const char *chan);
+-
+-/*! \brief Get channel by name or uniqueid prefix (locks channel) */
+-struct ast_channel *ast_get_channel_by_name_prefix_locked(const char *name, const int namelen);
+-
+-/*! \brief Get channel by name or uniqueid prefix (locks channel) */
+-struct ast_channel *ast_walk_channel_by_name_prefix_locked(const struct ast_channel *chan, const char *name, const int namelen);
+-
+-/*! \brief 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);
+-
+-/*! \brief Get next channel by exten (and optionally context) and lock it */
+-struct ast_channel *ast_walk_channel_by_exten_locked(const struct ast_channel *chan, const char *exten,
+- const char *context);
+-
+-/*! \brief Search for a channel based on the passed channel matching callback
+- * Search for a channel based on the specified is_match callback, and return the
+- * first channel that we match. When returned, the channel will be locked. Note
+- * that the is_match callback is called with the passed channel locked, and should
+- * return 0 if there is no match, and non-zero if there is.
+- * \param is_match callback executed on each channel until non-zero is returned, or we
+- * run out of channels to search.
+- * \param data data passed to the is_match callback during each invocation.
+- * \return Returns the matched channel, or NULL if no channel was matched.
+- */
+-struct ast_channel *ast_channel_search_locked(int (*is_match)(struct ast_channel *, void *), void *data);
+-
+-/*! ! \brief Waits for a digit
++/*!
++ * \brief Waits for a digit
+ * \param c channel to wait for a digit on
+ * \param ms how many milliseconds to wait
+- * \return Returns <0 on error, 0 on no entry, and the digit on success. */
++ * \return Returns <0 on error, 0 on no entry, and the digit on success.
++ */
+ int ast_waitfordigit(struct ast_channel *c, int ms);
+
+-/*! \brief Wait for a digit
+- Same as ast_waitfordigit() with audio fd for outputting read audio and ctrlfd to monitor for reading.
++/*!
++ * \brief Wait for a digit
++ * Same as ast_waitfordigit() with audio fd for outputting read audio and ctrlfd to monitor for reading.
+ * \param c channel to wait for a digit on
+ * \param ms how many milliseconds to wait
+ * \param audiofd audio file descriptor to write to if audio frames are received
+ * \param ctrlfd control file descriptor to monitor for reading
+- * \return Returns 1 if ctrlfd becomes available */
++ * \return Returns 1 if ctrlfd becomes available
++ */
+ int ast_waitfordigit_full(struct ast_channel *c, int ms, int audiofd, int ctrlfd);
+
+-/*! Reads multiple digits
++/*!
++ * \brief Reads multiple digits
+ * \param c channel to read from
+ * \param s string to read in to. Must be at least the size of your length
+ * \param len how many digits to read (maximum)
+ * \param timeout how long to timeout between digits
+ * \param rtimeout timeout to wait on the first digit
+ * \param enders digits to end the string
++ * \details
+ * Read in a digit string "s", max length "len", maximum timeout between
+- digits "timeout" (-1 for none), terminated by anything in "enders". Give them rtimeout
+- for the first digit. Returns 0 on normal return, or 1 on a timeout. In the case of
+- a timeout, any digits that were read before the timeout will still be available in s.
+- RETURNS 2 in full version when ctrlfd is available, NOT 1*/
++ * digits "timeout" (-1 for none), terminated by anything in "enders". Give them rtimeout
++ * for the first digit.
++ * \return Returns 0 on normal return, or 1 on a timeout. In the case of
++ * a timeout, any digits that were read before the timeout will still be available in s.
++ * RETURNS 2 in full version when ctrlfd is available, NOT 1
++ */
+ int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders);
+ int ast_readstring_full(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders, int audiofd, int ctrlfd);
+
+@@ -1364,28 +1610,37 @@
+ #define AST_BRIDGE_IGNORE_SIGS (1 << 4)
+
+
+-/*! \brief Makes two channel formats compatible
++/*!
++ * \brief Makes two channel formats compatible
+ * \param c0 first channel to make compatible
+ * \param c1 other channel to make compatible
+- * Set two channels to compatible formats -- call before ast_channel_bridge in general .
+- * \return Returns 0 on success and -1 if it could not be done */
++ * \details
++ * Set two channels to compatible formats -- call before ast_channel_bridge in general.
++ * \return Returns 0 on success and -1 if it could not be done
++ */
+ int ast_channel_make_compatible(struct ast_channel *c0, struct ast_channel *c1);
+
+-/*! Bridge two channels together (early)
++/*!
++ * \brief Bridge two channels together (early)
+ * \param c0 first channel to bridge
+ * \param c1 second channel to bridge
++ * \details
+ * Bridge two channels (c0 and c1) together early. This implies either side may not be answered yet.
+- * \return Returns 0 on success and -1 if it could not be done */
++ * \return Returns 0 on success and -1 if it could not be done
++ */
+ int ast_channel_early_bridge(struct ast_channel *c0, struct ast_channel *c1);
+
+-/*! Bridge two channels together
++/*!
++ * \brief Bridge two channels together
+ * \param c0 first channel to bridge
+ * \param c1 second channel to bridge
+ * \param config config for the channels
+ * \param fo destination frame(?)
+ * \param rc destination channel(?)
++ * \details
+ * Bridge two channels (c0 and c1) together. If an important frame occurs, we return that frame in
+- *rf (remember, it could be NULL) and which channel (0 or 1) in rc */
++ * *rf (remember, it could be NULL) and which channel (0 or 1) in rc
++ */
+ /* int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc); */
+ int ast_channel_bridge(struct ast_channel *c0,struct ast_channel *c1,
+ struct ast_bridge_config *config, struct ast_frame **fo, struct ast_channel **rc);
+@@ -1396,6 +1651,7 @@
+ * \param original channel to make a copy of
+ * \param clone copy of the original channel
+ *
++ * \details
+ * This is a very strange and freaky function used primarily for transfer. Suppose that
+ * "original" and "clone" are two channels in random situations. This function takes
+ * the guts out of "clone" and puts them into the "original" channel, then alerts the
+@@ -1407,100 +1663,114 @@
+ */
+ int ast_channel_masquerade(struct ast_channel *original, struct ast_channel *clone);
+
+-/*! Gives the string form of a given cause code */
+ /*!
++ * \brief Gives the string form of a given cause code.
++ *
+ * \param state cause to get the description of
+- * Give a name to a cause code
+- * Returns the text form of the binary cause code given
++ * \return the text form of the binary cause code given
+ */
+ const char *ast_cause2str(int state) attribute_pure;
+
+-/*! Convert the string form of a cause code to a number */
+ /*!
++ * \brief Convert the string form of a cause code to a number
++ *
+ * \param name string form of the cause
+- * Returns the cause code
++ * \return the cause code
+ */
+ int ast_str2cause(const char *name) attribute_pure;
+
+-/*! Gives the string form of a given channel state */
+ /*!
++ * \brief Gives the string form of a given channel state
++ *
+ * \param ast_channel_state state to get the name of
+- * Give a name to a state
+- * Returns the text form of the binary state given
++ * \return the text form of the binary state given
+ */
+ const char *ast_state2str(enum ast_channel_state);
+
+-/*! Gives the string form of a given transfer capability */
+ /*!
+- * \param transfercapability transfercapabilty to get the name of
+- * Give a name to a transfercapbility
+- * See above
+- * Returns the text form of the binary transfer capability
++ * \brief Gives the string form of a given transfer capability
++ *
++ * \param transfercapability transfer capability to get the name of
++ * \return the text form of the binary transfer capability
+ */
+ char *ast_transfercapability2str(int transfercapability) attribute_const;
+
+-/* Options: Some low-level drivers may implement "options" allowing fine tuning of the
+- low level channel. See frame.h for options. Note that many channel drivers may support
+- none or a subset of those features, and you should not count on this if you want your
+- asterisk application to be portable. They're mainly useful for tweaking performance */
++/*
++ * Options: Some low-level drivers may implement "options" allowing fine tuning of the
++ * low level channel. See frame.h for options. Note that many channel drivers may support
++ * none or a subset of those features, and you should not count on this if you want your
++ * asterisk application to be portable. They're mainly useful for tweaking performance
++ */
+
+-/*! Sets an option on a channel */
+ /*!
++ * \brief Sets an option on a channel
++ *
+ * \param channel channel to set options on
+ * \param option option to change
+ * \param data data specific to option
+ * \param datalen length of the data
+ * \param block blocking or not
++ * \details
+ * Set an option on a channel (see frame.h), optionally blocking awaiting the reply
+- * Returns 0 on success and -1 on failure
++ * \return 0 on success and -1 on failure
+ */
+ int ast_channel_setoption(struct ast_channel *channel, int option, void *data, int datalen, int block);
+
+-/*! Pick the best codec */
+-/* Choose the best codec... Uhhh... Yah. */
++/*! Pick the best codec
++ * Choose the best codec... Uhhh... Yah. */
+ int ast_best_codec(int fmts);
+
+
+-/*! Checks the value of an option */
+ /*!
++ * \brief Checks the value of an option
++ *
+ * Query the value of an option
+ * Works similarly to setoption except only reads the options.
+ */
+ int ast_channel_queryoption(struct ast_channel *channel, int option, void *data, int *datalen, int block);
+
+-/*! Checks for HTML support on a channel */
+-/*! Returns 0 if channel does not support HTML or non-zero if it does */
++/*!
++ * \brief Checks for HTML support on a channel
++ * \return 0 if channel does not support HTML or non-zero if it does
++ */
+ int ast_channel_supports_html(struct ast_channel *channel);
+
+-/*! Sends HTML on given channel */
+-/*! Send HTML or URL on link. Returns 0 on success or -1 on failure */
++/*!
++ * \brief Sends HTML on given channel
++ * Send HTML or URL on link.
++ * \return 0 on success or -1 on failure
++ */
+ int ast_channel_sendhtml(struct ast_channel *channel, int subclass, const char *data, int datalen);
+
+-/*! Sends a URL on a given link */
+-/*! Send URL on link. Returns 0 on success or -1 on failure */
++/*!
++ * \brief Sends a URL on a given link
++ * Send URL on link.
++ * \return 0 on success or -1 on failure
++ */
+ int ast_channel_sendurl(struct ast_channel *channel, const char *url);
+
+-/*! Defers DTMF */
+-/*! Defer DTMF so that you only read things like hangups and audio. Returns
+- non-zero if channel was already DTMF-deferred or 0 if channel is just now
+- being DTMF-deferred */
++/*!
++ * \brief Defers DTMF so that you only read things like hangups and audio.
++ * \return non-zero if channel was already DTMF-deferred or
++ * 0 if channel is just now being DTMF-deferred
++ */
+ int ast_channel_defer_dtmf(struct ast_channel *chan);
+
+-/*! Undo defer. ast_read will return any dtmf characters that were queued */
++/*! Undo defer. ast_read will return any DTMF characters that were queued */
+ void ast_channel_undefer_dtmf(struct ast_channel *chan);
+
+ /*! Initiate system shutdown -- prevents new channels from being allocated.
+- If "hangup" is non-zero, all existing channels will receive soft
+- hangups */
++ * \param hangup If "hangup" is non-zero, all existing channels will receive soft
++ * hangups */
+ void ast_begin_shutdown(int hangup);
+
+ /*! Cancels an existing shutdown and returns to normal operation */
+ void ast_cancel_shutdown(void);
+
+-/*! Returns number of active/allocated channels */
++/*! \return number of active/allocated channels */
+ int ast_active_channels(void);
+
+-/*! Returns non-zero if Asterisk is being shut down */
++/*! \return non-zero if Asterisk is being shut down */
+ int ast_shutting_down(void);
+
+ /*! Activate a given generator */
+@@ -1558,105 +1828,133 @@
+ *
+ * \param rate number of timer ticks per second
+ *
++ * \details
+ * If timers are supported, force a scheduled expiration on the
+ * timer fd, at which point we call the callback function / data
+ *
+- * Call this function with a rate of 0 to turn off the timer ticks
++ * \note Call this function with a rate of 0 to turn off the timer ticks
+ *
+ * \version 1.6.1 changed samples parameter to rate, accomodates new timing methods
+ */
+ int ast_settimeout(struct ast_channel *c, unsigned int rate, int (*func)(const void *data), void *data);
+
+-/*! \brief Transfer a channel (if supported). Returns -1 on error, 0 if not supported
+- and 1 if supported and requested
+- \param chan current channel
+- \param dest destination extension for transfer
+-*/
++/*!
++ * \brief Transfer a channel (if supported).
++ * \retval -1 on error
++ * \retval 0 if not supported
++ * \retval 1 if supported and requested
++ * \param chan current channel
++ * \param dest destination extension for transfer
++ */
+ int ast_transfer(struct ast_channel *chan, char *dest);
+
+-/*! \brief Start masquerading a channel
+- XXX This is a seriously whacked out operation. We're essentially putting the guts of
+- the clone channel into the original channel. Start by killing off the original
+- channel's backend. I'm not sure we're going to keep this function, because
+- while the features are nice, the cost is very high in terms of pure nastiness. XXX
+- \param chan Channel to masquerade
+-*/
++/*!
++ * \brief Start masquerading a channel
++ * \details
++ * XXX This is a seriously whacked out operation. We're essentially putting the guts of
++ * the clone channel into the original channel. Start by killing off the original
++ * channel's backend. I'm not sure we're going to keep this function, because
++ * while the features are nice, the cost is very high in terms of pure nastiness. XXX
++ * \param chan Channel to masquerade
++ */
+ int ast_do_masquerade(struct ast_channel *chan);
+
+-/*! \brief Find bridged channel
+- \param chan Current channel
++/*!
++ * \brief Find bridged channel
++ *
++ * \note This function does _not_ return a reference to the bridged channel.
++ * The reason for this is mostly historical. It _should_ return a reference,
++ * but it will take a lot of work to make the code base account for that.
++ * So, for now, the old rules still apply for how to handle this function.
++ * If this function is being used from the channel thread that owns the channel,
++ * then a reference is already held, and channel locking is not required to
++ * guarantee that the channel will stay around. If this function is used
++ * outside of the associated channel thread, the channel parameter 'chan'
++ * MUST be locked before calling this function. Also, 'chan' must remain locked
++ * for the entire time that the result of this function is being used.
++ *
++ * \param chan Current channel
++ *
++ * \return A pointer to the bridged channel
+ */
+ struct ast_channel *ast_bridged_channel(struct ast_channel *chan);
+
+ /*!
+- \brief Inherits channel variable from parent to child channel
+- \param parent Parent channel
+- \param child Child channel
+-
+- Scans all channel variables in the parent channel, looking for those
+- that should be copied into the child channel.
+- Variables whose names begin with a single '_' are copied into the
+- child channel with the prefix removed.
+- Variables whose names begin with '__' are copied into the child
+- channel with their names unchanged.
+-*/
++ * \brief Inherits channel variable from parent to child channel
++ * \param parent Parent channel
++ * \param child Child channel
++ *
++ * \details
++ * Scans all channel variables in the parent channel, looking for those
++ * that should be copied into the child channel.
++ * Variables whose names begin with a single '_' are copied into the
++ * child channel with the prefix removed.
++ * Variables whose names begin with '__' are copied into the child
++ * channel with their names unchanged.
++ */
+ void ast_channel_inherit_variables(const struct ast_channel *parent, struct ast_channel *child);
+
+ /*!
+- \brief adds a list of channel variables to a channel
+- \param chan the channel
+- \param vars a linked list of variables
+-
+- Variable names can be for a regular channel variable or a dialplan function
+- that has the ability to be written to.
+-*/
++ * \brief adds a list of channel variables to a channel
++ * \param chan the channel
++ * \param vars a linked list of variables
++ *
++ * \details
++ * Variable names can be for a regular channel variable or a dialplan function
++ * that has the ability to be written to.
++ */
+ void ast_set_variables(struct ast_channel *chan, struct ast_variable *vars);
+
+ /*!
+- \brief An opaque 'object' structure use by silence generators on channels.
++ * \brief An opaque 'object' structure use by silence generators on channels.
+ */
+ struct ast_silence_generator;
+
+ /*!
+- \brief Starts a silence generator on the given channel.
+- \param chan The channel to generate silence on
+- \return An ast_silence_generator pointer, or NULL if an error occurs
+-
+- This function will cause SLINEAR silence to be generated on the supplied
+- channel until it is disabled; if the channel cannot be put into SLINEAR
+- mode then the function will fail.
+-
+- The pointer returned by this function must be preserved and passed to
+- ast_channel_stop_silence_generator when you wish to stop the silence
+- generation.
++ * \brief Starts a silence generator on the given channel.
++ * \param chan The channel to generate silence on
++ * \return An ast_silence_generator pointer, or NULL if an error occurs
++ *
++ * \details
++ * This function will cause SLINEAR silence to be generated on the supplied
++ * channel until it is disabled; if the channel cannot be put into SLINEAR
++ * mode then the function will fail.
++ *
++ * \note
++ * The pointer returned by this function must be preserved and passed to
++ * ast_channel_stop_silence_generator when you wish to stop the silence
++ * generation.
+ */
+ struct ast_silence_generator *ast_channel_start_silence_generator(struct ast_channel *chan);
+
+ /*!
+- \brief Stops a previously-started silence generator on the given channel.
+- \param chan The channel to operate on
+- \param state The ast_silence_generator pointer return by a previous call to
+- ast_channel_start_silence_generator.
+- \return nothing
+-
+- This function will stop the operating silence generator and return the channel
+- to its previous write format.
++ * \brief Stops a previously-started silence generator on the given channel.
++ * \param chan The channel to operate on
++ * \param state The ast_silence_generator pointer return by a previous call to
++ * ast_channel_start_silence_generator.
++ * \return nothing
++ *
++ * \details
++ * This function will stop the operating silence generator and return the channel
++ * to its previous write format.
+ */
+ void ast_channel_stop_silence_generator(struct ast_channel *chan, struct ast_silence_generator *state);
+
+ /*!
+- \brief Check if the channel can run in internal timing mode.
+- \param chan The channel to check
+- \return boolean
+-
+- This function will return 1 if internal timing is enabled and the timing
+- device is available.
++ * \brief Check if the channel can run in internal timing mode.
++ * \param chan The channel to check
++ * \return boolean
++ *
++ * \details
++ * This function will return 1 if internal timing is enabled and the timing
++ * device is available.
+ */
+ int ast_internal_timing_enabled(struct ast_channel *chan);
+
+ /* Misc. functions below */
+
+-/*! \brief if fd is a valid descriptor, set *pfd with the descriptor
++/*!
++ * \brief if fd is a valid descriptor, set *pfd with the descriptor
+ * \return Return 1 (not -1!) if added, 0 otherwise (so we can add the
+ * return value to the index into the array)
+ */
+@@ -1699,12 +1997,14 @@
+ }
+ #endif
+
+-/*! \brief Waits for activity on a group of channels
++/*!
++ * \brief Waits for activity on a group of channels
+ * \param nfds the maximum number of file descriptors in the sets
+ * \param rfds file descriptors to check for read availability
+ * \param wfds file descriptors to check for write availability
+ * \param efds file descriptors to check for exceptions (OOB data)
+ * \param tvp timeout while waiting for events
++ * \details
+ * This is the same as a standard select(), except it guarantees the
+ * behaviour where the passed struct timeval is updated with how much
+ * time was not slept while waiting for the specified events
+@@ -1761,23 +2061,23 @@
+ /*! \brief print call- and pickup groups into buffer */
+ char *ast_print_group(char *buf, int buflen, ast_group_t group);
+
+-/*! \brief Convert enum channelreloadreason to text string for manager event
+- \param reason Enum channelreloadreason - reason for reload (manager, cli, start etc)
+-*/
++/*!
++ * \brief Convert enum channelreloadreason to text string for manager event
++ * \param reason The reason for reload (manager, cli, start etc)
++ */
+ const char *channelreloadreason2txt(enum channelreloadreason reason);
+
+ /*! \brief return an ast_variable list of channeltypes */
+ struct ast_variable *ast_channeltype_list(void);
+
+ /*!
+- \brief return an english explanation of the code returned thru __ast_request_and_dial's 'outstate' argument
+- \param reason The integer argument, usually taken from AST_CONTROL_ macros
+- \return char pointer explaining the code
++ * \brief return an english explanation of the code returned thru __ast_request_and_dial's 'outstate' argument
++ * \param reason The integer argument, usually taken from AST_CONTROL_ macros
++ * \return char pointer explaining the code
+ */
+ const char *ast_channel_reason2str(int reason);
+
+-/*! \brief channel group info
+- */
++/*! \brief channel group info */
+ struct ast_group_info {
+ struct ast_channel *chan;
+ char *category;
+@@ -1785,7 +2085,518 @@
+ AST_LIST_ENTRY(ast_group_info) group_list;
+ };
+
++#define ast_channel_lock(chan) ao2_lock(chan)
++#define ast_channel_unlock(chan) ao2_unlock(chan)
++#define ast_channel_trylock(chan) ao2_trylock(chan)
+
++/*!
++ * \brief Lock two channels.
++ */
++#define ast_channel_lock_both(chan1, chan2) do { \
++ ast_channel_lock(chan1); \
++ while (ast_channel_trylock(chan2)) { \
++ ast_channel_unlock(chan1); \
++ sched_yield(); \
++ ast_channel_lock(chan1); \
++ } \
++ } while (0)
++
++/*!
++ * \brief Increase channel reference count
++ *
++ * \param c the channel
++ *
++ * \retval c always
++ *
++ * \since 1.6.3
++ */
++#define ast_channel_ref(c) ({ ao2_ref(c, +1); (c); })
++
++/*!
++ * \brief Decrease channel reference count
++ *
++ * \param c the channel
++ *
++ * \retval NULL always
++ *
++ * \since 1.6.3
++ */
++#define ast_channel_unref(c) ({ ao2_ref(c, -1); (struct ast_channel *) (NULL); })
++
++/*! Channel Iterating @{ */
++
++/*!
++ * \brief A channel iterator
++ *
++ * This is an opaque type.
++ */
++struct ast_channel_iterator;
++
++/*!
++ * \brief Destroy a channel iterator
++ *
++ * \arg i the itereator to destroy
++ *
++ * This function is used to destroy a channel iterator that was retrieved by
++ * using one of the channel_iterator_new() functions.
++ *
++ * \return NULL, for convenience to clear out the pointer to the iterator that
++ * was just destroyed.
++ *
++ * \since 1.6.3
++ */
++struct ast_channel_iterator *ast_channel_iterator_destroy(struct ast_channel_iterator *i);
++
++/*!
++ * \brief Create a new channel iterator based on extension
++ *
++ * \arg ao2_flags astobj2 iterator flags
++ * \arg exten The extension that channels must be in
++ * \arg context The context that channels must be in (optional)
++ *
++ * After creating an iterator using this function, the ast_channel_iterator_next()
++ * function can be used to iterate through all channels that are currently
++ * in the specified context and extension.
++ *
++ * \retval NULL on failure
++ * \retval a new channel iterator based on the specified parameters
++ *
++ * \since 1.6.3
++ */
++struct ast_channel_iterator *ast_channel_iterator_by_exten_new(int ao2_flags, const char *exten,
++ const char *context);
++
++/*!
++ * \brief Create a new channel iterator based on name
++ *
++ * \arg ao2_flags astobj2 iterator flags
++ * \arg name channel name or channel uniqueid to match
++ * \arg name_len number of characters in the channel name to match on. This
++ * would be used to match based on name prefix. If matching on the full
++ * channel name is desired, then this parameter should be 0.
++ *
++ * After creating an iterator using this function, the ast_channel_iterator_next()
++ * function can be used to iterate through all channels that exist that have
++ * the specified name or name prefix.
++ *
++ * \retval NULL on failure
++ * \retval a new channel iterator based on the specified parameters
++ *
++ * \since 1.6.3
++ */
++struct ast_channel_iterator *ast_channel_iterator_by_name_new(int ao2_flags, const char *name,
++ size_t name_len);
++
++/*!
++ * \brief Create a new channel iterator
++ *
++ * \arg ao2_flags astobj2 iterator flags
++ *
++ * After creating an iterator using this function, the ast_channel_iterator_next()
++ * function can be used to iterate through all channels that exist.
++ *
++ * \retval NULL on failure
++ * \retval a new channel iterator
++ *
++ * \since 1.6.3
++ */
++struct ast_channel_iterator *ast_channel_iterator_all_new(int ao2_flags);
++
++/*!
++ * \brief Get the next channel for a channel iterator
++ *
++ * \arg i the channel iterator that was created using one of the
++ * channel_iterator_new() functions.
++ *
++ * This function should be used to iterate through all channels that match a
++ * specified set of parameters that were provided when the iterator was created.
++ *
++ * \retval the next channel that matches the parameters used when the iterator
++ * was created.
++ * \retval NULL, if no more channels match the iterator parameters.
++ *
++ * \since 1.6.3
++ */
++struct ast_channel *ast_channel_iterator_next(struct ast_channel_iterator *i);
++
++/*! @} End channel iterator definitions. */
++
++/*!
++ * \brief Call a function with every active channel
++ *
++ * This function executes a callback one time for each active channel on the
++ * system. The channel is provided as an argument to the function.
++ *
++ * \since 1.6.3
++ */
++struct ast_channel *ast_channel_callback(ao2_callback_data_fn *cb_fn, void *arg,
++ void *data, int ao2_flags);
++
++/*! @{ Channel search functions */
++
++/*!
++ * \brief Find a channel by name
++ *
++ * \arg name the name or uniqueid of the channel to search for
++ *
++ * Find a channel that has the same name as the provided argument.
++ *
++ * \retval a channel with the name specified by the argument
++ * \retval NULL if no channel was found
++ *
++ * \since 1.6.3
++ */
++struct ast_channel *ast_channel_get_by_name(const char *name);
++
++/*!
++ * \brief Find a channel by a name prefix
++ *
++ * \arg name The channel name or uniqueid prefix to search for
++ * \arg name_len Only search for up to this many characters from the name
++ *
++ * Find a channel that has the same name prefix as specified by the arguments.
++ *
++ * \retval a channel with the name prefix specified by the arguments
++ * \retval NULL if no channel was found
++ *
++ * \since 1.6.3
++ */
++struct ast_channel *ast_channel_get_by_name_prefix(const char *name, size_t name_len);
++
++/*!
++ * \brief Find a channel by extension and context
++ *
++ * \arg exten the extension to search for
++ * \arg context the context to search for (optional)
++ *
++ * Return a channel that is currently at the specified extension and context.
++ *
++ * \retval a channel that is at the specified extension and context
++ * \retval NULL if no channel was found
++ *
++ * \since 1.6.3
++ */
++struct ast_channel *ast_channel_get_by_exten(const char *exten, const char *context);
++
++/*! @} End channel search functions. */
++
++/*!
++ * \since 1.6.3
++ * \brief Copy the source caller information to the destination caller.
++ *
++ * \param dest Destination caller
++ * \param src Source caller
++ *
++ * \return Nothing
++ */
++void ast_party_caller_copy(struct ast_callerid *dest, const struct ast_callerid *src);
++
++/*!
++ * \since 1.6.3
++ * \brief Initialize the given connected line structure.
++ *
++ * \param init Connected line structure to initialize.
++ *
++ * \return Nothing
++ */
++void ast_party_connected_line_init(struct ast_party_connected_line *init);
++
++/*!
++ * \since 1.6.3
++ * \brief Copy the source connected line information to the destination connected line.
++ *
++ * \param dest Destination connected line
++ * \param src Source connected line
++ *
++ * \return Nothing
++ */
++void ast_party_connected_line_copy(struct ast_party_connected_line *dest, const struct ast_party_connected_line *src);
++
++/*!
++ * \since 1.6.3
++ * \brief Initialize the given connected line structure using the given
++ * guide for a set update operation.
++ *
++ * \details
++ * The initialization is needed to allow a set operation to know if a
++ * value needs to be updated. Simple integers need the guide's original
++ * value in case the set operation is not trying to set a new value.
++ * String values are simply set to NULL pointers if they are not going
++ * to be updated.
++ *
++ * \param init Connected line structure to initialize.
++ * \param guide Source connected line to use as a guide in initializing.
++ *
++ * \return Nothing
++ */
++void ast_party_connected_line_set_init(struct ast_party_connected_line *init, const struct ast_party_connected_line *guide);
++
++/*!
++ * \since 1.6.3
++ * \brief Set the connected line information based on another connected line source
++ *
++ * This is similar to ast_party_connected_line_copy, except that NULL values for
++ * strings in the src parameter indicate not to update the corresponding dest values.
++ *
++ * \param src The source connected line to use as a guide to set the dest
++ * \param dest The connected line one wishes to update
++ *
++ * \return Nada
++ */
++void ast_party_connected_line_set(struct ast_party_connected_line *dest, const struct ast_party_connected_line *src);
++
++/*!
++ * \since 1.6.3
++ * \brief Collect the caller party information into a connected line structure.
++ *
++ * \param connected Collected caller information for the connected line
++ * \param cid Caller information.
++ *
++ * \return Nothing
++ *
++ * \warning This is a shallow copy.
++ * \warning DO NOT call ast_party_connected_line_free() on the filled in
++ * connected line structure!
++ */
++void ast_party_connected_line_collect_caller(struct ast_party_connected_line *connected, struct ast_callerid *cid);
++
++/*!
++ * \since 1.6.3
++ * \brief Destroy the connected line information contents
++ *
++ * \param doomed The connected line information to destroy.
++ *
++ * \return Nothing
++ */
++void ast_party_connected_line_free(struct ast_party_connected_line *doomed);
++
++/*!
++ * \since 1.6.3
++ * \brief Copy the source redirecting information to the destination redirecting.
++ *
++ * \param dest Destination redirecting
++ * \param src Source redirecting
++ *
++ * \return Nothing
++ */
++void ast_party_redirecting_copy(struct ast_party_redirecting *dest, const struct ast_party_redirecting *src);
++
++/*!
++ * \since 1.6.3
++ * \brief Initialize the given redirecting id structure using the given guide
++ * for a set update operation.
++ *
++ * \details
++ * The initialization is needed to allow a set operation to know if a
++ * value needs to be updated. Simple integers need the guide's original
++ * value in case the set operation is not trying to set a new value.
++ * String values are simply set to NULL pointers if they are not going
++ * to be updated.
++ *
++ * \param init Redirecting id structure to initialize.
++ * \param guide Source redirecting id to use as a guide in initializing.
++ *
++ * \return Nothing
++ */
++void ast_party_redirecting_set_init(struct ast_party_redirecting *init, const struct ast_party_redirecting *guide);
++
++/*!
++ * \since 1.6.3
++ * \brief Destroy the redirecting information contents
++ *
++ * \param doomed The redirecting information to destroy.
++ *
++ * \return Nothing
++ */
++void ast_party_redirecting_free(struct ast_party_redirecting *doomed);
++
++/*!
++ * \since 1.6.3
++ * \brief Copy the caller information to the connected line information.
++ *
++ * \param dest Destination connected line information
++ * \param src Source caller information
++ *
++ * \return Nothing
++ *
++ * \note Assumes locks are already acquired
++ */
++void ast_connected_line_copy_from_caller(struct ast_party_connected_line *dest, const struct ast_callerid *src);
++
++/*!
++ * \since 1.6.3
++ * \brief Copy the connected line information to the caller information.
++ *
++ * \param dest Destination caller information
++ * \param src Source connected line information
++ *
++ * \return Nothing
++ *
++ * \note Assumes locks are already acquired
++ */
++void ast_connected_line_copy_to_caller(struct ast_callerid *dest, const struct ast_party_connected_line *src);
++
++/*!
++ * \since 1.6.3
++ * \brief Set the connected line information in the Asterisk channel
++ *
++ * \param chan Asterisk channel to set connected line information
++ * \param connected Connected line information
++ *
++ * \return Nothing
++ *
++ * \note The channel does not need to be locked before calling this function.
++ */
++void ast_channel_set_connected_line(struct ast_channel *chan, const struct ast_party_connected_line *connected);
++
++/*!
++ * \since 1.6.3
++ * \brief Build the connected line information data frame.
++ *
++ * \param data Buffer to fill with the frame data
++ * \param datalen Size of the buffer to fill
++ * \param connected Connected line information
++ *
++ * \retval -1 if error
++ * \retval Amount of data buffer used
++ */
++int ast_connected_line_build_data(unsigned char *data, size_t datalen, const struct ast_party_connected_line *connected);
++
++/*!
++ * \since 1.6.3
++ * \brief Parse connected line indication frame data
++ *
++ * \param data Buffer with the frame data to parse
++ * \param datalen Size of the buffer
++ * \param connected Extracted connected line information
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ *
++ * \note The filled in connected line structure needs to be initialized by
++ * ast_party_connected_line_set_init() before calling. If defaults are not
++ * required use ast_party_connected_line_init().
++ * \note The filled in connected line structure needs to be destroyed by
++ * ast_party_connected_line_free() when it is no longer needed.
++ */
++int ast_connected_line_parse_data(const unsigned char *data, size_t datalen, struct ast_party_connected_line *connected);
++
++/*!
++ * \since 1.6.3
++ * \brief Indicate that the connected line information has changed
++ *
++ * \param chan Asterisk channel to indicate connected line information
++ * \param connected Connected line information
++ *
++ * \return Nothing
++ */
++void ast_channel_update_connected_line(struct ast_channel *chan, const struct ast_party_connected_line *connected);
++
++/*!
++ * \since 1.6.3
++ * \brief Queue a connected line update frame on a channel
++ *
++ * \param chan Asterisk channel to indicate connected line information
++ * \param connected Connected line information
++ *
++ * \return Nothing
++ */
++void ast_channel_queue_connected_line_update(struct ast_channel *chan, const struct ast_party_connected_line *connected);
++
++/*!
++ * \since 1.6.3
++ * \brief Set the redirecting id information in the Asterisk channel
++ *
++ * \param chan Asterisk channel to set redirecting id information
++ * \param redirecting Redirecting id information
++ *
++ * \return Nothing
++ *
++ * \note The channel does not need to be locked before calling this function.
++ */
++void ast_channel_set_redirecting(struct ast_channel *chan, const struct ast_party_redirecting *redirecting);
++
++/*!
++ * \since 1.6.3
++ * \brief Build the redirecting id data frame.
++ *
++ * \param data Buffer to fill with the frame data
++ * \param datalen Size of the buffer to fill
++ * \param redirecting Redirecting id information
++ *
++ * \retval -1 if error
++ * \retval Amount of data buffer used
++ */
++int ast_redirecting_build_data(unsigned char *data, size_t datalen, const struct ast_party_redirecting *redirecting);
++
++/*!
++ * \since 1.6.3
++ * \brief Parse redirecting indication frame data
++ *
++ * \param data Buffer with the frame data to parse
++ * \param datalen Size of the buffer
++ * \param redirecting Extracted redirecting id information
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ *
++ * \note The filled in id structure needs to be initialized by
++ * ast_party_redirecting_set_init() before calling.
++ * \note The filled in id structure needs to be destroyed by
++ * ast_party_redirecting_free() when it is no longer needed.
++ */
++int ast_redirecting_parse_data(const unsigned char *data, size_t datalen, struct ast_party_redirecting *redirecting);
++
++/*!
++ * \since 1.6.3
++ * \brief Indicate that the redirecting id has changed
++ *
++ * \param chan Asterisk channel to indicate redirecting id information
++ * \param redirecting Redirecting id information
++ *
++ * \return Nothing
++ */
++void ast_channel_update_redirecting(struct ast_channel *chan, const struct ast_party_redirecting *redirecting);
++
++/*!
++ * \since 1.6.3
++ * \brief Queue a redirecting update frame on a channel
++ *
++ * \param chan Asterisk channel to indicate redirecting id information
++ * \param redirecting Redirecting id information
++ *
++ * \return Nothing
++ */
++void ast_channel_queue_redirecting_update(struct ast_channel *chan, const struct ast_party_redirecting *redirecting);
++
++/*!
++ * \since 1.6.3
++ * \brief Run a connected line interception macro and update a channel's connected line
++ * information
++ *
++ * Whenever we want to update a channel's connected line information, we may need to run
++ * a macro so that an administrator can manipulate the information before sending it
++ * out. This function both runs the macro and sends the update to the channel.
++ *
++ * \param autoservice_chan Channel to place into autoservice while the macro is running.
++ * It is perfectly safe for this to be NULL
++ * \param macro_chan The channel to run the macro on. Also the channel from which we
++ * determine which macro we need to run.
++ * \param connected_info Either an ast_party_connected_line or ast_frame pointer of type
++ * AST_CONTROL_CONNECTED_LINE
++ * \param caller If true, then run CONNECTED_LINE_CALLER_SEND_MACRO, otherwise run
++ * CONNECTED_LINE_CALLEE_SEND_MACRO
++ * \param frame If true, then connected_info is an ast_frame pointer, otherwise it is an
++ * ast_party_connected_line pointer.
++ * \retval 0 Success
++ * \retval -1 Either the macro does not exist, or there was an error while attempting to
++ * run the macro
++ *
++ * \todo Have multiple return codes based on the MACRO_RESULT
++ * \todo Make constants so that caller and frame can be more expressive than just '1' and
++ * '0'
++ */
++int ast_channel_connected_line_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *connected_info, int caller, int frame);
+ #if defined(__cplusplus) || defined(c_plusplus)
+ }
+ #endif
+Index: include/asterisk/_private.h
+===================================================================
+--- a/include/asterisk/_private.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/_private.h (.../trunk) (revision 202568)
+@@ -41,6 +41,7 @@
+ int ast_timing_init(void); /*!< Provided by timing.c */
+ int ast_indications_init(void); /*!< Provided by indications.c */
+ int ast_indications_reload(void);/*!< Provided by indications.c */
++void ast_stun_init(void); /*!< Provided by stun.c */
+
+ /*!
+ * \brief Reload asterisk modules.
+Index: include/asterisk/manager.h
+===================================================================
+--- a/include/asterisk/manager.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/manager.h (.../trunk) (revision 202568)
+@@ -22,6 +22,7 @@
+ #include "asterisk/network.h"
+ #include "asterisk/lock.h"
+ #include "asterisk/datastore.h"
++#include "asterisk/xmldoc.h"
+
+ /*!
+ \file
+@@ -116,14 +117,19 @@
+ struct manager_action {
+ /*! Name of the action */
+ const char *action;
+- /*! Short description of the action */
+- const char *synopsis;
+- /*! Detailed description of the action */
+- const char *description;
++ AST_DECLARE_STRING_FIELDS(
++ AST_STRING_FIELD(synopsis); /*!< Synopsis text (short description). */
++ AST_STRING_FIELD(description); /*!< Description (help text) */
++ AST_STRING_FIELD(syntax); /*!< Syntax text */
++ AST_STRING_FIELD(arguments); /*!< Description of each argument. */
++ AST_STRING_FIELD(seealso); /*!< See also */
++ );
+ /*! Permission required for action. EVENT_FLAG_* */
+ int authority;
+ /*! Function to be called */
+ int (*func)(struct mansession *s, const struct message *m);
++ /*! Where the documentation come from. */
++ enum ast_doc_src docsrc;
+ /*! For easy linking */
+ AST_RWLIST_ENTRY(manager_action) list;
+ };
+@@ -132,6 +138,8 @@
+ * \note Use ast_manager_register2() to register with help text for new manager commands */
+ #define ast_manager_register(a, b, c, d) ast_manager_register2(a, b, c, d, NULL)
+
++/*! \brief Register a manager callback using XML documentation to describe the manager. */
++#define ast_manager_register_xml(a, b, c) ast_manager_register2(a, b, c, NULL, NULL)
+
+ /*! \brief Register a manager command with the manager interface
+ \param action Name of the requested Action:
+Index: include/asterisk/features.h
+===================================================================
+--- a/include/asterisk/features.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/features.h (.../trunk) (revision 202568)
+@@ -36,6 +36,21 @@
+
+ #define PARK_APP_NAME "Park"
+
++#define AST_FEATURE_RETURN_HANGUP -1
++#define AST_FEATURE_RETURN_SUCCESSBREAK 0
++#define AST_FEATURE_RETURN_PBX_KEEPALIVE AST_PBX_KEEPALIVE
++#define AST_FEATURE_RETURN_NO_HANGUP_PEER AST_PBX_NO_HANGUP_PEER
++#define AST_FEATURE_RETURN_PASSDIGITS 21
++#define AST_FEATURE_RETURN_STOREDIGITS 22
++#define AST_FEATURE_RETURN_SUCCESS 23
++#define AST_FEATURE_RETURN_KEEPTRYING 24
++#define AST_FEATURE_RETURN_PARKFAILED 25
++
++#define FEATURE_SENSE_CHAN (1 << 0)
++#define FEATURE_SENSE_PEER (1 << 1)
++
++typedef int (*ast_feature_operation)(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data);
++
+ /*! \brief main call feature structure */
+
+ enum {
+@@ -53,7 +68,7 @@
+ char sname[FEATURE_SNAME_LEN];
+ char exten[FEATURE_MAX_LEN];
+ char default_exten[FEATURE_MAX_LEN];
+- int (*operation)(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data);
++ ast_feature_operation operation;
+ unsigned int flags;
+ char app[FEATURE_APP_LEN];
+ char app_args[FEATURE_APP_ARGS_LEN];
+@@ -61,14 +76,6 @@
+ AST_LIST_ENTRY(ast_call_feature) feature_entry;
+ };
+
+-#define AST_FEATURE_RETURN_HANGUP -1
+-#define AST_FEATURE_RETURN_SUCCESSBREAK 0
+-#define AST_FEATURE_RETURN_PASSDIGITS 21
+-#define AST_FEATURE_RETURN_STOREDIGITS 22
+-#define AST_FEATURE_RETURN_SUCCESS 23
+-#define AST_FEATURE_RETURN_KEEPTRYING 24
+-#define AST_FEATURE_RETURN_PARKFAILED 25
+-
+ /*!
+ * \brief Park a call and read back parked location
+ * \param chan the channel to actually be parked
+@@ -123,6 +130,14 @@
+ \param feature the ast_call_feature object which was registered before*/
+ void ast_unregister_feature(struct ast_call_feature *feature);
+
++/*! \brief detect a feature before bridging
++ \param chan
++ \param ast_flags ptr
++ \param char ptr of input code
++ \retval ast_call_feature ptr to be set if found
++ \return result, was feature found or not */
++int ast_feature_detect(struct ast_channel *chan, struct ast_flags *features, const char *code, struct ast_call_feature *feature);
++
+ /*! \brief look for a call feature entry by its sname
+ \param name a string ptr, should match "automon", "blindxfer", "atxfer", etc. */
+ struct ast_call_feature *ast_find_call_feature(const char *name);
+Index: include/asterisk/http.h
+===================================================================
+--- a/include/asterisk/http.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/http.h (.../trunk) (revision 202568)
+@@ -52,27 +52,40 @@
+ * be run earlier in the startup process so modules have it available.
+ */
+
+-
+-/*! \brief HTTP Callbacks take the socket
+-
+- \note The method and the path as arguments and should
+- return the content, allocated with malloc(). Status should be changed to reflect
+- the status of the request if it isn't 200 and title may be set to a malloc()'d string
+- to an appropriate title for non-200 responses. Content length may also be specified.
+-\verbatim
+- The return value may include additional headers at the front and MUST include a blank
+- line with \r\n to provide separation between user headers and content (even if no
+- content is specified)
+-\endverbatim
+-*/
+-
++/*! \brief HTTP Request methods known by Asterisk */
+ enum ast_http_method {
++ AST_HTTP_UNKNOWN = -1, /*!< Unknown response */
+ AST_HTTP_GET = 0,
+ AST_HTTP_POST,
++ AST_HTTP_HEAD,
++ AST_HTTP_PUT, /*!< Not supported in Asterisk */
+ };
++
+ struct ast_http_uri;
+
+-typedef struct ast_str *(*ast_http_callback)(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *params, struct ast_variable *headers, int *status, char **title, int *contentlength);
++/*! \brief HTTP Callbacks
++ *
++ * \note The callback function receives server instance, uri, http method,
++ * get method (if present in URI), and http headers as arguments and should
++ * use the ast_http_send() function for sending content allocated with ast_str
++ * and/or content from an opened file descriptor.
++ *
++ * Status and status text should be sent as arguments to the ast_http_send()
++ * function to reflect the status of the request (200 or 304, for example).
++ * Content length is calculated by ast_http_send() automatically.
++ *
++ * Static content may be indicated to the ast_http_send() function, to indicate
++ * that it may be cached.
++ *
++ * \verbatim
++ * The return value may include additional headers at the front and MUST
++ * include a blank line with \r\n to provide separation between user headers
++ * and content (even if no content is specified)
++ * \endverbatim
++ *
++ * For an error response, the ast_http_error() function may be used.
++*/
++typedef int (*ast_http_callback)(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers);
+
+ /*! \brief Definition of a URI handler */
+ struct ast_http_uri {
+@@ -81,12 +94,6 @@
+ const char *uri;
+ ast_http_callback callback;
+ unsigned int has_subtree:1;
+- /*! This handler serves static content */
+- unsigned int static_content:1;
+- /*! This handler accepts GET requests */
+- unsigned int supports_get:1;
+- /*! This handler accepts POST requests */
+- unsigned int supports_post:1;
+ /*! Structure is malloc'd */
+ unsigned int mallocd:1;
+ /*! Data structure is malloc'd */
+@@ -97,6 +104,9 @@
+ const char *key;
+ };
+
++/*! \brief Get cookie from Request headers */
++struct ast_variable *ast_http_get_cookies(struct ast_variable *headers);
++
+ /*! \brief Register a URI handler */
+ int ast_http_uri_link(struct ast_http_uri *urihandler);
+
+@@ -106,9 +116,59 @@
+ /*! \brief Unregister all handlers with matching key */
+ void ast_http_uri_unlink_all_with_key(const char *key);
+
+-/*! \brief Return an ast_str malloc()'d string containing an HTTP error message */
+-struct ast_str *ast_http_error(int status, const char *title, const char *extra_header, const char *text);
++/*!\brief Return http method name string
++ * \since 1.6.3
++ */
++const char *ast_get_http_method(enum ast_http_method method) attribute_pure;
+
++/*!\brief Return mime type based on extension
++ * \param ftype filename extension
++ * \return String containing associated MIME type
++ * \since 1.6.3
++ */
++const char *ast_http_ftype2mtype(const char *ftype) attribute_pure;
++
++/*!\brief Return manager id, if exist, from request headers
++ * \param headers List of HTTP headers
++ * \return 32-bit associated manager session identifier
++ * \since 1.6.3
++ */
++uint32_t ast_http_manid_from_vars(struct ast_variable *headers) attribute_pure;
++
++/*! \brief Generic function for sending http/1.1 response.
++ * \param ser TCP/TLS session object
++ * \param method GET/POST/HEAD
++ * \param status_code HTTP response code (200/401/403/404/500)
++ * \param status_title English equivalent to the status_code parameter
++ * \param http_header An ast_str object containing all headers
++ * \param out An ast_str object containing the body of the response
++ * \param fd If out is NULL, a file descriptor where the body of the response is held (otherwise -1)
++ * \param static_content Zero if the content is dynamically generated and should not be cached; nonzero otherwise
++ *
++ * \note Function determines the HTTP response header from status_code,
++ * status_header, and http_header.
++ *
++ * Extra HTTP headers MUST be present only in the http_header argument. The
++ * argument "out" should contain only content of the response (no headers!).
++ *
++ * HTTP content can be constructed from the argument "out", if it is not NULL;
++ * otherwise, the function will read content from FD.
++ *
++ * This function calculates the content-length http header itself.
++ *
++ * Both the http_header and out arguments will be freed by this function;
++ * however, if FD is open, it will remain open.
++ *
++ * \since 1.6.3
++ */
++void ast_http_send(struct ast_tcptls_session_instance *ser, enum ast_http_method method, int status_code, const char *status_title, struct ast_str *http_header, struct ast_str *out, const int fd, unsigned int static_content);
++
++/*!\brief Send http "401 Unauthorized" response and close socket */
++void ast_http_auth(struct ast_tcptls_session_instance *ser, const char *realm, const unsigned long nonce, const unsigned long opaque, int stale, const char *text);
++
++/*!\brief Send HTTP error message and close socket */
++void ast_http_error(struct ast_tcptls_session_instance *ser, int status, const char *title, const char *text);
++
+ /*!
+ * \brief Return the current prefix
+ * \param buf[out] destination buffer for previous
+@@ -117,4 +177,15 @@
+ */
+ void ast_http_prefix(char *buf, int len);
+
++
++/*!\brief Get post variables from client Request Entity-Body, if content type is application/x-www-form-urlencoded.
++ * \param ser TCP/TLS session object
++ * \param headers List of HTTP headers
++ * \return List of variables within the POST body
++ * \note Since returned list is malloc'd, list should be free'd by the calling function
++ * \since 1.6.3
++ */
++struct ast_variable *ast_http_get_post_vars(struct ast_tcptls_session_instance *ser, struct ast_variable *headers);
++
++
+ #endif /* _ASTERISK_SRV_H */
+Index: include/asterisk/app.h
+===================================================================
+--- a/include/asterisk/app.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/app.h (.../trunk) (revision 202568)
+@@ -106,9 +106,29 @@
+ int ast_app_getdata(struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout);
+
+ /*! \brief Full version with audiofd and controlfd. NOTE: returns '2' on ctrlfd available, not '1' like other full functions */
+-int ast_app_getdata_full(struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout, int audiofd, int ctrlfd);
++int ast_app_getdata_full(struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout, int audiofd, int ctrlfd);
+
+ /*!
++ * \since 1.6.3
++ * \brief Run a macro on a channel, placing a second channel into autoservice.
++ *
++ * This is a shorthand method that makes it very easy to run a macro on any given
++ * channel. It is perfectly reasonable to supply a NULL autoservice_chan here in case
++ * there is no channel to place into autoservice. It is very important that the
++ * autoservice_chan parameter is not locked prior to calling ast_app_run_macro. A
++ * deadlock could result, otherwise.
++ *
++ * \param autoservice_chan A channel to place into autoservice while the macro is run
++ * \param macro_chan The channel to run the macro on
++ * \param macro_name The name of the macro to run
++ * \param macro_args The arguments to pass to the macro
++ * \retval 0 success
++ * \retval -1 failure
++ */
++int ast_app_run_macro(struct ast_channel *autoservice_chan, struct ast_channel
++ *macro_chan, const char * const macro_name, const char * const macro_args);
++
++/*!
+ * \brief Set voicemail function callbacks
+ * \param[in] inboxcount2_func set function pointer
+ * \param[in] sayname_func set function pointer
+@@ -427,19 +447,19 @@
+
+ Example usage:
+ \code
+- enum {
++ enum my_app_option_flags {
+ OPT_JUMP = (1 << 0),
+ OPT_BLAH = (1 << 1),
+ OPT_BLORT = (1 << 2),
+- } my_app_option_flags;
++ };
+
+- enum {
++ enum my_app_option_args {
+ OPT_ARG_BLAH = 0,
+ OPT_ARG_BLORT,
+ !! this entry tells how many possible arguments there are,
+ and must be the last entry in the list
+ OPT_ARG_ARRAY_SIZE,
+- } my_app_option_args;
++ };
+
+ AST_APP_OPTIONS(my_app_options, {
+ AST_APP_OPTION('j', OPT_JUMP),
+Index: include/asterisk/image.h
+===================================================================
+--- a/include/asterisk/image.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/image.h (.../trunk) (revision 202568)
+@@ -51,7 +51,7 @@
+ * \retval 0 on success
+ * \retval -1 on error
+ */
+-int ast_send_image(struct ast_channel *chan, char *filename);
++int ast_send_image(struct ast_channel *chan, const char *filename);
+
+ /*!
+ * \brief Make an image
+@@ -62,7 +62,7 @@
+ * \retval an ast_frame on success
+ * \retval NULL on failure
+ */
+-struct ast_frame *ast_read_image(char *filename, const char *preflang, int format);
++struct ast_frame *ast_read_image(const char *filename, const char *preflang, int format);
+
+ /*!
+ * \brief Register image format
+Index: include/asterisk/linkedlists.h
+===================================================================
+--- a/include/asterisk/linkedlists.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/linkedlists.h (.../trunk) (revision 202568)
+@@ -765,20 +765,47 @@
+ * calling this macro (the list entries are \b moved to the target list).
+ */
+ #define AST_LIST_APPEND_LIST(head, list, field) do { \
+- if (!(head)->first) { \
++ if (!(list)->first) { \
++ break; \
++ } \
++ if (!(head)->first) { \
+ (head)->first = (list)->first; \
+ (head)->last = (list)->last; \
+- } else { \
++ } else { \
+ (head)->last->field.next = (list)->first; \
+ (head)->last = (list)->last; \
+- } \
+- (list)->first = NULL; \
+- (list)->last = NULL; \
++ } \
++ (list)->first = NULL; \
++ (list)->last = NULL; \
+ } while (0)
+
+ #define AST_RWLIST_APPEND_LIST AST_LIST_APPEND_LIST
+
+ /*!
++ \brief Inserts a whole list after a specific entry in a list
++ \param head This is a pointer to the list head structure
++ \param list This is a pointer to the list to be inserted.
++ \param elm This is a pointer to the entry after which the new list should
++ be inserted.
++ \param field This is the name of the field (declared using AST_LIST_ENTRY())
++ used to link entries of the lists together.
++
++ Note: The source list (the \a list parameter) will be empty after
++ calling this macro (the list entries are \b moved to the target list).
++ */
++#define AST_LIST_INSERT_LIST_AFTER(head, list, elm, field) do { \
++ (list)->last->field.next = (elm)->field.next; \
++ (elm)->field.next = (list)->first; \
++ if ((head)->last == elm) { \
++ (head)->last = (list)->last; \
++ } \
++ (list)->first = NULL; \
++ (list)->last = NULL; \
++} while(0)
++
++#define AST_RWLIST_INSERT_LIST_AFTER AST_LIST_INSERT_LIST_AFTER
++
++/*!
+ * \brief Removes and returns the head entry from a list.
+ * \param head This is a pointer to the list head structure
+ * \param field This is the name of the field (declared using AST_LIST_ENTRY())
+Index: include/asterisk/doxygen/reviewboard.h
+===================================================================
+--- a/include/asterisk/doxygen/reviewboard.h (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/include/asterisk/doxygen/reviewboard.h (.../trunk) (revision 202568)
+@@ -0,0 +1,127 @@
++/*
++* Asterisk -- An open source telephony toolkit.
++*
++* Copyright (C) 1999 - 2009, Digium, Inc.
++*
++* See http://www.asterisk.org for more information about
++* the Asterisk project. Please do not directly contact
++* any of the maintainers of this project for assistance;
++* the project provides a web site, mailing lists and IRC
++* channels for your use.
++*
++* 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.
++*/
++
++/*!
++* \file
++*/
++
++/*!
++ * \page Reviewboard Reviewboard Usage and Guidelines
++ *
++ * \AsteriskTrunkWarning
++ *
++ * <hr/>
++ *
++ * \section ReviewboardGuidelines Usage Guidelines
++ *
++ * Mantis (https://issues.asterisk.org) and Reviewboard (https://reviewboard.asterisk.org)
++ * are both utilities that the Asterisk development community uses to help
++ * track and review code being written for Asterisk. Since both systems
++ * are used for posting patches, it is worth discussing when it is appropriate
++ * to use reviewboard and when not.
++ *
++ * Here are the situations in which it is appropriate to post code to reviewboard:
++ * - A committer has a patch that they would like to get some feedback on before
++ * merging into one of the main branches.
++ * - A committer or bug marshal has requested a contributor to post their patch
++ * from Mantis on reviewboard to aid in the review process. This typically
++ * happens with complex code contributions where reviewboard can help aid in
++ * providing feedback.
++ *
++ * We do encourage all interested parties to participate in the review process.
++ * However, aside from the cases mentioned above, we prefer that all code
++ * submissions first go through Mantis.
++ *
++ * \note It is acceptable for a committer to post patches to reviewboard before
++ * they are complete to get some feedback on the approach being taken. However,
++ * if the code is not yet ready to be merged, it \b must be documented as such.
++ * A review request with a patch proposed for merging should have documented
++ * testing and should not have blatant coding guidelines violations. Lack of
++ * these things is careless and shows disrespect for those reviewing your code.
++ *
++ * <hr/>
++ *
++ * \section ReviewboardPosting Posting Code to Reviewboard
++ *
++ * \subsection postreview Using post-review
++ *
++ * The easiest way to post a patch to reviewboard is by using the
++ * post-review tool. We have post-review in our repotools svn repository.
++ *
++ \verbatim
++ $ svn co http://svn.digium.com/svn/repotools
++ \endverbatim
++ *
++ * Essentially, post-review is a script that will take the output of "svn
++ * diff" and create a review request out of it for you. So, once you have
++ * a working copy with the changes you expect in the output of "svn diff",
++ * you just run the following command:
++ *
++ \verbatim
++ $ post-review
++ \endverbatim
++ *
++ * If it complains about not knowing which reviewboard server to use, add
++ * the server option:
++ *
++ \verbatim
++ $ post-review --server=https://reviewboard.asterisk.org
++ \endverbatim
++ *
++ * \subsection postreviewnewfiles Dealing with New Files
++ *
++ * I have one final note about an oddity with using post-review. If you
++ * maintain your code in a team branch, and the new code includes new
++ * files, there are some additional steps you must take to get post-review
++ * to behave properly.
++ *
++ * You would start by getting your changes applied to a trunk working copy:
++ *
++ \verbatim
++ $ cd .../trunk
++ \endverbatim
++ *
++ * Then, apply the changes from your branch:
++ *
++ \verbatim
++ $ svn merge .../trunk .../team/group/my_new_code
++ \endverbatim
++ *
++ * Now, the code is merged into your working copy. However, for a new
++ * file, subversion treats it as a copy of existing content and not new
++ * content, so new files don't show up in "svn diff" at this point. To get
++ * it to show up in the diff, use the following commands so svn treats it
++ * as new content and publishes it in the diff:
++ *
++ \verbatim
++ $ svn revert my_new_file.c
++ $ svn add my_new_file.c
++ \endverbatim
++ *
++ * Now, it should work, and you can run "post-review" as usual.
++ *
++ * \subsection postreviewupdate Updating Patch on Existing Review Request
++ *
++ * Most of the time, a patch on reviewboard will require multiple iterations
++ * before other sign off on it being ready to be merged. To update the diff
++ * for an existing review request, you can use post-review and the -r option.
++ * Apply the current version of the diff to a working copy as described above,
++ * and then run the following command:
++ *
++ \verbatim
++ $ post-review -r <review request number>
++ \endverbatim
++ */
+
+Property changes on: include/asterisk/doxygen/reviewboard.h
+___________________________________________________________________
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+Added: svn:eol-style
+ + native
+
+Index: include/asterisk/doxygen/commits.h
+===================================================================
+--- a/include/asterisk/doxygen/commits.h (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/include/asterisk/doxygen/commits.h (.../trunk) (revision 202568)
+@@ -0,0 +1,114 @@
++/*
++ * Asterisk -- An open source telephony toolkit.
++ *
++ * Copyright (C) 1999 - 2009, Digium, Inc.
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * 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.
++ */
++
++/*!
++ * \file
++ */
++
++/*!
++ * \page CommitMessages Guidelines for Commit Messages
++ *
++ * \AsteriskTrunkWarning
++ *
++ * <hr/>
++ *
++ * \section CommitMsgFormatting Commit Message Formatting
++ *
++ * The following illustrates the basic outline for commit messages:
++ *
++ \verbatim
++ <One-liner summary of changes>
++
++ <Verbose description of the changes>
++
++ <Special Tags>
++ \endverbatim
++ *
++ * Some commit history viewers treat the first line of commit messages as the
++ * summary for the commit. So, an effort should be made to format our commit
++ * messages in that fashion. The verbose description may contain multiple
++ * paragraphs, itemized lists, etc. Always end the first sentence (and any
++ * subsequent sentences) with punctuation.
++ *
++ * Commit messages should be wrapped at 80 %columns.
++ *
++ * \note For trivial commits, such as "fix the build", or "fix spelling mistake",
++ * the verbose description may not be necessary.
++ *
++ * <hr/>
++ *
++ * \section CommitMsgTags Special Tags for Commit Messages
++ *
++ * \subsection MantisTags Mantis (https://issues.asterisk.org/)
++ *
++ * To have a commit noted in an issue, use a tag of the form:
++ * \arg (issue #1234)
++ *
++ * To have a commit automatically close an issue, use a tag of the form:
++ * \arg (closes issue #1234)
++ *
++ * When making a commit for a mantis issue, it is easiest to use the
++ * provided commit %message template functionality. It will format the
++ * special tags appropriately, and will also include information about who
++ * reported the issue, which patches are being applied, and who did testing.
++ *
++ * Assuming that you have bug marshal access (and if you have commit access,
++ * it is pretty safe to assume that you do), you will find the commit %message
++ * template section directly below the issue details section and above the
++ * issue relationships section. You will have to click the '+' next to
++ * "Commit message template" to make the contents of the section visible.
++ *
++ * Here is an example of what the template will generate for you:
++ *
++ \verbatim
++ (closes issue #1234)
++ Reported by: SomeGuy
++ Patches:
++ fix_bug_1234.diff uploaded by SomeDeveloper (license 5678)
++ \endverbatim
++ *
++ * If the patch being committed was written by the person doing the commit,
++ * and is not available to reference as an upload to the issue, there is no
++ * need to include something like "fixed by me", as that will be the default
++ * assumption when a specific patch is not referenced.
++ *
++ * \subsection ReviewBoardTags Review Board (https://reviewboard.asterisk.org/)
++ *
++ * To have a commit set a review request as submitted, include the full URL
++ * to the review request. For example:
++ * \arg Review: %https://reviewboard.asterisk.org/r/95/
++ *
++ * \note The trailing slash in the review URL is required.
++ *
++ * <hr/>
++ *
++ * \section CommitMsgSvnmerge Commit Messages with svnmerge
++ *
++ * When using the svnmerge tool for merging changes between branches, use the
++ * commit %message generated by svnmerge. The '-f' option to svnmerge allows
++ * you to specify a file for svnmerge to write out a commit %message to. The
++ * '-F' option to svn commit allows you to specify a file that contains the
++ * commit %message.
++ *
++ * If you are using the expect script wrappers for svnmerge from repotools,
++ * a commit %message is automatically placed in the file '../merge.msg'.
++ *
++ * For more detailed information about working with branches and merging,
++ * see the following page on %asterisk.org:
++ * \arg http://www.asterisk.org/developers/svn-branching-merging
++ */
++
++
+
+Property changes on: include/asterisk/doxygen/commits.h
+___________________________________________________________________
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+Added: svn:eol-style
+ + native
+
+Index: include/asterisk/doxygen/licensing.h
+===================================================================
+--- a/include/asterisk/doxygen/licensing.h (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/include/asterisk/doxygen/licensing.h (.../trunk) (revision 202568)
+@@ -0,0 +1,153 @@
++/*
++ * Asterisk -- An open source telephony toolkit.
++ *
++ * Copyright (C) 1999 - 2009, Digium, Inc.
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * 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.
++ */
++
++/*!
++ * \file
++ */
++
++/*!
++ * \page Licensing Asterisk Licensing Information
++ *
++ * \section license Asterisk License
++ * \verbinclude LICENSE
++ *
++ * \section otherlicenses Licensing of 3rd Party Code
++ *
++ * This section contains a (not yet complete) list of libraries that are used
++ * by various parts of Asterisk, including related licensing information.
++ *
++ * \subsection alsa_lib ALSA Library
++ * \arg <b>Library</b>: libasound
++ * \arg <b>Website</b>: http://www.alsa-project.org
++ * \arg <b>Used by</b>: chan_alsa
++ * \arg <b>License</b>: LGPL
++ *
++ * \subsection openssl_lib OpenSSL
++ * \arg <b>Library</b>: libcrypto, libssl
++ * \arg <b>Website</b>: http://www.openssl.org
++ * \arg <b>Used by</b>: Asterisk core (TLS for manager and HTTP), res_crypto
++ * \arg <b>License</b>: Apache 2.0
++ * \arg <b>Note</b>: An exception has been granted to allow linking of
++ * OpenSSL with Asterisk.
++ *
++ * \subsection curl_lib Curl
++ * \arg <b>Library</b>: libcurl
++ * \arg <b>Website</b>: http://curl.haxx.se
++ * \arg <b>Used by</b>: func_curl, res_config_curl, res_curl
++ * \arg <b>License</b>: BSD
++ *
++ * \subsection portaudio_lib PortAudio
++ * \arg <b>Library</b>: libportaudio
++ * \arg <b>Website</b>: http://www.portaudio.com
++ * \arg <b>Used by</b>: chan_console
++ * \arg <b>License</b>: BSD
++ * \arg <b>Note</b>: Even though PortAudio is licensed under a BSD style
++ * license, PortAudio will make use of some audio interface,
++ * depending on how it was built. That audio interface may
++ * introduce additional licensing restrictions. On Linux,
++ * this would most commonly be ALSA: \ref alsa_lib.
++ *
++ * \subsection rawlist Raw list of libraries that used by any part of Asterisk
++ * \li c-client.a (app_voicemail with IMAP support)
++ * \li libSDL-1.2.so.0
++ * \li libSaClm.so.2
++ * \li libSaEvt.so.2
++ * \li libX11.so.6
++ * \li libXau.so.6
++ * \li libXdmcp.so.6
++ * \li libasound.so.2
++ * \li libc.so.6
++ * \li libcom_err.so.2
++ * \li libcrypt.so.1
++ * \li libcrypto.so.0.9.8 (chan_h323)
++ * \li libcurl.so.4
++ * \li libdirect-1.0.so.0
++ * \li libdirectfb-1.0.so.0
++ * \li libdl.so.2
++ * \li libexpat.so (chan_h323)
++ * \li libfusion-1.0.so.0
++ * \li libgcc_s.so (chan_h323)
++ * \li libgcrypt.so.11 (chan_h323)
++ * \li libglib-2.0.so.0
++ * \li libgmime-2.0.so.2
++ * \li libgmodule-2.0.so.0
++ * \li libgnutls.so.13 (chan_h323)
++ * \li libgobject-2.0.so.0
++ * \li libgpg-error.so.0 (chan_h323)
++ * \li libgssapi_krb5.so.2
++ * \li libgthread-2.0.so.0
++ * \li libidn.so.11
++ * \li libiksemel.so.3
++ * \li libisdnnet.so
++ * \li libjack.so.0
++ * \li libjpeg.so.62
++ * \li libk5crypto.so.3
++ * \li libkeyutils.so.1
++ * \li libkrb5.so.3
++ * \li libkrb5support.so.0
++ * \li liblber-2.4.so.2 (chan_h323)
++ * \li libldap_r-2.4.so.2 (chan_h323)
++ * \li libltdl.so.3
++ * \li liblua5.1.so.0
++ * \li libm.so.6
++ * \li libmISDN.so
++ * \li libnbs.so.1
++ * \li libncurses.so.5
++ * \li libnetsnmp.so.15
++ * \li libnetsnmpagent.so.15
++ * \li libnetsnmphelpers.so.15
++ * \li libnetsnmpmibs.so.15
++ * \li libnsl.so.1
++ * \li libodbc.so.1
++ * \li libogg.so.0
++ * \li libopenh323.so (chan_h323)
++ * \li libpcre.so.3
++ * \li libperl.so.5.8
++ * \li libportaudio.so.2
++ * \li libpq.so.5
++ * \li libpri.so.1.4
++ * \li libpt.so (chan_h323)
++ * \li libpthread.so.0
++ * \li libradiusclient-ng.so.2
++ * \li libresample.so.1.0
++ * \li libresolv.so.2 (chan_h323)
++ * \li librt.so.1
++ * \li libsasl2.so.2 (chan_h323)
++ * \li libselinux.so.1
++ * \li libsensors.so.3
++ * \li libspandsp.so.1
++ * \li libspeex.so.1
++ * \li libsqlite.so.0
++ * \li libsqlite3.so.0
++ * \li libss7.so.1
++ * \li libssl.so.0.9.8 (chan_h323)
++ * \li libstdc++.so (chan_h323, chan_vpb)
++ * \li libsuppserv.so
++ * \li libsybdb.so.5
++ * \li libsysfs.so.2
++ * \li libtasn1.so.3 (chan_h323)
++ * \li libtds.so.4
++ * \li libtiff.so.4
++ * \li libtonezone.so.1.0
++ * \li libvorbis.so.0
++ * \li libvorbisenc.so.2
++ * \li libvpb.a (chan_vpb)
++ * \li libwrap.so.0
++ * \li libxcb-xlib.so.0
++ * \li libxcb.so.1
++ * \li libz.so.1 (chan_h323)
++ * \li linux-vdso.so.1
++*/
+
+Property changes on: include/asterisk/doxygen/licensing.h
+___________________________________________________________________
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+Added: svn:eol-style
+ + native
+
+Index: include/asterisk/doxygen/releases.h
+===================================================================
+--- a/include/asterisk/doxygen/releases.h (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/include/asterisk/doxygen/releases.h (.../trunk) (revision 202568)
+@@ -0,0 +1,298 @@
++/*
++ * Asterisk -- An open source telephony toolkit.
++ *
++ * Copyright (C) 1999 - 2009, Digium, Inc.
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * 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.
++ */
++
++/*!
++ * \file
++ */
++
++/*!
++ * \page ReleaseStatus Asterisk Release Status
++ *
++ * @AsteriskTrunkWarning
++ *
++ * \section warranty Warranty
++ * The following warranty applies to all open source releases of Asterisk:
++ *
++ * NO WARRANTY
++ *
++ * BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
++ * FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
++ * OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
++ * PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
++ * OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
++ * TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
++ * PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
++ * REPAIR OR CORRECTION.
++
++ * IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
++ * WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
++ * REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
++ * INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
++ * OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
++ * TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
++ * YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
++ * PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
++ * POSSIBILITY OF SUCH DAMAGES.
++ *
++ * \section releasestatustypes Release Status Types
++ *
++ * Release management is a essentially an agreement between the development
++ * community and the %user community on what kind of updates can be expected
++ * for Asterisk releases, and what types of changes these updates will contain.
++ * Once these policies are established, the development community works very
++ * hard to adhere to them. However, the development community does reserve
++ * the right to make exceptions to these rules for special cases as the need
++ * arises.
++ *
++ * Asterisk releases are in various states of maintenance. The states are
++ * defined here:
++ *
++ * \arg <b>None</b> - This release series is receiving no updates whatsoever.
++ * \arg <b>Security-Only</b> - This release series is receiving updates, but
++ * only to address security issues. Security issues found and fixed in
++ * this release series will be accompanied by a published security advisory
++ * from the Asterisk project.
++ * \arg <b>Full-Support</b> - This release series is receiving updates for all
++ * types of bugs.
++ * \arg <b>Full-Development</b> - Changes in this part of Asterisk include bug
++ * fixes, as well as new %features and architectural improvements.
++ *
++ * \section AsteriskReleases Asterisk Maintenance Levels
++ *
++ * \htmlonly
++ * <table border="1">
++ * <tr>
++ * <td><b>Name</b></td>
++ * <td><b>SVN Branch</b></td>
++ * <td><b>Status</b></td>
++ * <td><b>Notes</b></td>
++ * </tr>
++ * <tr>
++ * <td>Asterisk 1.0</td>
++ * <td>/branches/1.0</td>
++ * <td>None</td>
++ * </tr>
++ * <tr>
++ * <td>Asterisk 1.2</td>
++ * <td>/branches/1.2</td>
++ * <td>Security-Only</td>
++ * </tr>
++ * <tr>
++ * <td>Asterisk 1.4</td>
++ * <td>/branches/1.4</td>
++ * <td>Full-Support</td>
++ * </tr>
++ * <tr>
++ * <td>Asterisk 1.6.0</td>
++ * <td>/branches/1.6.0</td>
++ * <td>Full-Support</td>
++ * </tr>
++ * <tr>
++ * <td>Asterisk 1.6.1</td>
++ * <td>/branches/1.6.1</td>
++ * <td>Full-Support</td>
++ * <td>Still in beta</td>
++ * </tr>
++ * <tr>
++ * <td>Asterisk trunk</td>
++ * <td>/trunk</td>
++ * <td>Full-Development</td>
++ * <td>No releases are made directly from trunk.</td>
++ * </tr>
++ * </table>
++ * \endhtmlonly
++ *
++ * For more information on how and when Asterisk releases are made, see the
++ * release policies page:
++ * \arg \ref ReleasePolicies
++ */
++
++/*!
++ * \page ReleasePolicies Asterisk Release and Commit Policies
++ *
++ * \AsteriskTrunkWarning
++ *
++ * \section releasestatus Asterisk Release Status
++ *
++ * For more information on the current status of each Asterisk release series,
++ * please see the Asterisk Release Status page:
++ *
++ * \arg \ref ReleaseStatus
++ *
++ * <hr/>
++ *
++ * \section commitmonitoring Commit Monitoring
++ *
++ * To monitor commits to Asterisk and related projects, visit
++ * <a href="http://lists.digium.com/">http://lists.digium.com</a>. The Digium
++ * mailing list server hosts a %number of mailing lists for commits.
++ *
++ * <hr/>
++ *
++ * \section ast10policy Asterisk 1.0
++ *
++ * \subsection svnbranch SVN Branch
++ *
++ * \arg /branches/1.0
++ *
++ * \subsection ast10releases Release and Commit Policy
++ * No more releases of Asterisk 1.0 will be made for any reason.
++ *
++ * No commits should be made to the Asterisk 1.0 branch.
++ *
++ * <hr/>
++ *
++ * \section ast12policy Asterisk 1.2
++ *
++ * \subsection svnbranch SVN Branch
++ *
++ * \arg /branches/1.2
++ *
++ * \subsection ast12releases Release and Commit Policy
++ *
++ * There will be no more scheduled releases of Asterisk 1.2.
++ *
++ * Commits to the Asterisk 1.2 branch should only address security issues or
++ * regressions introduced by previous security fixes. For a security issue, the
++ * commit should be accompanied by an
++ * <a href="http://downloads.asterisk.org/pub/security/">Asterisk Security Advisory</a>
++ * and an immediate release. When a commit goes in to fix a regression, the previous
++ * security advisory that is related to the change that introduced the bug should get
++ * updated to indicate that there is an updated version of the fix. A release should
++ * be made immediately for these regression fixes, as well.
++ *
++ * \subsection ast12releasenumbers Release Numbering
++ *
++ * - 1.2.X - a release that contains new security fixes
++ * - 1.2.X.Y - a release that contains fixes to the security patches released in
++ * version 1.2.X
++ *
++ * <hr/>
++ *
++ * \section ast14policy Asterisk 1.4
++ *
++ * \subsection svnbranch SVN Branch
++ *
++ * \arg /branches/1.4
++ *
++ * \subsection ast14releases Release and Commit Policy
++ *
++ * Asterisk 1.4 is receiving regular bug fix release updates. An attempt is made to
++ * make releases of every four to six weeks. Since this release series is receiving
++ * changes for all types of bugs, the number of changes in a single release can be
++ * significant. 1.4.X releases go through a release candidate testing cycle to help
++ * catch any regressions that may have been introduced.
++ *
++ * Commits to Asterisk 1.4 must be to address bugs only. No new %features should be
++ * introduced into Asterisk 1.4 to reduce the %number of changes to this established
++ * release series. The only exceptions to this %rule are for cases where something
++ * that may be considered a feature is needed to address a bug or security issue.
++ *
++ * \subsection ast14releasenumbers Release Numbering
++ *
++ * - 1.4.X - a release that contains new bug fixes to the 1.4 release series
++ * - 1.4.X.Y - a release that contains very few changes on top of 1.4.X. This
++ * may be for a security patch, or for a regression introduced in 1.4.X.
++ *
++ * <hr/>
++ *
++ * \section ast16policy Asterisk 1.6
++ *
++ * \subsection svnbranch SVN Branch
++ *
++ * \arg /branches/1.6.*
++ *
++ * \subsection ast16releases Release and Commit Policy
++ *
++ * Asterisk 1.6 is managed in a different way than previous Asterisk release series.
++ * From a high level, it was inspired by the release model used for Linux 2.6.
++ * The intended time frame for 1.6.X releases is every 2 or 3 months. Each 1.6.X
++ * release gets its own branch. The 1.6.X branches are branches off of trunk.
++ * Once the branch is created, it only receives bug fixes. Each 1.6.X release goes
++ * through a beta and release candidate testing cycle.
++ *
++ * After a 1.6.X release is published, it will be maintained until 1.6.[X + 3] is
++ * released. While a 1.6.X release branch is still maintained, it will receive only
++ * bug fixes. Periodic maintenance releases will be made and labeled as 1.6.X.Y.
++ * 1.6.X.Y releases should go through a release candidate test cycle before being
++ * published.
++ *
++ * For now, all previous 1.6 release will be maintained for security issues. Once
++ * we have more 1.6 releases to deal with, this part of the policy will likely change.
++ *
++ * For some history on the motivations for Asterisk 1.6 release management, see the
++ * first two sections of this
++ * <a href="http://lists.digium.com/pipermail/asterisk-dev/2007-October/030083.html">mailing list post</a>.
++ *
++ * \subsection ast16releasenumbers Release Numbering
++ *
++ * - 1.6.X - a release that includes new functionality
++ * - 1.6.X.Y - a release that contains fixes for bugs or security issues identified
++ * in the 1.6.X release series.
++ *
++ * <hr/>
++ *
++ * \section asttrunk Asterisk Trunk
++ *
++ * \subsection svnbranch SVN Branch
++ *
++ * \arg /trunk
++ *
++ * \subsection asttrunkpolicy Release and Commit Policy
++ *
++ * No releases are ever made directly from Asterisk trunk.
++ *
++ * Asterisk trunk is used as the main development area for upcoming Asterisk 1.6
++ * releases. Commits to Asterisk trunk are not limited. They can be bug fixes,
++ * new %features, and architectural improvements. However, for larger sets
++ * of changes, developers should work with the Asterisk project leaders to
++ * schedule them for inclusion. Care is taken not to include too many invasive
++ * sets of changes for each new Asterisk 1.6 release.
++ *
++ * No changes should go into Asterisk trunk that are not ready to go into a
++ * release. While the upcoming release will go through a beta and release
++ * candidate test cycle, code should not be in trunk until the code has been
++ * tested and reviewed such that there is reasonable belief that the code
++ * is ready to go.
++ *
++ * <hr/>
++ *
++ * \section astteam Asterisk Team Branches
++ *
++ * \subsection svnbranch SVN Branch
++ *
++ * \arg /team/&lt;developername&gt;
++ *
++ * \subsection astteampolicy Release and Commit Policy
++ *
++ * The Asterisk subversion repository has a special directory called "team"
++ * where developers can make their own personal development branches. This is
++ * where new %features, bug fixes, and architectural improvements are developed
++ * while they are in %progress.
++ *
++ * Just about anything goes as far as commits to this area goes. However,
++ * developers should keep in mind that anything committed here, as well as
++ * anywhere else on Digium's SVN server, falls under the contributor license
++ * agreement.
++ *
++ * In addition to each developer having their own space for working on projects,
++ * there is also a team/group folder where %group development efforts take place.
++ *
++ * Finally, in each developer folder, there is a folder called "private". This
++ * is where developers can create branches for working on things that they are
++ * not ready for the whole world to see.
++ */
+
+Property changes on: include/asterisk/doxygen/releases.h
+___________________________________________________________________
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+Added: svn:eol-style
+ + native
+
+Index: include/asterisk/smdi.h
+===================================================================
+--- a/include/asterisk/smdi.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/smdi.h (.../trunk) (revision 202568)
+@@ -85,8 +85,9 @@
+ */
+ struct ast_smdi_interface;
+
+-AST_OPTIONAL_API(void, ast_smdi_interface_unref, (struct ast_smdi_interface
+- *iface), { return; });
++AST_OPTIONAL_API(void, ast_smdi_interface_unref,
++ (struct ast_smdi_interface *iface),
++ { return; });
+
+ /*!
+ * \brief Get the next SMDI message from the queue.
+@@ -98,8 +99,9 @@
+ *
+ * \return the next SMDI message, or NULL if there were no pending messages.
+ */
+-AST_OPTIONAL_API(struct ast_smdi_md_message *, ast_smdi_md_message_pop, (struct
+- ast_smdi_interface *iface), { return NULL; });
++AST_OPTIONAL_API(struct ast_smdi_md_message *, ast_smdi_md_message_pop,
++ (struct ast_smdi_interface *iface),
++ { return NULL; });
+
+ /*!
+ * \brief Get the next SMDI message from the queue.
+@@ -114,7 +116,8 @@
+ * the timeout has expired.
+ */
+ AST_OPTIONAL_API(struct ast_smdi_md_message *, ast_smdi_md_message_wait,
+- (struct ast_smdi_interface *iface, int timeout), { return NULL; });
++ (struct ast_smdi_interface *iface, int timeout),
++ { return NULL; });
+
+ /*!
+ * \brief Put an SMDI message back in the front of the queue.
+@@ -125,8 +128,9 @@
+ * should be used if a message was popped but is not going to be processed for
+ * some reason, and the message needs to be returned to the queue.
+ */
+-AST_OPTIONAL_API(void, ast_smdi_md_message_putback, (struct ast_smdi_interface
+- *iface, struct ast_smdi_md_message *msg), { return; });
++AST_OPTIONAL_API(void, ast_smdi_md_message_putback,
++ (struct ast_smdi_interface *iface, struct ast_smdi_md_message *msg),
++ { return; });
+
+ /*!
+ * \brief Get the next SMDI message from the queue.
+@@ -139,7 +143,8 @@
+ * \return the next SMDI message, or NULL if there were no pending messages.
+ */
+ AST_OPTIONAL_API(struct ast_smdi_mwi_message *, ast_smdi_mwi_message_pop,
+- (struct ast_smdi_interface *iface), { return NULL; });
++ (struct ast_smdi_interface *iface),
++ { return NULL; });
+
+ /*!
+ * \brief Get the next SMDI message from the queue.
+@@ -154,11 +159,13 @@
+ * the timeout has expired.
+ */
+ AST_OPTIONAL_API(struct ast_smdi_mwi_message *, ast_smdi_mwi_message_wait,
+- (struct ast_smdi_interface *iface, int timeout), { return NULL; });
+-AST_OPTIONAL_API(struct ast_smdi_mwi_message *,
+- ast_smdi_mwi_message_wait_station, (struct ast_smdi_interface *iface, int
+- timeout, const char *station), { return NULL; });
++ (struct ast_smdi_interface *iface, int timeout),
++ { return NULL; });
+
++AST_OPTIONAL_API(struct ast_smdi_mwi_message *, ast_smdi_mwi_message_wait_station,
++ (struct ast_smdi_interface *iface, int timeout, const char *station),
++ { return NULL; });
++
+ /*!
+ * \brief Put an SMDI message back in the front of the queue.
+ * \param iface a pointer to the interface to use.
+@@ -168,8 +175,9 @@
+ * should be used if a message was popped but is not going to be processed for
+ * some reason, and the message needs to be returned to the queue.
+ */
+-AST_OPTIONAL_API(void, ast_smdi_mwi_message_putback, (struct ast_smdi_interface
+- *iface, struct ast_smdi_mwi_message *msg), { return; });
++AST_OPTIONAL_API(void, ast_smdi_mwi_message_putback,
++ (struct ast_smdi_interface *iface, struct ast_smdi_mwi_message *msg),
++ { return; });
+
+ /*!
+ * \brief Find an SMDI interface with the specified name.
+@@ -180,30 +188,35 @@
+ * #ASTOBJ_UNREF(iface, ast_smdi_interface_destroy).
+ */
+ AST_OPTIONAL_API(struct ast_smdi_interface *, ast_smdi_interface_find,
+- (const char *iface_name), { return NULL; });
++ (const char *iface_name),
++ { return NULL; });
+
+ /*!
+ * \brief Set the MWI indicator for a mailbox.
+ * \param iface the interface to use.
+ * \param mailbox the mailbox to use.
+ */
+-AST_OPTIONAL_API(int, ast_smdi_mwi_set, (struct ast_smdi_interface *iface,
+- const char *mailbox), { return -1; });
++AST_OPTIONAL_API(int, ast_smdi_mwi_set,
++ (struct ast_smdi_interface *iface, const char *mailbox),
++ { return -1; });
+
+ /*!
+ * \brief Unset the MWI indicator for a mailbox.
+ * \param iface the interface to use.
+ * \param mailbox the mailbox to use.
+ */
+-AST_OPTIONAL_API(int, ast_smdi_mwi_unset, (struct ast_smdi_interface *iface,
+- const char *mailbox), { return -1; });
++AST_OPTIONAL_API(int, ast_smdi_mwi_unset,
++ (struct ast_smdi_interface *iface, const char *mailbox),
++ { return -1; });
+
+ /*! \brief ast_smdi_md_message destructor. */
+ AST_OPTIONAL_API(void, ast_smdi_md_message_destroy,
+- (struct ast_smdi_md_message *msg), { return; });
++ (struct ast_smdi_md_message *msg),
++ { return; });
+
+ /*! \brief ast_smdi_mwi_message destructor. */
+-AST_OPTIONAL_API(void, ast_smdi_mwi_message_destroy, (struct
+- ast_smdi_mwi_message *msg), { return; });
++AST_OPTIONAL_API(void, ast_smdi_mwi_message_destroy,
++ (struct ast_smdi_mwi_message *msg),
++ { return; });
+
+ #endif /* !ASTERISK_SMDI_H */
+Index: include/asterisk/speech.h
+===================================================================
+--- a/include/asterisk/speech.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/speech.h (.../trunk) (revision 202568)
+@@ -78,13 +78,13 @@
+ /*! Destroy any data set on the speech structure by the engine */
+ int (*destroy)(struct ast_speech *speech);
+ /*! Load a local grammar on the speech structure */
+- int (*load)(struct ast_speech *speech, char *grammar_name, char *grammar);
++ int (*load)(struct ast_speech *speech, const char *grammar_name, const char *grammar);
+ /*! Unload a local grammar */
+- int (*unload)(struct ast_speech *speech, char *grammar_name);
++ int (*unload)(struct ast_speech *speech, const char *grammar_name);
+ /*! Activate a loaded grammar */
+- int (*activate)(struct ast_speech *speech, char *grammar_name);
++ int (*activate)(struct ast_speech *speech, const char *grammar_name);
+ /*! Deactivate a loaded grammar */
+- int (*deactivate)(struct ast_speech *speech, char *grammar_name);
++ int (*deactivate)(struct ast_speech *speech, const char *grammar_name);
+ /*! Write audio to the speech engine */
+ int (*write)(struct ast_speech *speech, void *data, int len);
+ /*! Signal DTMF was received */
+@@ -92,7 +92,7 @@
+ /*! Prepare engine to accept audio */
+ int (*start)(struct ast_speech *speech);
+ /*! Change an engine specific setting */
+- int (*change)(struct ast_speech *speech, char *name, const char *value);
++ int (*change)(struct ast_speech *speech, const char *name, const char *value);
+ /*! Change the type of results we want back */
+ int (*change_results_type)(struct ast_speech *speech, enum ast_speech_results_type results_type);
+ /*! Try to get results */
+@@ -117,13 +117,13 @@
+ };
+
+ /*! \brief Activate a grammar on a speech structure */
+-int ast_speech_grammar_activate(struct ast_speech *speech, char *grammar_name);
++int ast_speech_grammar_activate(struct ast_speech *speech, const char *grammar_name);
+ /*! \brief Deactivate a grammar on a speech structure */
+-int ast_speech_grammar_deactivate(struct ast_speech *speech, char *grammar_name);
++int ast_speech_grammar_deactivate(struct ast_speech *speech, const char *grammar_name);
+ /*! \brief Load a grammar on a speech structure (not globally) */
+-int ast_speech_grammar_load(struct ast_speech *speech, char *grammar_name, char *grammar);
++int ast_speech_grammar_load(struct ast_speech *speech, const char *grammar_name, const char *grammar);
+ /*! \brief Unload a grammar */
+-int ast_speech_grammar_unload(struct ast_speech *speech, char *grammar_name);
++int ast_speech_grammar_unload(struct ast_speech *speech, const char *grammar_name);
+ /*! \brief Get speech recognition results */
+ struct ast_speech_result *ast_speech_results_get(struct ast_speech *speech);
+ /*! \brief Free a set of results */
+@@ -131,7 +131,7 @@
+ /*! \brief Indicate to the speech engine that audio is now going to start being written */
+ void ast_speech_start(struct ast_speech *speech);
+ /*! \brief Create a new speech structure */
+-struct ast_speech *ast_speech_new(char *engine_name, int formats);
++struct ast_speech *ast_speech_new(const char *engine_name, int formats);
+ /*! \brief Destroy a speech structure */
+ int ast_speech_destroy(struct ast_speech *speech);
+ /*! \brief Write audio to the speech engine */
+@@ -139,7 +139,7 @@
+ /*! \brief Signal to the engine that DTMF was received */
+ int ast_speech_dtmf(struct ast_speech *speech, const char *dtmf);
+ /*! \brief Change an engine specific attribute */
+-int ast_speech_change(struct ast_speech *speech, char *name, const char *value);
++int ast_speech_change(struct ast_speech *speech, const char *name, const char *value);
+ /*! \brief Change the type of results we want */
+ int ast_speech_change_results_type(struct ast_speech *speech, enum ast_speech_results_type results_type);
+ /*! \brief Change state of a speech structure */
+@@ -147,7 +147,7 @@
+ /*! \brief Register a speech recognition engine */
+ int ast_speech_register(struct ast_speech_engine *engine);
+ /*! \brief Unregister a speech recognition engine */
+-int ast_speech_unregister(char *engine_name);
++int ast_speech_unregister(const char *engine_name);
+
+ #if defined(__cplusplus) || defined(c_plusplus)
+ }
+Index: include/asterisk/abstract_jb.h
+===================================================================
+--- a/include/asterisk/abstract_jb.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/abstract_jb.h (.../trunk) (revision 202568)
+@@ -84,7 +84,7 @@
+ /*! \brief Jitterbuffer configuration. */
+ struct ast_jb_conf conf;
+ /*! \brief Jitterbuffer implementation to be used. */
+- struct ast_jb_impl *impl;
++ const struct ast_jb_impl *impl;
+ /*! \brief Jitterbuffer object, passed to the implementation. */
+ void *jbobj;
+ /*! \brief The time the jitterbuffer was created. */
+Index: include/asterisk/event.h
+===================================================================
+--- a/include/asterisk/event.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/event.h (.../trunk) (revision 202568)
+@@ -157,6 +157,20 @@
+ enum ast_event_ie_type ie_type, uint32_t uint);
+
+ /*!
++ * \brief Append a bitflags parameter to a subscription
++ *
++ * \param sub the dynamic subscription allocated with ast_event_subscribe_new()
++ * \param ie_type the information element type for the parameter
++ * \param flags the flags that must be present in the event to match this subscription
++ *
++ * \retval 0 success
++ * \retval non-zero failure
++ * \since 1.6.3
++ */
++int ast_event_sub_append_ie_bitflags(struct ast_event_sub *sub,
++ enum ast_event_ie_type ie_type, uint32_t flags);
++
++/*!
+ * \brief Append a string parameter to a subscription
+ *
+ * \param sub the dynamic subscription allocated with ast_event_subscribe_new()
+@@ -447,6 +461,24 @@
+ uint32_t data);
+
+ /*!
++ * \brief Append an information element that has a bitflags payload
++ *
++ * \param event the event that the IE will be appended to
++ * \param ie_type the type of IE to append
++ * \param flags the flags that are the payload of the IE
++ *
++ * \retval 0 success
++ * \retval -1 failure
++ * \since 1.6.3
++ *
++ * The pointer to the event will get updated with the new location for the event
++ * that now contains the appended information element. If the re-allocation of
++ * the memory for this event fails, it will be set to NULL.
++ */
++int ast_event_append_ie_bitflags(struct ast_event **event, enum ast_event_ie_type ie_type,
++ uint32_t bitflags);
++
++/*!
+ * \brief Append an information element that has a raw payload
+ *
+ * \param event the event that the IE will be appended to
+@@ -477,6 +509,18 @@
+ uint32_t ast_event_get_ie_uint(const struct ast_event *event, enum ast_event_ie_type ie_type);
+
+ /*!
++ * \brief Get the value of an information element that has a bitflags payload
++ *
++ * \param event The event to get the IE from
++ * \param ie_type the type of information element to retrieve
++ *
++ * \return This returns the payload of the information element with the given type.
++ * However, an IE with a payload of 0, and the case where no IE is found
++ * yield the same return value.
++ */
++uint32_t ast_event_get_ie_bitflags(const struct ast_event *event, enum ast_event_ie_type ie_type);
++
++/*!
+ * \brief Get the value of an information element that has a string payload
+ *
+ * \param event The event to get the IE from
+@@ -615,7 +659,7 @@
+ enum ast_event_ie_type ast_event_iterator_get_ie_type(struct ast_event_iterator *iterator);
+
+ /*!
+- * \brief Get the value of the current IE in the ierator as an integer payload
++ * \brief Get the value of the current IE in the iterator as an integer payload
+ *
+ * \param iterator The iterator instance
+ *
+@@ -624,6 +668,15 @@
+ uint32_t ast_event_iterator_get_ie_uint(struct ast_event_iterator *iterator);
+
+ /*!
++ * \brief Get the value of the current IE in the iterator as a bitflags payload
++ *
++ * \param iterator The iterator instance
++ *
++ * \return This returns the payload of the information element as bitflags.
++ */
++uint32_t ast_event_iterator_get_ie_bitflags(struct ast_event_iterator *iterator);
++
++/*!
+ * \brief Get the value of the current IE in the iterator as a string payload
+ *
+ * \param iterator The iterator instance
+Index: include/asterisk/event_defs.h
+===================================================================
+--- a/include/asterisk/event_defs.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/event_defs.h (.../trunk) (revision 202568)
+@@ -137,6 +137,8 @@
+ AST_EVENT_IE_PLTYPE_STR,
+ /*! Raw data, compared with memcmp */
+ AST_EVENT_IE_PLTYPE_RAW,
++ /*! Bit flags (unsigned integer, compared using boolean logic) */
++ AST_EVENT_IE_PLTYPE_BITFLAGS,
+ };
+
+ /*!
+Index: include/asterisk/compat.h
+===================================================================
+--- a/include/asterisk/compat.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/compat.h (.../trunk) (revision 202568)
+@@ -187,10 +187,10 @@
+ #define GLOB_ABORTED GLOB_ABEND
+ #endif
+ #include <glob.h>
+-#ifdef SOLARIS
++#if !defined(HAVE_GLOB_NOMAGIC) || !defined(HAVE_GLOB_BRACE)
+ #define MY_GLOB_FLAGS GLOB_NOCHECK
+ #else
+-#define MY_GLOB_FLAGS (GLOB_NOMAGIC|GLOB_BRACE)
++#define MY_GLOB_FLAGS (GLOB_NOMAGIC | GLOB_BRACE)
+ #endif
+
+ #endif
+Index: include/asterisk/ast_expr.h
+===================================================================
+--- a/include/asterisk/ast_expr.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/ast_expr.h (.../trunk) (revision 202568)
+@@ -31,8 +31,24 @@
+ extern "C" {
+ #endif
+
++/*!\brief Evaluate the given expression
++ * \param expr An expression
++ * \param buf Result buffer
++ * \param length Size of the result buffer, in bytes
++ * \param chan Channel to use for evaluating included dialplan functions, if any
++ * \return Length of the result string, in bytes
++ */
+ int ast_expr(char *expr, char *buf, int length, struct ast_channel *chan);
+
++/*!\brief Evaluate the given expression
++ * \param str Dynamic result buffer
++ * \param maxlen <0 if the size of the buffer should remain constant, >0 if the size of the buffer should expand to that many bytes, maximum, or 0 for unlimited expansion of the result buffer
++ * \param chan Channel to use for evaluating included dialplan functions, if any
++ * \param expr An expression
++ * \return Length of the result string, in bytes
++ */
++int ast_str_expr(struct ast_str **str, ssize_t maxlen, struct ast_channel *chan, char *expr);
++
+ #if defined(__cplusplus) || defined(c_plusplus)
+ }
+ #endif
+Index: include/asterisk/module.h
+===================================================================
+--- a/include/asterisk/module.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/module.h (.../trunk) (revision 202568)
+@@ -58,10 +58,11 @@
+ };
+
+ enum ast_module_load_result {
+- AST_MODULE_LOAD_SUCCESS = 0, /*!< Module loaded and configured */
+- AST_MODULE_LOAD_DECLINE = 1, /*!< Module is not configured */
+- AST_MODULE_LOAD_SKIP = 2, /*!< Module was skipped for some reason */
+- AST_MODULE_LOAD_FAILURE = -1, /*!< Module could not be loaded properly */
++ AST_MODULE_LOAD_SUCCESS = 0, /*!< Module loaded and configured */
++ AST_MODULE_LOAD_DECLINE = 1, /*!< Module is not configured */
++ AST_MODULE_LOAD_SKIP = 2, /*!< Module was skipped for some reason */
++ AST_MODULE_LOAD_PRIORITY = 3, /*!< Module is not loaded yet, but is added to prioity heap */
++ AST_MODULE_LOAD_FAILURE = -1, /*!< Module could not be loaded properly */
+ };
+
+ /*!
+@@ -423,7 +424,7 @@
+ * \retval 0 success
+ * \retval -1 failure.
+ */
+-int ast_register_application2(const char *app, int (*execute)(struct ast_channel *, void *),
++int ast_register_application2(const char *app, int (*execute)(struct ast_channel *, const char *),
+ const char *synopsis, const char *description, void *mod);
+
+ /*!
+Index: include/asterisk/monitor.h
+===================================================================
+--- a/include/asterisk/monitor.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/monitor.h (.../trunk) (revision 202568)
+@@ -51,27 +51,34 @@
+ };
+
+ /* Start monitoring a channel */
+-AST_OPTIONAL_API(int, ast_monitor_start, (struct ast_channel *chan, const char
+- *format_spec, const char *fname_base, int need_lock, int stream_action),
+- { return -1; });
++AST_OPTIONAL_API(int, ast_monitor_start,
++ (struct ast_channel *chan, const char *format_spec,
++ const char *fname_base, int need_lock, int stream_action),
++ { return -1; });
+
+ /* Stop monitoring a channel */
+-AST_OPTIONAL_API(int, ast_monitor_stop, (struct ast_channel *chan, int
+- need_lock), { return -1; });
++AST_OPTIONAL_API(int, ast_monitor_stop,
++ (struct ast_channel *chan, int need_lock),
++ { return -1; });
+
+ /* Change monitoring filename of a channel */
+-AST_OPTIONAL_API(int, ast_monitor_change_fname, (struct ast_channel *chan,
+- const char *fname_base, int need_lock), { return -1; });
++AST_OPTIONAL_API(int, ast_monitor_change_fname,
++ (struct ast_channel *chan, const char *fname_base,
++ int need_lock),
++ { return -1; });
+
+-AST_OPTIONAL_API(void, ast_monitor_setjoinfiles, (struct ast_channel *chan,
+- int turnon), { return; });
++AST_OPTIONAL_API(void, ast_monitor_setjoinfiles,
++ (struct ast_channel *chan, int turnon),
++ { return; });
+
+ /* Pause monitoring of a channel */
+-AST_OPTIONAL_API(int, ast_monitor_pause, (struct ast_channel *chan),
+- { return -1; });
++AST_OPTIONAL_API(int, ast_monitor_pause,
++ (struct ast_channel *chan),
++ { return -1; });
+
+ /* Unpause monitoring of a channel */
+-AST_OPTIONAL_API(int, ast_monitor_unpause, (struct ast_channel *chan),
+- { return -1; });
++AST_OPTIONAL_API(int, ast_monitor_unpause,
++ (struct ast_channel *chan),
++ { return -1; });
+
+ #endif /* _ASTERISK_MONITOR_H */
+Index: include/asterisk/frame.h
+===================================================================
+--- a/include/asterisk/frame.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/frame.h (.../trunk) (revision 202568)
+@@ -39,54 +39,56 @@
+ char framing[32];
+ };
+
+-/*! \page Def_Frame AST Multimedia and signalling frames
+- \section Def_AstFrame What is an ast_frame ?
+- A frame of data read used to communicate between
+- between channels and applications.
+- Frames are divided into frame types and subclasses.
++/*!
++ * \page Def_Frame AST Multimedia and signalling frames
++ * \section Def_AstFrame What is an ast_frame ?
++ * A frame of data read used to communicate between
++ * between channels and applications.
++ * Frames are divided into frame types and subclasses.
++ *
++ * \par Frame types
++ * \arg \b VOICE: Voice data, subclass is codec (AST_FORMAT_*)
++ * \arg \b VIDEO: Video data, subclass is codec (AST_FORMAT_*)
++ * \arg \b DTMF: A DTMF digit, subclass is the digit
++ * \arg \b IMAGE: Image transport, mostly used in IAX
++ * \arg \b TEXT: Text messages and character by character (real time text)
++ * \arg \b HTML: URL's and web pages
++ * \arg \b MODEM: Modulated data encodings, such as T.38 and V.150
++ * \arg \b IAX: Private frame type for the IAX protocol
++ * \arg \b CNG: Comfort noice frames
++ * \arg \b CONTROL:A control frame, subclass defined as AST_CONTROL_
++ * \arg \b NULL: Empty, useless frame
++ *
++ * \par Files
++ * \arg frame.h Definitions
++ * \arg frame.c Function library
++ * \arg \ref Def_Channel Asterisk channels
++ * \section Def_ControlFrame Control Frames
++ * Control frames send signalling information between channels
++ * and devices. They are prefixed with AST_CONTROL_, like AST_CONTROL_FRAME_HANGUP
++ * \arg \b HANGUP The other end has hungup
++ * \arg \b RING Local ring
++ * \arg \b RINGING The other end is ringing
++ * \arg \b ANSWER The other end has answered
++ * \arg \b BUSY Remote end is busy
++ * \arg \b TAKEOFFHOOK Make it go off hook (what's "it" ? )
++ * \arg \b OFFHOOK Line is off hook
++ * \arg \b CONGESTION Congestion (circuit is busy, not available)
++ * \arg \b FLASH Other end sends flash hook
++ * \arg \b WINK Other end sends wink
++ * \arg \b OPTION Send low-level option
++ * \arg \b RADIO_KEY Key radio (see app_rpt.c)
++ * \arg \b RADIO_UNKEY Un-key radio (see app_rpt.c)
++ * \arg \b PROGRESS Other end indicates call progress
++ * \arg \b PROCEEDING Indicates proceeding
++ * \arg \b HOLD Call is placed on hold
++ * \arg \b UNHOLD Call is back from hold
++ * \arg \b VIDUPDATE Video update requested
++ * \arg \b SRCUPDATE The source of media has changed
++ * \arg \b CONNECTED_LINE Connected line has changed
++ * \arg \b REDIRECTING Call redirecting information has changed.
++ */
+
+- \par Frame types
+- \arg \b VOICE: Voice data, subclass is codec (AST_FORMAT_*)
+- \arg \b VIDEO: Video data, subclass is codec (AST_FORMAT_*)
+- \arg \b DTMF: A DTMF digit, subclass is the digit
+- \arg \b IMAGE: Image transport, mostly used in IAX
+- \arg \b TEXT: Text messages and character by character (real time text)
+- \arg \b HTML: URL's and web pages
+- \arg \b MODEM: Modulated data encodings, such as T.38 and V.150
+- \arg \b IAX: Private frame type for the IAX protocol
+- \arg \b CNG: Comfort noice frames
+- \arg \b CONTROL: A control frame, subclass defined as AST_CONTROL_
+- \arg \b NULL: Empty, useless frame
+-
+- \par Files
+- \arg frame.h Definitions
+- \arg frame.c Function library
+- \arg \ref Def_Channel Asterisk channels
+- \section Def_ControlFrame Control Frames
+- Control frames send signalling information between channels
+- and devices. They are prefixed with AST_CONTROL_, like AST_CONTROL_FRAME_HANGUP
+- \arg \b HANGUP The other end has hungup
+- \arg \b RING Local ring
+- \arg \b RINGING The other end is ringing
+- \arg \b ANSWER The other end has answered
+- \arg \b BUSY Remote end is busy
+- \arg \b TAKEOFFHOOK Make it go off hook (what's "it" ? )
+- \arg \b OFFHOOK Line is off hook
+- \arg \b CONGESTION Congestion (circuit is busy, not available)
+- \arg \b FLASH Other end sends flash hook
+- \arg \b WINK Other end sends wink
+- \arg \b OPTION Send low-level option
+- \arg \b RADIO_KEY Key radio (see app_rpt.c)
+- \arg \b RADIO_UNKEY Un-key radio (see app_rpt.c)
+- \arg \b PROGRESS Other end indicates call progress
+- \arg \b PROCEEDING Indicates proceeding
+- \arg \b HOLD Call is placed on hold
+- \arg \b UNHOLD Call is back from hold
+- \arg \b VIDUPDATE Video update requested
+- \arg \b SRCUPDATE The source of media has changed
+-
+-*/
+-
+ /*!
+ * \brief Frame types
+ *
+@@ -319,6 +321,9 @@
+ AST_CONTROL_VIDUPDATE = 18, /*!< Indicate video frame update */
+ AST_CONTROL_T38 = 19, /*!< T38 state change request/notification */
+ AST_CONTROL_SRCUPDATE = 20, /*!< Indicate source of media has changed */
++ AST_CONTROL_TRANSFER = 21, /*!< Indicate status of a transfer request */
++ AST_CONTROL_CONNECTED_LINE = 22,/*!< Indicate connected line has changed */
++ AST_CONTROL_REDIRECTING = 23 /*!< Indicate redirecting id has changed */
+ };
+
+ enum ast_control_t38 {
+@@ -329,6 +334,11 @@
+ AST_T38_REFUSED /*!< T38 refused for some reason (usually rejected by remote end) */
+ };
+
++enum ast_control_transfer {
++ AST_TRANSFER_SUCCESS = 0, /*!< Transfer request on the channel worked */
++ AST_TRANSFER_FAILED, /*!< Transfer request on the channel failed */
++};
++
+ #define AST_SMOOTHER_FLAG_G729 (1 << 0)
+ #define AST_SMOOTHER_FLAG_BE (1 << 1)
+
+@@ -381,6 +391,21 @@
+ */
+ #define AST_OPTION_T38_STATE 10
+
++/*! Request that the channel driver deliver frames in a specific format */
++#define AST_OPTION_FORMAT_READ 11
++
++/*! Request that the channel driver be prepared to accept frames in a specific format */
++#define AST_OPTION_FORMAT_WRITE 12
++
++/*! Request that the channel driver make two channels of the same tech type compatible if possible */
++#define AST_OPTION_MAKE_COMPATIBLE 13
++
++/*! Get or set the digit detection state of the channel */
++#define AST_OPTION_DIGIT_DETECT 14
++
++/*! Get or set the fax tone detection state of the channel */
++#define AST_OPTION_FAX_DETECT 15
++
+ struct oprmode {
+ struct ast_channel *peer;
+ int mode;
+@@ -430,9 +455,9 @@
+ #endif
+
+ /*!
+- * \brief Frees a frame
++ * \brief Frees a frame or list of frames
+ *
+- * \param fr Frame to free
++ * \param fr Frame to free, or head of list to free
+ * \param cache Whether to consider this frame for frame caching
+ */
+ void ast_frame_free(struct ast_frame *fr, int cache);
+@@ -446,6 +471,11 @@
+ * data malloc'd. If you need to store frames, say for queueing, then
+ * you should call this function.
+ * \return Returns a frame on success, NULL on error
++ * \note This function may modify the frame passed to it, so you must
++ * not assume the frame will be intact after the isolated frame has
++ * been produced. In other words, calling this function on a frame
++ * should be the last operation you do with that frame before freeing
++ * it (or exiting the block, if the frame is on the stack.)
+ */
+ struct ast_frame *ast_frisolate(struct ast_frame *fr);
+
+Index: include/asterisk/autochan.h
+===================================================================
+--- a/include/asterisk/autochan.h (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/include/asterisk/autochan.h (.../trunk) (revision 202568)
+@@ -0,0 +1,112 @@
++/*
++ * Asterisk -- An open source telephony toolkit.
++ *
++ * Copyright (C) 2009, Digium, Inc.
++ *
++ * Mark Michelson <mmichelson@digium.com>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * 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.
++ */
++
++/*!
++ * \file
++ * \brief "smart" channels that update automatically if a channel is masqueraded
++ *
++ * \author Mark Michelson <mmichelson@digium.com>
++ */
++
++#include "asterisk.h"
++#include "asterisk/linkedlists.h"
++
++#ifndef _ASTERISK_AUTOCHAN_H
++#define _ASTERISK_AUTOCHAN_H
++
++struct ast_autochan {
++ struct ast_channel *chan;
++ AST_LIST_ENTRY(ast_autochan) list;
++};
++
++/*!
++ * \par Just what the $!@# is an autochan?
++ *
++ * An ast_autochan is a structure which contains an ast_channel. The pointer
++ * inside an autochan has the ability to update itself if the channel it points
++ * to is masqueraded into a different channel.
++ *
++ * This has a great benefit for any application or service which creates a thread
++ * outside of the channel's main operating thread which keeps a pointer to said
++ * channel. when a masquerade occurs on the channel, the autochan's chan pointer
++ * will automatically update to point to the new channel.
++ *
++ * Some rules for autochans
++ *
++ * 1. If you are going to use an autochan, then be sure to always refer to the
++ * channel using the chan pointer inside the autochan if possible, since this is
++ * the pointer that will be updated during a masquerade.
++ *
++ * 2. If you are going to save off a pointer to the autochan's chan, then be sure
++ * to save off the pointer using ast_channel_ref and to unref the channel when you
++ * are finished with the pointer. If you do not do this and a masquerade occurs on
++ * the channel, then it is possible that your saved pointer will become invalid.
++ */
++
++/*!
++ * \brief set up a new ast_autochan structure
++ *
++ * \details
++ * Allocates and initializes an ast_autochan, sets the
++ * autochan's chan pointer to point to the chan parameter, and
++ * adds the autochan to the global list of autochans. The newly-
++ * created autochan is returned to the caller. This function will
++ * cause the refcount of chan to increase by 1.
++ *
++ * \param chan The channel our new autochan will point to
++ *
++ * \note autochans must be freed using ast_autochan_destroy
++ *
++ * \retval NULL Failure
++ * \retval non-NULL success
++ */
++struct ast_autochan *ast_autochan_setup(struct ast_channel *chan);
++
++/*!
++ * \brief destroy an ast_autochan structure
++ *
++ * \details
++ * Removes the passed-in autochan from the list of autochans and
++ * unrefs the channel that is pointed to. Also frees the autochan
++ * struct itself. This function will unref the channel reference
++ * which was made in ast_autochan_setup
++ *
++ * \param autochan The autochan that you wish to destroy
++ *
++ * \retval void
++ */
++void ast_autochan_destroy(struct ast_autochan *autochan);
++
++/*!
++ * \brief Switch what channel autochans point to
++ *
++ * \details
++ * Traverses the list of autochans. All autochans which point to
++ * old_chan will be updated to point to new_chan instead. Currently
++ * this is only called from ast_do_masquerade in channel.c.
++ *
++ * \pre Both channels must be locked before calling this function.
++ *
++ * \param old_chan The channel that autochans may currently point to
++ * \param new_chan The channel that we want to point those autochans to now
++ *
++ * \retval void
++ */
++void ast_autochan_new_channel(struct ast_channel *old_chan, struct ast_channel *new_chan);
++
++#endif /* _ASTERISK_AUTOCHAN_H */
+
+Property changes on: include/asterisk/autochan.h
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+
+Index: include/asterisk/taskprocessor.h
+===================================================================
+--- a/include/asterisk/taskprocessor.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/taskprocessor.h (.../trunk) (revision 202568)
+@@ -73,7 +73,7 @@
+ * TPS_REF_IF_EXISTS reference type is specified and the taskprocessor does not exist
+ * \since 1.6.1
+ */
+-struct ast_taskprocessor *ast_taskprocessor_get(char *name, enum ast_tps_options create);
++struct ast_taskprocessor *ast_taskprocessor_get(const char *name, enum ast_tps_options create);
+
+ /*! \brief Unreference the specified taskprocessor and its reference count will decrement.
+ *
+Index: include/asterisk/astobj2.h
+===================================================================
+--- a/include/asterisk/astobj2.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/astobj2.h (.../trunk) (revision 202568)
+@@ -404,24 +404,24 @@
+
+ #if defined(REF_DEBUG)
+
+-#define ao2_t_alloc(data_size, destructor_fn, debug_msg) _ao2_alloc_debug((data_size), (destructor_fn), (debug_msg), __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
+-#define ao2_alloc(data_size, destructor_fn) _ao2_alloc_debug((data_size), (destructor_fn), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
++#define ao2_t_alloc(data_size, destructor_fn, debug_msg) __ao2_alloc_debug((data_size), (destructor_fn), (debug_msg), __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
++#define ao2_alloc(data_size, destructor_fn) __ao2_alloc_debug((data_size), (destructor_fn), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
+
+ #elif defined(__AST_DEBUG_MALLOC)
+
+-#define ao2_t_alloc(data_size, destructor_fn, debug_msg) _ao2_alloc_debug((data_size), (destructor_fn), (debug_msg), __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
+-#define ao2_alloc(data_size, destructor_fn) _ao2_alloc_debug((data_size), (destructor_fn), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
++#define ao2_t_alloc(data_size, destructor_fn, debug_msg) __ao2_alloc_debug((data_size), (destructor_fn), (debug_msg), __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
++#define ao2_alloc(data_size, destructor_fn) __ao2_alloc_debug((data_size), (destructor_fn), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
+
+ #else
+
+-#define ao2_t_alloc(data_size, destructor_fn, debug_msg) _ao2_alloc((data_size), (destructor_fn))
+-#define ao2_alloc(data_size, destructor_fn) _ao2_alloc((data_size), (destructor_fn))
++#define ao2_t_alloc(data_size, destructor_fn, debug_msg) __ao2_alloc((data_size), (destructor_fn))
++#define ao2_alloc(data_size, destructor_fn) __ao2_alloc((data_size), (destructor_fn))
+
+ #endif
+
+-void *_ao2_alloc_debug(const size_t data_size, ao2_destructor_fn destructor_fn, char *tag,
++void *__ao2_alloc_debug(const size_t data_size, ao2_destructor_fn destructor_fn, char *tag,
+ const char *file, int line, const char *funcname, int ref_debug);
+-void *_ao2_alloc(const size_t data_size, ao2_destructor_fn destructor_fn);
++void *__ao2_alloc(const size_t data_size, ao2_destructor_fn destructor_fn);
+
+ /*! @} */
+
+@@ -450,19 +450,18 @@
+
+ #ifdef REF_DEBUG
+
+-#define ao2_t_ref(o,delta,tag) _ao2_ref_debug((o), (delta), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+-#define ao2_ref(o,delta) _ao2_ref_debug((o), (delta), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
++#define ao2_t_ref(o,delta,tag) __ao2_ref_debug((o), (delta), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
++#define ao2_ref(o,delta) __ao2_ref_debug((o), (delta), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
+ #else
+
+-#define ao2_t_ref(o,delta,tag) _ao2_ref((o), (delta))
+-#define ao2_ref(o,delta) _ao2_ref((o), (delta))
++#define ao2_t_ref(o,delta,tag) __ao2_ref((o), (delta))
++#define ao2_ref(o,delta) __ao2_ref((o), (delta))
+
+ #endif
+
+-int _ao2_ref_debug(void *o, int delta, char *tag, char *file, int line, const char *funcname);
+-int _ao2_ref(void *o, int delta);
+-/*! @} */
++int __ao2_ref_debug(void *o, int delta, char *tag, char *file, int line, const char *funcname);
++int __ao2_ref(void *o, int delta);
+
+ /*! @} */
+
+@@ -475,8 +474,8 @@
+ #ifndef DEBUG_THREADS
+ int ao2_lock(void *a);
+ #else
+-#define ao2_lock(a) _ao2_lock(a, __FILE__, __PRETTY_FUNCTION__, __LINE__, #a)
+-int _ao2_lock(void *a, const char *file, const char *func, int line, const char *var);
++#define ao2_lock(a) __ao2_lock(a, __FILE__, __PRETTY_FUNCTION__, __LINE__, #a)
++int __ao2_lock(void *a, const char *file, const char *func, int line, const char *var);
+ #endif
+
+ /*! \brief
+@@ -488,8 +487,8 @@
+ #ifndef DEBUG_THREADS
+ int ao2_unlock(void *a);
+ #else
+-#define ao2_unlock(a) _ao2_unlock(a, __FILE__, __PRETTY_FUNCTION__, __LINE__, #a)
+-int _ao2_unlock(void *a, const char *file, const char *func, int line, const char *var);
++#define ao2_unlock(a) __ao2_unlock(a, __FILE__, __PRETTY_FUNCTION__, __LINE__, #a)
++int __ao2_unlock(void *a, const char *file, const char *func, int line, const char *var);
+ #endif
+
+ /*! \brief
+@@ -501,8 +500,8 @@
+ #ifndef DEBUG_THREADS
+ int ao2_trylock(void *a);
+ #else
+-#define ao2_trylock(a) _ao2_trylock(a, __FILE__, __PRETTY_FUNCTION__, __LINE__, #a)
+-int _ao2_trylock(void *a, const char *file, const char *func, int line, const char *var);
++#define ao2_trylock(a) __ao2_trylock(a, __FILE__, __PRETTY_FUNCTION__, __LINE__, #a)
++int __ao2_trylock(void *a, const char *file, const char *func, int line, const char *var);
+ #endif
+
+ /*!
+@@ -707,27 +706,27 @@
+
+ #if defined(REF_DEBUG)
+
+-#define ao2_t_container_alloc(arg1,arg2,arg3,arg4) _ao2_container_alloc_debug((arg1), (arg2), (arg3), (arg4), __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
+-#define ao2_container_alloc(arg1,arg2,arg3) _ao2_container_alloc_debug((arg1), (arg2), (arg3), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
++#define ao2_t_container_alloc(arg1,arg2,arg3,arg4) __ao2_container_alloc_debug((arg1), (arg2), (arg3), (arg4), __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
++#define ao2_container_alloc(arg1,arg2,arg3) __ao2_container_alloc_debug((arg1), (arg2), (arg3), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
+
+ #elif defined(__AST_DEBUG_MALLOC)
+
+-#define ao2_t_container_alloc(arg1,arg2,arg3,arg4) _ao2_container_alloc_debug((arg1), (arg2), (arg3), (arg4), __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
+-#define ao2_container_alloc(arg1,arg2,arg3) _ao2_container_alloc_debug((arg1), (arg2), (arg3), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
++#define ao2_t_container_alloc(arg1,arg2,arg3,arg4) __ao2_container_alloc_debug((arg1), (arg2), (arg3), (arg4), __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
++#define ao2_container_alloc(arg1,arg2,arg3) __ao2_container_alloc_debug((arg1), (arg2), (arg3), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
+
+ #else
+
+-#define ao2_t_container_alloc(arg1,arg2,arg3,arg4) _ao2_container_alloc((arg1), (arg2), (arg3))
+-#define ao2_container_alloc(arg1,arg2,arg3) _ao2_container_alloc((arg1), (arg2), (arg3))
++#define ao2_t_container_alloc(arg1,arg2,arg3,arg4) __ao2_container_alloc((arg1), (arg2), (arg3))
++#define ao2_container_alloc(arg1,arg2,arg3) __ao2_container_alloc((arg1), (arg2), (arg3))
+
+ #endif
+
+-struct ao2_container *_ao2_container_alloc(const unsigned int n_buckets,
+- ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn);
+-struct ao2_container *_ao2_container_alloc_debug(const unsigned int n_buckets,
+- ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn,
+- char *tag, char *file, int line, const char *funcname,
+- int ref_debug);
++struct ao2_container *__ao2_container_alloc(const unsigned int n_buckets,
++ ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn);
++struct ao2_container *__ao2_container_alloc_debug(const unsigned int n_buckets,
++ ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn,
++ char *tag, char *file, int line, const char *funcname,
++ int ref_debug);
+
+ /*! \brief
+ * Returns the number of elements in a container.
+@@ -762,18 +761,18 @@
+ */
+ #ifdef REF_DEBUG
+
+-#define ao2_t_link(arg1, arg2, arg3) _ao2_link_debug((arg1), (arg2), (arg3), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+-#define ao2_link(arg1, arg2) _ao2_link_debug((arg1), (arg2), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
++#define ao2_t_link(arg1, arg2, arg3) __ao2_link_debug((arg1), (arg2), (arg3), __FILE__, __LINE__, __PRETTY_FUNCTION__)
++#define ao2_link(arg1, arg2) __ao2_link_debug((arg1), (arg2), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
+ #else
+
+-#define ao2_t_link(arg1, arg2, arg3) _ao2_link((arg1), (arg2))
+-#define ao2_link(arg1, arg2) _ao2_link((arg1), (arg2))
++#define ao2_t_link(arg1, arg2, arg3) __ao2_link((arg1), (arg2))
++#define ao2_link(arg1, arg2) __ao2_link((arg1), (arg2))
+
+ #endif
+
+-void *_ao2_link_debug(struct ao2_container *c, void *new_obj, char *tag, char *file, int line, const char *funcname);
+-void *_ao2_link(struct ao2_container *c, void *newobj);
++void *__ao2_link_debug(struct ao2_container *c, void *new_obj, char *tag, char *file, int line, const char *funcname);
++void *__ao2_link(struct ao2_container *c, void *newobj);
+
+ /*!
+ * \brief Remove an object from a container
+@@ -793,18 +792,18 @@
+ */
+ #ifdef REF_DEBUG
+
+-#define ao2_t_unlink(arg1, arg2, arg3) _ao2_unlink_debug((arg1), (arg2), (arg3), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+-#define ao2_unlink(arg1, arg2) _ao2_unlink_debug((arg1), (arg2), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
++#define ao2_t_unlink(arg1, arg2, arg3) __ao2_unlink_debug((arg1), (arg2), (arg3), __FILE__, __LINE__, __PRETTY_FUNCTION__)
++#define ao2_unlink(arg1, arg2) __ao2_unlink_debug((arg1), (arg2), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
+ #else
+
+-#define ao2_t_unlink(arg1, arg2, arg3) _ao2_unlink((arg1), (arg2))
+-#define ao2_unlink(arg1, arg2) _ao2_unlink((arg1), (arg2))
++#define ao2_t_unlink(arg1, arg2, arg3) __ao2_unlink((arg1), (arg2))
++#define ao2_unlink(arg1, arg2) __ao2_unlink((arg1), (arg2))
+
+ #endif
+
+-void *_ao2_unlink_debug(struct ao2_container *c, void *obj, char *tag, char *file, int line, const char *funcname);
+-void *_ao2_unlink(struct ao2_container *c, void *obj);
++void *__ao2_unlink_debug(struct ao2_container *c, void *obj, char *tag, char *file, int line, const char *funcname);
++void *__ao2_unlink(struct ao2_container *c, void *obj);
+
+
+ /*! \brief Used as return value if the flag OBJ_MULTIPLE is set */
+@@ -896,22 +895,20 @@
+ */
+ #ifdef REF_DEBUG
+
+-#define ao2_t_callback(c,flags,cb_fn,arg,tag) _ao2_callback_debug((c), (flags), (cb_fn), (arg), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+-#define ao2_callback(c,flags,cb_fn,arg) _ao2_callback_debug((c), (flags), (cb_fn), (arg), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
++#define ao2_t_callback(c,flags,cb_fn,arg,tag) __ao2_callback_debug((c), (flags), (cb_fn), (arg), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
++#define ao2_callback(c,flags,cb_fn,arg) __ao2_callback_debug((c), (flags), (cb_fn), (arg), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
+ #else
+
+-#define ao2_t_callback(c,flags,cb_fn,arg,tag) _ao2_callback((c), (flags), (cb_fn), (arg))
+-#define ao2_callback(c,flags,cb_fn,arg) _ao2_callback((c), (flags), (cb_fn), (arg))
++#define ao2_t_callback(c,flags,cb_fn,arg,tag) __ao2_callback((c), (flags), (cb_fn), (arg))
++#define ao2_callback(c,flags,cb_fn,arg) __ao2_callback((c), (flags), (cb_fn), (arg))
+
+ #endif
+
+-void *_ao2_callback_debug(struct ao2_container *c, enum search_flags flags,
+- ao2_callback_fn *cb_fn, void *arg, char *tag,
+- char *file, int line, const char *funcname);
+-void *_ao2_callback(struct ao2_container *c,
+- enum search_flags flags,
+- ao2_callback_fn *cb_fn, void *arg);
++void *__ao2_callback_debug(struct ao2_container *c, enum search_flags flags, ao2_callback_fn *cb_fn,
++ void *arg, char *tag, char *file, int line, const char *funcname);
++void *__ao2_callback(struct ao2_container *c, enum search_flags flags, ao2_callback_fn *cb_fn, void *arg);
++
+ /*! @} */
+
+ /*! \brief
+@@ -930,36 +927,41 @@
+ * \see ao2_callback()
+ */
+ #ifdef REF_DEBUG
+-#define ao2_t_callback_data(arg1,arg2,arg3,arg4,arg5,arg6) _ao2_callback_data_debug((arg1), (arg2), (arg3), (arg4), (arg5), (arg6), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+-#define ao2_callback_data(arg1,arg2,arg3,arg4,arg5) _ao2_callback_data_debug((arg1), (arg2), (arg3), (arg4), (arg5), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
++
++#define ao2_t_callback_data(arg1,arg2,arg3,arg4,arg5,arg6) __ao2_callback_data_debug((arg1), (arg2), (arg3), (arg4), (arg5), (arg6), __FILE__, __LINE__, __PRETTY_FUNCTION__)
++#define ao2_callback_data(arg1,arg2,arg3,arg4,arg5) __ao2_callback_data_debug((arg1), (arg2), (arg3), (arg4), (arg5), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
++
+ #else
+-#define ao2_t_callback_data(arg1,arg2,arg3,arg4,arg5,arg6) _ao2_callback_data((arg1), (arg2), (arg3), (arg4), (arg5))
+-#define ao2_callback_data(arg1,arg2,arg3,arg4,arg5) _ao2_callback_data((arg1), (arg2), (arg3), (arg4), (arg5))
++
++#define ao2_t_callback_data(arg1,arg2,arg3,arg4,arg5,arg6) __ao2_callback_data((arg1), (arg2), (arg3), (arg4), (arg5))
++#define ao2_callback_data(arg1,arg2,arg3,arg4,arg5) __ao2_callback_data((arg1), (arg2), (arg3), (arg4), (arg5))
++
+ #endif
+-void *_ao2_callback_data_debug(struct ao2_container *c, enum search_flags flags,
+- ao2_callback_data_fn *cb_fn, void *arg, void *data, char *tag,
+- char *file, int line, const char *funcname);
+-void *_ao2_callback_data(struct ao2_container *c,
+- enum search_flags flags,
+- ao2_callback_data_fn *cb_fn, void *arg, void *data);
+
++void *__ao2_callback_data_debug(struct ao2_container *c, enum search_flags flags,
++ ao2_callback_data_fn *cb_fn, void *arg, void *data, char *tag,
++ char *file, int line, const char *funcname);
++void *__ao2_callback_data(struct ao2_container *c, enum search_flags flags,
++ ao2_callback_data_fn *cb_fn, void *arg, void *data);
++
+ /*! ao2_find() is a short hand for ao2_callback(c, flags, c->cmp_fn, arg)
+ * XXX possibly change order of arguments ?
+ */
+ #ifdef REF_DEBUG
+
+-#define ao2_t_find(arg1,arg2,arg3,arg4) _ao2_find_debug((arg1), (arg2), (arg3), (arg4), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+-#define ao2_find(arg1,arg2,arg3) _ao2_find_debug((arg1), (arg2), (arg3), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
++#define ao2_t_find(arg1,arg2,arg3,arg4) __ao2_find_debug((arg1), (arg2), (arg3), (arg4), __FILE__, __LINE__, __PRETTY_FUNCTION__)
++#define ao2_find(arg1,arg2,arg3) __ao2_find_debug((arg1), (arg2), (arg3), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
+ #else
+
+-#define ao2_t_find(arg1,arg2,arg3,arg4) _ao2_find((arg1), (arg2), (arg3))
+-#define ao2_find(arg1,arg2,arg3) _ao2_find((arg1), (arg2), (arg3))
++#define ao2_t_find(arg1,arg2,arg3,arg4) __ao2_find((arg1), (arg2), (arg3))
++#define ao2_find(arg1,arg2,arg3) __ao2_find((arg1), (arg2), (arg3))
+
+ #endif
+
+-void *_ao2_find_debug(struct ao2_container *c, void *arg, enum search_flags flags, char *tag, char *file, int line, const char *funcname);
+-void *_ao2_find(struct ao2_container *c, void *arg, enum search_flags flags);
++void *__ao2_find_debug(struct ao2_container *c, void *arg, enum search_flags flags, char *tag,
++ char *file, int line, const char *funcname);
++void *__ao2_find(struct ao2_container *c, void *arg, enum search_flags flags);
+
+ /*! \brief
+ *
+@@ -1060,18 +1062,18 @@
+
+ #ifdef REF_DEBUG
+
+-#define ao2_t_iterator_next(arg1, arg2) _ao2_iterator_next_debug((arg1), (arg2), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+-#define ao2_iterator_next(arg1) _ao2_iterator_next_debug((arg1), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
++#define ao2_t_iterator_next(arg1, arg2) __ao2_iterator_next_debug((arg1), (arg2), __FILE__, __LINE__, __PRETTY_FUNCTION__)
++#define ao2_iterator_next(arg1) __ao2_iterator_next_debug((arg1), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
+ #else
+
+-#define ao2_t_iterator_next(arg1, arg2) _ao2_iterator_next((arg1))
+-#define ao2_iterator_next(arg1) _ao2_iterator_next((arg1))
++#define ao2_t_iterator_next(arg1, arg2) __ao2_iterator_next((arg1))
++#define ao2_iterator_next(arg1) __ao2_iterator_next((arg1))
+
+ #endif
+
+-void *_ao2_iterator_next_debug(struct ao2_iterator *a, char *tag, char *file, int line, const char *funcname);
+-void *_ao2_iterator_next(struct ao2_iterator *a);
++void *__ao2_iterator_next_debug(struct ao2_iterator *a, char *tag, char *file, int line, const char *funcname);
++void *__ao2_iterator_next(struct ao2_iterator *a);
+
+ /* extra functions */
+ void ao2_bt(void); /* backtrace */
+Index: include/asterisk/cli.h
+===================================================================
+--- a/include/asterisk/cli.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/cli.h (.../trunk) (revision 202568)
+@@ -97,7 +97,7 @@
+ \code
+ static char *test_new_cli(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+ {
+- static char *choices = { "one", "two", "three", NULL };
++ static const char * const choices[] = { "one", "two", "three", NULL };
+
+ switch (cmd) {
+ case CLI_INIT:
+@@ -128,7 +128,7 @@
+ /*! \brief calling arguments for new-style handlers.
+ * \arg \ref CLI_command_API
+ */
+-enum ast_cli_fn {
++enum ast_cli_command {
+ CLI_INIT = -2, /* return the usage string */
+ CLI_GENERATE = -3, /* behave as 'generator', remap argv to struct ast_cli_args */
+ CLI_HANDLER = -4, /* run the normal handler */
+@@ -136,27 +136,25 @@
+
+ /* argument for new-style CLI handler */
+ struct ast_cli_args {
+- int fd;
+- int argc;
+- char **argv;
++ const int fd;
++ const int argc;
++ const char * const *argv;
+ const char *line; /* the current input line */
+ const char *word; /* the word we want to complete */
+- int pos; /* position of the word to complete */
+- int n; /* the iteration count (n-th entry we generate) */
++ const int pos; /* position of the word to complete */
++ const int n; /* the iteration count (n-th entry we generate) */
+ };
+
+-struct ast_cli_entry;
+-typedef char *(*cli_fn)(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
+-
+ /*! \brief descriptor for a cli entry.
+ * \arg \ref CLI_command_API
+ */
+ struct ast_cli_entry {
+- char * const cmda[AST_MAX_CMD_LEN]; /*!< words making up the command.
+- * set the first entry to NULL for a new-style entry. */
++ const char * const cmda[AST_MAX_CMD_LEN]; /*!< words making up the command.
++ * set the first entry to NULL for a new-style entry.
++ */
+
+- const char *summary; /*!< Summary of the command (< 60 characters) */
+- const char *usage; /*!< Detailed usage information */
++ const char * const summary; /*!< Summary of the command (< 60 characters) */
++ const char * usage; /*!< Detailed usage information */
+
+ int inuse; /*!< For keeping track of usage */
+ struct module *module; /*!< module this belongs to */
+@@ -166,7 +164,7 @@
+ */
+ int args; /*!< number of non-null entries in cmda */
+ char *command; /*!< command, non-null for new-style entries */
+- cli_fn handler;
++ char *(*handler)(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
+ /*! For linking */
+ AST_LIST_ENTRY(ast_cli_entry) list;
+ };
+@@ -183,7 +181,7 @@
+ \code
+ char *my_generate(const char *line, const char *word, int pos, int n)
+ {
+- static char *choices = { "one", "two", "three", NULL };
++ static const char * const choices[] = { "one", "two", "three", NULL };
+ if (pos == 2)
+ return ast_cli_complete(word, choices, n);
+ else
+@@ -191,7 +189,7 @@
+ }
+ \endcode
+ */
+-char *ast_cli_complete(const char *word, char *const choices[], int pos);
++char *ast_cli_complete(const char *word, const char * const choices[], int pos);
+
+ /*!
+ * \brief Interprets a command
+Index: include/asterisk/calendar.h
+===================================================================
+--- a/include/asterisk/calendar.h (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/include/asterisk/calendar.h (.../trunk) (revision 202568)
+@@ -0,0 +1,187 @@
++/*
++ * Asterisk -- An open source telephony toolkit.
++ *
++ * Copyright (C) 2008 - 2009, Digium, Inc.
++ *
++ * Terry Wilson <twilson@digium.com>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * 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.
++ */
++
++#ifndef _ASTERISK_CALENDAR_H
++#define _ASTERISK_CALENDAR_H
++
++#include "asterisk.h"
++#include "asterisk/stringfields.h"
++#include "asterisk/config.h"
++#include "asterisk/linkedlists.h"
++#include "asterisk/lock.h"
++
++/*! \file calendar.h
++ * \brief A general API for managing calendar events with Asterisk
++ *
++ * \author Terry Wilson <twilson@digium.com>
++ *
++ * \note This API implements an abstraction for handling different calendaring
++ * technologies in Asterisk. The services provided by the API are a dialplan
++ * function to query whether or not a calendar is busy at the present time, a
++ * adialplan function to query specific information about events in a time range,
++ * a devicestate provider, and notification of calendar events through execution
++ * of dialplan apps or dialplan logic at a specific context and extension. The
++ * information available through the CALENDAR_EVENT() dialplan function are:
++ *
++ * SUMMARY, DESCRIPTION, ORGANIZER, LOCATION
++ * CALENDAR, UID, START, END, and BUSYSTATE
++ *
++ * BUSYSTATE can have the values 0 (free), 1 (tentatively busy), or 2 (busy)
++ *
++ * Usage
++ * All calendaring configuration data is located in calendar.conf and is only read
++ * directly by the Calendaring API. Each calendar technology resource must register
++ * a load_calendar callback which will be passed an ast_calendar_load_data structure.
++ * The load_calendar callback function should then set the values it needs from this
++ * cfg, load the calendar data, and then loop updating the calendar data and events
++ * baesd on the refresh interval in the ast_calendar object. Each call to
++ * the load_calendar callback will be will run in its own thread.
++ *
++ * Updating events involves creating an astobj2 container of new events and passing
++ * it to the API through ast_calendar_merge_events.
++ *
++ * Calendar technology resource modules must also register an unref_calendar callback
++ * which will only be called when the resource module calls ast_calendar_unregister()
++ * to unregister that module's calendar type (usually done in module_unload())
++ */
++
++extern struct ast_config *ast_calendar_config;
++
++struct ast_calendar;
++struct ast_calendar_event;
++
++/*! \brief Individual calendaring technology data */
++struct ast_calendar_tech {
++ const char *type;
++ const char *description;
++ const char *module;
++ int (* is_busy)(struct ast_calendar *calendar); /*!< Override default busy determination */
++ void *(* load_calendar)(void *data); /*!< Create private structure, add calendar events, etc. */
++ void *(* unref_calendar)(void *obj); /*!< Function to be called to free the private structure */
++ int (* write_event)(struct ast_calendar_event *event); /*!< Function for writing an event to the calendar */
++ AST_LIST_ENTRY(ast_calendar_tech) list;
++};
++
++enum ast_calendar_busy_state {
++ AST_CALENDAR_BS_FREE = 0,
++ AST_CALENDAR_BS_BUSY_TENTATIVE,
++ AST_CALENDAR_BS_BUSY,
++};
++
++struct ast_calendar_attendee {
++ char *data;
++ AST_LIST_ENTRY(ast_calendar_attendee) next;
++};
++
++/* \brief Calendar events */
++struct ast_calendar_event {
++ AST_DECLARE_STRING_FIELDS(
++ AST_STRING_FIELD(summary);
++ AST_STRING_FIELD(description);
++ AST_STRING_FIELD(organizer);
++ AST_STRING_FIELD(location);
++ AST_STRING_FIELD(uid);
++ );
++ struct ast_calendar *owner; /*!< The calendar that owns this event */
++ time_t start; /*!< Start of event (UTC) */
++ time_t end; /*!< End of event (UTC) */
++ time_t alarm; /*!< Time for event notification */
++ enum ast_calendar_busy_state busy_state; /*!< The busy status of the event */
++ int notify_sched; /*!< The sched for event notification */
++ int bs_start_sched; /*!< The sched for changing the device state at the start of an event */
++ int bs_end_sched; /*!< The sched for changing the device state at the end of an event */
++ AST_LIST_HEAD_NOLOCK(attendees, ast_calendar_attendee) attendees;
++};
++
++/*! \brief Asterisk calendar structure */
++struct ast_calendar {
++ const struct ast_calendar_tech *tech;
++ void *tech_pvt;
++ AST_DECLARE_STRING_FIELDS(
++ AST_STRING_FIELD(name); /*!< Name from config file [name] */
++ AST_STRING_FIELD(notify_channel); /*!< Channel to use for notification */
++ AST_STRING_FIELD(notify_context); /*!< Optional context to execute from for notification */
++ AST_STRING_FIELD(notify_extension); /*!< Optional extension to execute from for notification */
++ AST_STRING_FIELD(notify_app); /*!< Optional dialplan app to execute for notification */
++ AST_STRING_FIELD(notify_appdata); /*!< Optional arguments for dialplan app */
++ );
++ int autoreminder; /*!< If set, override any calendar_tech specific notification times and use this time (in mins) */
++ int notify_waittime; /*!< Maxiumum time to allow for a notification attempt */
++ int refresh; /*!< When to refresh the calendar events */
++ int timeframe; /*!< Span (in mins) of calendar data to pull with each request */
++ pthread_t thread; /*!< The thread that the calendar is loaded/updated in */
++ ast_cond_t unload;
++ int unloading:1;
++ int pending_deletion:1;
++ struct ao2_container *events; /*!< The events that are known at this time */
++};
++
++/*! \brief Register a new calendar technology
++ *
++ * \param tech calendar technology to register
++ *
++ * \retval 0 success
++ * \retval -1 failure
++ */
++int ast_calendar_register(struct ast_calendar_tech *tech);
++
++/*! \brief Unregister a new calendar technology
++ *
++ * \param tech calendar technology to unregister
++ *
++ * \retval 0 success
++ * \retva -1 failure
++ */
++void ast_calendar_unregister(struct ast_calendar_tech *tech);
++
++/*! \brief Allocate an astobj2 ast_calendar_event object
++ *
++ * \param cal calendar to allocate an event for
++ *
++ * \return a new, initialized calendar event
++ */
++struct ast_calendar_event *ast_calendar_event_alloc(struct ast_calendar *cal);
++
++/*! \brief Allocate an astobj2 container for ast_calendar_event objects
++ *
++ * \return a new event container
++ */
++struct ao2_container *ast_calendar_event_container_alloc(void);
++
++/*! \brief Add an event to the list of events for a calendar
++ *
++ * \param cal calendar containing the events to be merged
++ * \param new_events an oa2 container of events to be merged into cal->events
++ */
++void ast_calendar_merge_events(struct ast_calendar *cal, struct ao2_container *new_events);
++
++/*! \brief Unreference an ast_calendar_event
++ *
++ * \param event event to unref
++ *
++ * \return NULL
++ */
++struct ast_calendar_event *ast_calendar_unref_event(struct ast_calendar_event *event);
++
++/*! \brief Remove all events from calendar
++ *
++ * \param cal calendar whose events need to be cleared
++ */
++void ast_calendar_clear_events(struct ast_calendar *cal);
++
++#endif /* _ASTERISK_CALENDAR_H */
+
+Property changes on: include/asterisk/calendar.h
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+
+Index: include/asterisk/optional_api.h
+===================================================================
+--- a/include/asterisk/optional_api.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/optional_api.h (.../trunk) (revision 202568)
+@@ -32,14 +32,14 @@
+ *
+ * To accomodate this situation, the AST_OPTIONAL_API macro allows an API
+ * function to be declared in a special way, if Asterisk being built on a
+- * platform that supports the GCC 'weak' and 'alias' attributes. If so,
+- * the API function is actually a weak symbol, which means if the provider
+- * of the API is not loaded, the symbol can still be referenced (unlike a
++ * platform that supports special compiler and dynamic linker attributes.
++ * If so the API function will actually be a weak symbol, which means if the
++ * provider of the API is not loaded, the symbol can still be referenced (unlike a
+ * strong symbol, which would cause an immediate fault if not defined when
+ * referenced), but it will return NULL signifying the linker/loader was
+ * not able to resolve the symbol. In addition, the macro defines a hidden
+ * 'stub' version of the API call, using a provided function body, and uses
+- * the alias attribute to make the API function symbol actually resolve to
++ * various methods to make the API function symbol actually resolve to
+ * that hidden stub, but only when the *real* provider of the symbol has
+ * not been found.
+ *
+@@ -57,13 +57,25 @@
+ * safely know that the API is not available, and to avoid using any
+ * other APIs from the not-present provider.
+ *
++ * In addition to this declaration in the header file, the actual definition of
++ * the API function must use the AST_OPTIONAL_API_NAME macro to (possibly)
++ * modify the real name of the API function, depending on the specific
++ * implementation requirements. The corresponding example from res_agi.c:
++ *
++ * \code
++ * int AST_OPTIONAL_API_NAME(ast_agi_register)(struct ast_module *mod, agi_command *cmd)
++ * {
++ * ...
++ * }
++ * \endcode
++ *
+ * In the module providing the API, the AST_OPTIONAL_API macro must
+ * be informed that it should not build the hidden stub function or
+ * apply special aliases to the function prototype; this can be done
+ * by defining AST_API_MODULE just before including the header file
+ * containing the AST_OPTIONAL_API macro calls.
+ *
+- * \note If the GCC 'weak' and 'alias' attributes are not available,
++ * \note If the platform does not provide adequate resources,
+ * then the AST_OPTIONAL_API macro will result in a non-optional function
+ * definition; this means that any consumers of the API functions so
+ * defined will require that the provider of the API functions be
+@@ -83,17 +95,115 @@
+ */
+ #define AST_OPTIONAL_API_UNAVAILABLE INT_MIN
+
+-#if defined(HAVE_ATTRIBUTE_weak_import) && !defined(AST_API_MODULE)
+-#define AST_OPTIONAL_API(result, name, proto, stub) result name proto __attribute__((weak_import));
+-#define AST_OPTIONAL_API_ATTR(result, attr, name, proto, stub) result name proto __attribute__((weak_import,attr));
+-#elif defined(HAVE_ATTRIBUTE_weak) && defined(HAVE_ATTRIBUTE_alias) && !defined(AST_API_MODULE) && !defined(HAVE_ATTRIBUTE_weak_import)
+-#define AST_OPTIONAL_API(result, name, proto, stub) \
+- static result __##name proto stub; \
+- result __attribute__((weak, alias("__" __stringify(name)))) name proto;
+-#define AST_OPTIONAL_API_ATTR(result, attr, name, proto, stub) \
+- static result __attribute__((attr)) __##name proto stub; \
+- result __attribute__((weak, alias("__" __stringify(name)), attr)) name proto;
++
++#if defined(HAVE_ATTRIBUTE_weak_import)
++
++/*
++ * This is the Darwin (Mac OS/X) implementation, that only provides the
++ * 'weak_import' compiler attribute for weak symbols. On this platform,
++ *
++ * - The module providing the API will only provide a '__' prefixed version
++ * of the API function to other modules (this will be hidden from the other
++ * modules by the macros), so any modules compiled against older versions
++ * of the module that provided a non-prefixed version of the API function
++ * will fail to link at runtime.
++ * - In the API module itself, access to the API function without using a
++ * prefixed name is provided by a static pointer variable that holds the
++ * function address.
++ * - 'Consumer' modules of the API will use a combination of a weak_import
++ * symbol, a local stub function, a pointer variable and a constructor function
++ * (which initializes that pointer variable as the module is being loaded)
++ * to provide safe, optional access to the API function without any special
++ * code being required.
++ */
++
++#define AST_OPTIONAL_API_NAME(name) __##name
++
++#if defined(AST_API_MODULE)
++
++#define AST_OPTIONAL_API(result, name, proto, stub) \
++ result AST_OPTIONAL_API_NAME(name) proto; \
++ static attribute_unused typeof(AST_OPTIONAL_API_NAME(name)) * const name = AST_OPTIONAL_API_NAME(name);
++
++#define AST_OPTIONAL_API_ATTR(result, attr, name, proto, stub) \
++ result __attribute__((attr)) AST_OPTIONAL_API_NAME(name) proto; \
++ static attribute_unused typeof(AST_OPTIONAL_API_NAME(name)) * const name = AST_OPTIONAL_API_NAME(name);
++
+ #else
++
++#define AST_OPTIONAL_API(result, name, proto, stub) \
++ static result __stub__##name proto stub; \
++ __attribute__((weak_import)) typeof(__stub__##name) AST_OPTIONAL_API_NAME(name); \
++ static attribute_unused typeof(__stub__##name) * name; \
++ static void __attribute__((constructor)) __init__##name(void) { name = AST_OPTIONAL_API_NAME(name) ? : __stub__##name; }
++
++#define AST_OPTIONAL_API_ATTR(result, attr, name, proto, stub) \
++ static __attribute__((attr)) result __stub__##name proto stub; \
++ __attribute__((attr, weak_import)) typeof(__stub__##name) AST_OPTIONAL_API_NAME(name); \
++ static attribute_unused __attribute__((attr)) typeof(__stub__##name) * name; \
++ static void __attribute__((constructor)) __init__##name(void) { name = AST_OPTIONAL_API_NAME(name) ? : __stub__##name; }
++
++
++#endif
++
++/* End of Darwin (Mac OS/X) implementation */
++
++#elif defined(HAVE_ATTRIBUTE_weakref)
++
++/*
++ * This is the generic GCC implementation, used when the 'weakref'
++ * compiler attribute is available. On these platforms:
++ *
++ * - The module providing the API will provide a '__' prefixed version
++ * of the API function to other modules (this will be hidden from the other
++ * modules by the macros), and also a non-prefixed alias so that modules
++ * compiled against older versions of the module that provided a non-prefixed
++ * version of the API function will continue to link properly.
++ * - In the API module itself, access to the API function without using a
++ * prefixed name is provided by the non-prefixed alias described above.
++ * - 'Consumer' modules of the API will use a combination of a weakref
++ * symbol, a local stub function, a pointer variable and a constructor function
++ * (which initializes that pointer variable as the module is being loaded)
++ * to provide safe, optional access to the API function without any special
++ * code being required.
++ */
++
++#define AST_OPTIONAL_API_NAME(name) __##name
++
++#if defined(AST_API_MODULE)
++
++#define AST_OPTIONAL_API(result, name, proto, stub) \
++ result AST_OPTIONAL_API_NAME(name) proto; \
++ __attribute__((alias(__stringify(AST_OPTIONAL_API_NAME(name))))) typeof(AST_OPTIONAL_API_NAME(name)) name;
++
++#define AST_OPTIONAL_API_ATTR(result, attr, name, proto, stub) \
++ result __attribute__((attr)) AST_OPTIONAL_API_NAME(name) proto; \
++ __attribute__((alias(__stringify(AST_OPTIONAL_API_NAME(name))))) typeof(AST_OPTIONAL_API_NAME(name)) name;
++
++#else
++
++#define AST_OPTIONAL_API(result, name, proto, stub) \
++ static result __stub__##name proto stub; \
++ static __attribute__((weakref(__stringify(AST_OPTIONAL_API_NAME(name))))) typeof(__stub__##name) __ref__##name; \
++ static attribute_unused typeof(__stub__##name) * name; \
++ static void __attribute__((constructor)) __init__##name(void) { name = __ref__##name ? : __stub__##name; }
++
++#define AST_OPTIONAL_API_ATTR(result, attr, name, proto, stub) \
++ static __attribute__((attr)) result __stub__##name proto stub; \
++ static __attribute__((attr, weakref(__stringify(AST_OPTIONAL_API_NAME(name))))) typeof(__stub__##name) __ref__##name; \
++ static attribute_unused __attribute__((attr)) typeof(__stub__##name) * name; \
++ static void __attribute__((constructor)) __init__##name(void) { name = __ref__##name ? : __stub__##name; }
++
++#endif
++
++/* End of GCC implementation */
++
++#else
++
++/* This is the non-optional implementation. */
++
++#define AST_OPTIONAL_API_NAME(name) name
++
+ /*!
+ * \brief Define an optional API function
+ *
+@@ -108,7 +218,8 @@
+ * { return AST_OPTIONAL_API_UNAVAILABLE; });
+ * \endcode
+ */
+-#define AST_OPTIONAL_API(result, name, proto, stub) result name proto;
++#define AST_OPTIONAL_API(result, name, proto, stub) result AST_OPTIONAL_API_NAME(name) proto
++
+ /*!
+ * \brief Define an optional API function with compiler attributes
+ *
+@@ -118,7 +229,10 @@
+ * \param proto The prototype (arguments) of the function
+ * \param stub The code block that will be used by the hidden stub when needed
+ */
+-#define AST_OPTIONAL_API_ATTR(result, attr, name, proto, stub) result __attribute__((attr)) name proto;
++#define AST_OPTIONAL_API_ATTR(result, attr, name, proto, stub) result __attribute__((attr)) AST_OPTIONAL_API_NAME(name) proto
++
++/* End of non-optional implementation */
++
+ #endif
+
+ #undef AST_API_MODULE
+Index: include/asterisk/logger.h
+===================================================================
+--- a/include/asterisk/logger.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/logger.h (.../trunk) (revision 202568)
+@@ -123,17 +123,6 @@
+ #endif
+ #define AST_LOG_DEBUG __LOG_DEBUG, _A_
+
+-#ifdef LOG_EVENT
+-#undef LOG_EVENT
+-#endif
+-#define __LOG_EVENT 1
+-#define LOG_EVENT __LOG_EVENT, _A_
+-
+-#ifdef AST_LOG_EVENT
+-#undef AST_LOG_EVENT
+-#endif
+-#define AST_LOG_EVENT __LOG_EVENT, _A_
+-
+ #ifdef LOG_NOTICE
+ #undef LOG_NOTICE
+ #endif
+@@ -206,6 +195,37 @@
+ unsigned int ast_verbose_get_by_file(const char *file);
+
+ /*!
++ * \brief Register a new logger level
++ * \param name The name of the level to be registered
++ * \retval -1 if an error occurs
++ * \retval non-zero level to be used with ast_log for sending messages to this level
++ * \since 1.6.3
++ */
++int ast_logger_register_level(const char *name);
++
++/*!
++ * \brief Unregister a previously registered logger level
++ * \param name The name of the level to be unregistered
++ * \return nothing
++ * \since 1.6.3
++ */
++void ast_logger_unregister_level(const char *name);
++
++/*!
++ * \brief Send a log message to a dynamically registered log level
++ * \param level The log level to send the message to
++ *
++ * Like ast_log, the log message may include printf-style formats, and
++ * the data for these must be provided as additional parameters after
++ * the log message.
++ *
++ * \return nothing
++ * \since 1.6.3
++ */
++
++#define ast_log_dynamic_level(level, ...) ast_log(level, __FILE__, __LINE__, __PRETTY_FUNCTION__, __VA_ARGS__)
++
++/*!
+ * \brief Log a DEBUG message
+ * \param level The minimum value of option_debug for this message
+ * to get logged
+Index: include/asterisk/lock.h
+===================================================================
+--- a/include/asterisk/lock.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/lock.h (.../trunk) (revision 202568)
+@@ -58,7 +58,9 @@
+ #ifndef HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK
+ #include "asterisk/time.h"
+ #endif
++
+ #include "asterisk/logger.h"
++#include "asterisk/astobj2.h"
+
+ /* internal macro to profile mutexes. Only computes the delay on
+ * non-blocking calls.
+@@ -272,13 +274,13 @@
+ do { \
+ char __filename[80], __func[80], __mutex_name[80]; \
+ int __lineno; \
+- int __res = ast_find_lock_info(&chan->lock_dont_use, __filename, sizeof(__filename), &__lineno, __func, sizeof(__func), __mutex_name, sizeof(__mutex_name)); \
++ int __res = ast_find_lock_info(ao2_object_get_lockaddr(chan), __filename, sizeof(__filename), &__lineno, __func, sizeof(__func), __mutex_name, sizeof(__mutex_name)); \
+ ast_channel_unlock(chan); \
+ usleep(1); \
+ if (__res < 0) { /* Shouldn't ever happen, but just in case... */ \
+ ast_channel_lock(chan); \
+ } else { \
+- __ast_pthread_mutex_lock(__filename, __lineno, __func, __mutex_name, &chan->lock_dont_use); \
++ __ao2_lock(chan, __filename, __func, __lineno, __mutex_name); \
+ } \
+ } while (0)
+
+@@ -2024,33 +2026,4 @@
+ })
+ #endif
+
+-#ifndef DEBUG_CHANNEL_LOCKS
+-/*! \brief Lock a channel. If DEBUG_CHANNEL_LOCKS is defined
+- in the Makefile, print relevant output for debugging */
+-#define ast_channel_lock(x) ast_mutex_lock(&x->lock_dont_use)
+-/*! \brief Unlock a channel. If DEBUG_CHANNEL_LOCKS is defined
+- in the Makefile, print relevant output for debugging */
+-#define ast_channel_unlock(x) ast_mutex_unlock(&x->lock_dont_use)
+-/*! \brief Try locking a channel. If DEBUG_CHANNEL_LOCKS is defined
+- in the Makefile, print relevant output for debugging */
+-#define ast_channel_trylock(x) ast_mutex_trylock(&x->lock_dont_use)
+-#else
+-
+-#define ast_channel_lock(a) __ast_channel_lock(a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+-/*! \brief Lock AST channel (and print debugging output)
+-\note You need to enable DEBUG_CHANNEL_LOCKS for this function */
+-int __ast_channel_lock(struct ast_channel *chan, const char *file, int lineno, const char *func);
+-
+-#define ast_channel_unlock(a) __ast_channel_unlock(a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+-/*! \brief Unlock AST channel (and print debugging output)
+-\note You need to enable DEBUG_CHANNEL_LOCKS for this function
+-*/
+-int __ast_channel_unlock(struct ast_channel *chan, const char *file, int lineno, const char *func);
+-
+-#define ast_channel_trylock(a) __ast_channel_trylock(a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+-/*! \brief Lock AST channel (and print debugging output)
+-\note You need to enable DEBUG_CHANNEL_LOCKS for this function */
+-int __ast_channel_trylock(struct ast_channel *chan, const char *file, int lineno, const char *func);
+-#endif
+-
+ #endif /* _ASTERISK_LOCK_H */
+Index: include/asterisk/pbx.h
+===================================================================
+--- a/include/asterisk/pbx.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/pbx.h (.../trunk) (revision 202568)
+@@ -27,6 +27,7 @@
+ #include "asterisk/chanvars.h"
+ #include "asterisk/hashtab.h"
+ #include "asterisk/stringfields.h"
++#include "asterisk/xmldoc.h"
+
+ #if defined(__cplusplus) || defined(c_plusplus)
+ extern "C" {
+@@ -34,6 +35,7 @@
+
+ #define AST_MAX_APP 32 /*!< Max length of an application */
+
++#define AST_PBX_GOTO_FAILED -3
+ #define AST_PBX_KEEP 0
+ #define AST_PBX_REPLACE 1
+
+@@ -72,12 +74,6 @@
+ /*! \brief Typedef for devicestate and hint callbacks */
+ typedef int (*ast_state_cb_type)(char *context, char* id, enum ast_extension_states state, void *data);
+
+-/*! \brief From where the documentation come from */
+-enum ast_doc_src {
+- AST_XML_DOC, /*!< From XML documentation */
+- AST_STATIC_DOC /*!< From application/function registration */
+-};
+-
+ /*! \brief Data structure associated with a custom dialplan function */
+ struct ast_custom_function {
+ const char *name; /*!< Name */
+@@ -89,8 +85,20 @@
+ AST_STRING_FIELD(seealso); /*!< See also */
+ );
+ enum ast_doc_src docsrc; /*!< Where the documentation come from */
+- int (*read)(struct ast_channel *, const char *, char *, char *, size_t); /*!< Read function, if read is supported */
+- int (*write)(struct ast_channel *, const char *, char *, const char *); /*!< Write function, if write is supported */
++ /*! Read function, if read is supported */
++ int (*read)(struct ast_channel *, const char *, char *, char *, size_t);
++ /*! Read function, if read is supported. Note: only one of read or read2
++ * needs to be implemented. In new code, read2 should be implemented as
++ * the way forward, but they should return identical results, within the
++ * constraints of buffer size, if both are implemented. That is, if the
++ * read function is handed a 16-byte buffer, and the result is 17 bytes
++ * long, then the first 15 bytes (remember NULL terminator) should be
++ * the same for both the read and the read2 methods. */
++ int (*read2)(struct ast_channel *, const char *, char *, struct ast_str **, ssize_t);
++ /*! If no read2 function is provided, what maximum size? */
++ size_t read_max;
++ /*! Write function, if write is supported */
++ int (*write)(struct ast_channel *, const char *, char *, const char *);
+ struct ast_module *mod; /*!< Module this custom function belongs to */
+ AST_RWLIST_ENTRY(ast_custom_function) acflist;
+ };
+@@ -197,7 +205,7 @@
+ * \retval 0 success
+ * \retval -1 failure
+ */
+-int pbx_exec(struct ast_channel *c, struct ast_app *app, void *data);
++int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data);
+
+ /*!
+ * \brief Register a new context or find an existing one
+@@ -421,6 +429,24 @@
+ int ast_get_hint(char *hint, int hintsize, char *name, int namesize,
+ struct ast_channel *c, const char *context, const char *exten);
+
++/*!
++ * \brief If an extension hint exists, return non-zero
++ *
++ * \param hint buffer for hint
++ * \param hintsize Maximum size of hint buffer (<0 to prevent growth, >0 to limit growth to that number of bytes, or 0 for unlimited growth)
++ * \param name buffer for name portion of hint
++ * \param namesize Maximum size of name buffer (<0 to prevent growth, >0 to limit growth to that number of bytes, or 0 for unlimited growth)
++ * \param c Channel from which to return the hint. This is only important when the hint or name contains an expression to be expanded.
++ * \param context which context to look in
++ * \param exten which extension to search for
++ *
++ * \return If an extension within the given context with the priority PRIORITY_HINT
++ * is found, a non zero value will be returned.
++ * Otherwise, 0 is returned.
++ */
++int ast_str_get_hint(struct ast_str **hint, ssize_t hintsize, struct ast_str **name, ssize_t namesize,
++ struct ast_channel *c, const char *context, const char *exten);
++
+ /*!
+ * \brief Determine whether an extension exists
+ *
+@@ -945,23 +971,61 @@
+ /*!\brief Parse and set a single channel variable, where the name and value are separated with an '=' character.
+ * \note Will lock the channel.
+ */
+-int pbx_builtin_setvar(struct ast_channel *chan, void *data);
++int pbx_builtin_setvar(struct ast_channel *chan, const char *data);
+
+ /*!\brief Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character.
+ * \note Will lock the channel.
+ */
+-int pbx_builtin_setvar_multiple(struct ast_channel *chan, void *data);
++int pbx_builtin_setvar_multiple(struct ast_channel *chan, const char *data);
+
+-int pbx_builtin_raise_exception(struct ast_channel *chan, void *data);
++int pbx_builtin_raise_exception(struct ast_channel *chan, const char *data);
+
+ /*! @name Substitution routines, using static string buffers
+ * @{ */
+ void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count);
+ void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count);
+ void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int cp2_size, size_t *used);
+-void ast_str_substitute_variables(struct ast_str **buf, size_t maxlen, struct ast_channel *chan, const char *templ);
+ /*! @} */
++/*! @} */
+
++/*! @name Substitution routines, using dynamic string buffers */
++
++/*!
++ * \param buf Result will be placed in this buffer.
++ * \param maxlen -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes.
++ * \param chan Channel variables from which to extract values, and channel to pass to any dialplan functions.
++ * \param headp If no channel is specified, a channel list from which to extract variable values
++ * \param var Variable name to retrieve.
++ */
++const char *ast_str_retrieve_variable(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, struct varshead *headp, const char *var);
++
++/*!
++ * \param buf Result will be placed in this buffer.
++ * \param maxlen -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes.
++ * \param chan Channel variables from which to extract values, and channel to pass to any dialplan functions.
++ * \param templ Variable template to expand.
++ */
++void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ);
++
++/*!
++ * \param buf Result will be placed in this buffer.
++ * \param maxlen -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes.
++ * \param headp If no channel is specified, a channel list from which to extract variable values
++ * \param templ Variable template to expand.
++ */
++void ast_str_substitute_variables_varshead(struct ast_str **buf, ssize_t maxlen, struct varshead *headp, const char *templ);
++
++/*!
++ * \param buf Result will be placed in this buffer.
++ * \param maxlen -1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes.
++ * \param c Channel variables from which to extract values, and channel to pass to any dialplan functions.
++ * \param headp If no channel is specified, a channel list from which to extract variable values
++ * \param templ Variable template to expand.
++ * \param used Number of bytes read from the template.
++ */
++void ast_str_substitute_variables_full(struct ast_str **buf, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *templ, size_t *used);
++/*! @} */
++
+ int ast_extension_patmatch(const char *pattern, const char *data);
+
+ /*! Set "autofallthrough" flag, if newval is <0, does not actually set. If
+@@ -1049,6 +1113,21 @@
+ int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len);
+
+ /*!
++ * \brief executes a read operation on a function
++ *
++ * \param chan Channel to execute on
++ * \param function Data containing the function call string (will be modified)
++ * \param str A dynamic string buffer into which to place the result.
++ * \param maxlen <0 if the dynamic buffer should not grow; >0 if the dynamic buffer should be limited to that number of bytes; 0 if the dynamic buffer has no upper limit
++ *
++ * This application executes a function in read mode on a given channel.
++ *
++ * \retval 0 success
++ * \retval non-zero failure
++ */
++int ast_func_read2(struct ast_channel *chan, const char *function, struct ast_str **str, ssize_t maxlen);
++
++/*!
+ * \brief executes a write operation on a function
+ *
+ * \param chan Channel to execute on
+@@ -1120,6 +1199,14 @@
+ unsigned int ast_hashtab_hash_contexts(const void *obj);
+ /*! @} */
+
++/*!
++ * \brief Command completion for the list of installed applications.
++ *
++ * This can be called from a CLI command completion function that wants to
++ * complete from the list of available applications.
++ */
++char *ast_complete_applications(const char *line, const char *word, int state);
++
+ #if defined(__cplusplus) || defined(c_plusplus)
+ }
+ #endif
+Index: include/asterisk/strings.h
+===================================================================
+--- a/include/asterisk/strings.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/strings.h (.../trunk) (revision 202568)
+@@ -281,7 +281,7 @@
+ * string. It will also place a space in the result buffer in between each
+ * string from 'w'.
+ */
+-void ast_join(char *s, size_t len, char * const w[]);
++void ast_join(char *s, size_t len, const char * const w[]);
+
+ /*
+ \brief Parse a time (integer) string.
+@@ -454,7 +454,7 @@
+ * \param buf A pointer to the ast_str structure.
+ */
+ AST_INLINE_API(
+-size_t attribute_pure ast_str_strlen(struct ast_str *buf),
++size_t attribute_pure ast_str_strlen(const struct ast_str *buf),
+ {
+ return buf->__AST_STR_USED;
+ }
+@@ -465,7 +465,7 @@
+ * \retval Current maximum length of the buffer.
+ */
+ AST_INLINE_API(
+-size_t attribute_pure ast_str_size(struct ast_str *buf),
++size_t attribute_pure ast_str_size(const struct ast_str *buf),
+ {
+ return buf->__AST_STR_LEN;
+ }
+@@ -476,9 +476,13 @@
+ * \retval A pointer to the enclosed string.
+ */
+ AST_INLINE_API(
+-char * attribute_pure ast_str_buffer(struct ast_str *buf),
++char * attribute_pure ast_str_buffer(const struct ast_str *buf),
+ {
+- return buf->__AST_STR_STR;
++ /* for now, cast away the const qualifier on the pointer
++ * being returned; eventually, it should become truly const
++ * and only be modified via accessor functions
++ */
++ return (char *) buf->__AST_STR_STR;
+ }
+ )
+
+Index: include/asterisk/stun.h
+===================================================================
+--- a/include/asterisk/stun.h (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/include/asterisk/stun.h (.../trunk) (revision 202568)
+@@ -0,0 +1,71 @@
++/*
++ * Asterisk -- An open source telephony toolkit.
++ *
++ * Copyright (C) 1999 - 2008, Digium, Inc.
++ *
++ * Mark Spencer <markster@digium.com>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * 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.
++ */
++
++/*!
++ * \file stun.h
++ * \brief STUN support.
++ *
++ * STUN is defined in RFC 3489.
++ */
++
++#ifndef _ASTERISK_STUN_H
++#define _ASTERISK_STUN_H
++
++#include "asterisk/network.h"
++
++#if defined(__cplusplus) || defined(c_plusplus)
++extern "C" {
++#endif
++
++enum ast_stun_result {
++ AST_STUN_IGNORE = 0,
++ AST_STUN_ACCEPT,
++};
++
++struct stun_attr;
++
++/*! \brief Generic STUN request
++ * send a generic stun request to the server specified.
++ * \param s the socket used to send the request
++ * \param dst the address of the STUN server
++ * \param username if non null, add the username in the request
++ * \param answer if non null, the function waits for a response and
++ * puts here the externally visible address.
++ * \return 0 on success, other values on error.
++ * The interface it may change in the future.
++ */
++int ast_stun_request(int s, struct sockaddr_in *dst, const char *username, struct sockaddr_in *answer);
++
++/*! \brief callback type to be invoked on stun responses. */
++typedef int (stun_cb_f)(struct stun_attr *attr, void *arg);
++
++/*! \brief handle an incoming STUN message.
++ *
++ * Do some basic sanity checks on packet size and content,
++ * try to extract a bit of information, and possibly reply.
++ * At the moment this only processes BIND requests, and returns
++ * the externally visible address of the request.
++ * If a callback is specified, invoke it with the attribute.
++ */
++int ast_stun_handle_packet(int s, struct sockaddr_in *src, unsigned char *data, size_t len, stun_cb_f *stun_cb, void *arg);
++
++#if defined(__cplusplus) || defined(c_plusplus)
++}
++#endif
++
++#endif /* _ASTERISK_STUN_H */
+
+Property changes on: include/asterisk/stun.h
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+
+Index: include/asterisk/stringfields.h
+===================================================================
+--- a/include/asterisk/stringfields.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/stringfields.h (.../trunk) (revision 202568)
+@@ -57,25 +57,23 @@
+
+ Fields will default to pointing to an empty string, and will revert to
+ that when ast_string_field_set() is called with a NULL argument.
+- A string field will \b never contain NULL (this feature is not used
+- in this code, but comes from external requirements).
++ A string field will \b never contain NULL.
+
+ ast_string_field_init(x, 0) will reset fields to the
+ initial value while keeping the pool allocated.
+
+ Reading the fields is much like using 'const char * const' fields in the
+- structure: you cannot write to the field or to the memory it points to
+- (XXX perhaps the latter is too much of a restriction since values
+- are not shared).
++ structure: you cannot write to the field or to the memory it points to.
+
+ Writing to the fields must be done using the wrapper macros listed below;
+ and assignments are always by value (i.e. strings are copied):
+ * ast_string_field_set() stores a simple value;
+- * ast_string_field_build() builds the string using a printf-style;
++ * ast_string_field_build() builds the string using a printf-style format;
+ * ast_string_field_build_va() is the varargs version of the above (for
+- portability reasons it uses two vararg);
++ portability reasons it uses two vararg arguments);
+ * variants of these function allow passing a pointer to the field
+ as an argument.
++
+ \code
+ ast_string_field_set(x, foo, "infinite loop");
+ ast_string_field_set(x, foo, NULL); // set to an empty string
+@@ -110,6 +108,9 @@
+
+ Don't declare instances of this type directly; use the AST_STRING_FIELD()
+ macro instead.
++
++ In addition to the string itself, the amount of space allocated for the
++ field is stored in the two bytes immediately preceding it.
+ */
+ typedef const char * ast_string_field;
+
+@@ -117,7 +118,7 @@
+ \internal
+ \brief A constant empty string used for fields that have no other value
+ */
+-extern const char __ast_string_field_empty[];
++extern const char *__ast_string_field_empty;
+
+ /*!
+ \internal
+@@ -125,19 +126,19 @@
+ */
+ struct ast_string_field_pool {
+ struct ast_string_field_pool *prev; /*!< pointer to the previous pool, if any */
++ size_t size; /*!< the total size of the pool */
++ size_t used; /*!< the space used in the pool */
++ size_t active; /*!< the amount of space actively in use by fields */
+ char base[0]; /*!< storage space for the fields */
+ };
+
+ /*!
+ \internal
+ \brief Structure used to manage the storage for a set of string fields.
+- Because of the way pools are managed, we can only allocate from the topmost
+- pool, so the numbers here reflect just that.
+ */
+ struct ast_string_field_mgr {
+- size_t size; /*!< the total size of the current pool */
+- size_t used; /*!< the space used in the current pool */
+- ast_string_field last_alloc; /*!< the last field allocated */
++ ast_string_field last_alloc; /*!< the last field allocated */
++ struct ast_string_field_pool *embedded_pool; /*!< pointer to the embedded pool, if any */
+ #if defined(__AST_DEBUG_MALLOC)
+ const char *owner_file; /*!< filename of owner */
+ const char *owner_func; /*!< function name of owner */
+@@ -159,7 +160,8 @@
+ the pool has enough space available. If so, the additional space will be
+ allocated to this field and the field's address will not be changed.
+ */
+-int __ast_string_field_ptr_grow(struct ast_string_field_mgr *mgr, size_t needed,
++int __ast_string_field_ptr_grow(struct ast_string_field_mgr *mgr,
++ struct ast_string_field_pool **pool_head, size_t needed,
+ const ast_string_field *ptr);
+
+ /*!
+@@ -181,7 +183,7 @@
+ \internal
+ \brief Set a field to a complex (built) value
+ \param mgr Pointer to the pool manager structure
+- \param fields Pointer to the first entry of the field array
++ \param pool_head Pointer to the current pool
+ \param ptr Pointer to a field within the structure
+ \param format printf-style format string
+ \return nothing
+@@ -194,7 +196,7 @@
+ \internal
+ \brief Set a field to a complex (built) value
+ \param mgr Pointer to the pool manager structure
+- \param fields Pointer to the first entry of the field array
++ \param pool_head Pointer to the current pool
+ \param ptr Pointer to a field within the structure
+ \param format printf-style format string
+ \param args va_list of the args for the format_string
+@@ -253,26 +255,76 @@
+ int needed, const char *file, int lineno, const char *func);
+
+ /*!
++ * \brief Allocate a structure with embedded stringfields in a single allocation
++ * \param n Number of structures to allocate (see ast_calloc)
++ * \param type The type of structure to allocate
++ * \param size The number of bytes of space (minimum) to allocate for stringfields to use
++ *
++ * This function will allocate memory for one or more structures that use stringfields, and
++ * also allocate space for the stringfields and initialize the stringfield management
++ * structure embedded in the outer structure.
++ *
++ * \since 1.6.3
++ */
++#define ast_calloc_with_stringfields(n, type, size) \
++ __ast_calloc_with_stringfields(n, sizeof(type), offsetof(type, __field_mgr), offsetof(type, __field_mgr_pool), \
++ size, __FILE__, __LINE__, __PRETTY_FUNCTION__)
++
++/*!
++ * \internal
++ * \brief internal version of ast_calloc_with_stringfields
++ */
++void * attribute_malloc __ast_calloc_with_stringfields(unsigned int num_structs, size_t struct_size, size_t field_mgr_offset,
++ size_t field_mgr_pool_offset, size_t pool_size, const char *file,
++ int lineno, const char *func);
++
++/*!
++ \internal
++ \brief Release a field's allocation from a pool
++ \param pool_head Pointer to the current pool
++ \param ptr Field to be released
++ \return nothing
++
++ This function will search the pool list to find the pool that contains
++ the allocation for the specified field, then remove the field's allocation
++ from that pool's 'active' count. If the pool's active count reaches zero,
++ and it is not the current pool, then it will be freed.
++ */
++void __ast_string_field_release_active(struct ast_string_field_pool *pool_head,
++ const ast_string_field ptr);
++
++/* the type of storage used to track how many bytes were allocated for a field */
++
++typedef uint16_t ast_string_field_allocation;
++
++/*!
++ \brief Macro to provide access to the allocation field that lives immediately in front of a string field
++ \param x Pointer to the string field
++*/
++#define AST_STRING_FIELD_ALLOCATION(x) *((ast_string_field_allocation *) (x - sizeof(ast_string_field_allocation)))
++
++/*!
+ \brief Set a field to a simple string value
+ \param x Pointer to a structure containing fields
+ \param ptr Pointer to a field within the structure
+- \param data String value to be copied into the field
++ \param data String value to be copied into the field
+ \return nothing
+ */
+-#define ast_string_field_ptr_set(x, ptr, data) do { \
+- const char *__d__ = (data); \
+- size_t __dlen__ = (__d__) ? strlen(__d__) + 1 : 1; \
+- const char **__p__ = (const char **) (ptr); \
+- char *__q__; \
+- if (__dlen__ == 1) \
+- *__p__ = __ast_string_field_empty; \
+- else if (!__ast_string_field_ptr_grow(&(x)->__field_mgr, __dlen__, ptr)) { \
+- __q__ = (char *) *__p__; \
+- memcpy(__q__, __d__, __dlen__); \
+- } else if ((*__p__ = __ast_string_field_alloc_space(&(x)->__field_mgr, &(x)->__field_mgr_pool, __dlen__))) { \
+- __q__ = (char *) *__p__; \
+- memcpy(__q__, __d__, __dlen__); \
+- } \
++#define ast_string_field_ptr_set(x, ptr, data) do { \
++ const char *__d__ = (data); \
++ size_t __dlen__ = (__d__) ? strlen(__d__) + 1 : 1; \
++ ast_string_field *__p__ = (ast_string_field *) (ptr); \
++ if (__dlen__ == 1) { \
++ __ast_string_field_release_active((x)->__field_mgr_pool, *__p__); \
++ *__p__ = __ast_string_field_empty; \
++ } else if ((__dlen__ <= AST_STRING_FIELD_ALLOCATION(*__p__)) || \
++ (!__ast_string_field_ptr_grow(&(x)->__field_mgr, &(x)->__field_mgr_pool, __dlen__, __p__)) || \
++ (*__p__ = __ast_string_field_alloc_space(&(x)->__field_mgr, &(x)->__field_mgr_pool, __dlen__))) { \
++ if (*__p__ != (*ptr)) { \
++ __ast_string_field_release_active((x)->__field_mgr_pool, (*ptr)); \
++ } \
++ memcpy(* (void **) __p__, __d__, __dlen__); \
++ } \
+ } while (0)
+
+ /*!
+Index: include/asterisk/agi.h
+===================================================================
+--- a/include/asterisk/agi.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/agi.h (.../trunk) (revision 202568)
+@@ -40,22 +40,22 @@
+ } AGI;
+
+ typedef struct agi_command {
+- char *cmda[AST_MAX_CMD_LEN]; /*!< Null terminated list of the words of the command */
++ const char * const cmda[AST_MAX_CMD_LEN]; /*!< Null terminated list of the words of the command */
+ /*! Handler for the command (channel, AGI state, # of arguments, argument list).
+ Returns RESULT_SHOWUSAGE for improper arguments */
+- int (*handler)(struct ast_channel *chan, AGI *agi, int argc, char *argv[]);
++ int (* const handler)(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[]);
+ /*! Summary of the command (< 60 characters) */
+- char *summary;
++ const char * const summary;
+ /*! Detailed usage information */
+- char *usage;
++ const char * const usage;
+ /*! Does this application run dead */
+- int dead;
++ const int dead;
+ /*! AGI command syntax description */
+- char *syntax;
++ const char * const syntax;
+ /*! See also content */
+- char *seealso;
++ const char * const seealso;
+ /*! Where the documentation come from. */
+- enum ast_doc_src docsrc;
++ const enum ast_doc_src docsrc;
+ /*! Pointer to module that registered the agi command */
+ struct ast_module *mod;
+ /*! Linked list pointer */
+@@ -72,7 +72,8 @@
+ * \return 1 on success, 0 if the command is already registered
+ *
+ */
+-AST_OPTIONAL_API(int, ast_agi_register, (struct ast_module *mod, agi_command *cmd),
++AST_OPTIONAL_API(int, ast_agi_register,
++ (struct ast_module *mod, agi_command *cmd),
+ { return AST_OPTIONAL_API_UNAVAILABLE; });
+
+ /*!
+@@ -85,7 +86,8 @@
+ * \return 1 on success, 0 if the command was not already registered
+ *
+ */
+-AST_OPTIONAL_API(int, ast_agi_unregister, (struct ast_module *mod, agi_command *cmd),
++AST_OPTIONAL_API(int, ast_agi_unregister,
++ (struct ast_module *mod, agi_command *cmd),
+ { return AST_OPTIONAL_API_UNAVAILABLE; });
+
+ /*!
+@@ -103,7 +105,8 @@
+ * will be unregistered. In other words, this function registers all the provided commands, or none
+ * of them.
+ */
+-AST_OPTIONAL_API(int, ast_agi_register_multiple, (struct ast_module *mod, struct agi_command *cmd, unsigned int len),
++AST_OPTIONAL_API(int, ast_agi_register_multiple,
++ (struct ast_module *mod, struct agi_command *cmd, unsigned int len),
+ { return AST_OPTIONAL_API_UNAVAILABLE; });
+
+ /*!
+@@ -120,7 +123,8 @@
+ * \note If any command fails to unregister, this function will continue to unregister the
+ * remaining commands in the array; it will not reregister the already-unregistered commands.
+ */
+-AST_OPTIONAL_API(int, ast_agi_unregister_multiple, (struct ast_module *mod, struct agi_command *cmd, unsigned int len),
++AST_OPTIONAL_API(int, ast_agi_unregister_multiple,
++ (struct ast_module *mod, struct agi_command *cmd, unsigned int len),
+ { return AST_OPTIONAL_API_UNAVAILABLE; });
+
+ /*!
+@@ -134,7 +138,8 @@
+ * \return 0 for success, -1 for failure, AST_OPTIONAL_API_UNAVAILABLE if res_agi is not loaded
+ *
+ */
+-AST_OPTIONAL_API_ATTR(int, format(printf, 3, 4), ast_agi_send, (int fd, struct ast_channel *chan, char *fmt, ...),
++AST_OPTIONAL_API_ATTR(int, format(printf, 3, 4), ast_agi_send,
++ (int fd, struct ast_channel *chan, char *fmt, ...),
+ { return AST_OPTIONAL_API_UNAVAILABLE; });
+
+ #if defined(__cplusplus) || defined(c_plusplus)
+Index: include/asterisk/autoconfig.h.in
+===================================================================
+--- a/include/asterisk/autoconfig.h.in (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/autoconfig.h.in (.../trunk) (revision 202568)
+@@ -94,9 +94,6 @@
+ /* Define to 1 if you have the `atexit' function. */
+ #undef HAVE_ATEXIT
+
+-/* Define to 1 if your GCC C compiler supports the 'alias' attribute. */
+-#undef HAVE_ATTRIBUTE_alias
+-
+ /* Define to 1 if your GCC C compiler supports the 'always_inline' attribute.
+ */
+ #undef HAVE_ATTRIBUTE_always_inline
+@@ -123,12 +120,12 @@
+ attribute. */
+ #undef HAVE_ATTRIBUTE_warn_unused_result
+
+-/* Define to 1 if your GCC C compiler supports the 'weak' attribute. */
+-#undef HAVE_ATTRIBUTE_weak
+-
+ /* Define to 1 if your GCC C compiler supports the 'weak_import' attribute. */
+ #undef HAVE_ATTRIBUTE_weak_import
+
++/* Define to 1 if your GCC C compiler supports the 'weakref' attribute. */
++#undef HAVE_ATTRIBUTE_weakref
++
+ /* Define this to indicate the ${BKTR_DESCRIP} library */
+ #undef HAVE_BKTR
+
+@@ -192,6 +189,12 @@
+ /* Define if your system has the DAHDI headers. */
+ #undef HAVE_DAHDI
+
++/* Define if your system has the DAHDI_ECHOCANCEL_FAX_MODE headers. */
++#undef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
++
++/* Define DAHDI_ECHOCANCEL_FAX_MODE headers version */
++#undef HAVE_DAHDI_ECHOCANCEL_FAX_MODE_VERSION
++
+ /* Define if your system has the DAHDI_HALF_FULL headers. */
+ #undef HAVE_DAHDI_HALF_FULL
+
+@@ -358,6 +361,18 @@
+ /* Define to 1 if you have the `glob' function. */
+ #undef HAVE_GLOB
+
++/* Define if your system has the GLOB_BRACE headers. */
++#undef HAVE_GLOB_BRACE
++
++/* Define GLOB_BRACE headers version */
++#undef HAVE_GLOB_BRACE_VERSION
++
++/* Define if your system has the GLOB_NOMAGIC headers. */
++#undef HAVE_GLOB_NOMAGIC
++
++/* Define GLOB_NOMAGIC headers version */
++#undef HAVE_GLOB_NOMAGIC_VERSION
++
+ /* Define if your system has the GMIME libraries. */
+ #undef HAVE_GMIME
+
+@@ -382,6 +397,12 @@
+ /* Define to indicate the ${HOARD_DESCRIP} library version */
+ #undef HAVE_HOARD_VERSION
+
++/* Define this to indicate the ${ICAL_DESCRIP} library */
++#undef HAVE_ICAL
++
++/* Define to indicate the ${ICAL_DESCRIP} library version */
++#undef HAVE_ICAL_VERSION
++
+ /* Define this to indicate the ${ICONV_DESCRIP} library */
+ #undef HAVE_ICONV
+
+@@ -575,6 +596,9 @@
+ /* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+ #undef HAVE_NDIR_H
+
++/* Define if your system has the NEON libraries. */
++#undef HAVE_NEON
++
+ /* Define to 1 if you have the <netdb.h> header file. */
+ #undef HAVE_NETDB_H
+
+@@ -674,6 +698,12 @@
+ /* Define to indicate the ${PRI_PROG_W_CAUSE_DESCRIP} library version */
+ #undef HAVE_PRI_PROG_W_CAUSE_VERSION
+
++/* Define this to indicate the ${PRI_SERVICE_MESSAGES_DESCRIP} library */
++#undef HAVE_PRI_SERVICE_MESSAGES
++
++/* Define to indicate the ${PRI_SERVICE_MESSAGES_DESCRIP} library version */
++#undef HAVE_PRI_SERVICE_MESSAGES_VERSION
++
+ /* Define to indicate the ${PRI_DESCRIP} library version */
+ #undef HAVE_PRI_VERSION
+
+@@ -1181,9 +1211,6 @@
+ /* Define to the version of this package. */
+ #undef PACKAGE_VERSION
+
+-/* Define to 1 if the C compiler supports function prototypes. */
+-#undef PROTOTYPES
+-
+ /* Define to necessary symbol if this constant uses a non-standard name on
+ your system. */
+ #undef PTHREAD_CREATE_JOINABLE
+@@ -1200,11 +1227,6 @@
+ /* Define to the type of arg 5 for `select'. */
+ #undef SELECT_TYPE_ARG5
+
+-/* Define to 1 if the `setvbuf' function takes the buffering type as its
+- second argument and the buffer pointer as the third, as on System V before
+- release 3. */
+-#undef SETVBUF_REVERSED
+-
+ /* The size of `int', as computed by sizeof. */
+ #undef SIZEOF_INT
+
+@@ -1225,21 +1247,31 @@
+ /* Define to 1 if your <sys/time.h> declares `struct tm'. */
+ #undef TM_IN_SYS_TIME
+
+-/* Define to 1 if on AIX 3.
+- System headers sometimes define this.
+- We just want to avoid a redefinition error message. */
++/* Enable extensions on AIX 3, Interix. */
+ #ifndef _ALL_SOURCE
+ # undef _ALL_SOURCE
+ #endif
+-
+-/* Number of bits in a file offset, on hosts where this is settable. */
+-#undef _FILE_OFFSET_BITS
+-
+ /* Enable GNU extensions on systems that have them. */
+ #ifndef _GNU_SOURCE
+ # undef _GNU_SOURCE
+ #endif
++/* Enable threading extensions on Solaris. */
++#ifndef _POSIX_PTHREAD_SEMANTICS
++# undef _POSIX_PTHREAD_SEMANTICS
++#endif
++/* Enable extensions on HP NonStop. */
++#ifndef _TANDEM_SOURCE
++# undef _TANDEM_SOURCE
++#endif
++/* Enable general extensions on Solaris. */
++#ifndef __EXTENSIONS__
++# undef __EXTENSIONS__
++#endif
+
++
++/* Number of bits in a file offset, on hosts where this is settable. */
++#undef _FILE_OFFSET_BITS
++
+ /* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
+ #undef _LARGEFILE_SOURCE
+
+@@ -1256,20 +1288,6 @@
+ /* Define to 1 if you need to in order for `stat' and other things to work. */
+ #undef _POSIX_SOURCE
+
+-/* Enable extensions on Solaris. */
+-#ifndef __EXTENSIONS__
+-# undef __EXTENSIONS__
+-#endif
+-#ifndef _POSIX_PTHREAD_SEMANTICS
+-# undef _POSIX_PTHREAD_SEMANTICS
+-#endif
+-#ifndef _TANDEM_SOURCE
+-# undef _TANDEM_SOURCE
+-#endif
+-
+-/* Define like PROTOTYPES; this can be used by system headers. */
+-#undef __PROTOTYPES
+-
+ /* Define to empty if `const' does not conform to ANSI C. */
+ #undef const
+
+Index: include/asterisk/extconf.h
+===================================================================
+--- a/include/asterisk/extconf.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/extconf.h (.../trunk) (revision 202568)
+@@ -185,7 +185,7 @@
+ * \version 1.6.1 renamed function from localized_context_create to localized_context_find_or_create
+ */
+ struct ast_context *localized_context_find_or_create(struct ast_context **extcontexts, void *tab, const char *name, const char *registrar);
+-int localized_pbx_builtin_setvar(struct ast_channel *chan, void *data);
++int localized_pbx_builtin_setvar(struct ast_channel *chan, const void *data);
+ int localized_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar);
+ int localized_context_add_switch2(struct ast_context *con, const char *value,
+ const char *data, int eval, const char *registrar);
+Index: include/asterisk/tcptls.h
+===================================================================
+--- a/include/asterisk/tcptls.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/tcptls.h (.../trunk) (revision 202568)
+@@ -72,12 +72,19 @@
+ /*! Don't verify certificate when connecting to a server */
+ AST_SSL_DONT_VERIFY_SERVER = (1 << 1),
+ /*! Don't compare "Common Name" against IP or hostname */
+- AST_SSL_IGNORE_COMMON_NAME = (1 << 2)
++ AST_SSL_IGNORE_COMMON_NAME = (1 << 2),
++ /*! Use SSLv2 for outgoing client connections */
++ AST_SSL_SSLV2_CLIENT = (1 << 3),
++ /*! Use SSLv3 for outgoing client connections */
++ AST_SSL_SSLV3_CLIENT = (1 << 4),
++ /*! Use TLSv1 for outgoing client connections */
++ AST_SSL_TLSV1_CLIENT = (1 << 5)
+ };
+
+ struct ast_tls_config {
+ int enabled;
+ char *certfile;
++ char *pvtfile;
+ char *cipher;
+ char *cafile;
+ char *capath;
+@@ -173,6 +180,11 @@
+ void ast_tcptls_server_stop(struct ast_tcptls_session_args *desc);
+ int ast_ssl_setup(struct ast_tls_config *cfg);
+
++/*!
++ * \brief Used to parse conf files containing tls/ssl options.
++ */
++int ast_tls_read_conf(struct ast_tls_config *tls_cfg, struct ast_tcptls_session_args *tls_desc, const char *varname, const char *value);
++
+ HOOK_T ast_tcptls_server_read(struct ast_tcptls_session_instance *ser, void *buf, size_t count);
+ HOOK_T ast_tcptls_server_write(struct ast_tcptls_session_instance *ser, const void *buf, size_t count);
+
+Index: include/asterisk/compiler.h
+===================================================================
+--- a/include/asterisk/compiler.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/compiler.h (.../trunk) (revision 202568)
+@@ -68,16 +68,4 @@
+ /* Some older version of GNU gcc (3.3.5 on OpenBSD 4.3 for example) dont like 'NULL' as sentinel */
+ #define SENTINEL ((char *)NULL)
+
+-#ifdef HAVE_ATTRIBUTE_weak
+-#define attribute_weak __attribute__((weak))
+-#else
+-#define attribute_weak
+-#endif
+-
+-#ifdef HAVE_ATTRIBUTE_weak_import
+-#define attribute_weak_import __attribute__((weak_import))
+-#else
+-#define attribute_weak_import
+-#endif
+-
+ #endif /* _ASTERISK_COMPILER_H */
+Index: include/asterisk/callerid.h
+===================================================================
+--- a/include/asterisk/callerid.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/callerid.h (.../trunk) (revision 202568)
+@@ -86,21 +86,24 @@
+ void callerid_init(void);
+
+ /*! \brief Generates a CallerID FSK stream in ulaw format suitable for transmission.
+- * \param buf Buffer to use. If "buf" is supplied, it will use that buffer instead of allocating its own. "buf" must be at least 32000 bytes in size of you want to be sure you don't have an overrun.
++ * \param buf Buffer to use. If "buf" is supplied, it will use that buffer instead of allocating its own.
++ * "buf" must be at least 32000 bytes in size of you want to be sure you don't have an overrun.
+ * \param number Use NULL for no number or "P" for "private"
+ * \param name name to be used
+ * \param flags passed flags
+ * \param callwaiting callwaiting flag
+ * \param codec -- either AST_FORMAT_ULAW or AST_FORMAT_ALAW
++ * \details
+ * This function creates a stream of callerid (a callerid spill) data in ulaw format.
+ * \return It returns the size
+ * (in bytes) of the data (if it returns a size of 0, there is probably an error)
+-*/
++ */
+ int callerid_generate(unsigned char *buf, const char *number, const char *name, int flags, int callwaiting, int codec);
+
+ /*! \brief Create a callerID state machine
+ * \param cid_signalling Type of signalling in use
+ *
++ * \details
+ * This function returns a malloc'd instance of the callerid_state data structure.
+ * \return Returns a pointer to a malloc'd callerid_state structure, or NULL on error.
+ */
+@@ -112,9 +115,11 @@
+ * \param samples number of samples contained within the buffer.
+ * \param codec which codec (AST_FORMAT_ALAW or AST_FORMAT_ULAW)
+ *
++ * \details
+ * Send received audio to the Caller*ID demodulator.
+- * \return Returns -1 on error, 0 for "needs more samples",
+- * and 1 if the CallerID spill reception is complete.
++ * \retval -1 on error
++ * \retval 0 for "needs more samples"
++ * \retval 1 if the CallerID spill reception is complete.
+ */
+ int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int samples, int codec);
+
+@@ -124,9 +129,11 @@
+ * \param samples number of samples contained within the buffer.
+ * \param codec which codec (AST_FORMAT_ALAW or AST_FORMAT_ULAW)
+ *
++ * \details
+ * Send received audio to the Caller*ID demodulator (for japanese style lines).
+- * \return Returns -1 on error, 0 for "needs more samples",
+- * and 1 if the CallerID spill reception is complete.
++ * \retval -1 on error
++ * \retval 0 for "needs more samples"
++ * \retval 1 if the CallerID spill reception is complete.
+ */
+ int callerid_feed_jp(struct callerid_state *cid, unsigned char *ubuf, int samples, int codec);
+
+@@ -136,6 +143,7 @@
+ * \param name Pass the address of a pointer-to-char (will contain the name)
+ * \param flags Pass the address of an int variable(will contain the various callerid flags)
+ *
++ * \details
+ * This function extracts a callerid string out of a callerid_state state machine.
+ * If no number is found, *number will be set to NULL. Likewise for the name.
+ * Flags can contain any of the following:
+@@ -144,18 +152,16 @@
+ */
+ void callerid_get(struct callerid_state *cid, char **number, char **name, int *flags);
+
+-/*! Get and parse DTMF-based callerid */
+ /*!
++ * \brief Get and parse DTMF-based callerid
+ * \param cidstring The actual transmitted string.
+ * \param number The cid number is returned here.
+ * \param flags The cid flags are returned here.
+- * This function parses DTMF callerid.
+ */
+ void callerid_get_dtmf(char *cidstring, char *number, int *flags);
+
+-/*! \brief Free a callerID state
++/*! \brief This function frees callerid_state cid.
+ * \param cid This is the callerid_state state machine to free
+- * This function frees callerid_state cid.
+ */
+ void callerid_free(struct callerid_state *cid);
+
+@@ -165,36 +171,44 @@
+ * \param number Caller-ID Number
+ * \param codec Asterisk codec (either AST_FORMAT_ALAW or AST_FORMAT_ULAW)
+ *
++ * \details
+ * Acts like callerid_generate except uses an asterisk format callerid string.
+ */
+ int ast_callerid_generate(unsigned char *buf, const char *name, const char *number, int codec);
+
+-/*! \brief Generate message waiting indicator
+- * \param active The message indicator state
++/*!
++ * \brief Generate message waiting indicator
++ * \param active The message indicator state
+ * -- either 0 no messages in mailbox or 1 messages in mailbox
+- * \param type Format of message (any of CID_MWI_TYPE_*)
+- * \see callerid_generate() for more info as it use the same encoding
+- * \version 1.6.1 changed mdmf parameter to type, added name, number and flags for caller id message generation
+-*/
+-int vmwi_generate(unsigned char *buf, int active, int type, int codec, const char *name,
++ * \param type Format of message (any of CID_MWI_TYPE_*)
++ * \see callerid_generate() for more info as it uses the same encoding
++ * \version 1.6.1 changed mdmf parameter to type, added name, number and flags for caller id message generation
++ */
++int ast_callerid_vmwi_generate(unsigned char *buf, int active, int type, int codec, const char *name,
+ const char *number, int flags);
+
+ /*! \brief Generate Caller-ID spill but in a format suitable for Call Waiting(tm)'s Caller*ID(tm)
+- * See ast_callerid_generate() for other details
++ * \see ast_callerid_generate() for other details
+ */
+ int ast_callerid_callwaiting_generate(unsigned char *buf, const char *name, const char *number, int codec);
+
+ /*! \brief Destructively parse inbuf into name and location (or number)
++ * \details
+ * Parses callerid stream from inbuf and changes into useable form, outputed in name and location.
+ * \param instr buffer of callerid stream (in audio form) to be parsed. Warning, data in buffer is changed.
+ * \param name address of a pointer-to-char for the name value of the stream.
+ * \param location address of a pointer-to-char for the phone number value of the stream.
++ * \note XXX 'name' is not parsed consistently e.g. we have
++ * input location name
++ * " foo bar " <123> 123 ' foo bar ' (with spaces around)
++ * " foo bar " NULL 'foo bar' (without spaces around)
++ * The parsing of leading and trailing space/quotes should be more consistent.
+ * \return Returns 0 on success, -1 on failure.
+ */
+ int ast_callerid_parse(char *instr, char **name, char **location);
+
+-/*! Generate a CAS (CPE Alert Signal) tone for 'n' samples */
+ /*!
++ * \brief Generate a CAS (CPE Alert Signal) tone for 'n' samples
+ * \param outbuf Allocated buffer for data. Must be at least 2400 bytes unless no SAS is desired
+ * \param sas Non-zero if CAS should be preceeded by SAS
+ * \param len How many samples to generate.
+@@ -203,23 +217,26 @@
+ */
+ int ast_gen_cas(unsigned char *outbuf, int sas, int len, int codec);
+
+-/*! \brief Shrink a phone number in place to just digits (more accurately it just removes ()'s, .'s, and -'s... */
+ /*!
++ * \brief Shrink a phone number in place to just digits (more accurately it just removes ()'s, .'s, and -'s...
+ * \param n The number to be stripped/shrunk
+ * \return Returns nothing important
+ */
+ void ast_shrink_phone_number(char *n);
+
+-/*! \brief Check if a string consists only of digits and + \#
+- \param n number to be checked.
+- \return Returns 0 if n is a number, 1 if it's not.
++/*!
++ * \brief Check if a string consists only of digits and + \#
++ * \param n number to be checked.
++ * \return Returns 0 if n is a number, 1 if it's not.
+ */
+ int ast_isphonenumber(const char *n);
+
+-/*! \brief Check if a string consists only of digits and and + \# ( ) - .
+- (meaning it can be cleaned with ast_shrink_phone_number)
+- \param exten The extension (or URI) to be checked.
+- \return Returns 0 if n is a number, 1 if it's not.
++/*!
++ * \brief Check if a string consists only of digits and and + \# ( ) - .
++ * (meaning it can be cleaned with ast_shrink_phone_number)
++ * \param exten The extension (or URI) to be checked.
++ * \retval 1 if string is valid AST shrinkable phone number
++ * \retval 0 if not
+ */
+ int ast_is_shrinkable_phonenumber(const char *exten);
+
+@@ -289,71 +306,171 @@
+
+ /* Various defines and bits for handling PRI- and SS7-type restriction */
+
+-#define AST_PRES_NUMBER_TYPE 0x03
++#define AST_PRES_NUMBER_TYPE 0x03
+ #define AST_PRES_USER_NUMBER_UNSCREENED 0x00
+ #define AST_PRES_USER_NUMBER_PASSED_SCREEN 0x01
+ #define AST_PRES_USER_NUMBER_FAILED_SCREEN 0x02
+-#define AST_PRES_NETWORK_NUMBER 0x03
++#define AST_PRES_NETWORK_NUMBER 0x03
+
+-#define AST_PRES_RESTRICTION 0x60
+-#define AST_PRES_ALLOWED 0x00
+-#define AST_PRES_RESTRICTED 0x20
+-#define AST_PRES_UNAVAILABLE 0x40
+-#define AST_PRES_RESERVED 0x60
++#define AST_PRES_RESTRICTION 0x60
++#define AST_PRES_ALLOWED 0x00
++#define AST_PRES_RESTRICTED 0x20
++#define AST_PRES_UNAVAILABLE 0x40
++#define AST_PRES_RESERVED 0x60
+
+ #define AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED \
+- AST_PRES_USER_NUMBER_UNSCREENED + AST_PRES_ALLOWED
++ (AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_UNSCREENED)
+
+ #define AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN \
+- AST_PRES_USER_NUMBER_PASSED_SCREEN + AST_PRES_ALLOWED
++ (AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_PASSED_SCREEN)
+
+ #define AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN \
+- AST_PRES_USER_NUMBER_FAILED_SCREEN + AST_PRES_ALLOWED
++ (AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_FAILED_SCREEN)
+
+ #define AST_PRES_ALLOWED_NETWORK_NUMBER \
+- AST_PRES_NETWORK_NUMBER + AST_PRES_ALLOWED
++ (AST_PRES_ALLOWED | AST_PRES_NETWORK_NUMBER)
+
+ #define AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED \
+- AST_PRES_USER_NUMBER_UNSCREENED + AST_PRES_RESTRICTED
++ (AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_UNSCREENED)
+
+ #define AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN \
+- AST_PRES_USER_NUMBER_PASSED_SCREEN + AST_PRES_RESTRICTED
++ (AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_PASSED_SCREEN)
+
+ #define AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN \
+- AST_PRES_USER_NUMBER_FAILED_SCREEN + AST_PRES_RESTRICTED
++ (AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_FAILED_SCREEN)
+
+ #define AST_PRES_PROHIB_NETWORK_NUMBER \
+- AST_PRES_NETWORK_NUMBER + AST_PRES_RESTRICTED
++ (AST_PRES_RESTRICTED | AST_PRES_NETWORK_NUMBER)
+
+ #define AST_PRES_NUMBER_NOT_AVAILABLE \
+- AST_PRES_NETWORK_NUMBER + AST_PRES_UNAVAILABLE
++ (AST_PRES_UNAVAILABLE | AST_PRES_NETWORK_NUMBER)
+
+ int ast_parse_caller_presentation(const char *data);
+ const char *ast_describe_caller_presentation(int data);
+ const char *ast_named_caller_presentation(int data);
+
+-/*! \page Def_CallerPres Caller ID Presentation
++/*!
++ * \page Def_CallerPres Caller ID Presentation
++ *
++ * Caller ID presentation values are used to set properties to a
++ * caller ID in PSTN networks, and as RPID value in SIP transactions.
++ *
++ * The following values are available to use:
++ * \arg \b Defined value, text string in config file, explanation
++ *
++ * \arg \b AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, "allowed_not_screened", Presentation Allowed, Not Screened,
++ * \arg \b AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, "allowed_passed_screen", Presentation Allowed, Passed Screen,
++ * \arg \b AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN, "allowed_failed_screen", Presentation Allowed, Failed Screen,
++ * \arg \b AST_PRES_ALLOWED_NETWORK_NUMBER, "allowed", Presentation Allowed, Network Number,
++ * \arg \b AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED, "prohib_not_screened", Presentation Prohibited, Not Screened,
++ * \arg \b AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN, "prohib_passed_screen", Presentation Prohibited, Passed Screen,
++ * \arg \b AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN, "prohib_failed_screen", Presentation Prohibited, Failed Screen,
++ * \arg \b AST_PRES_PROHIB_NETWORK_NUMBER, "prohib", Presentation Prohibited, Network Number,
++ *
++ * \par References
++ * \arg \ref callerid.h Definitions
++ * \arg \ref callerid.c Functions
++ * \arg \ref CID Caller ID names and numbers
++ */
+
+- Caller ID presentation values are used to set properties to a
+- caller ID in PSTN networks, and as RPID value in SIP transactions.
++/*!
++ * \brief redirecting reason codes.
++ *
++ * This list attempts to encompass redirecting reasons
++ * as defined by several channel technologies.
++ */
++enum AST_REDIRECTING_REASON {
++ AST_REDIRECTING_REASON_UNKNOWN,
++ AST_REDIRECTING_REASON_USER_BUSY,
++ AST_REDIRECTING_REASON_NO_ANSWER,
++ AST_REDIRECTING_REASON_UNAVAILABLE,
++ AST_REDIRECTING_REASON_UNCONDITIONAL,
++ AST_REDIRECTING_REASON_TIME_OF_DAY,
++ AST_REDIRECTING_REASON_DO_NOT_DISTURB,
++ AST_REDIRECTING_REASON_DEFLECTION,
++ AST_REDIRECTING_REASON_FOLLOW_ME,
++ AST_REDIRECTING_REASON_OUT_OF_ORDER,
++ AST_REDIRECTING_REASON_AWAY,
++ AST_REDIRECTING_REASON_CALL_FWD_DTE, /* This is something defined in Q.931, and no I don't know what it means */
++};
+
+- The following values are available to use:
+- \arg \b Defined value, text string in config file, explanation
++/*!
++ * \since 1.6.3
++ * \brief Convert redirecting reason text code to value (used in config file parsing)
++ *
++ * \param data text string from config file
++ *
++ * \retval Q931_REDIRECTING_REASON from callerid.h
++ * \retval -1 if not in table
++ */
++int ast_redirecting_reason_parse(const char *data);
+
+- \arg \b AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, "allowed_not_screened", Presentation Allowed, Not Screened,
+- \arg \b AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, "allowed_passed_screen", Presentation Allowed, Passed Screen,
+- \arg \b AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN, "allowed_failed_screen", Presentation Allowed, Failed Screen,
+- \arg \b AST_PRES_ALLOWED_NETWORK_NUMBER, "allowed", Presentation Allowed, Network Number,
+- \arg \b AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED, "prohib_not_screened", Presentation Prohibited, Not Screened,
+- \arg \b AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN, "prohib_passed_screen", Presentation Prohibited, Passed Screen,
+- \arg \b AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN, "prohib_failed_screen", Presentation Prohibited, Failed Screen,
+- \arg \b AST_PRES_PROHIB_NETWORK_NUMBER, "prohib", Presentation Prohibited, Network Number,
++/*!
++ * \since 1.6.3
++ * \brief Convert redirecting reason value to explanatory string
++ *
++ * \param data Q931_REDIRECTING_REASON from callerid.h
++ *
++ * \return string for human presentation
++ */
++const char *ast_redirecting_reason_describe(int data);
+
+- \par References
+- \arg \ref callerid.h Definitions
+- \arg \ref callerid.c Functions
+- \arg \ref CID Caller ID names and numbers
+-*/
++/*!
++ * \since 1.6.3
++ * \brief Convert redirecting reason value to text code
++ *
++ * \param data Q931_REDIRECTING_REASON from callerid.h
++ *
++ * \return string for config file
++ */
++const char *ast_redirecting_reason_name(int data);
+
++/*!
++ * \brief Connected line update source code
++ */
++enum AST_CONNECTED_LINE_UPDATE_SOURCE {
++ /*! Update for unknown reason (May be interpreted to mean from answer) */
++ AST_CONNECTED_LINE_UPDATE_SOURCE_UNKNOWN,
++ /*! Update from normal call answering */
++ AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER,
++ /*! Update from call diversion (Deprecated, use REDIRECTING updates instead.) */
++ AST_CONNECTED_LINE_UPDATE_SOURCE_DIVERSION,
++ /*! Update from call transfer(active) (Party has already answered) */
++ AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER,
++ /*! Update from call transfer(alerting) (Party has not answered yet) */
++ AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING
++};
+
++/*!
++ * \since 1.6.3
++ * \brief Convert connected line update source text code to value (used in config file parsing)
++ *
++ * \param data text string from config file
++ *
++ * \retval AST_CONNECTED_LINE_UPDATE_SOURCE from callerid.h
++ * \retval -1 if not in table
++ */
++int ast_connected_line_source_parse(const char *data);
++
++/*!
++ * \since 1.6.3
++ * \brief Convert connected line update source value to explanatory string
++ *
++ * \param data AST_CONNECTED_LINE_UPDATE_SOURCE from callerid.h
++ *
++ * \return string for human presentation
++ */
++const char *ast_connected_line_source_describe(int data);
++
++/*!
++ * \since 1.6.3
++ * \brief Convert connected line update source value to text code
++ *
++ * \param data AST_CONNECTED_LINE_UPDATE_SOURCE from callerid.h
++ *
++ * \return string for config file
++ */
++const char *ast_connected_line_source_name(int data);
++
++
+ #endif /* _ASTERISK_CALLERID_H */
+Index: include/asterisk/doxyref.h
+===================================================================
+--- a/include/asterisk/doxyref.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/doxyref.h (.../trunk) (revision 202568)
+@@ -1,7 +1,7 @@
+ /*
+ * Asterisk -- An open source telephony toolkit.
+ *
+- * Copyright (C) 1999 - 2008, Digium, Inc.
++ * Copyright (C) 1999 - 2009, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+@@ -15,9 +15,11 @@
+ */
+
+ /*!
+- * \file
+- * \brief This file generates Doxygen pages from files in the /doc
+- * directory of the Asterisk source code tree
++ * \file
++ *
++ * This is the main header file used for generating miscellaneous developer
++ * documentation using doxygen. This also pulls in all of the documentation
++ * that is in include/asterisk/doxygen/.
+ */
+
+ /*
+@@ -34,6 +36,7 @@
+ * \arg \ref CommitMessages : Information on formatting and special tags for commit messages
+ * \arg \ref ReleaseStatus : The current support level for various Asterisk releases
+ * \arg \ref ReleasePolicies : Asterisk Release and Commit Policies
++ * \arg \ref Reviewboard : Reviewboard Usage and Guidelines
+ * \arg \ref AstCREDITS : A Thank You to contributors (unfortunately out of date)
+ *
+ * \section apisandinterfaces Asterisk APIs and Interfaces
+@@ -61,274 +64,13 @@
+ *
+ * \section weblinks Web sites
+ * \arg \b Main: Asterisk Developer's website http://www.asterisk.org/developers/
+- * \arg \b Bugs: The Issue Tracker http://bugs.digium.com
++ * \arg \b Bugs: The Issue Tracker https://issues.asterisk.org
+ * \arg \b Lists: List Server http://lists.digium.com
+ * \arg \b Wiki: The Asterisk Wiki http://www.voip-info.org
+ * \arg \b Docs: The Asterisk Documentation Project http://www.asteriskdocs.org
+ * \arg \b Digium: The Asterisk Company http://www.digium.com
+ */
+
+-/*!
+- * \page ReleaseStatus Asterisk Release Status
+- *
+- * @AsteriskTrunkWarning
+- *
+- * \section warranty Warranty
+- * The following warranty applies to all open source releases of Asterisk:
+- *
+- * NO WARRANTY
+- *
+- * BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+- * FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+- * OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+- * PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+- * OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+- * TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+- * PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+- * REPAIR OR CORRECTION.
+-
+- * IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+- * WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+- * REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+- * INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+- * OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+- * TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+- * YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+- * PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+- * POSSIBILITY OF SUCH DAMAGES.
+- *
+- * \section releasestatustypes Release Status Types
+- *
+- * Release management is a essentially an agreement between the development
+- * community and the %user community on what kind of updates can be expected
+- * for Asterisk releases, and what types of changes these updates will contain.
+- * Once these policies are established, the development community works very
+- * hard to adhere to them. However, the development community does reserve
+- * the right to make exceptions to these rules for special cases as the need
+- * arises.
+- *
+- * Asterisk releases are in various states of maintenance. The states are
+- * defined here:
+- *
+- * \arg <b>None</b> - This release series is receiving no updates whatsoever.
+- * \arg <b>Security-Only</b> - This release series is receiving updates, but
+- * only to address security issues. Security issues found and fixed in
+- * this release series will be accompanied by a published security advisory
+- * from the Asterisk project.
+- * \arg <b>Full-Support</b> - This release series is receiving updates for all
+- * types of bugs.
+- * \arg <b>Full-Development</b> - Changes in this part of Asterisk include bug
+- * fixes, as well as new %features and architectural improvements.
+- *
+- * \section AsteriskReleases Asterisk Maintenance Levels
+- *
+- * \htmlonly
+- * <table border="1">
+- * <tr>
+- * <td><b>Name</b></td>
+- * <td><b>SVN Branch</b></td>
+- * <td><b>Status</b></td>
+- * <td><b>Notes</b></td>
+- * </tr>
+- * <tr>
+- * <td>Asterisk 1.0</td>
+- * <td>/branches/1.0</td>
+- * <td>None</td>
+- * </tr>
+- * <tr>
+- * <td>Asterisk 1.2</td>
+- * <td>/branches/1.2</td>
+- * <td>Security-Only</td>
+- * </tr>
+- * <tr>
+- * <td>Asterisk 1.4</td>
+- * <td>/branches/1.4</td>
+- * <td>Full-Support</td>
+- * </tr>
+- * <tr>
+- * <td>Asterisk 1.6.0</td>
+- * <td>/branches/1.6.0</td>
+- * <td>Full-Support</td>
+- * </tr>
+- * <tr>
+- * <td>Asterisk 1.6.1</td>
+- * <td>/branches/1.6.1</td>
+- * <td>Full-Support</td>
+- * <td>Still in beta</td>
+- * </tr>
+- * <tr>
+- * <td>Asterisk trunk</td>
+- * <td>/trunk</td>
+- * <td>Full-Development</td>
+- * <td>No releases are made directly from trunk.</td>
+- * </tr>
+- * </table>
+- * \endhtmlonly
+- *
+- * For more information on how and when Asterisk releases are made, see the
+- * release policies page:
+- * \arg \ref ReleasePolicies
+- */
+-
+-/*!
+- * \page ReleasePolicies Asterisk Release and Commit Policies
+- *
+- * \AsteriskTrunkWarning
+- *
+- * \section releasestatus Asterisk Release Status
+- *
+- * For more information on the current status of each Asterisk release series,
+- * please see the Asterisk Release Status page:
+- *
+- * \arg \ref ReleaseStatus
+- *
+- * <hr/>
+- *
+- * \section commitmonitoring Commit Monitoring
+- *
+- * To monitor commits to Asterisk and related projects, visit
+- * <a href="http://lists.digium.com/">http://lists.digium.com</a>. The Digium
+- * mailing list server hosts a %number of mailing lists for commits.
+- *
+- * <hr/>
+- *
+- * \section ast10policy Asterisk 1.0
+- *
+- * \subsection svnbranch SVN Branch
+- *
+- * \arg /branches/1.0
+- *
+- * \subsection ast10releases Release and Commit Policy
+- * No more releases of Asterisk 1.0 will be made for any reason.
+- *
+- * No commits should be made to the Asterisk 1.0 branch.
+- *
+- * <hr/>
+- *
+- * \section ast12policy Asterisk 1.2
+- *
+- * \subsection svnbranch SVN Branch
+- *
+- * \arg /branches/1.2
+- *
+- * \subsection ast12releases Release and Commit Policy
+- *
+- * There will be no more scheduled releases of Asterisk 1.2.
+- *
+- * Commits to the Asterisk 1.2 branch should only address security issues or
+- * regressions introduced by previous security fixes. For a security issue, the
+- * commit should be accompanied by an
+- * <a href="http://downloads.digium.com/pub/security/">Asterisk Security Advisory</a>
+- * and an immediate release. When a commit goes in to fix a regression, the previous
+- * security advisory that is related to the change that introduced the bug should get
+- * updated to indicate that there is an updated version of the fix. A release should
+- * be made immediately for these regression fixes, as well.
+- *
+- * <hr/>
+- *
+- * \section ast14policy Asterisk 1.4
+- *
+- * \subsection svnbranch SVN Branch
+- *
+- * \arg /branches/1.4
+- *
+- * \subsection ast14releases Release and Commit Policy
+- *
+- * Asterisk 1.4 is receiving regular bug fix release updates. An attempt is made to
+- * make releases of every four to six weeks. Since this release series is receiving
+- * changes for all types of bugs, the number of changes in a single release can be
+- * significant. 1.4.X releases go through a release candidate testing cycle to help
+- * catch any regressions that may have been introduced.
+- *
+- * Commits to Asterisk 1.4 must be to address bugs only. No new %features should be
+- * introduced into Asterisk 1.4 to reduce the %number of changes to this established
+- * release series. The only exceptions to this %rule are for cases where something
+- * that may be considered a feature is needed to address a bug or security issue.
+- *
+- * <hr/>
+- *
+- * \section ast16policy Asterisk 1.6
+- *
+- * \subsection svnbranch SVN Branch
+- *
+- * \arg /branches/1.6.*
+- *
+- * \subsection ast16releases Release and Commit Policy
+- *
+- * Asterisk 1.6 is managed in a different way than previous Asterisk release series.
+- * From a high level, it was inspired by the release model used for Linux 2.6.
+- * The intended time frame for 1.6.X releases is every 2 or 3 months. Each 1.6.X
+- * release gets its own branch. The 1.6.X branches are branches off of trunk.
+- * Once the branch is created, it only receives bug fixes. Each 1.6.X release goes
+- * through a beta and release candidate testing cycle.
+- *
+- * After a 1.6.X release is published, it will be maintained until 1.6.[X + 3] is
+- * released. While a 1.6.X release branch is still maintained, it will receive only
+- * bug fixes. Periodic maintenance releases will be made and labeled as 1.6.X.Y.
+- * 1.6.X.Y releases should go through a release candidate test cycle before being
+- * published.
+- *
+- * For now, all previous 1.6 release will be maintained for security issues. Once
+- * we have more 1.6 releases to deal with, this part of the policy will likely change.
+- *
+- * For some history on the motivations for Asterisk 1.6 release management, see the
+- * first two sections of this
+- * <a href="http://lists.digium.com/pipermail/asterisk-dev/2007-October/030083.html">mailing list post</a>.
+- *
+- * <hr/>
+- *
+- * \section asttrunk Asterisk Trunk
+- *
+- * \subsection svnbranch SVN Branch
+- *
+- * \arg /trunk
+- *
+- * \subsection asttrunkpolicy Release and Commit Policy
+- *
+- * No releases are ever made directly from Asterisk trunk.
+- *
+- * Asterisk trunk is used as the main development area for upcoming Asterisk 1.6
+- * releases. Commits to Asterisk trunk are not limited. They can be bug fixes,
+- * new %features, and architectural improvements. However, for larger sets
+- * of changes, developers should work with the Asterisk project leaders to
+- * schedule them for inclusion. Care is taken not to include too many invasive
+- * sets of changes for each new Asterisk 1.6 release.
+- *
+- * No changes should go into Asterisk trunk that are not ready to go into a
+- * release. While the upcoming release will go through a beta and release
+- * candidate test cycle, code should not be in trunk until the code has been
+- * tested and reviewed such that there is reasonable belief that the code
+- * is ready to go.
+- *
+- * <hr/>
+- *
+- * \section astteam Asterisk Team Branches
+- *
+- * \subsection svnbranch SVN Branch
+- *
+- * \arg /team/&lt;developername&gt;
+- *
+- * \subsection astteampolicy Release and Commit Policy
+- *
+- * The Asterisk subversion repository has a special directory called "team"
+- * where developers can make their own personal development branches. This is
+- * where new %features, bug fixes, and architectural improvements are developed
+- * while they are in %progress.
+- *
+- * Just about anything goes as far as commits to this area goes. However,
+- * developers should keep in mind that anything committed here, as well as
+- * anywhere else on Digium's SVN server, falls under the contributor license
+- * agreement.
+- *
+- * In addition to each developer having their own space for working on projects,
+- * there is also a team/group folder where %group development efforts take place.
+- *
+- * Finally, in each developer folder, there is a folder called "private". This
+- * is where developers can create branches for working on things that they are
+- * not ready for the whole world to see.
+- */
+-
+ /*!
+ * \page CodeGuide Coding Guidelines
+ * \AsteriskTrunkWarning
+@@ -338,98 +80,6 @@
+ * \verbinclude CODING-GUIDELINES
+ */
+
+-/*!
+- * \page CommitMessages Guidelines for Commit Messages
+- *
+- * \AsteriskTrunkWarning
+- *
+- * <hr/>
+- *
+- * \section CommitMsgFormatting Commit Message Formatting
+- *
+- * The following illustrates the basic outline for commit messages:
+- *
+- \verbatim
+- <One-liner summary of changes>
+-
+- <Verbose description of the changes>
+-
+- <Special Tags>
+- \endverbatim
+- *
+- * Some commit history viewers treat the first line of commit messages as the
+- * summary for the commit. So, an effort should be made to format our commit
+- * messages in that fashion. The verbose description may contain multiple
+- * paragraphs, itemized lists, etc.
+- *
+- * Commit messages should be wrapped at 80 %columns.
+- *
+- * \note For trivial commits, such as "fix the build", or "fix spelling mistake",
+- * the verbose description may not be necessary.
+- *
+- * <hr/>
+- *
+- * \section CommitMsgTags Special Tags for Commit Messages
+- *
+- * \subsection MantisTags Mantis (http://bugs.digium.com/)
+- *
+- * To have a commit noted in an issue, use a tag of the form:
+- * \arg (issue #1234)
+- *
+- * To have a commit automatically close an issue, use a tag of the form:
+- * \arg (closes issue #1234)
+- *
+- * When making a commit for a mantis issue, it is easiest to use the
+- * provided commit %message template functionality. It will format the
+- * special tags appropriately, and will also include information about who
+- * reported the issue, which patches are being applied, and who did testing.
+- *
+- * Assuming that you have bug marshal access (and if you have commit access,
+- * it is pretty safe to assume that you do), you will find the commit %message
+- * template section directly below the issue details section and above the
+- * issue relationships section. You will have to click the '+' next to
+- * "Commit message template" to make the contents of the section visible.
+- *
+- * Here is an example of what the template will generate for you:
+- *
+- \verbatim
+- (closes issue #1234)
+- Reported by: SomeGuy
+- Patches:
+- fix_bug_1234.diff uploaded by SomeDeveloper (license 5678)
+- \endverbatim
+- *
+- * If the patch being committed was written by the person doing the commit,
+- * and is not available to reference as an upload to the issue, there is no
+- * need to include something like "fixed by me", as that will be the default
+- * assumption when a specific patch is not referenced.
+- *
+- * \subsection ReviewBoardTags Review Board (http://reviewboard.digium.com/)
+- *
+- * To have a commit set a review request as submitted, include the full URL
+- * to the review request. For example:
+- * \arg Review: %http://reviewboard.digium.com/r/95/
+- *
+- * \note The trailing slash in the review URL is required.
+- *
+- * <hr/>
+- *
+- * \section CommitMsgSvnmerge Commit Messages with svnmerge
+- *
+- * When using the svnmerge tool for merging changes between branches, use the
+- * commit %message generated by svnmerge. The '-f' option to svnmerge allows
+- * you to specify a file for svnmerge to write out a commit %message to. The
+- * '-F' option to svn commit allows you to specify a file that contains the
+- * commit %message.
+- *
+- * If you are using the expect script wrappers for svnmerge from repotools,
+- * a commit %message is automatically placed in the file '../merge.msg'.
+- *
+- * For more detailed information about working with branches and merging,
+- * see the following page on %asterisk.org:
+- * \arg http://www.asterisk.org/developers/svn-branching-merging
+- */
+-
+ /*!
+ * \page AstAPI Asterisk API
+ * \section Asteriskapi Asterisk API
+@@ -1018,136 +668,4 @@
+ * http://www.sqlite.org
+ */
+
+-/*!
+- * \page Licensing Asterisk Licensing Information
+- *
+- * \section license Asterisk License
+- * \verbinclude LICENSE
+- *
+- * \section otherlicenses Licensing of 3rd Party Code
+- *
+- * This section contains a (not yet complete) list of libraries that are used
+- * by various parts of Asterisk, including related licensing information.
+- *
+- * \subsection alsa_lib ALSA Library
+- * \arg <b>Library</b>: libasound
+- * \arg <b>Website</b>: http://www.alsa-project.org
+- * \arg <b>Used by</b>: chan_alsa
+- * \arg <b>License</b>: LGPL
+- *
+- * \subsection openssl_lib OpenSSL
+- * \arg <b>Library</b>: libcrypto, libssl
+- * \arg <b>Website</b>: http://www.openssl.org
+- * \arg <b>Used by</b>: Asterisk core (TLS for manager and HTTP), res_crypto
+- * \arg <b>License</b>: Apache 2.0
+- * \arg <b>Note</b>: An exception has been granted to allow linking of
+- * OpenSSL with Asterisk.
+- *
+- * \subsection curl_lib Curl
+- * \arg <b>Library</b>: libcurl
+- * \arg <b>Website</b>: http://curl.haxx.se
+- * \arg <b>Used by</b>: func_curl, res_config_curl, res_curl
+- * \arg <b>License</b>: BSD
+- *
+- * \subsection portaudio_lib PortAudio
+- * \arg <b>Library</b>: libportaudio
+- * \arg <b>Website</b>: http://www.portaudio.com
+- * \arg <b>Used by</b>: chan_console
+- * \arg <b>License</b>: BSD
+- * \arg <b>Note</b>: Even though PortAudio is licensed under a BSD style
+- * license, PortAudio will make use of some audio interface,
+- * depending on how it was built. That audio interface may
+- * introduce additional licensing restrictions. On Linux,
+- * this would most commonly be ALSA: \ref alsa_lib.
+- *
+- * \subsection rawlist Raw list of libraries that used by any part of Asterisk
+- * \li c-client.a (app_voicemail with IMAP support)
+- * \li libSDL-1.2.so.0
+- * \li libSaClm.so.2
+- * \li libSaEvt.so.2
+- * \li libX11.so.6
+- * \li libXau.so.6
+- * \li libXdmcp.so.6
+- * \li libasound.so.2
+- * \li libc.so.6
+- * \li libcom_err.so.2
+- * \li libcrypt.so.1
+- * \li libcrypto.so.0.9.8 (chan_h323)
+- * \li libcurl.so.4
+- * \li libdirect-1.0.so.0
+- * \li libdirectfb-1.0.so.0
+- * \li libdl.so.2
+- * \li libexpat.so (chan_h323)
+- * \li libfusion-1.0.so.0
+- * \li libgcc_s.so (chan_h323)
+- * \li libgcrypt.so.11 (chan_h323)
+- * \li libglib-2.0.so.0
+- * \li libgmime-2.0.so.2
+- * \li libgmodule-2.0.so.0
+- * \li libgnutls.so.13 (chan_h323)
+- * \li libgobject-2.0.so.0
+- * \li libgpg-error.so.0 (chan_h323)
+- * \li libgssapi_krb5.so.2
+- * \li libgthread-2.0.so.0
+- * \li libidn.so.11
+- * \li libiksemel.so.3
+- * \li libisdnnet.so
+- * \li libjack.so.0
+- * \li libjpeg.so.62
+- * \li libk5crypto.so.3
+- * \li libkeyutils.so.1
+- * \li libkrb5.so.3
+- * \li libkrb5support.so.0
+- * \li liblber-2.4.so.2 (chan_h323)
+- * \li libldap_r-2.4.so.2 (chan_h323)
+- * \li libltdl.so.3
+- * \li liblua5.1.so.0
+- * \li libm.so.6
+- * \li libmISDN.so
+- * \li libnbs.so.1
+- * \li libncurses.so.5
+- * \li libnetsnmp.so.15
+- * \li libnetsnmpagent.so.15
+- * \li libnetsnmphelpers.so.15
+- * \li libnetsnmpmibs.so.15
+- * \li libnsl.so.1
+- * \li libodbc.so.1
+- * \li libogg.so.0
+- * \li libopenh323.so (chan_h323)
+- * \li libpcre.so.3
+- * \li libperl.so.5.8
+- * \li libportaudio.so.2
+- * \li libpq.so.5
+- * \li libpri.so.1.4
+- * \li libpt.so (chan_h323)
+- * \li libpthread.so.0
+- * \li libradiusclient-ng.so.2
+- * \li libresample.so.1.0
+- * \li libresolv.so.2 (chan_h323)
+- * \li librt.so.1
+- * \li libsasl2.so.2 (chan_h323)
+- * \li libselinux.so.1
+- * \li libsensors.so.3
+- * \li libspandsp.so.1
+- * \li libspeex.so.1
+- * \li libsqlite.so.0
+- * \li libsqlite3.so.0
+- * \li libss7.so.1
+- * \li libssl.so.0.9.8 (chan_h323)
+- * \li libstdc++.so (chan_h323, chan_vpb)
+- * \li libsuppserv.so
+- * \li libsybdb.so.5
+- * \li libsysfs.so.2
+- * \li libtasn1.so.3 (chan_h323)
+- * \li libtds.so.4
+- * \li libtiff.so.4
+- * \li libtonezone.so.1.0
+- * \li libvorbis.so.0
+- * \li libvorbisenc.so.2
+- * \li libvpb.a (chan_vpb)
+- * \li libwrap.so.0
+- * \li libxcb-xlib.so.0
+- * \li libxcb.so.1
+- * \li libz.so.1 (chan_h323)
+- * \li linux-vdso.so.1
+-*/
++
+Index: include/asterisk/xmldoc.h
+===================================================================
+--- a/include/asterisk/xmldoc.h (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/include/asterisk/xmldoc.h (.../trunk) (revision 202568)
+@@ -23,6 +23,13 @@
+
+ #include "asterisk/xml.h"
+
++/*! \brief From where the documentation come from, this structure is useful for
++ * use it inside application/functions/manager actions structure. */
++enum ast_doc_src {
++ AST_XML_DOC, /*!< From XML documentation */
++ AST_STATIC_DOC /*!< From application/function registration */
++};
++
+ #ifdef AST_XML_DOCS
+
+ /*!
+Index: main/rtp.c
+===================================================================
+--- a/main/rtp.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/rtp.c (.../trunk) (revision 202568)
+@@ -1,4917 +0,0 @@
+-/*
+- * Asterisk -- An open source telephony toolkit.
+- *
+- * Copyright (C) 1999 - 2006, Digium, Inc.
+- *
+- * Mark Spencer <markster@digium.com>
+- *
+- * See http://www.asterisk.org for more information about
+- * the Asterisk project. Please do not directly contact
+- * any of the maintainers of this project for assistance;
+- * the project provides a web site, mailing lists and IRC
+- * channels for your use.
+- *
+- * 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.
+- */
+-
+-/*!
+- * \file
+- *
+- * \brief Supports RTP and RTCP with Symmetric RTP support for NAT traversal.
+- *
+- * \author Mark Spencer <markster@digium.com>
+- *
+- * \note RTP is defined in RFC 3550.
+- */
+-
+-#include "asterisk.h"
+-
+-ASTERISK_FILE_VERSION(__FILE__, "$Revision: 197619 $")
+-
+-#include <sys/time.h>
+-#include <signal.h>
+-#include <fcntl.h>
+-#include <math.h>
+-
+-#include "asterisk/rtp.h"
+-#include "asterisk/pbx.h"
+-#include "asterisk/frame.h"
+-#include "asterisk/channel.h"
+-#include "asterisk/acl.h"
+-#include "asterisk/config.h"
+-#include "asterisk/lock.h"
+-#include "asterisk/utils.h"
+-#include "asterisk/netsock.h"
+-#include "asterisk/cli.h"
+-#include "asterisk/manager.h"
+-#include "asterisk/unaligned.h"
+-
+-#define MAX_TIMESTAMP_SKEW 640
+-
+-#define RTP_SEQ_MOD (1<<16) /*!< A sequence number can't be more than 16 bits */
+-#define RTCP_DEFAULT_INTERVALMS 5000 /*!< Default milli-seconds between RTCP reports we send */
+-#define RTCP_MIN_INTERVALMS 500 /*!< Min milli-seconds between RTCP reports we send */
+-#define RTCP_MAX_INTERVALMS 60000 /*!< Max milli-seconds between RTCP reports we send */
+-
+-#define RTCP_PT_FUR 192
+-#define RTCP_PT_SR 200
+-#define RTCP_PT_RR 201
+-#define RTCP_PT_SDES 202
+-#define RTCP_PT_BYE 203
+-#define RTCP_PT_APP 204
+-
+-#define RTP_MTU 1200
+-
+-#define DEFAULT_DTMF_TIMEOUT (150 * (8000 / 1000)) /*!< samples */
+-
+-static int dtmftimeout = DEFAULT_DTMF_TIMEOUT;
+-
+-static int rtpstart = 5000; /*!< First port for RTP sessions (set in rtp.conf) */
+-static int rtpend = 31000; /*!< Last port for RTP sessions (set in rtp.conf) */
+-static int rtpdebug; /*!< Are we debugging? */
+-static int rtcpdebug; /*!< Are we debugging RTCP? */
+-static int rtcpstats; /*!< Are we debugging RTCP? */
+-static int rtcpinterval = RTCP_DEFAULT_INTERVALMS; /*!< Time between rtcp reports in millisecs */
+-static int stundebug; /*!< Are we debugging stun? */
+-static struct sockaddr_in rtpdebugaddr; /*!< Debug packets to/from this host */
+-static struct sockaddr_in rtcpdebugaddr; /*!< Debug RTCP packets to/from this host */
+-#ifdef SO_NO_CHECK
+-static int nochecksums;
+-#endif
+-static int strictrtp;
+-
+-enum strict_rtp_state {
+- STRICT_RTP_OPEN = 0, /*! No RTP packets should be dropped, all sources accepted */
+- STRICT_RTP_LEARN, /*! Accept next packet as source */
+- STRICT_RTP_CLOSED, /*! Drop all RTP packets not coming from source that was learned */
+-};
+-
+-/* Uncomment this to enable more intense native bridging, but note: this is currently buggy */
+-/* #define P2P_INTENSE */
+-
+-/*!
+- * \brief Structure representing a RTP session.
+- *
+- * RTP session is defined on page 9 of RFC 3550: "An association among a set of participants communicating with RTP. A participant may be involved in multiple RTP sessions at the same time [...]"
+- *
+- */
+-
+-/*! \brief RTP session description */
+-struct ast_rtp {
+- int s;
+- struct ast_frame f;
+- unsigned char rawdata[8192 + AST_FRIENDLY_OFFSET];
+- unsigned int ssrc; /*!< Synchronization source, RFC 3550, page 10. */
+- unsigned int themssrc; /*!< Their SSRC */
+- unsigned int rxssrc;
+- unsigned int lastts;
+- unsigned int lastrxts;
+- unsigned int lastividtimestamp;
+- unsigned int lastovidtimestamp;
+- unsigned int lastitexttimestamp;
+- unsigned int lastotexttimestamp;
+- unsigned int lasteventseqn;
+- int lastrxseqno; /*!< Last received sequence number */
+- unsigned short seedrxseqno; /*!< What sequence number did they start with?*/
+- unsigned int seedrxts; /*!< What RTP timestamp did they start with? */
+- unsigned int rxcount; /*!< How many packets have we received? */
+- unsigned int rxoctetcount; /*!< How many octets have we received? should be rxcount *160*/
+- unsigned int txcount; /*!< How many packets have we sent? */
+- unsigned int txoctetcount; /*!< How many octets have we sent? (txcount*160)*/
+- unsigned int cycles; /*!< Shifted count of sequence number cycles */
+- double rxjitter; /*!< Interarrival jitter at the moment */
+- double rxtransit; /*!< Relative transit time for previous packet */
+- int lasttxformat;
+- int lastrxformat;
+-
+- int rtptimeout; /*!< RTP timeout time (negative or zero means disabled, negative value means temporarily disabled) */
+- int rtpholdtimeout; /*!< RTP timeout when on hold (negative or zero means disabled, negative value means temporarily disabled). */
+- int rtpkeepalive; /*!< Send RTP comfort noice packets for keepalive */
+-
+- /* DTMF Reception Variables */
+- char resp;
+- unsigned int lastevent;
+- unsigned int dtmf_duration; /*!< Total duration in samples since the digit start event */
+- unsigned int dtmf_timeout; /*!< When this timestamp is reached we consider END frame lost and forcibly abort digit */
+- unsigned int dtmfsamples;
+- /* DTMF Transmission Variables */
+- unsigned int lastdigitts;
+- char sending_digit; /*!< boolean - are we sending digits */
+- char send_digit; /*!< digit we are sending */
+- int send_payload;
+- int send_duration;
+- int nat;
+- unsigned int flags;
+- struct sockaddr_in us; /*!< Socket representation of the local endpoint. */
+- struct sockaddr_in them; /*!< Socket representation of the remote endpoint. */
+- struct sockaddr_in altthem; /*!< Alternate source of remote media */
+- struct timeval rxcore;
+- struct timeval txcore;
+- double drxcore; /*!< The double representation of the first received packet */
+- struct timeval lastrx; /*!< timeval when we last received a packet */
+- struct timeval dtmfmute;
+- struct ast_smoother *smoother;
+- int *ioid;
+- unsigned short seqno; /*!< Sequence number, RFC 3550, page 13. */
+- unsigned short rxseqno;
+- struct sched_context *sched;
+- struct io_context *io;
+- void *data;
+- ast_rtp_callback callback;
+-#ifdef P2P_INTENSE
+- ast_mutex_t bridge_lock;
+-#endif
+- struct rtpPayloadType current_RTP_PT[MAX_RTP_PT];
+- int rtp_lookup_code_cache_isAstFormat; /*!< a cache for the result of rtp_lookup_code(): */
+- int rtp_lookup_code_cache_code;
+- int rtp_lookup_code_cache_result;
+- struct ast_rtcp *rtcp;
+- struct ast_codec_pref pref;
+- struct ast_rtp *bridged; /*!< Who we are Packet bridged to */
+-
+- enum strict_rtp_state strict_rtp_state; /*!< Current state that strict RTP protection is in */
+- struct sockaddr_in strict_rtp_address; /*!< Remote address information for strict RTP purposes */
+-
+- int set_marker_bit:1; /*!< Whether to set the marker bit or not */
+- struct rtp_red *red;
+-};
+-
+-static struct ast_frame *red_t140_to_red(struct rtp_red *red);
+-static int red_write(const void *data);
+-
+-struct rtp_red {
+- struct ast_frame t140; /*!< Primary data */
+- struct ast_frame t140red; /*!< Redundant t140*/
+- unsigned char pt[RED_MAX_GENERATION]; /*!< Payload types for redundancy data */
+- unsigned char ts[RED_MAX_GENERATION]; /*!< Time stamps */
+- unsigned char len[RED_MAX_GENERATION]; /*!< length of each generation */
+- int num_gen; /*!< Number of generations */
+- int schedid; /*!< Timer id */
+- int ti; /*!< How long to buffer data before send */
+- unsigned char t140red_data[64000];
+- unsigned char buf_data[64000]; /*!< buffered primary data */
+- int hdrlen;
+- long int prev_ts;
+-};
+-
+-/* Forward declarations */
+-static int ast_rtcp_write(const void *data);
+-static void timeval2ntp(struct timeval tv, unsigned int *msw, unsigned int *lsw);
+-static int ast_rtcp_write_sr(const void *data);
+-static int ast_rtcp_write_rr(const void *data);
+-static unsigned int ast_rtcp_calc_interval(struct ast_rtp *rtp);
+-static int ast_rtp_senddigit_continuation(struct ast_rtp *rtp);
+-int ast_rtp_senddigit_end(struct ast_rtp *rtp, char digit);
+-
+-#define FLAG_3389_WARNING (1 << 0)
+-#define FLAG_NAT_ACTIVE (3 << 1)
+-#define FLAG_NAT_INACTIVE (0 << 1)
+-#define FLAG_NAT_INACTIVE_NOWARN (1 << 1)
+-#define FLAG_HAS_DTMF (1 << 3)
+-#define FLAG_P2P_SENT_MARK (1 << 4)
+-#define FLAG_P2P_NEED_DTMF (1 << 5)
+-#define FLAG_CALLBACK_MODE (1 << 6)
+-#define FLAG_DTMF_COMPENSATE (1 << 7)
+-#define FLAG_HAS_STUN (1 << 8)
+-
+-/*!
+- * \brief Structure defining an RTCP session.
+- *
+- * The concept "RTCP session" is not defined in RFC 3550, but since
+- * this structure is analogous to ast_rtp, which tracks a RTP session,
+- * it is logical to think of this as a RTCP session.
+- *
+- * RTCP packet is defined on page 9 of RFC 3550.
+- *
+- */
+-struct ast_rtcp {
+- int rtcp_info;
+- int s; /*!< Socket */
+- struct sockaddr_in us; /*!< Socket representation of the local endpoint. */
+- struct sockaddr_in them; /*!< Socket representation of the remote endpoint. */
+- struct sockaddr_in altthem; /*!< Alternate source for RTCP */
+- unsigned int soc; /*!< What they told us */
+- unsigned int spc; /*!< What they told us */
+- unsigned int themrxlsr; /*!< The middle 32 bits of the NTP timestamp in the last received SR*/
+- struct timeval rxlsr; /*!< Time when we got their last SR */
+- struct timeval txlsr; /*!< Time when we sent or last SR*/
+- unsigned int expected_prior; /*!< no. packets in previous interval */
+- unsigned int received_prior; /*!< no. packets received in previous interval */
+- int schedid; /*!< Schedid returned from ast_sched_add() to schedule RTCP-transmissions*/
+- unsigned int rr_count; /*!< number of RRs we've sent, not including report blocks in SR's */
+- unsigned int sr_count; /*!< number of SRs we've sent */
+- unsigned int lastsrtxcount; /*!< Transmit packet count when last SR sent */
+- double accumulated_transit; /*!< accumulated a-dlsr-lsr */
+- double rtt; /*!< Last reported rtt */
+- unsigned int reported_jitter; /*!< The contents of their last jitter entry in the RR */
+- unsigned int reported_lost; /*!< Reported lost packets in their RR */
+- char quality[AST_MAX_USER_FIELD];
+- char quality_jitter[AST_MAX_USER_FIELD];
+- char quality_loss[AST_MAX_USER_FIELD];
+- char quality_rtt[AST_MAX_USER_FIELD];
+-
+- double reported_maxjitter;
+- double reported_minjitter;
+- double reported_normdev_jitter;
+- double reported_stdev_jitter;
+- unsigned int reported_jitter_count;
+-
+- double reported_maxlost;
+- double reported_minlost;
+- double reported_normdev_lost;
+- double reported_stdev_lost;
+-
+- double rxlost;
+- double maxrxlost;
+- double minrxlost;
+- double normdev_rxlost;
+- double stdev_rxlost;
+- unsigned int rxlost_count;
+-
+- double maxrxjitter;
+- double minrxjitter;
+- double normdev_rxjitter;
+- double stdev_rxjitter;
+- unsigned int rxjitter_count;
+- double maxrtt;
+- double minrtt;
+- double normdevrtt;
+- double stdevrtt;
+- unsigned int rtt_count;
+- int sendfur;
+-};
+-
+-/*!
+- * \brief STUN support code
+- *
+- * This code provides some support for doing STUN transactions.
+- * Eventually it should be moved elsewhere as other protocols
+- * than RTP can benefit from it - e.g. SIP.
+- * STUN is described in RFC3489 and it is based on the exchange
+- * of UDP packets between a client and one or more servers to
+- * determine the externally visible address (and port) of the client
+- * once it has gone through the NAT boxes that connect it to the
+- * outside.
+- * The simplest request packet is just the header defined in
+- * struct stun_header, and from the response we may just look at
+- * one attribute, STUN_MAPPED_ADDRESS, that we find in the response.
+- * By doing more transactions with different server addresses we
+- * may determine more about the behaviour of the NAT boxes, of
+- * course - the details are in the RFC.
+- *
+- * All STUN packets start with a simple header made of a type,
+- * length (excluding the header) and a 16-byte random transaction id.
+- * Following the header we may have zero or more attributes, each
+- * structured as a type, length and a value (whose format depends
+- * on the type, but often contains addresses).
+- * Of course all fields are in network format.
+- */
+-
+-typedef struct { unsigned int id[4]; } __attribute__((packed)) stun_trans_id;
+-
+-struct stun_header {
+- unsigned short msgtype;
+- unsigned short msglen;
+- stun_trans_id id;
+- unsigned char ies[0];
+-} __attribute__((packed));
+-
+-struct stun_attr {
+- unsigned short attr;
+- unsigned short len;
+- unsigned char value[0];
+-} __attribute__((packed));
+-
+-/*
+- * The format normally used for addresses carried by STUN messages.
+- */
+-struct stun_addr {
+- unsigned char unused;
+- unsigned char family;
+- unsigned short port;
+- unsigned int addr;
+-} __attribute__((packed));
+-
+-#define STUN_IGNORE (0)
+-#define STUN_ACCEPT (1)
+-
+-/*! \brief STUN message types
+- * 'BIND' refers to transactions used to determine the externally
+- * visible addresses. 'SEC' refers to transactions used to establish
+- * a session key for subsequent requests.
+- * 'SEC' functionality is not supported here.
+- */
+-
+-#define STUN_BINDREQ 0x0001
+-#define STUN_BINDRESP 0x0101
+-#define STUN_BINDERR 0x0111
+-#define STUN_SECREQ 0x0002
+-#define STUN_SECRESP 0x0102
+-#define STUN_SECERR 0x0112
+-
+-/*! \brief Basic attribute types in stun messages.
+- * Messages can also contain custom attributes (codes above 0x7fff)
+- */
+-#define STUN_MAPPED_ADDRESS 0x0001
+-#define STUN_RESPONSE_ADDRESS 0x0002
+-#define STUN_CHANGE_REQUEST 0x0003
+-#define STUN_SOURCE_ADDRESS 0x0004
+-#define STUN_CHANGED_ADDRESS 0x0005
+-#define STUN_USERNAME 0x0006
+-#define STUN_PASSWORD 0x0007
+-#define STUN_MESSAGE_INTEGRITY 0x0008
+-#define STUN_ERROR_CODE 0x0009
+-#define STUN_UNKNOWN_ATTRIBUTES 0x000a
+-#define STUN_REFLECTED_FROM 0x000b
+-
+-/*! \brief helper function to print message names */
+-static const char *stun_msg2str(int msg)
+-{
+- switch (msg) {
+- case STUN_BINDREQ:
+- return "Binding Request";
+- case STUN_BINDRESP:
+- return "Binding Response";
+- case STUN_BINDERR:
+- return "Binding Error Response";
+- case STUN_SECREQ:
+- return "Shared Secret Request";
+- case STUN_SECRESP:
+- return "Shared Secret Response";
+- case STUN_SECERR:
+- return "Shared Secret Error Response";
+- }
+- return "Non-RFC3489 Message";
+-}
+-
+-/*! \brief helper function to print attribute names */
+-static const char *stun_attr2str(int msg)
+-{
+- switch (msg) {
+- case STUN_MAPPED_ADDRESS:
+- return "Mapped Address";
+- case STUN_RESPONSE_ADDRESS:
+- return "Response Address";
+- case STUN_CHANGE_REQUEST:
+- return "Change Request";
+- case STUN_SOURCE_ADDRESS:
+- return "Source Address";
+- case STUN_CHANGED_ADDRESS:
+- return "Changed Address";
+- case STUN_USERNAME:
+- return "Username";
+- case STUN_PASSWORD:
+- return "Password";
+- case STUN_MESSAGE_INTEGRITY:
+- return "Message Integrity";
+- case STUN_ERROR_CODE:
+- return "Error Code";
+- case STUN_UNKNOWN_ATTRIBUTES:
+- return "Unknown Attributes";
+- case STUN_REFLECTED_FROM:
+- return "Reflected From";
+- }
+- return "Non-RFC3489 Attribute";
+-}
+-
+-/*! \brief here we store credentials extracted from a message */
+-struct stun_state {
+- const char *username;
+- const char *password;
+-};
+-
+-static int stun_process_attr(struct stun_state *state, struct stun_attr *attr)
+-{
+- if (stundebug)
+- ast_verbose("Found STUN Attribute %s (%04x), length %d\n",
+- stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len));
+- switch (ntohs(attr->attr)) {
+- case STUN_USERNAME:
+- state->username = (const char *) (attr->value);
+- break;
+- case STUN_PASSWORD:
+- state->password = (const char *) (attr->value);
+- break;
+- default:
+- if (stundebug)
+- ast_verbose("Ignoring STUN attribute %s (%04x), length %d\n",
+- stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len));
+- }
+- return 0;
+-}
+-
+-/*! \brief append a string to an STUN message */
+-static void append_attr_string(struct stun_attr **attr, int attrval, const char *s, int *len, int *left)
+-{
+- int size = sizeof(**attr) + strlen(s);
+- if (*left > size) {
+- (*attr)->attr = htons(attrval);
+- (*attr)->len = htons(strlen(s));
+- memcpy((*attr)->value, s, strlen(s));
+- (*attr) = (struct stun_attr *)((*attr)->value + strlen(s));
+- *len += size;
+- *left -= size;
+- }
+-}
+-
+-/*! \brief append an address to an STUN message */
+-static void append_attr_address(struct stun_attr **attr, int attrval, struct sockaddr_in *sock_in, int *len, int *left)
+-{
+- int size = sizeof(**attr) + 8;
+- struct stun_addr *addr;
+- if (*left > size) {
+- (*attr)->attr = htons(attrval);
+- (*attr)->len = htons(8);
+- addr = (struct stun_addr *)((*attr)->value);
+- addr->unused = 0;
+- addr->family = 0x01;
+- addr->port = sock_in->sin_port;
+- addr->addr = sock_in->sin_addr.s_addr;
+- (*attr) = (struct stun_attr *)((*attr)->value + 8);
+- *len += size;
+- *left -= size;
+- }
+-}
+-
+-/*! \brief wrapper to send an STUN message */
+-static int stun_send(int s, struct sockaddr_in *dst, struct stun_header *resp)
+-{
+- return sendto(s, resp, ntohs(resp->msglen) + sizeof(*resp), 0,
+- (struct sockaddr *)dst, sizeof(*dst));
+-}
+-
+-/*! \brief helper function to generate a random request id */
+-static void stun_req_id(struct stun_header *req)
+-{
+- int x;
+- for (x = 0; x < 4; x++)
+- req->id.id[x] = ast_random();
+-}
+-
+-size_t ast_rtp_alloc_size(void)
+-{
+- return sizeof(struct ast_rtp);
+-}
+-
+-/*! \brief callback type to be invoked on stun responses. */
+-typedef int (stun_cb_f)(struct stun_attr *attr, void *arg);
+-
+-/*! \brief handle an incoming STUN message.
+- *
+- * Do some basic sanity checks on packet size and content,
+- * try to extract a bit of information, and possibly reply.
+- * At the moment this only processes BIND requests, and returns
+- * the externally visible address of the request.
+- * If a callback is specified, invoke it with the attribute.
+- */
+-static int stun_handle_packet(int s, struct sockaddr_in *src,
+- unsigned char *data, size_t len, stun_cb_f *stun_cb, void *arg)
+-{
+- struct stun_header *hdr = (struct stun_header *)data;
+- struct stun_attr *attr;
+- struct stun_state st;
+- int ret = STUN_IGNORE;
+- int x;
+-
+- /* On entry, 'len' is the length of the udp payload. After the
+- * initial checks it becomes the size of unprocessed options,
+- * while 'data' is advanced accordingly.
+- */
+- if (len < sizeof(struct stun_header)) {
+- ast_debug(1, "Runt STUN packet (only %d, wanting at least %d)\n", (int) len, (int) sizeof(struct stun_header));
+- return -1;
+- }
+- len -= sizeof(struct stun_header);
+- data += sizeof(struct stun_header);
+- x = ntohs(hdr->msglen); /* len as advertised in the message */
+- if (stundebug)
+- ast_verbose("STUN Packet, msg %s (%04x), length: %d\n", stun_msg2str(ntohs(hdr->msgtype)), ntohs(hdr->msgtype), x);
+- if (x > len) {
+- ast_debug(1, "Scrambled STUN packet length (got %d, expecting %d)\n", x, (int)len);
+- } else
+- len = x;
+- memset(&st, 0, sizeof(st));
+- while (len) {
+- if (len < sizeof(struct stun_attr)) {
+- ast_debug(1, "Runt Attribute (got %d, expecting %d)\n", (int)len, (int) sizeof(struct stun_attr));
+- break;
+- }
+- attr = (struct stun_attr *)data;
+- /* compute total attribute length */
+- x = ntohs(attr->len) + sizeof(struct stun_attr);
+- if (x > len) {
+- ast_debug(1, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", x, (int)len);
+- break;
+- }
+- if (stun_cb)
+- stun_cb(attr, arg);
+- if (stun_process_attr(&st, attr)) {
+- ast_debug(1, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr));
+- break;
+- }
+- /* Clear attribute id: in case previous entry was a string,
+- * this will act as the terminator for the string.
+- */
+- attr->attr = 0;
+- data += x;
+- len -= x;
+- }
+- /* Null terminate any string.
+- * XXX NOTE, we write past the size of the buffer passed by the
+- * caller, so this is potentially dangerous. The only thing that
+- * saves us is that usually we read the incoming message in a
+- * much larger buffer in the struct ast_rtp
+- */
+- *data = '\0';
+-
+- /* Now prepare to generate a reply, which at the moment is done
+- * only for properly formed (len == 0) STUN_BINDREQ messages.
+- */
+- if (len == 0) {
+- unsigned char respdata[1024];
+- struct stun_header *resp = (struct stun_header *)respdata;
+- int resplen = 0; /* len excluding header */
+- int respleft = sizeof(respdata) - sizeof(struct stun_header);
+-
+- resp->id = hdr->id;
+- resp->msgtype = 0;
+- resp->msglen = 0;
+- attr = (struct stun_attr *)resp->ies;
+- switch (ntohs(hdr->msgtype)) {
+- case STUN_BINDREQ:
+- if (stundebug)
+- ast_verbose("STUN Bind Request, username: %s\n",
+- st.username ? st.username : "<none>");
+- if (st.username)
+- append_attr_string(&attr, STUN_USERNAME, st.username, &resplen, &respleft);
+- append_attr_address(&attr, STUN_MAPPED_ADDRESS, src, &resplen, &respleft);
+- resp->msglen = htons(resplen);
+- resp->msgtype = htons(STUN_BINDRESP);
+- stun_send(s, src, resp);
+- ret = STUN_ACCEPT;
+- break;
+- default:
+- if (stundebug)
+- ast_verbose("Dunno what to do with STUN message %04x (%s)\n", ntohs(hdr->msgtype), stun_msg2str(ntohs(hdr->msgtype)));
+- }
+- }
+- return ret;
+-}
+-
+-/*! \brief Extract the STUN_MAPPED_ADDRESS from the stun response.
+- * This is used as a callback for stun_handle_response
+- * when called from ast_stun_request.
+- */
+-static int stun_get_mapped(struct stun_attr *attr, void *arg)
+-{
+- struct stun_addr *addr = (struct stun_addr *)(attr + 1);
+- struct sockaddr_in *sa = (struct sockaddr_in *)arg;
+-
+- if (ntohs(attr->attr) != STUN_MAPPED_ADDRESS || ntohs(attr->len) != 8)
+- return 1; /* not us. */
+- sa->sin_port = addr->port;
+- sa->sin_addr.s_addr = addr->addr;
+- return 0;
+-}
+-
+-/*! \brief Generic STUN request
+- * Send a generic stun request to the server specified,
+- * possibly waiting for a reply and filling the 'reply' field with
+- * the externally visible address. Note that in this case the request
+- * will be blocking.
+- * (Note, the interface may change slightly in the future).
+- *
+- * \param s the socket used to send the request
+- * \param dst the address of the STUN server
+- * \param username if non null, add the username in the request
+- * \param answer if non null, the function waits for a response and
+- * puts here the externally visible address.
+- * \return 0 on success, other values on error.
+- */
+-int ast_stun_request(int s, struct sockaddr_in *dst,
+- const char *username, struct sockaddr_in *answer)
+-{
+- struct stun_header *req;
+- unsigned char reqdata[1024];
+- int reqlen, reqleft;
+- struct stun_attr *attr;
+- int res = 0;
+- int retry;
+-
+- req = (struct stun_header *)reqdata;
+- stun_req_id(req);
+- reqlen = 0;
+- reqleft = sizeof(reqdata) - sizeof(struct stun_header);
+- req->msgtype = 0;
+- req->msglen = 0;
+- attr = (struct stun_attr *)req->ies;
+- if (username)
+- append_attr_string(&attr, STUN_USERNAME, username, &reqlen, &reqleft);
+- req->msglen = htons(reqlen);
+- req->msgtype = htons(STUN_BINDREQ);
+- for (retry = 0; retry < 3; retry++) { /* XXX make retries configurable */
+- /* send request, possibly wait for reply */
+- unsigned char reply_buf[1024];
+- fd_set rfds;
+- struct timeval to = { 3, 0 }; /* timeout, make it configurable */
+- struct sockaddr_in src;
+- socklen_t srclen;
+-
+- res = stun_send(s, dst, req);
+- if (res < 0) {
+- ast_log(LOG_WARNING, "ast_stun_request send #%d failed error %d, retry\n",
+- retry, res);
+- continue;
+- }
+- if (answer == NULL)
+- break;
+- FD_ZERO(&rfds);
+- FD_SET(s, &rfds);
+- res = ast_select(s + 1, &rfds, NULL, NULL, &to);
+- if (res <= 0) /* timeout or error */
+- continue;
+- memset(&src, '\0', sizeof(src));
+- srclen = sizeof(src);
+- /* XXX pass -1 in the size, because stun_handle_packet might
+- * write past the end of the buffer.
+- */
+- res = recvfrom(s, reply_buf, sizeof(reply_buf) - 1,
+- 0, (struct sockaddr *)&src, &srclen);
+- if (res < 0) {
+- ast_log(LOG_WARNING, "ast_stun_request recvfrom #%d failed error %d, retry\n",
+- retry, res);
+- continue;
+- }
+- memset(answer, '\0', sizeof(struct sockaddr_in));
+- stun_handle_packet(s, &src, reply_buf, res,
+- stun_get_mapped, answer);
+- res = 0; /* signal regular exit */
+- break;
+- }
+- return res;
+-}
+-
+-/*! \brief send a STUN BIND request to the given destination.
+- * Optionally, add a username if specified.
+- */
+-void ast_rtp_stun_request(struct ast_rtp *rtp, struct sockaddr_in *suggestion, const char *username)
+-{
+- ast_stun_request(rtp->s, suggestion, username, NULL);
+-}
+-
+-/*! \brief List of current sessions */
+-static AST_RWLIST_HEAD_STATIC(protos, ast_rtp_protocol);
+-
+-static void timeval2ntp(struct timeval when, unsigned int *msw, unsigned int *lsw)
+-{
+- unsigned int sec, usec, frac;
+- sec = when.tv_sec + 2208988800u; /* Sec between 1900 and 1970 */
+- usec = when.tv_usec;
+- frac = (usec << 12) + (usec << 8) - ((usec * 3650) >> 6);
+- *msw = sec;
+- *lsw = frac;
+-}
+-
+-int ast_rtp_fd(struct ast_rtp *rtp)
+-{
+- return rtp->s;
+-}
+-
+-int ast_rtcp_fd(struct ast_rtp *rtp)
+-{
+- if (rtp->rtcp)
+- return rtp->rtcp->s;
+- return -1;
+-}
+-
+-unsigned int ast_rtcp_calc_interval(struct ast_rtp *rtp)
+-{
+- unsigned int interval;
+- /*! \todo XXX Do a more reasonable calculation on this one
+- * Look in RFC 3550 Section A.7 for an example*/
+- interval = rtcpinterval;
+- return interval;
+-}
+-
+-/* \brief Put RTP timeout timers on hold during another transaction, like T.38 */
+-void ast_rtp_set_rtptimers_onhold(struct ast_rtp *rtp)
+-{
+- rtp->rtptimeout = (-1) * rtp->rtptimeout;
+- rtp->rtpholdtimeout = (-1) * rtp->rtpholdtimeout;
+-}
+-
+-/*! \brief Set rtp timeout */
+-void ast_rtp_set_rtptimeout(struct ast_rtp *rtp, int timeout)
+-{
+- rtp->rtptimeout = timeout;
+-}
+-
+-/*! \brief Set rtp hold timeout */
+-void ast_rtp_set_rtpholdtimeout(struct ast_rtp *rtp, int timeout)
+-{
+- rtp->rtpholdtimeout = timeout;
+-}
+-
+-/*! \brief set RTP keepalive interval */
+-void ast_rtp_set_rtpkeepalive(struct ast_rtp *rtp, int period)
+-{
+- rtp->rtpkeepalive = period;
+-}
+-
+-/*! \brief Get rtp timeout */
+-int ast_rtp_get_rtptimeout(struct ast_rtp *rtp)
+-{
+- if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */
+- return 0;
+- return rtp->rtptimeout;
+-}
+-
+-/*! \brief Get rtp hold timeout */
+-int ast_rtp_get_rtpholdtimeout(struct ast_rtp *rtp)
+-{
+- if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */
+- return 0;
+- return rtp->rtpholdtimeout;
+-}
+-
+-/*! \brief Get RTP keepalive interval */
+-int ast_rtp_get_rtpkeepalive(struct ast_rtp *rtp)
+-{
+- return rtp->rtpkeepalive;
+-}
+-
+-void ast_rtp_set_data(struct ast_rtp *rtp, void *data)
+-{
+- rtp->data = data;
+-}
+-
+-void ast_rtp_set_callback(struct ast_rtp *rtp, ast_rtp_callback callback)
+-{
+- rtp->callback = callback;
+-}
+-
+-void ast_rtp_setnat(struct ast_rtp *rtp, int nat)
+-{
+- rtp->nat = nat;
+-}
+-
+-int ast_rtp_getnat(struct ast_rtp *rtp)
+-{
+- return ast_test_flag(rtp, FLAG_NAT_ACTIVE);
+-}
+-
+-void ast_rtp_setdtmf(struct ast_rtp *rtp, int dtmf)
+-{
+- ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF);
+-}
+-
+-void ast_rtp_setdtmfcompensate(struct ast_rtp *rtp, int compensate)
+-{
+- ast_set2_flag(rtp, compensate ? 1 : 0, FLAG_DTMF_COMPENSATE);
+-}
+-
+-void ast_rtp_setstun(struct ast_rtp *rtp, int stun_enable)
+-{
+- ast_set2_flag(rtp, stun_enable ? 1 : 0, FLAG_HAS_STUN);
+-}
+-
+-static void rtp_bridge_lock(struct ast_rtp *rtp)
+-{
+-#ifdef P2P_INTENSE
+- ast_mutex_lock(&rtp->bridge_lock);
+-#endif
+- return;
+-}
+-
+-static void rtp_bridge_unlock(struct ast_rtp *rtp)
+-{
+-#ifdef P2P_INTENSE
+- ast_mutex_unlock(&rtp->bridge_lock);
+-#endif
+- return;
+-}
+-
+-/*! \brief Calculate normal deviation */
+-static double normdev_compute(double normdev, double sample, unsigned int sample_count)
+-{
+- normdev = normdev * sample_count + sample;
+- sample_count++;
+-
+- return normdev / sample_count;
+-}
+-
+-static double stddev_compute(double stddev, double sample, double normdev, double normdev_curent, unsigned int sample_count)
+-{
+-/*
+- for the formula check http://www.cs.umd.edu/~austinjp/constSD.pdf
+- return sqrt( (sample_count*pow(stddev,2) + sample_count*pow((sample-normdev)/(sample_count+1),2) + pow(sample-normdev_curent,2)) / (sample_count+1));
+- we can compute the sigma^2 and that way we would have to do the sqrt only 1 time at the end and would save another pow 2 compute
+- optimized formula
+-*/
+-#define SQUARE(x) ((x) * (x))
+-
+- stddev = sample_count * stddev;
+- sample_count++;
+-
+- return stddev +
+- ( sample_count * SQUARE( (sample - normdev) / sample_count ) ) +
+- ( SQUARE(sample - normdev_curent) / sample_count );
+-
+-#undef SQUARE
+-}
+-
+-static struct ast_frame *send_dtmf(struct ast_rtp *rtp, enum ast_frame_type type)
+-{
+- if (((ast_test_flag(rtp, FLAG_DTMF_COMPENSATE) && type == AST_FRAME_DTMF_END) ||
+- (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) {
+- ast_debug(1, "Ignore potential DTMF echo from '%s'\n", ast_inet_ntoa(rtp->them.sin_addr));
+- rtp->resp = 0;
+- rtp->dtmfsamples = 0;
+- return &ast_null_frame;
+- }
+- ast_debug(1, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, ast_inet_ntoa(rtp->them.sin_addr));
+- if (rtp->resp == 'X') {
+- rtp->f.frametype = AST_FRAME_CONTROL;
+- rtp->f.subclass = AST_CONTROL_FLASH;
+- } else {
+- rtp->f.frametype = type;
+- rtp->f.subclass = rtp->resp;
+- }
+- rtp->f.datalen = 0;
+- rtp->f.samples = 0;
+- rtp->f.mallocd = 0;
+- rtp->f.src = "RTP";
+- return &rtp->f;
+-
+-}
+-
+-static inline int rtp_debug_test_addr(struct sockaddr_in *addr)
+-{
+- if (rtpdebug == 0)
+- return 0;
+- if (rtpdebugaddr.sin_addr.s_addr) {
+- if (((ntohs(rtpdebugaddr.sin_port) != 0)
+- && (rtpdebugaddr.sin_port != addr->sin_port))
+- || (rtpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
+- return 0;
+- }
+- return 1;
+-}
+-
+-static inline int rtcp_debug_test_addr(struct sockaddr_in *addr)
+-{
+- if (rtcpdebug == 0)
+- return 0;
+- if (rtcpdebugaddr.sin_addr.s_addr) {
+- if (((ntohs(rtcpdebugaddr.sin_port) != 0)
+- && (rtcpdebugaddr.sin_port != addr->sin_port))
+- || (rtcpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
+- return 0;
+- }
+- return 1;
+-}
+-
+-
+-static struct ast_frame *process_cisco_dtmf(struct ast_rtp *rtp, unsigned char *data, int len)
+-{
+- unsigned int event;
+- char resp = 0;
+- struct ast_frame *f = NULL;
+- unsigned char seq;
+- unsigned int flags;
+- unsigned int power;
+-
+- /* We should have at least 4 bytes in RTP data */
+- if (len < 4)
+- return f;
+-
+- /* The format of Cisco RTP DTMF packet looks like next:
+- +0 - sequence number of DTMF RTP packet (begins from 1,
+- wrapped to 0)
+- +1 - set of flags
+- +1 (bit 0) - flaps by different DTMF digits delimited by audio
+- or repeated digit without audio???
+- +2 (+4,+6,...) - power level? (rises from 0 to 32 at begin of tone
+- then falls to 0 at its end)
+- +3 (+5,+7,...) - detected DTMF digit (0..9,*,#,A-D,...)
+- Repeated DTMF information (bytes 4/5, 6/7) is history shifted right
+- by each new packet and thus provides some redudancy.
+-
+- Sample of Cisco RTP DTMF packet is (all data in hex):
+- 19 07 00 02 12 02 20 02
+- showing end of DTMF digit '2'.
+-
+- The packets
+- 27 07 00 02 0A 02 20 02
+- 28 06 20 02 00 02 0A 02
+- shows begin of new digit '2' with very short pause (20 ms) after
+- previous digit '2'. Bit +1.0 flips at begin of new digit.
+-
+- Cisco RTP DTMF packets comes as replacement of audio RTP packets
+- so its uses the same sequencing and timestamping rules as replaced
+- audio packets. Repeat interval of DTMF packets is 20 ms and not rely
+- on audio framing parameters. Marker bit isn't used within stream of
+- DTMFs nor audio stream coming immediately after DTMF stream. Timestamps
+- are not sequential at borders between DTMF and audio streams,
+- */
+-
+- seq = data[0];
+- flags = data[1];
+- power = data[2];
+- event = data[3] & 0x1f;
+-
+- if (option_debug > 2 || rtpdebug)
+- ast_debug(0, "Cisco DTMF Digit: %02x (len=%d, seq=%d, flags=%02x, power=%d, history count=%d)\n", event, len, seq, flags, power, (len - 4) / 2);
+- if (event < 10) {
+- resp = '0' + event;
+- } else if (event < 11) {
+- resp = '*';
+- } else if (event < 12) {
+- resp = '#';
+- } else if (event < 16) {
+- resp = 'A' + (event - 12);
+- } else if (event < 17) {
+- resp = 'X';
+- }
+- if ((!rtp->resp && power) || (rtp->resp && (rtp->resp != resp))) {
+- rtp->resp = resp;
+- /* Why we should care on DTMF compensation at reception? */
+- if (!ast_test_flag(rtp, FLAG_DTMF_COMPENSATE)) {
+- f = send_dtmf(rtp, AST_FRAME_DTMF_BEGIN);
+- rtp->dtmfsamples = 0;
+- }
+- } else if ((rtp->resp == resp) && !power) {
+- f = send_dtmf(rtp, AST_FRAME_DTMF_END);
+- f->samples = rtp->dtmfsamples * 8;
+- rtp->resp = 0;
+- } else if (rtp->resp == resp)
+- rtp->dtmfsamples += 20 * 8;
+- rtp->dtmf_timeout = dtmftimeout;
+- return f;
+-}
+-
+-/*!
+- * \brief Process RTP DTMF and events according to RFC 2833.
+- *
+- * RFC 2833 is "RTP Payload for DTMF Digits, Telephony Tones and Telephony Signals".
+- *
+- * \param rtp
+- * \param data
+- * \param len
+- * \param seqno
+- * \param timestamp
+- * \returns
+- */
+-static struct ast_frame *process_rfc2833(struct ast_rtp *rtp, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp)
+-{
+- unsigned int event;
+- unsigned int event_end;
+- unsigned int samples;
+- char resp = 0;
+- struct ast_frame *f = NULL;
+-
+- /* Figure out event, event end, and samples */
+- event = ntohl(*((unsigned int *)(data)));
+- event >>= 24;
+- event_end = ntohl(*((unsigned int *)(data)));
+- event_end <<= 8;
+- event_end >>= 24;
+- samples = ntohl(*((unsigned int *)(data)));
+- samples &= 0xFFFF;
+-
+- /* Print out debug if turned on */
+- if (rtpdebug || option_debug > 2)
+- ast_debug(0, "- RTP 2833 Event: %08x (len = %d)\n", event, len);
+-
+- /* Figure out what digit was pressed */
+- if (event < 10) {
+- resp = '0' + event;
+- } else if (event < 11) {
+- resp = '*';
+- } else if (event < 12) {
+- resp = '#';
+- } else if (event < 16) {
+- resp = 'A' + (event - 12);
+- } else if (event < 17) { /* Event 16: Hook flash */
+- resp = 'X';
+- } else {
+- /* Not a supported event */
+- ast_log(LOG_DEBUG, "Ignoring RTP 2833 Event: %08x. Not a DTMF Digit.\n", event);
+- return &ast_null_frame;
+- }
+-
+- if (ast_test_flag(rtp, FLAG_DTMF_COMPENSATE)) {
+- if ((rtp->lastevent != timestamp) || (rtp->resp && rtp->resp != resp)) {
+- rtp->resp = resp;
+- rtp->dtmf_timeout = 0;
+- f = send_dtmf(rtp, AST_FRAME_DTMF_END);
+- f->len = 0;
+- rtp->lastevent = timestamp;
+- }
+- } else {
+- /* The duration parameter measures the complete
+- duration of the event (from the beginning) - RFC2833.
+- Account for the fact that duration is only 16 bits long
+- (about 8 seconds at 8000 Hz) and can wrap is digit
+- is hold for too long. */
+- unsigned int new_duration = rtp->dtmf_duration;
+- unsigned int last_duration = new_duration & 0xFFFF;
+-
+- if (last_duration > 64000 && samples < last_duration)
+- new_duration += 0xFFFF + 1;
+- new_duration = (new_duration & ~0xFFFF) | samples;
+-
+- if (event_end & 0x80) {
+- /* End event */
+- if ((rtp->lastevent != seqno) && rtp->resp) {
+- rtp->dtmf_duration = new_duration;
+- f = send_dtmf(rtp, AST_FRAME_DTMF_END);
+- f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, 8000), ast_tv(0, 0));
+- rtp->resp = 0;
+- rtp->dtmf_duration = rtp->dtmf_timeout = 0;
+- }
+- } else {
+- /* Begin/continuation */
+-
+- if (rtp->resp && rtp->resp != resp) {
+- /* Another digit already began. End it */
+- f = send_dtmf(rtp, AST_FRAME_DTMF_END);
+- f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, 8000), ast_tv(0, 0));
+- rtp->resp = 0;
+- rtp->dtmf_duration = rtp->dtmf_timeout = 0;
+- }
+-
+-
+- if (rtp->resp) {
+- /* Digit continues */
+- rtp->dtmf_duration = new_duration;
+- } else {
+- /* New digit began */
+- rtp->resp = resp;
+- f = send_dtmf(rtp, AST_FRAME_DTMF_BEGIN);
+- rtp->dtmf_duration = samples;
+- }
+-
+- rtp->dtmf_timeout = timestamp + rtp->dtmf_duration + dtmftimeout;
+- }
+-
+- rtp->lastevent = seqno;
+- }
+-
+- rtp->dtmfsamples = samples;
+-
+- return f;
+-}
+-
+-/*!
+- * \brief Process Comfort Noise RTP.
+- *
+- * This is incomplete at the moment.
+- *
+-*/
+-static struct ast_frame *process_rfc3389(struct ast_rtp *rtp, unsigned char *data, int len)
+-{
+- struct ast_frame *f = NULL;
+- /* Convert comfort noise into audio with various codecs. Unfortunately this doesn't
+- totally help us out becuase we don't have an engine to keep it going and we are not
+- guaranteed to have it every 20ms or anything */
+- if (rtpdebug)
+- ast_debug(0, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", rtp->lastrxformat, len);
+-
+- if (!(ast_test_flag(rtp, FLAG_3389_WARNING))) {
+- ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client IP: %s\n",
+- ast_inet_ntoa(rtp->them.sin_addr));
+- ast_set_flag(rtp, FLAG_3389_WARNING);
+- }
+-
+- /* Must have at least one byte */
+- if (!len)
+- return NULL;
+- if (len < 24) {
+- rtp->f.data.ptr = rtp->rawdata + AST_FRIENDLY_OFFSET;
+- rtp->f.datalen = len - 1;
+- rtp->f.offset = AST_FRIENDLY_OFFSET;
+- memcpy(rtp->f.data.ptr, data + 1, len - 1);
+- } else {
+- rtp->f.data.ptr = NULL;
+- rtp->f.offset = 0;
+- rtp->f.datalen = 0;
+- }
+- rtp->f.frametype = AST_FRAME_CNG;
+- rtp->f.subclass = data[0] & 0x7f;
+- rtp->f.datalen = len - 1;
+- rtp->f.samples = 0;
+- rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0;
+- f = &rtp->f;
+- return f;
+-}
+-
+-static int rtpread(int *id, int fd, short events, void *cbdata)
+-{
+- struct ast_rtp *rtp = cbdata;
+- struct ast_frame *f;
+- f = ast_rtp_read(rtp);
+- if (f) {
+- if (rtp->callback)
+- rtp->callback(rtp, f, rtp->data);
+- }
+- return 1;
+-}
+-
+-struct ast_frame *ast_rtcp_read(struct ast_rtp *rtp)
+-{
+- socklen_t len;
+- int position, i, packetwords;
+- int res;
+- struct sockaddr_in sock_in;
+- unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET];
+- unsigned int *rtcpheader;
+- int pt;
+- struct timeval now;
+- unsigned int length;
+- int rc;
+- double rttsec;
+- uint64_t rtt = 0;
+- unsigned int dlsr;
+- unsigned int lsr;
+- unsigned int msw;
+- unsigned int lsw;
+- unsigned int comp;
+- struct ast_frame *f = &ast_null_frame;
+-
+- double reported_jitter;
+- double reported_normdev_jitter_current;
+- double normdevrtt_current;
+- double reported_lost;
+- double reported_normdev_lost_current;
+-
+- if (!rtp || !rtp->rtcp)
+- return &ast_null_frame;
+-
+- len = sizeof(sock_in);
+-
+- res = recvfrom(rtp->rtcp->s, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET,
+- 0, (struct sockaddr *)&sock_in, &len);
+- rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET);
+-
+- if (res < 0) {
+- ast_assert(errno != EBADF);
+- if (errno != EAGAIN) {
+- ast_log(LOG_WARNING, "RTCP Read error: %s. Hanging up.\n", strerror(errno));
+- return NULL;
+- }
+- return &ast_null_frame;
+- }
+-
+- packetwords = res / 4;
+-
+- if (rtp->nat) {
+- /* Send to whoever sent to us */
+- if (((rtp->rtcp->them.sin_addr.s_addr != sock_in.sin_addr.s_addr) ||
+- (rtp->rtcp->them.sin_port != sock_in.sin_port)) &&
+- ((rtp->rtcp->altthem.sin_addr.s_addr != sock_in.sin_addr.s_addr) ||
+- (rtp->rtcp->altthem.sin_port != sock_in.sin_port))) {
+- memcpy(&rtp->rtcp->them, &sock_in, sizeof(rtp->rtcp->them));
+- if (option_debug || rtpdebug)
+- ast_debug(0, "RTCP NAT: Got RTCP from other end. Now sending to address %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
+- }
+- }
+-
+- ast_debug(1, "Got RTCP report of %d bytes\n", res);
+-
+- /* Process a compound packet */
+- position = 0;
+- while (position < packetwords) {
+- i = position;
+- length = ntohl(rtcpheader[i]);
+- pt = (length & 0xff0000) >> 16;
+- rc = (length & 0x1f000000) >> 24;
+- length &= 0xffff;
+-
+- if ((i + length) > packetwords) {
+- if (option_debug || rtpdebug)
+- ast_log(LOG_DEBUG, "RTCP Read too short\n");
+- return &ast_null_frame;
+- }
+-
+- if (rtcp_debug_test_addr(&sock_in)) {
+- ast_verbose("\n\nGot RTCP from %s:%d\n", ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port));
+- ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown");
+- ast_verbose("Reception reports: %d\n", rc);
+- ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]);
+- }
+-
+- i += 2; /* Advance past header and ssrc */
+-
+- switch (pt) {
+- case RTCP_PT_SR:
+- gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */
+- rtp->rtcp->spc = ntohl(rtcpheader[i+3]);
+- rtp->rtcp->soc = ntohl(rtcpheader[i + 4]);
+- rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/
+-
+- if (rtcp_debug_test_addr(&sock_in)) {
+- ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096);
+- ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2]));
+- ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4]));
+- }
+- i += 5;
+- if (rc < 1)
+- break;
+- /* Intentional fall through */
+- case RTCP_PT_RR:
+- /* Don't handle multiple reception reports (rc > 1) yet */
+- /* Calculate RTT per RFC */
+- gettimeofday(&now, NULL);
+- timeval2ntp(now, &msw, &lsw);
+- if (ntohl(rtcpheader[i + 4]) && ntohl(rtcpheader[i + 5])) { /* We must have the LSR && DLSR */
+- comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16);
+- lsr = ntohl(rtcpheader[i + 4]);
+- dlsr = ntohl(rtcpheader[i + 5]);
+- rtt = comp - lsr - dlsr;
+-
+- /* Convert end to end delay to usec (keeping the calculation in 64bit space)
+- sess->ee_delay = (eedelay * 1000) / 65536; */
+- if (rtt < 4294) {
+- rtt = (rtt * 1000000) >> 16;
+- } else {
+- rtt = (rtt * 1000) >> 16;
+- rtt *= 1000;
+- }
+- rtt = rtt / 1000.;
+- rttsec = rtt / 1000.;
+- rtp->rtcp->rtt = rttsec;
+-
+- if (comp - dlsr >= lsr) {
+- rtp->rtcp->accumulated_transit += rttsec;
+-
+- if (rtp->rtcp->rtt_count == 0)
+- rtp->rtcp->minrtt = rttsec;
+-
+- if (rtp->rtcp->maxrtt<rttsec)
+- rtp->rtcp->maxrtt = rttsec;
+-
+- if (rtp->rtcp->minrtt>rttsec)
+- rtp->rtcp->minrtt = rttsec;
+-
+- normdevrtt_current = normdev_compute(rtp->rtcp->normdevrtt, rttsec, rtp->rtcp->rtt_count);
+-
+- rtp->rtcp->stdevrtt = stddev_compute(rtp->rtcp->stdevrtt, rttsec, rtp->rtcp->normdevrtt, normdevrtt_current, rtp->rtcp->rtt_count);
+-
+- rtp->rtcp->normdevrtt = normdevrtt_current;
+-
+- rtp->rtcp->rtt_count++;
+- } else if (rtcp_debug_test_addr(&sock_in)) {
+- ast_verbose("Internal RTCP NTP clock skew detected: "
+- "lsr=%u, now=%u, dlsr=%u (%d:%03dms), "
+- "diff=%d\n",
+- lsr, comp, dlsr, dlsr / 65536,
+- (dlsr % 65536) * 1000 / 65536,
+- dlsr - (comp - lsr));
+- }
+- }
+-
+- rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]);
+- reported_jitter = (double) rtp->rtcp->reported_jitter;
+-
+- if (rtp->rtcp->reported_jitter_count == 0)
+- rtp->rtcp->reported_minjitter = reported_jitter;
+-
+- if (reported_jitter < rtp->rtcp->reported_minjitter)
+- rtp->rtcp->reported_minjitter = reported_jitter;
+-
+- if (reported_jitter > rtp->rtcp->reported_maxjitter)
+- rtp->rtcp->reported_maxjitter = reported_jitter;
+-
+- reported_normdev_jitter_current = normdev_compute(rtp->rtcp->reported_normdev_jitter, reported_jitter, rtp->rtcp->reported_jitter_count);
+-
+- rtp->rtcp->reported_stdev_jitter = stddev_compute(rtp->rtcp->reported_stdev_jitter, reported_jitter, rtp->rtcp->reported_normdev_jitter, reported_normdev_jitter_current, rtp->rtcp->reported_jitter_count);
+-
+- rtp->rtcp->reported_normdev_jitter = reported_normdev_jitter_current;
+-
+- rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff;
+-
+- reported_lost = (double) rtp->rtcp->reported_lost;
+-
+- /* using same counter as for jitter */
+- if (rtp->rtcp->reported_jitter_count == 0)
+- rtp->rtcp->reported_minlost = reported_lost;
+-
+- if (reported_lost < rtp->rtcp->reported_minlost)
+- rtp->rtcp->reported_minlost = reported_lost;
+-
+- if (reported_lost > rtp->rtcp->reported_maxlost)
+- rtp->rtcp->reported_maxlost = reported_lost;
+-
+- reported_normdev_lost_current = normdev_compute(rtp->rtcp->reported_normdev_lost, reported_lost, rtp->rtcp->reported_jitter_count);
+-
+- rtp->rtcp->reported_stdev_lost = stddev_compute(rtp->rtcp->reported_stdev_lost, reported_lost, rtp->rtcp->reported_normdev_lost, reported_normdev_lost_current, rtp->rtcp->reported_jitter_count);
+-
+- rtp->rtcp->reported_normdev_lost = reported_normdev_lost_current;
+-
+- rtp->rtcp->reported_jitter_count++;
+-
+- if (rtcp_debug_test_addr(&sock_in)) {
+- ast_verbose(" Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24));
+- ast_verbose(" Packets lost so far: %d\n", rtp->rtcp->reported_lost);
+- ast_verbose(" Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff));
+- ast_verbose(" Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16);
+- ast_verbose(" Interarrival jitter: %u\n", rtp->rtcp->reported_jitter);
+- ast_verbose(" Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096);
+- ast_verbose(" DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0);
+- if (rtt)
+- ast_verbose(" RTT: %lu(sec)\n", (unsigned long) rtt);
+- }
+-
+- if (rtt) {
+- manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From: %s:%d\r\n"
+- "PT: %d(%s)\r\n"
+- "ReceptionReports: %d\r\n"
+- "SenderSSRC: %u\r\n"
+- "FractionLost: %ld\r\n"
+- "PacketsLost: %d\r\n"
+- "HighestSequence: %ld\r\n"
+- "SequenceNumberCycles: %ld\r\n"
+- "IAJitter: %u\r\n"
+- "LastSR: %lu.%010lu\r\n"
+- "DLSR: %4.4f(sec)\r\n"
+- "RTT: %llu(sec)\r\n",
+- ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port),
+- pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown",
+- rc,
+- rtcpheader[i + 1],
+- (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24),
+- rtp->rtcp->reported_lost,
+- (long) (ntohl(rtcpheader[i + 2]) & 0xffff),
+- (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16,
+- rtp->rtcp->reported_jitter,
+- (unsigned long) ntohl(rtcpheader[i + 4]) >> 16, ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096,
+- ntohl(rtcpheader[i + 5])/65536.0,
+- (unsigned long long)rtt);
+- } else {
+- manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From: %s:%d\r\n"
+- "PT: %d(%s)\r\n"
+- "ReceptionReports: %d\r\n"
+- "SenderSSRC: %u\r\n"
+- "FractionLost: %ld\r\n"
+- "PacketsLost: %d\r\n"
+- "HighestSequence: %ld\r\n"
+- "SequenceNumberCycles: %ld\r\n"
+- "IAJitter: %u\r\n"
+- "LastSR: %lu.%010lu\r\n"
+- "DLSR: %4.4f(sec)\r\n",
+- ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port),
+- pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown",
+- rc,
+- rtcpheader[i + 1],
+- (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24),
+- rtp->rtcp->reported_lost,
+- (long) (ntohl(rtcpheader[i + 2]) & 0xffff),
+- (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16,
+- rtp->rtcp->reported_jitter,
+- (unsigned long) ntohl(rtcpheader[i + 4]) >> 16,
+- ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096,
+- ntohl(rtcpheader[i + 5])/65536.0);
+- }
+- break;
+- case RTCP_PT_FUR:
+- if (rtcp_debug_test_addr(&sock_in))
+- ast_verbose("Received an RTCP Fast Update Request\n");
+- rtp->f.frametype = AST_FRAME_CONTROL;
+- rtp->f.subclass = AST_CONTROL_VIDUPDATE;
+- rtp->f.datalen = 0;
+- rtp->f.samples = 0;
+- rtp->f.mallocd = 0;
+- rtp->f.src = "RTP";
+- f = &rtp->f;
+- break;
+- case RTCP_PT_SDES:
+- if (rtcp_debug_test_addr(&sock_in))
+- ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
+- break;
+- case RTCP_PT_BYE:
+- if (rtcp_debug_test_addr(&sock_in))
+- ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
+- break;
+- default:
+- ast_debug(1, "Unknown RTCP packet (pt=%d) received from %s:%d\n", pt, ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
+- break;
+- }
+- position += (length + 1);
+- }
+- rtp->rtcp->rtcp_info = 1;
+- return f;
+-}
+-
+-static void calc_rxstamp(struct timeval *when, struct ast_rtp *rtp, unsigned int timestamp, int mark)
+-{
+- struct timeval now;
+- double transit;
+- double current_time;
+- double d;
+- double dtv;
+- double prog;
+-
+- double normdev_rxjitter_current;
+- if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) {
+- gettimeofday(&rtp->rxcore, NULL);
+- rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000;
+- /* map timestamp to a real time */
+- rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */
+- rtp->rxcore.tv_sec -= timestamp / 8000;
+- rtp->rxcore.tv_usec -= (timestamp % 8000) * 125;
+- /* Round to 0.1ms for nice, pretty timestamps */
+- rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100;
+- if (rtp->rxcore.tv_usec < 0) {
+- /* Adjust appropriately if necessary */
+- rtp->rxcore.tv_usec += 1000000;
+- rtp->rxcore.tv_sec -= 1;
+- }
+- }
+-
+- gettimeofday(&now,NULL);
+- /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */
+- when->tv_sec = rtp->rxcore.tv_sec + timestamp / 8000;
+- when->tv_usec = rtp->rxcore.tv_usec + (timestamp % 8000) * 125;
+- if (when->tv_usec >= 1000000) {
+- when->tv_usec -= 1000000;
+- when->tv_sec += 1;
+- }
+- prog = (double)((timestamp-rtp->seedrxts)/8000.);
+- dtv = (double)rtp->drxcore + (double)(prog);
+- current_time = (double)now.tv_sec + (double)now.tv_usec/1000000;
+- transit = current_time - dtv;
+- d = transit - rtp->rxtransit;
+- rtp->rxtransit = transit;
+- if (d<0)
+- d=-d;
+- rtp->rxjitter += (1./16.) * (d - rtp->rxjitter);
+- if (rtp->rtcp && rtp->rxjitter > rtp->rtcp->maxrxjitter)
+- rtp->rtcp->maxrxjitter = rtp->rxjitter;
+- if (rtp->rtcp->rxjitter_count == 1)
+- rtp->rtcp->minrxjitter = rtp->rxjitter;
+- if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter)
+- rtp->rtcp->minrxjitter = rtp->rxjitter;
+-
+- normdev_rxjitter_current = normdev_compute(rtp->rtcp->normdev_rxjitter,rtp->rxjitter,rtp->rtcp->rxjitter_count);
+- rtp->rtcp->stdev_rxjitter = stddev_compute(rtp->rtcp->stdev_rxjitter,rtp->rxjitter,rtp->rtcp->normdev_rxjitter,normdev_rxjitter_current,rtp->rtcp->rxjitter_count);
+-
+- rtp->rtcp->normdev_rxjitter = normdev_rxjitter_current;
+- rtp->rtcp->rxjitter_count++;
+-}
+-
+-/*! \brief Perform a Packet2Packet RTP write */
+-static int bridge_p2p_rtp_write(struct ast_rtp *rtp, struct ast_rtp *bridged, unsigned int *rtpheader, int len, int hdrlen)
+-{
+- int res = 0, payload = 0, bridged_payload = 0, mark;
+- struct rtpPayloadType rtpPT;
+- int reconstruct = ntohl(rtpheader[0]);
+-
+- /* Get fields from packet */
+- payload = (reconstruct & 0x7f0000) >> 16;
+- mark = (((reconstruct & 0x800000) >> 23) != 0);
+-
+- /* Check what the payload value should be */
+- rtpPT = ast_rtp_lookup_pt(rtp, payload);
+-
+- /* If the payload is DTMF, and we are listening for DTMF - then feed it into the core */
+- if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) && !rtpPT.isAstFormat && rtpPT.code == AST_RTP_DTMF)
+- return -1;
+-
+- /* Otherwise adjust bridged payload to match */
+- bridged_payload = ast_rtp_lookup_code(bridged, rtpPT.isAstFormat, rtpPT.code);
+-
+- /* If the payload coming in is not one of the negotiated ones then send it to the core, this will cause formats to change and the bridge to break */
+- if (!bridged->current_RTP_PT[bridged_payload].code)
+- return -1;
+-
+-
+- /* If the mark bit has not been sent yet... do it now */
+- if (!ast_test_flag(rtp, FLAG_P2P_SENT_MARK)) {
+- mark = 1;
+- ast_set_flag(rtp, FLAG_P2P_SENT_MARK);
+- }
+-
+- /* Reconstruct part of the packet */
+- reconstruct &= 0xFF80FFFF;
+- reconstruct |= (bridged_payload << 16);
+- reconstruct |= (mark << 23);
+- rtpheader[0] = htonl(reconstruct);
+-
+- /* Send the packet back out */
+- res = sendto(bridged->s, (void *)rtpheader, len, 0, (struct sockaddr *)&bridged->them, sizeof(bridged->them));
+- if (res < 0) {
+- if (!bridged->nat || (bridged->nat && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
+- ast_debug(1, "RTP Transmission error of packet to %s:%d: %s\n", ast_inet_ntoa(bridged->them.sin_addr), ntohs(bridged->them.sin_port), strerror(errno));
+- } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) {
+- if (option_debug || rtpdebug)
+- ast_debug(0, "RTP NAT: Can't write RTP to private address %s:%d, waiting for other end to send audio...\n", ast_inet_ntoa(bridged->them.sin_addr), ntohs(bridged->them.sin_port));
+- ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN);
+- }
+- return 0;
+- } else if (rtp_debug_test_addr(&bridged->them))
+- ast_verbose("Sent RTP P2P packet to %s:%u (type %-2.2d, len %-6.6u)\n", ast_inet_ntoa(bridged->them.sin_addr), ntohs(bridged->them.sin_port), bridged_payload, len - hdrlen);
+-
+- return 0;
+-}
+-
+-struct ast_frame *ast_rtp_read(struct ast_rtp *rtp)
+-{
+- int res;
+- struct sockaddr_in sock_in;
+- socklen_t len;
+- unsigned int seqno;
+- int version;
+- int payloadtype;
+- int hdrlen = 12;
+- int padding;
+- int mark;
+- int ext;
+- int cc;
+- unsigned int ssrc;
+- unsigned int timestamp;
+- unsigned int *rtpheader;
+- struct rtpPayloadType rtpPT;
+- struct ast_rtp *bridged = NULL;
+- int prev_seqno;
+-
+- /* If time is up, kill it */
+- if (rtp->sending_digit)
+- ast_rtp_senddigit_continuation(rtp);
+-
+- len = sizeof(sock_in);
+-
+- /* Cache where the header will go */
+- res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET,
+- 0, (struct sockaddr *)&sock_in, &len);
+-
+- /* If strict RTP protection is enabled see if we need to learn this address or if the packet should be dropped */
+- if (rtp->strict_rtp_state == STRICT_RTP_LEARN) {
+- /* Copy over address that this packet was received on */
+- memcpy(&rtp->strict_rtp_address, &sock_in, sizeof(rtp->strict_rtp_address));
+- /* Now move over to actually protecting the RTP port */
+- rtp->strict_rtp_state = STRICT_RTP_CLOSED;
+- ast_debug(1, "Learned remote address is %s:%d for strict RTP purposes, now protecting the port.\n", ast_inet_ntoa(rtp->strict_rtp_address.sin_addr), ntohs(rtp->strict_rtp_address.sin_port));
+- } else if (rtp->strict_rtp_state == STRICT_RTP_CLOSED) {
+- /* If the address we previously learned doesn't match the address this packet came in on simply drop it */
+- if ((rtp->strict_rtp_address.sin_addr.s_addr != sock_in.sin_addr.s_addr) || (rtp->strict_rtp_address.sin_port != sock_in.sin_port)) {
+- ast_debug(1, "Received RTP packet from %s:%d, dropping due to strict RTP protection. Expected it to be from %s:%d\n", ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port), ast_inet_ntoa(rtp->strict_rtp_address.sin_addr), ntohs(rtp->strict_rtp_address.sin_port));
+- return &ast_null_frame;
+- }
+- }
+-
+- rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET);
+- if (res < 0) {
+- ast_assert(errno != EBADF);
+- if (errno != EAGAIN) {
+- ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up.\n", strerror(errno));
+- return NULL;
+- }
+- return &ast_null_frame;
+- }
+-
+- if (res < hdrlen) {
+- ast_log(LOG_WARNING, "RTP Read too short\n");
+- return &ast_null_frame;
+- }
+-
+- /* Get fields */
+- seqno = ntohl(rtpheader[0]);
+-
+- /* Check RTP version */
+- version = (seqno & 0xC0000000) >> 30;
+- if (!version) {
+- /* If the two high bits are 0, this might be a
+- * STUN message, so process it. stun_handle_packet()
+- * answers to requests, and it returns STUN_ACCEPT
+- * if the request is valid.
+- */
+- if ((stun_handle_packet(rtp->s, &sock_in, rtp->rawdata + AST_FRIENDLY_OFFSET, res, NULL, NULL) == STUN_ACCEPT) &&
+- (!rtp->them.sin_port && !rtp->them.sin_addr.s_addr)) {
+- memcpy(&rtp->them, &sock_in, sizeof(rtp->them));
+- }
+- return &ast_null_frame;
+- }
+-
+-#if 0 /* Allow to receive RTP stream with closed transmission path */
+- /* If we don't have the other side's address, then ignore this */
+- if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
+- return &ast_null_frame;
+-#endif
+-
+- /* Send to whoever send to us if NAT is turned on */
+- if (rtp->nat) {
+- if (((rtp->them.sin_addr.s_addr != sock_in.sin_addr.s_addr) ||
+- (rtp->them.sin_port != sock_in.sin_port)) &&
+- ((rtp->altthem.sin_addr.s_addr != sock_in.sin_addr.s_addr) ||
+- (rtp->altthem.sin_port != sock_in.sin_port))) {
+- rtp->them = sock_in;
+- if (rtp->rtcp) {
+- int h = 0;
+- memcpy(&rtp->rtcp->them, &sock_in, sizeof(rtp->rtcp->them));
+- h = ntohs(rtp->them.sin_port);
+- rtp->rtcp->them.sin_port = htons(h + 1);
+- }
+- rtp->rxseqno = 0;
+- ast_set_flag(rtp, FLAG_NAT_ACTIVE);
+- if (option_debug || rtpdebug)
+- ast_debug(0, "RTP NAT: Got audio from other end. Now sending to address %s:%d\n", ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port));
+- }
+- }
+-
+- /* If we are bridged to another RTP stream, send direct */
+- if ((bridged = ast_rtp_get_bridged(rtp)) && !bridge_p2p_rtp_write(rtp, bridged, rtpheader, res, hdrlen))
+- return &ast_null_frame;
+-
+- if (version != 2)
+- return &ast_null_frame;
+-
+- payloadtype = (seqno & 0x7f0000) >> 16;
+- padding = seqno & (1 << 29);
+- mark = seqno & (1 << 23);
+- ext = seqno & (1 << 28);
+- cc = (seqno & 0xF000000) >> 24;
+- seqno &= 0xffff;
+- timestamp = ntohl(rtpheader[1]);
+- ssrc = ntohl(rtpheader[2]);
+-
+- if (!mark && rtp->rxssrc && rtp->rxssrc != ssrc) {
+- if (option_debug || rtpdebug)
+- ast_debug(0, "Forcing Marker bit, because SSRC has changed\n");
+- mark = 1;
+- }
+-
+- rtp->rxssrc = ssrc;
+-
+- if (padding) {
+- /* Remove padding bytes */
+- res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1];
+- }
+-
+- if (cc) {
+- /* CSRC fields present */
+- hdrlen += cc*4;
+- }
+-
+- if (ext) {
+- /* RTP Extension present */
+- hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2;
+- hdrlen += 4;
+- if (option_debug) {
+- int profile;
+- profile = (ntohl(rtpheader[3]) & 0xffff0000) >> 16;
+- if (profile == 0x505a)
+- ast_debug(1, "Found Zfone extension in RTP stream - zrtp - not supported.\n");
+- else
+- ast_debug(1, "Found unknown RTP Extensions %x\n", profile);
+- }
+- }
+-
+- if (res < hdrlen) {
+- ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen);
+- return &ast_null_frame;
+- }
+-
+- rtp->rxcount++; /* Only count reasonably valid packets, this'll make the rtcp stats more accurate */
+-
+- if (rtp->rxcount==1) {
+- /* This is the first RTP packet successfully received from source */
+- rtp->seedrxseqno = seqno;
+- }
+-
+- /* Do not schedule RR if RTCP isn't run */
+- if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) {
+- /* Schedule transmission of Receiver Report */
+- rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
+- }
+- if ((int)rtp->lastrxseqno - (int)seqno > 100) /* if so it would indicate that the sender cycled; allow for misordering */
+- rtp->cycles += RTP_SEQ_MOD;
+-
+- prev_seqno = rtp->lastrxseqno;
+-
+- rtp->lastrxseqno = seqno;
+-
+- if (!rtp->themssrc)
+- rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */
+-
+- if (rtp_debug_test_addr(&sock_in))
+- ast_verbose("Got RTP packet from %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
+- ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port), payloadtype, seqno, timestamp,res - hdrlen);
+-
+- rtpPT = ast_rtp_lookup_pt(rtp, payloadtype);
+- if (!rtpPT.isAstFormat) {
+- struct ast_frame *f = NULL;
+-
+- /* This is special in-band data that's not one of our codecs */
+- if (rtpPT.code == AST_RTP_DTMF) {
+- /* It's special -- rfc2833 process it */
+- if (rtp_debug_test_addr(&sock_in)) {
+- unsigned char *data;
+- unsigned int event;
+- unsigned int event_end;
+- unsigned int duration;
+- data = rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen;
+- event = ntohl(*((unsigned int *)(data)));
+- event >>= 24;
+- event_end = ntohl(*((unsigned int *)(data)));
+- event_end <<= 8;
+- event_end >>= 24;
+- duration = ntohl(*((unsigned int *)(data)));
+- duration &= 0xFFFF;
+- ast_verbose("Got RTP RFC2833 from %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u, mark %d, event %08x, end %d, duration %-5.5d) \n", ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port), payloadtype, seqno, timestamp, res - hdrlen, (mark?1:0), event, ((event_end & 0x80)?1:0), duration);
+- }
+- f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp);
+- } else if (rtpPT.code == AST_RTP_CISCO_DTMF) {
+- /* It's really special -- process it the Cisco way */
+- if (rtp->lastevent <= seqno || (rtp->lastevent >= 65530 && seqno <= 6)) {
+- f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
+- rtp->lastevent = seqno;
+- }
+- } else if (rtpPT.code == AST_RTP_CN) {
+- /* Comfort Noise */
+- f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
+- } else {
+- ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", payloadtype, ast_inet_ntoa(rtp->them.sin_addr));
+- }
+- return f ? f : &ast_null_frame;
+- }
+- rtp->lastrxformat = rtp->f.subclass = rtpPT.code;
+- rtp->f.frametype = (rtp->f.subclass & AST_FORMAT_AUDIO_MASK) ? AST_FRAME_VOICE : (rtp->f.subclass & AST_FORMAT_VIDEO_MASK) ? AST_FRAME_VIDEO : AST_FRAME_TEXT;
+-
+- rtp->rxseqno = seqno;
+-
+- if (rtp->dtmf_timeout && rtp->dtmf_timeout < timestamp) {
+- rtp->dtmf_timeout = 0;
+-
+- if (rtp->resp) {
+- struct ast_frame *f;
+- f = send_dtmf(rtp, AST_FRAME_DTMF_END);
+- f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, 8000), ast_tv(0, 0));
+- rtp->resp = 0;
+- rtp->dtmf_timeout = rtp->dtmf_duration = 0;
+- return f;
+- }
+- }
+-
+- /* Record received timestamp as last received now */
+- rtp->lastrxts = timestamp;
+-
+- rtp->f.mallocd = 0;
+- rtp->f.datalen = res - hdrlen;
+- rtp->f.data.ptr = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET;
+- rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
+- rtp->f.seqno = seqno;
+-
+- if (rtp->f.subclass == AST_FORMAT_T140 && (int)seqno - (prev_seqno+1) > 0 && (int)seqno - (prev_seqno+1) < 10) {
+- unsigned char *data = rtp->f.data.ptr;
+-
+- memmove(rtp->f.data.ptr+3, rtp->f.data.ptr, rtp->f.datalen);
+- rtp->f.datalen +=3;
+- *data++ = 0xEF;
+- *data++ = 0xBF;
+- *data = 0xBD;
+- }
+-
+- if (rtp->f.subclass == AST_FORMAT_T140RED) {
+- unsigned char *data = rtp->f.data.ptr;
+- unsigned char *header_end;
+- int num_generations;
+- int header_length;
+- int length;
+- int diff =(int)seqno - (prev_seqno+1); /* if diff = 0, no drop*/
+- int x;
+-
+- rtp->f.subclass = AST_FORMAT_T140;
+- header_end = memchr(data, ((*data) & 0x7f), rtp->f.datalen);
+- header_end++;
+-
+- header_length = header_end - data;
+- num_generations = header_length / 4;
+- length = header_length;
+-
+- if (!diff) {
+- for (x = 0; x < num_generations; x++)
+- length += data[x * 4 + 3];
+-
+- if (!(rtp->f.datalen - length))
+- return &ast_null_frame;
+-
+- rtp->f.data.ptr += length;
+- rtp->f.datalen -= length;
+- } else if (diff > num_generations && diff < 10) {
+- length -= 3;
+- rtp->f.data.ptr += length;
+- rtp->f.datalen -= length;
+-
+- data = rtp->f.data.ptr;
+- *data++ = 0xEF;
+- *data++ = 0xBF;
+- *data = 0xBD;
+- } else {
+- for ( x = 0; x < num_generations - diff; x++)
+- length += data[x * 4 + 3];
+-
+- rtp->f.data.ptr += length;
+- rtp->f.datalen -= length;
+- }
+- }
+-
+- if (rtp->f.subclass & AST_FORMAT_AUDIO_MASK) {
+- rtp->f.samples = ast_codec_get_samples(&rtp->f);
+- if (rtp->f.subclass == AST_FORMAT_SLINEAR)
+- ast_frame_byteswap_be(&rtp->f);
+- calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark);
+- /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */
+- ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO);
+- rtp->f.ts = timestamp / 8;
+- rtp->f.len = rtp->f.samples / ((ast_format_rate(rtp->f.subclass) / 1000));
+- } else if (rtp->f.subclass & AST_FORMAT_VIDEO_MASK) {
+- /* Video -- samples is # of samples vs. 90000 */
+- if (!rtp->lastividtimestamp)
+- rtp->lastividtimestamp = timestamp;
+- rtp->f.samples = timestamp - rtp->lastividtimestamp;
+- rtp->lastividtimestamp = timestamp;
+- rtp->f.delivery.tv_sec = 0;
+- rtp->f.delivery.tv_usec = 0;
+- /* Pass the RTP marker bit as bit 0 in the subclass field.
+- * This is ok because subclass is actually a bitmask, and
+- * the low bits represent audio formats, that are not
+- * involved here since we deal with video.
+- */
+- if (mark)
+- rtp->f.subclass |= 0x1;
+- } else {
+- /* TEXT -- samples is # of samples vs. 1000 */
+- if (!rtp->lastitexttimestamp)
+- rtp->lastitexttimestamp = timestamp;
+- rtp->f.samples = timestamp - rtp->lastitexttimestamp;
+- rtp->lastitexttimestamp = timestamp;
+- rtp->f.delivery.tv_sec = 0;
+- rtp->f.delivery.tv_usec = 0;
+- }
+- rtp->f.src = "RTP";
+- return &rtp->f;
+-}
+-
+-/* The following array defines the MIME Media type (and subtype) for each
+- of our codecs, or RTP-specific data type. */
+-static const struct mimeType {
+- struct rtpPayloadType payloadType;
+- char *type;
+- char *subtype;
+- unsigned int sample_rate;
+-} mimeTypes[] = {
+- {{1, AST_FORMAT_G723_1}, "audio", "G723", 8000},
+- {{1, AST_FORMAT_GSM}, "audio", "GSM", 8000},
+- {{1, AST_FORMAT_ULAW}, "audio", "PCMU", 8000},
+- {{1, AST_FORMAT_ULAW}, "audio", "G711U", 8000},
+- {{1, AST_FORMAT_ALAW}, "audio", "PCMA", 8000},
+- {{1, AST_FORMAT_ALAW}, "audio", "G711A", 8000},
+- {{1, AST_FORMAT_G726}, "audio", "G726-32", 8000},
+- {{1, AST_FORMAT_ADPCM}, "audio", "DVI4", 8000},
+- {{1, AST_FORMAT_SLINEAR}, "audio", "L16", 8000},
+- {{1, AST_FORMAT_LPC10}, "audio", "LPC", 8000},
+- {{1, AST_FORMAT_G729A}, "audio", "G729", 8000},
+- {{1, AST_FORMAT_G729A}, "audio", "G729A", 8000},
+- {{1, AST_FORMAT_G729A}, "audio", "G.729", 8000},
+- {{1, AST_FORMAT_SPEEX}, "audio", "speex", 8000},
+- {{1, AST_FORMAT_ILBC}, "audio", "iLBC", 8000},
+- /* this is the sample rate listed in the RTP profile for the G.722
+- codec, *NOT* the actual sample rate of the media stream
+- */
+- {{1, AST_FORMAT_G722}, "audio", "G722", 8000},
+- {{1, AST_FORMAT_G726_AAL2}, "audio", "AAL2-G726-32", 8000},
+- {{0, AST_RTP_DTMF}, "audio", "telephone-event", 8000},
+- {{0, AST_RTP_CISCO_DTMF}, "audio", "cisco-telephone-event", 8000},
+- {{0, AST_RTP_CN}, "audio", "CN", 8000},
+- {{1, AST_FORMAT_JPEG}, "video", "JPEG", 90000},
+- {{1, AST_FORMAT_PNG}, "video", "PNG", 90000},
+- {{1, AST_FORMAT_H261}, "video", "H261", 90000},
+- {{1, AST_FORMAT_H263}, "video", "H263", 90000},
+- {{1, AST_FORMAT_H263_PLUS}, "video", "h263-1998", 90000},
+- {{1, AST_FORMAT_H264}, "video", "H264", 90000},
+- {{1, AST_FORMAT_MP4_VIDEO}, "video", "MP4V-ES", 90000},
+- {{1, AST_FORMAT_T140RED}, "text", "RED", 1000},
+- {{1, AST_FORMAT_T140}, "text", "T140", 1000},
+- {{1, AST_FORMAT_SIREN7}, "audio", "G7221", 16000},
+- {{1, AST_FORMAT_SIREN14}, "audio", "G7221", 32000},
+-};
+-
+-/*!
+- * \brief Mapping between Asterisk codecs and rtp payload types
+- *
+- * Static (i.e., well-known) RTP payload types for our "AST_FORMAT..."s:
+- * also, our own choices for dynamic payload types. This is our master
+- * table for transmission
+- *
+- * See http://www.iana.org/assignments/rtp-parameters for a list of
+- * assigned values
+- */
+-static const struct rtpPayloadType static_RTP_PT[MAX_RTP_PT] = {
+- [0] = {1, AST_FORMAT_ULAW},
+-#ifdef USE_DEPRECATED_G726
+- [2] = {1, AST_FORMAT_G726}, /* Technically this is G.721, but if Cisco can do it, so can we... */
+-#endif
+- [3] = {1, AST_FORMAT_GSM},
+- [4] = {1, AST_FORMAT_G723_1},
+- [5] = {1, AST_FORMAT_ADPCM}, /* 8 kHz */
+- [6] = {1, AST_FORMAT_ADPCM}, /* 16 kHz */
+- [7] = {1, AST_FORMAT_LPC10},
+- [8] = {1, AST_FORMAT_ALAW},
+- [9] = {1, AST_FORMAT_G722},
+- [10] = {1, AST_FORMAT_SLINEAR}, /* 2 channels */
+- [11] = {1, AST_FORMAT_SLINEAR}, /* 1 channel */
+- [13] = {0, AST_RTP_CN},
+- [16] = {1, AST_FORMAT_ADPCM}, /* 11.025 kHz */
+- [17] = {1, AST_FORMAT_ADPCM}, /* 22.050 kHz */
+- [18] = {1, AST_FORMAT_G729A},
+- [19] = {0, AST_RTP_CN}, /* Also used for CN */
+- [26] = {1, AST_FORMAT_JPEG},
+- [31] = {1, AST_FORMAT_H261},
+- [34] = {1, AST_FORMAT_H263},
+- [97] = {1, AST_FORMAT_ILBC},
+- [98] = {1, AST_FORMAT_H263_PLUS},
+- [99] = {1, AST_FORMAT_H264},
+- [101] = {0, AST_RTP_DTMF},
+- [102] = {1, AST_FORMAT_SIREN7},
+- [103] = {1, AST_FORMAT_H263_PLUS},
+- [104] = {1, AST_FORMAT_MP4_VIDEO},
+- [105] = {1, AST_FORMAT_T140RED}, /* Real time text chat (with redundancy encoding) */
+- [106] = {1, AST_FORMAT_T140}, /* Real time text chat */
+- [110] = {1, AST_FORMAT_SPEEX},
+- [111] = {1, AST_FORMAT_G726},
+- [112] = {1, AST_FORMAT_G726_AAL2},
+- [115] = {1, AST_FORMAT_SIREN14},
+- [121] = {0, AST_RTP_CISCO_DTMF}, /* Must be type 121 */
+-};
+-
+-void ast_rtp_pt_clear(struct ast_rtp* rtp)
+-{
+- int i;
+-
+- if (!rtp)
+- return;
+-
+- rtp_bridge_lock(rtp);
+-
+- for (i = 0; i < MAX_RTP_PT; ++i) {
+- rtp->current_RTP_PT[i].isAstFormat = 0;
+- rtp->current_RTP_PT[i].code = 0;
+- }
+-
+- rtp->rtp_lookup_code_cache_isAstFormat = 0;
+- rtp->rtp_lookup_code_cache_code = 0;
+- rtp->rtp_lookup_code_cache_result = 0;
+-
+- rtp_bridge_unlock(rtp);
+-}
+-
+-void ast_rtp_pt_default(struct ast_rtp* rtp)
+-{
+- int i;
+-
+- rtp_bridge_lock(rtp);
+-
+- /* Initialize to default payload types */
+- for (i = 0; i < MAX_RTP_PT; ++i) {
+- rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
+- rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
+- }
+-
+- rtp->rtp_lookup_code_cache_isAstFormat = 0;
+- rtp->rtp_lookup_code_cache_code = 0;
+- rtp->rtp_lookup_code_cache_result = 0;
+-
+- rtp_bridge_unlock(rtp);
+-}
+-
+-void ast_rtp_pt_copy(struct ast_rtp *dest, struct ast_rtp *src)
+-{
+- unsigned int i;
+-
+- rtp_bridge_lock(dest);
+- rtp_bridge_lock(src);
+-
+- for (i = 0; i < MAX_RTP_PT; ++i) {
+- dest->current_RTP_PT[i].isAstFormat =
+- src->current_RTP_PT[i].isAstFormat;
+- dest->current_RTP_PT[i].code =
+- src->current_RTP_PT[i].code;
+- }
+- dest->rtp_lookup_code_cache_isAstFormat = 0;
+- dest->rtp_lookup_code_cache_code = 0;
+- dest->rtp_lookup_code_cache_result = 0;
+-
+- rtp_bridge_unlock(src);
+- rtp_bridge_unlock(dest);
+-}
+-
+-/*! \brief Get channel driver interface structure */
+-static struct ast_rtp_protocol *get_proto(struct ast_channel *chan)
+-{
+- struct ast_rtp_protocol *cur = NULL;
+-
+- AST_RWLIST_RDLOCK(&protos);
+- AST_RWLIST_TRAVERSE(&protos, cur, list) {
+- if (cur->type == chan->tech->type)
+- break;
+- }
+- AST_RWLIST_UNLOCK(&protos);
+-
+- return cur;
+-}
+-
+-int ast_rtp_early_bridge(struct ast_channel *c0, struct ast_channel *c1)
+-{
+- struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */
+- struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */
+- struct ast_rtp *tdestp = NULL, *tsrcp = NULL; /* Text RTP channels */
+- struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
+- enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED, text_dest_res = AST_RTP_GET_FAILED;
+- enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED, text_src_res = AST_RTP_GET_FAILED;
+- int srccodec, destcodec, nat_active = 0;
+-
+- /* Lock channels */
+- ast_channel_lock(c0);
+- if (c1) {
+- while (ast_channel_trylock(c1)) {
+- ast_channel_unlock(c0);
+- usleep(1);
+- ast_channel_lock(c0);
+- }
+- }
+-
+- /* Find channel driver interfaces */
+- destpr = get_proto(c0);
+- if (c1)
+- srcpr = get_proto(c1);
+- if (!destpr) {
+- ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", c0->name);
+- ast_channel_unlock(c0);
+- if (c1)
+- ast_channel_unlock(c1);
+- return -1;
+- }
+- if (!srcpr) {
+- ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", c1 ? c1->name : "<unspecified>");
+- ast_channel_unlock(c0);
+- if (c1)
+- ast_channel_unlock(c1);
+- return -1;
+- }
+-
+- /* Get audio, video and text interface (if native bridge is possible) */
+- audio_dest_res = destpr->get_rtp_info(c0, &destp);
+- video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(c0, &vdestp) : AST_RTP_GET_FAILED;
+- text_dest_res = destpr->get_trtp_info ? destpr->get_trtp_info(c0, &tdestp) : AST_RTP_GET_FAILED;
+- if (srcpr) {
+- audio_src_res = srcpr->get_rtp_info(c1, &srcp);
+- video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(c1, &vsrcp) : AST_RTP_GET_FAILED;
+- text_src_res = srcpr->get_trtp_info ? srcpr->get_trtp_info(c1, &tsrcp) : AST_RTP_GET_FAILED;
+- }
+-
+- /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
+- if (audio_dest_res != AST_RTP_TRY_NATIVE || (video_dest_res != AST_RTP_GET_FAILED && video_dest_res != AST_RTP_TRY_NATIVE)) {
+- /* Somebody doesn't want to play... */
+- ast_channel_unlock(c0);
+- if (c1)
+- ast_channel_unlock(c1);
+- return -1;
+- }
+- if (audio_src_res == AST_RTP_TRY_NATIVE && (video_src_res == AST_RTP_GET_FAILED || video_src_res == AST_RTP_TRY_NATIVE) && srcpr->get_codec)
+- srccodec = srcpr->get_codec(c1);
+- else
+- srccodec = 0;
+- if (audio_dest_res == AST_RTP_TRY_NATIVE && (video_dest_res == AST_RTP_GET_FAILED || video_dest_res == AST_RTP_TRY_NATIVE) && destpr->get_codec)
+- destcodec = destpr->get_codec(c0);
+- else
+- destcodec = 0;
+- /* Ensure we have at least one matching codec */
+- if (srcp && !(srccodec & destcodec)) {
+- ast_channel_unlock(c0);
+- ast_channel_unlock(c1);
+- return 0;
+- }
+- /* Consider empty media as non-existent */
+- if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr)
+- srcp = NULL;
+- if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
+- nat_active = 1;
+- /* Bridge media early */
+- if (destpr->set_rtp_peer(c0, srcp, vsrcp, tsrcp, srccodec, nat_active))
+- ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
+- ast_channel_unlock(c0);
+- if (c1)
+- ast_channel_unlock(c1);
+- ast_debug(1, "Setting early bridge SDP of '%s' with that of '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
+- return 0;
+-}
+-
+-int ast_rtp_make_compatible(struct ast_channel *dest, struct ast_channel *src, int media)
+-{
+- struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */
+- struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */
+- struct ast_rtp *tdestp = NULL, *tsrcp = NULL; /* Text RTP channels */
+- struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
+- enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED, text_dest_res = AST_RTP_GET_FAILED;
+- enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED, text_src_res = AST_RTP_GET_FAILED;
+- int srccodec, destcodec;
+-
+- /* Lock channels */
+- ast_channel_lock(dest);
+- while (ast_channel_trylock(src)) {
+- ast_channel_unlock(dest);
+- usleep(1);
+- ast_channel_lock(dest);
+- }
+-
+- /* Find channel driver interfaces */
+- if (!(destpr = get_proto(dest))) {
+- ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", dest->name);
+- ast_channel_unlock(dest);
+- ast_channel_unlock(src);
+- return 0;
+- }
+- if (!(srcpr = get_proto(src))) {
+- ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", src->name);
+- ast_channel_unlock(dest);
+- ast_channel_unlock(src);
+- return 0;
+- }
+-
+- /* Get audio and video interface (if native bridge is possible) */
+- audio_dest_res = destpr->get_rtp_info(dest, &destp);
+- video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED;
+- text_dest_res = destpr->get_trtp_info ? destpr->get_trtp_info(dest, &tdestp) : AST_RTP_GET_FAILED;
+- audio_src_res = srcpr->get_rtp_info(src, &srcp);
+- video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED;
+- text_src_res = srcpr->get_trtp_info ? srcpr->get_trtp_info(src, &tsrcp) : AST_RTP_GET_FAILED;
+-
+- /* Ensure we have at least one matching codec */
+- if (srcpr->get_codec)
+- srccodec = srcpr->get_codec(src);
+- else
+- srccodec = 0;
+- if (destpr->get_codec)
+- destcodec = destpr->get_codec(dest);
+- else
+- destcodec = 0;
+-
+- /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
+- if (audio_dest_res != AST_RTP_TRY_NATIVE || (video_dest_res != AST_RTP_GET_FAILED && video_dest_res != AST_RTP_TRY_NATIVE) || audio_src_res != AST_RTP_TRY_NATIVE || (video_src_res != AST_RTP_GET_FAILED && video_src_res != AST_RTP_TRY_NATIVE) || !(srccodec & destcodec)) {
+- /* Somebody doesn't want to play... */
+- ast_channel_unlock(dest);
+- ast_channel_unlock(src);
+- return 0;
+- }
+- ast_rtp_pt_copy(destp, srcp);
+- if (vdestp && vsrcp)
+- ast_rtp_pt_copy(vdestp, vsrcp);
+- if (tdestp && tsrcp)
+- ast_rtp_pt_copy(tdestp, tsrcp);
+- if (media) {
+- /* Bridge early */
+- if (destpr->set_rtp_peer(dest, srcp, vsrcp, tsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
+- ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name);
+- }
+- ast_channel_unlock(dest);
+- ast_channel_unlock(src);
+- ast_debug(1, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name);
+- return 1;
+-}
+-
+-/*! \brief Make a note of a RTP payload type that was seen in a SDP "m=" line.
+- * By default, use the well-known value for this type (although it may
+- * still be set to a different value by a subsequent "a=rtpmap:" line)
+- */
+-void ast_rtp_set_m_type(struct ast_rtp* rtp, int pt)
+-{
+- if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].code == 0)
+- return; /* bogus payload type */
+-
+- rtp_bridge_lock(rtp);
+- rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
+- rtp_bridge_unlock(rtp);
+-}
+-
+-/*! \brief remove setting from payload type list if the rtpmap header indicates
+- an unknown media type */
+-void ast_rtp_unset_m_type(struct ast_rtp* rtp, int pt)
+-{
+- if (pt < 0 || pt > MAX_RTP_PT)
+- return; /* bogus payload type */
+-
+- rtp_bridge_lock(rtp);
+- rtp->current_RTP_PT[pt].isAstFormat = 0;
+- rtp->current_RTP_PT[pt].code = 0;
+- rtp_bridge_unlock(rtp);
+-}
+-
+-/*! \brief Make a note of a RTP payload type (with MIME type) that was seen in
+- * an SDP "a=rtpmap:" line.
+- * \return 0 if the MIME type was found and set, -1 if it wasn't found
+- */
+-int ast_rtp_set_rtpmap_type_rate(struct ast_rtp *rtp, int pt,
+- char *mimeType, char *mimeSubtype,
+- enum ast_rtp_options options,
+- unsigned int sample_rate)
+-{
+- unsigned int i;
+- int found = 0;
+-
+- if (pt < 0 || pt > MAX_RTP_PT)
+- return -1; /* bogus payload type */
+-
+- rtp_bridge_lock(rtp);
+-
+- for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) {
+- const struct mimeType *t = &mimeTypes[i];
+-
+- if (strcasecmp(mimeSubtype, t->subtype)) {
+- continue;
+- }
+-
+- if (strcasecmp(mimeType, t->type)) {
+- continue;
+- }
+-
+- /* if both sample rates have been supplied, and they don't match,
+- then this not a match; if one has not been supplied, then the
+- rates are not compared */
+- if (sample_rate && t->sample_rate &&
+- (sample_rate != t->sample_rate)) {
+- continue;
+- }
+-
+- found = 1;
+- rtp->current_RTP_PT[pt] = t->payloadType;
+-
+- if ((t->payloadType.code == AST_FORMAT_G726) &&
+- t->payloadType.isAstFormat &&
+- (options & AST_RTP_OPT_G726_NONSTANDARD)) {
+- rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2;
+- }
+-
+- break;
+- }
+-
+- rtp_bridge_unlock(rtp);
+-
+- return (found ? 0 : -2);
+-}
+-
+-int ast_rtp_set_rtpmap_type(struct ast_rtp *rtp, int pt,
+- char *mimeType, char *mimeSubtype,
+- enum ast_rtp_options options)
+-{
+- return ast_rtp_set_rtpmap_type_rate(rtp, pt, mimeType, mimeSubtype, options, 0);
+-}
+-
+-/*! \brief Return the union of all of the codecs that were set by rtp_set...() calls
+- * They're returned as two distinct sets: AST_FORMATs, and AST_RTPs */
+-void ast_rtp_get_current_formats(struct ast_rtp* rtp,
+- int* astFormats, int* nonAstFormats)
+-{
+- int pt;
+-
+- rtp_bridge_lock(rtp);
+-
+- *astFormats = *nonAstFormats = 0;
+- for (pt = 0; pt < MAX_RTP_PT; ++pt) {
+- if (rtp->current_RTP_PT[pt].isAstFormat) {
+- *astFormats |= rtp->current_RTP_PT[pt].code;
+- } else {
+- *nonAstFormats |= rtp->current_RTP_PT[pt].code;
+- }
+- }
+-
+- rtp_bridge_unlock(rtp);
+-}
+-
+-struct rtpPayloadType ast_rtp_lookup_pt(struct ast_rtp* rtp, int pt)
+-{
+- struct rtpPayloadType result;
+-
+- result.isAstFormat = result.code = 0;
+-
+- if (pt < 0 || pt > MAX_RTP_PT)
+- return result; /* bogus payload type */
+-
+- /* Start with negotiated codecs */
+- rtp_bridge_lock(rtp);
+- result = rtp->current_RTP_PT[pt];
+- rtp_bridge_unlock(rtp);
+-
+- /* If it doesn't exist, check our static RTP type list, just in case */
+- if (!result.code)
+- result = static_RTP_PT[pt];
+-
+- return result;
+-}
+-
+-/*! \brief Looks up an RTP code out of our *static* outbound list */
+-int ast_rtp_lookup_code(struct ast_rtp* rtp, const int isAstFormat, const int code)
+-{
+- int pt = 0;
+-
+- rtp_bridge_lock(rtp);
+-
+- if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat &&
+- code == rtp->rtp_lookup_code_cache_code) {
+- /* Use our cached mapping, to avoid the overhead of the loop below */
+- pt = rtp->rtp_lookup_code_cache_result;
+- rtp_bridge_unlock(rtp);
+- return pt;
+- }
+-
+- /* Check the dynamic list first */
+- for (pt = 0; pt < MAX_RTP_PT; ++pt) {
+- if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) {
+- rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
+- rtp->rtp_lookup_code_cache_code = code;
+- rtp->rtp_lookup_code_cache_result = pt;
+- rtp_bridge_unlock(rtp);
+- return pt;
+- }
+- }
+-
+- /* Then the static list */
+- for (pt = 0; pt < MAX_RTP_PT; ++pt) {
+- if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) {
+- rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
+- rtp->rtp_lookup_code_cache_code = code;
+- rtp->rtp_lookup_code_cache_result = pt;
+- rtp_bridge_unlock(rtp);
+- return pt;
+- }
+- }
+-
+- rtp_bridge_unlock(rtp);
+-
+- return -1;
+-}
+-
+-const char *ast_rtp_lookup_mime_subtype(const int isAstFormat, const int code,
+- enum ast_rtp_options options)
+-{
+- unsigned int i;
+-
+- for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) {
+- if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) {
+- if (isAstFormat &&
+- (code == AST_FORMAT_G726_AAL2) &&
+- (options & AST_RTP_OPT_G726_NONSTANDARD))
+- return "G726-32";
+- else
+- return mimeTypes[i].subtype;
+- }
+- }
+-
+- return "";
+-}
+-
+-unsigned int ast_rtp_lookup_sample_rate(int isAstFormat, int code)
+-{
+- unsigned int i;
+-
+- for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) {
+- if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) {
+- return mimeTypes[i].sample_rate;
+- }
+- }
+-
+- return 0;
+-}
+-
+-char *ast_rtp_lookup_mime_multiple(char *buf, size_t size, const int capability,
+- const int isAstFormat, enum ast_rtp_options options)
+-{
+- int format;
+- unsigned len;
+- char *end = buf;
+- char *start = buf;
+-
+- if (!buf || !size)
+- return NULL;
+-
+- snprintf(end, size, "0x%x (", capability);
+-
+- len = strlen(end);
+- end += len;
+- size -= len;
+- start = end;
+-
+- for (format = 1; format < AST_RTP_MAX; format <<= 1) {
+- if (capability & format) {
+- const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options);
+-
+- snprintf(end, size, "%s|", name);
+- len = strlen(end);
+- end += len;
+- size -= len;
+- }
+- }
+-
+- if (start == end)
+- ast_copy_string(start, "nothing)", size);
+- else if (size > 1)
+- *(end -1) = ')';
+-
+- return buf;
+-}
+-
+-/*! \brief Open RTP or RTCP socket for a session.
+- * Print a message on failure.
+- */
+-static int rtp_socket(const char *type)
+-{
+- int s = socket(AF_INET, SOCK_DGRAM, 0);
+- if (s < 0) {
+- if (type == NULL)
+- type = "RTP/RTCP";
+- ast_log(LOG_WARNING, "Unable to allocate %s socket: %s\n", type, strerror(errno));
+- } else {
+- long flags = fcntl(s, F_GETFL);
+- fcntl(s, F_SETFL, flags | O_NONBLOCK);
+-#ifdef SO_NO_CHECK
+- if (nochecksums)
+- setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
+-#endif
+- }
+- return s;
+-}
+-
+-/*!
+- * \brief Initialize a new RTCP session.
+- *
+- * \returns The newly initialized RTCP session.
+- */
+-static struct ast_rtcp *ast_rtcp_new(void)
+-{
+- struct ast_rtcp *rtcp;
+-
+- if (!(rtcp = ast_calloc(1, sizeof(*rtcp))))
+- return NULL;
+- rtcp->s = rtp_socket("RTCP");
+- rtcp->us.sin_family = AF_INET;
+- rtcp->them.sin_family = AF_INET;
+- rtcp->schedid = -1;
+-
+- if (rtcp->s < 0) {
+- ast_free(rtcp);
+- return NULL;
+- }
+-
+- return rtcp;
+-}
+-
+-/*!
+- * \brief Initialize a new RTP structure.
+- *
+- */
+-void ast_rtp_new_init(struct ast_rtp *rtp)
+-{
+-#ifdef P2P_INTENSE
+- ast_mutex_init(&rtp->bridge_lock);
+-#endif
+-
+- rtp->them.sin_family = AF_INET;
+- rtp->us.sin_family = AF_INET;
+- rtp->ssrc = ast_random();
+- rtp->seqno = ast_random() & 0xffff;
+- ast_set_flag(rtp, FLAG_HAS_DTMF);
+- rtp->strict_rtp_state = (strictrtp ? STRICT_RTP_LEARN : STRICT_RTP_OPEN);
+-}
+-
+-struct ast_rtp *ast_rtp_new_with_bindaddr(struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode, struct in_addr addr)
+-{
+- struct ast_rtp *rtp;
+- int x;
+- int startplace;
+-
+- if (!(rtp = ast_calloc(1, sizeof(*rtp))))
+- return NULL;
+-
+- ast_rtp_new_init(rtp);
+-
+- rtp->s = rtp_socket("RTP");
+- if (rtp->s < 0)
+- goto fail;
+- if (sched && rtcpenable) {
+- rtp->sched = sched;
+- rtp->rtcp = ast_rtcp_new();
+- }
+-
+- /*
+- * Try to bind the RTP port, x, and possibly the RTCP port, x+1 as well.
+- * Start from a random (even, by RTP spec) port number, and
+- * iterate until success or no ports are available.
+- * Note that the requirement of RTP port being even, or RTCP being the
+- * next one, cannot be enforced in presence of a NAT box because the
+- * mapping is not under our control.
+- */
+- x = (rtpend == rtpstart) ? rtpstart : (ast_random() % (rtpend - rtpstart)) + rtpstart;
+- x = x & ~1; /* make it an even number */
+- startplace = x; /* remember the starting point */
+- /* this is constant across the loop */
+- rtp->us.sin_addr = addr;
+- if (rtp->rtcp)
+- rtp->rtcp->us.sin_addr = addr;
+- for (;;) {
+- rtp->us.sin_port = htons(x);
+- if (!bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) {
+- /* bind succeeded, if no rtcp then we are done */
+- if (!rtp->rtcp)
+- break;
+- /* have rtcp, try to bind it */
+- rtp->rtcp->us.sin_port = htons(x + 1);
+- if (!bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us)))
+- break; /* success again, we are really done */
+- /*
+- * RTCP bind failed, so close and recreate the
+- * already bound RTP socket for the next round.
+- */
+- close(rtp->s);
+- rtp->s = rtp_socket("RTP");
+- if (rtp->s < 0)
+- goto fail;
+- }
+- /*
+- * If we get here, there was an error in one of the bind()
+- * calls, so make sure it is nothing unexpected.
+- */
+- if (errno != EADDRINUSE) {
+- /* We got an error that wasn't expected, abort! */
+- ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno));
+- goto fail;
+- }
+- /*
+- * One of the ports is in use. For the next iteration,
+- * increment by two and handle wraparound.
+- * If we reach the starting point, then declare failure.
+- */
+- x += 2;
+- if (x > rtpend)
+- x = (rtpstart + 1) & ~1;
+- if (x == startplace) {
+- ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n");
+- goto fail;
+- }
+- }
+- rtp->sched = sched;
+- rtp->io = io;
+- if (callbackmode) {
+- rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
+- ast_set_flag(rtp, FLAG_CALLBACK_MODE);
+- }
+- ast_rtp_pt_default(rtp);
+- return rtp;
+-
+-fail:
+- if (rtp->s >= 0)
+- close(rtp->s);
+- if (rtp->rtcp) {
+- close(rtp->rtcp->s);
+- ast_free(rtp->rtcp);
+- }
+- ast_free(rtp);
+- return NULL;
+-}
+-
+-struct ast_rtp *ast_rtp_new(struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode)
+-{
+- struct in_addr ia;
+-
+- memset(&ia, 0, sizeof(ia));
+- return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
+-}
+-
+-int ast_rtp_setqos(struct ast_rtp *rtp, int type_of_service, int class_of_service, char *desc)
+-{
+- return ast_netsock_set_qos(rtp->s, type_of_service, class_of_service, desc);
+-}
+-
+-void ast_rtp_new_source(struct ast_rtp *rtp)
+-{
+- if (rtp) {
+- rtp->set_marker_bit = 1;
+- }
+- return;
+-}
+-
+-void ast_rtp_set_peer(struct ast_rtp *rtp, struct sockaddr_in *them)
+-{
+- rtp->them.sin_port = them->sin_port;
+- rtp->them.sin_addr = them->sin_addr;
+- if (rtp->rtcp) {
+- int h = ntohs(them->sin_port);
+- rtp->rtcp->them.sin_port = htons(h + 1);
+- rtp->rtcp->them.sin_addr = them->sin_addr;
+- }
+- rtp->rxseqno = 0;
+- /* If strict RTP protection is enabled switch back to the learn state so we don't drop packets from above */
+- if (strictrtp)
+- rtp->strict_rtp_state = STRICT_RTP_LEARN;
+-}
+-
+-void ast_rtp_set_alt_peer(struct ast_rtp *rtp, struct sockaddr_in *alt)
+-{
+- rtp->altthem.sin_port = alt->sin_port;
+- rtp->altthem.sin_addr = alt->sin_addr;
+- if (rtp->rtcp) {
+- rtp->rtcp->altthem.sin_port = htons(ntohs(alt->sin_port) + 1);
+- rtp->rtcp->altthem.sin_addr = alt->sin_addr;
+- }
+-}
+-
+-int ast_rtp_get_peer(struct ast_rtp *rtp, struct sockaddr_in *them)
+-{
+- if ((them->sin_family != AF_INET) ||
+- (them->sin_port != rtp->them.sin_port) ||
+- (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) {
+- them->sin_family = AF_INET;
+- them->sin_port = rtp->them.sin_port;
+- them->sin_addr = rtp->them.sin_addr;
+- return 1;
+- }
+- return 0;
+-}
+-
+-void ast_rtp_get_us(struct ast_rtp *rtp, struct sockaddr_in *us)
+-{
+- *us = rtp->us;
+-}
+-
+-struct ast_rtp *ast_rtp_get_bridged(struct ast_rtp *rtp)
+-{
+- struct ast_rtp *bridged = NULL;
+-
+- rtp_bridge_lock(rtp);
+- bridged = rtp->bridged;
+- rtp_bridge_unlock(rtp);
+-
+- return bridged;
+-}
+-
+-void ast_rtp_stop(struct ast_rtp *rtp)
+-{
+- if (rtp->rtcp) {
+- AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
+- }
+- if (rtp->red) {
+- AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
+- free(rtp->red);
+- rtp->red = NULL;
+- }
+-
+- memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
+- memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
+- if (rtp->rtcp) {
+- memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr));
+- memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port));
+- }
+-
+- ast_clear_flag(rtp, FLAG_P2P_SENT_MARK);
+-}
+-
+-void ast_rtp_reset(struct ast_rtp *rtp)
+-{
+- memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
+- memset(&rtp->txcore, 0, sizeof(rtp->txcore));
+- memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
+- rtp->lastts = 0;
+- rtp->lastdigitts = 0;
+- rtp->lastrxts = 0;
+- rtp->lastividtimestamp = 0;
+- rtp->lastovidtimestamp = 0;
+- rtp->lastitexttimestamp = 0;
+- rtp->lastotexttimestamp = 0;
+- rtp->lasteventseqn = 0;
+- rtp->lastevent = 0;
+- rtp->lasttxformat = 0;
+- rtp->lastrxformat = 0;
+- rtp->dtmf_timeout = 0;
+- rtp->dtmfsamples = 0;
+- rtp->seqno = 0;
+- rtp->rxseqno = 0;
+-}
+-
+-/*! Get QoS values from RTP and RTCP data (used in "sip show channelstats") */
+-unsigned int ast_rtp_get_qosvalue(struct ast_rtp *rtp, enum ast_rtp_qos_vars value)
+-{
+- if (rtp == NULL) {
+- if (option_debug > 1)
+- ast_log(LOG_DEBUG, "NO RTP Structure? Kidding me? \n");
+- return 0;
+- }
+- if (option_debug > 1 && rtp->rtcp == NULL) {
+- ast_log(LOG_DEBUG, "NO RTCP structure. Maybe in RTP p2p bridging mode? \n");
+- }
+-
+- switch (value) {
+- case AST_RTP_TXCOUNT:
+- return (unsigned int) rtp->txcount;
+- case AST_RTP_RXCOUNT:
+- return (unsigned int) rtp->rxcount;
+- case AST_RTP_TXJITTER:
+- return (unsigned int) (rtp->rxjitter * 100.0);
+- case AST_RTP_RXJITTER:
+- return (unsigned int) (rtp->rtcp ? (rtp->rtcp->reported_jitter / (unsigned int) 65536.0) : 0);
+- case AST_RTP_RXPLOSS:
+- return rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0;
+- case AST_RTP_TXPLOSS:
+- return rtp->rtcp ? rtp->rtcp->reported_lost : 0;
+- case AST_RTP_RTT:
+- return (unsigned int) (rtp->rtcp ? (rtp->rtcp->rtt * 100) : 0);
+- }
+- return 0; /* To make the compiler happy */
+-}
+-
+-static double __ast_rtp_get_qos(struct ast_rtp *rtp, const char *qos, int *found)
+-{
+- *found = 1;
+-
+- if (!strcasecmp(qos, "remote_maxjitter"))
+- return rtp->rtcp->reported_maxjitter * 1000.0;
+- if (!strcasecmp(qos, "remote_minjitter"))
+- return rtp->rtcp->reported_minjitter * 1000.0;
+- if (!strcasecmp(qos, "remote_normdevjitter"))
+- return rtp->rtcp->reported_normdev_jitter * 1000.0;
+- if (!strcasecmp(qos, "remote_stdevjitter"))
+- return sqrt(rtp->rtcp->reported_stdev_jitter) * 1000.0;
+-
+- if (!strcasecmp(qos, "local_maxjitter"))
+- return rtp->rtcp->maxrxjitter * 1000.0;
+- if (!strcasecmp(qos, "local_minjitter"))
+- return rtp->rtcp->minrxjitter * 1000.0;
+- if (!strcasecmp(qos, "local_normdevjitter"))
+- return rtp->rtcp->normdev_rxjitter * 1000.0;
+- if (!strcasecmp(qos, "local_stdevjitter"))
+- return sqrt(rtp->rtcp->stdev_rxjitter) * 1000.0;
+-
+- if (!strcasecmp(qos, "maxrtt"))
+- return rtp->rtcp->maxrtt * 1000.0;
+- if (!strcasecmp(qos, "minrtt"))
+- return rtp->rtcp->minrtt * 1000.0;
+- if (!strcasecmp(qos, "normdevrtt"))
+- return rtp->rtcp->normdevrtt * 1000.0;
+- if (!strcasecmp(qos, "stdevrtt"))
+- return sqrt(rtp->rtcp->stdevrtt) * 1000.0;
+-
+- *found = 0;
+-
+- return 0.0;
+-}
+-
+-int ast_rtp_get_qos(struct ast_rtp *rtp, const char *qos, char *buf, unsigned int buflen)
+-{
+- double value;
+- int found;
+-
+- value = __ast_rtp_get_qos(rtp, qos, &found);
+-
+- if (!found)
+- return -1;
+-
+- snprintf(buf, buflen, "%.0lf", value);
+-
+- return 0;
+-}
+-
+-void ast_rtp_set_vars(struct ast_channel *chan, struct ast_rtp *rtp) {
+- char *audioqos;
+- char *audioqos_jitter;
+- char *audioqos_loss;
+- char *audioqos_rtt;
+- struct ast_channel *bridge;
+-
+- if (!rtp || !chan)
+- return;
+-
+- bridge = ast_bridged_channel(chan);
+-
+- audioqos = ast_rtp_get_quality(rtp, NULL, RTPQOS_SUMMARY);
+- audioqos_jitter = ast_rtp_get_quality(rtp, NULL, RTPQOS_JITTER);
+- audioqos_loss = ast_rtp_get_quality(rtp, NULL, RTPQOS_LOSS);
+- audioqos_rtt = ast_rtp_get_quality(rtp, NULL, RTPQOS_RTT);
+-
+- pbx_builtin_setvar_helper(chan, "RTPAUDIOQOS", audioqos);
+- pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSJITTER", audioqos_jitter);
+- pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSLOSS", audioqos_loss);
+- pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSRTT", audioqos_rtt);
+-
+- if (!bridge)
+- return;
+-
+- pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSBRIDGED", audioqos);
+- pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSJITTERBRIDGED", audioqos_jitter);
+- pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSLOSSBRIDGED", audioqos_loss);
+- pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSRTTBRIDGED", audioqos_rtt);
+-}
+-
+-static char *__ast_rtp_get_quality_jitter(struct ast_rtp *rtp)
+-{
+- /*
+- *ssrc our ssrc
+- *themssrc their ssrc
+- *lp lost packets
+- *rxjitter our calculated jitter(rx)
+- *rxcount no. received packets
+- *txjitter reported jitter of the other end
+- *txcount transmitted packets
+- *rlp remote lost packets
+- *rtt round trip time
+- */
+-#define RTCP_JITTER_FORMAT1 \
+- "minrxjitter=%f;" \
+- "maxrxjitter=%f;" \
+- "avgrxjitter=%f;" \
+- "stdevrxjitter=%f;" \
+- "reported_minjitter=%f;" \
+- "reported_maxjitter=%f;" \
+- "reported_avgjitter=%f;" \
+- "reported_stdevjitter=%f;"
+-
+-#define RTCP_JITTER_FORMAT2 \
+- "rxjitter=%f;"
+-
+- if (rtp->rtcp && rtp->rtcp->rtcp_info) {
+- snprintf(rtp->rtcp->quality_jitter, sizeof(rtp->rtcp->quality_jitter), RTCP_JITTER_FORMAT1,
+- rtp->rtcp->minrxjitter,
+- rtp->rtcp->maxrxjitter,
+- rtp->rtcp->normdev_rxjitter,
+- sqrt(rtp->rtcp->stdev_rxjitter),
+- rtp->rtcp->reported_minjitter,
+- rtp->rtcp->reported_maxjitter,
+- rtp->rtcp->reported_normdev_jitter,
+- sqrt(rtp->rtcp->reported_stdev_jitter)
+- );
+- } else {
+- snprintf(rtp->rtcp->quality_jitter, sizeof(rtp->rtcp->quality_jitter), RTCP_JITTER_FORMAT2,
+- rtp->rxjitter
+- );
+- }
+-
+- return rtp->rtcp->quality_jitter;
+-
+-#undef RTCP_JITTER_FORMAT1
+-#undef RTCP_JITTER_FORMAT2
+-}
+-
+-static char *__ast_rtp_get_quality_loss(struct ast_rtp *rtp)
+-{
+- unsigned int lost;
+- unsigned int extended;
+- unsigned int expected;
+- int fraction;
+-
+-#define RTCP_LOSS_FORMAT1 \
+- "minrxlost=%f;" \
+- "maxrxlost=%f;" \
+- "avgrxlostr=%f;" \
+- "stdevrxlost=%f;" \
+- "reported_minlost=%f;" \
+- "reported_maxlost=%f;" \
+- "reported_avglost=%f;" \
+- "reported_stdevlost=%f;"
+-
+-#define RTCP_LOSS_FORMAT2 \
+- "lost=%d;" \
+- "expected=%d;"
+-
+- if (rtp->rtcp && rtp->rtcp->rtcp_info && rtp->rtcp->maxrxlost > 0) {
+- snprintf(rtp->rtcp->quality_loss, sizeof(rtp->rtcp->quality_loss), RTCP_LOSS_FORMAT1,
+- rtp->rtcp->minrxlost,
+- rtp->rtcp->maxrxlost,
+- rtp->rtcp->normdev_rxlost,
+- sqrt(rtp->rtcp->stdev_rxlost),
+- rtp->rtcp->reported_minlost,
+- rtp->rtcp->reported_maxlost,
+- rtp->rtcp->reported_normdev_lost,
+- sqrt(rtp->rtcp->reported_stdev_lost)
+- );
+- } else {
+- extended = rtp->cycles + rtp->lastrxseqno;
+- expected = extended - rtp->seedrxseqno + 1;
+- if (rtp->rxcount > expected)
+- expected += rtp->rxcount - expected;
+- lost = expected - rtp->rxcount;
+-
+- if (!expected || lost <= 0)
+- fraction = 0;
+- else
+- fraction = (lost << 8) / expected;
+-
+- snprintf(rtp->rtcp->quality_loss, sizeof(rtp->rtcp->quality_loss), RTCP_LOSS_FORMAT2,
+- lost,
+- expected
+- );
+- }
+-
+- return rtp->rtcp->quality_loss;
+-
+-#undef RTCP_LOSS_FORMAT1
+-#undef RTCP_LOSS_FORMAT2
+-}
+-
+-static char *__ast_rtp_get_quality_rtt(struct ast_rtp *rtp)
+-{
+- if (rtp->rtcp && rtp->rtcp->rtcp_info) {
+- snprintf(rtp->rtcp->quality_rtt, sizeof(rtp->rtcp->quality_rtt), "minrtt=%f;maxrtt=%f;avgrtt=%f;stdevrtt=%f;",
+- rtp->rtcp->minrtt,
+- rtp->rtcp->maxrtt,
+- rtp->rtcp->normdevrtt,
+- sqrt(rtp->rtcp->stdevrtt)
+- );
+- } else {
+- snprintf(rtp->rtcp->quality_rtt, sizeof(rtp->rtcp->quality_rtt), "Not available");
+- }
+-
+- return rtp->rtcp->quality_rtt;
+-}
+-
+-static char *__ast_rtp_get_quality(struct ast_rtp *rtp)
+-{
+- /*
+- *ssrc our ssrc
+- *themssrc their ssrc
+- *lp lost packets
+- *rxjitter our calculated jitter(rx)
+- *rxcount no. received packets
+- *txjitter reported jitter of the other end
+- *txcount transmitted packets
+- *rlp remote lost packets
+- *rtt round trip time
+- */
+-
+- if (rtp->rtcp && rtp->rtcp->rtcp_info) {
+- snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality),
+- "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f",
+- rtp->ssrc,
+- rtp->themssrc,
+- rtp->rtcp->expected_prior - rtp->rtcp->received_prior,
+- rtp->rxjitter,
+- rtp->rxcount,
+- (double)rtp->rtcp->reported_jitter / 65536.0,
+- rtp->txcount,
+- rtp->rtcp->reported_lost,
+- rtp->rtcp->rtt
+- );
+- } else {
+- snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality), "ssrc=%u;themssrc=%u;rxjitter=%f;rxcount=%u;txcount=%u;",
+- rtp->ssrc,
+- rtp->themssrc,
+- rtp->rxjitter,
+- rtp->rxcount,
+- rtp->txcount
+- );
+- }
+-
+- return rtp->rtcp->quality;
+-}
+-
+-char *ast_rtp_get_quality(struct ast_rtp *rtp, struct ast_rtp_quality *qual, enum ast_rtp_quality_type qtype)
+-{
+- if (qual && rtp) {
+- qual->local_ssrc = rtp->ssrc;
+- qual->local_jitter = rtp->rxjitter;
+- qual->local_count = rtp->rxcount;
+- qual->remote_ssrc = rtp->themssrc;
+- qual->remote_count = rtp->txcount;
+-
+- if (rtp->rtcp) {
+- qual->local_lostpackets = rtp->rtcp->expected_prior - rtp->rtcp->received_prior;
+- qual->remote_lostpackets = rtp->rtcp->reported_lost;
+- qual->remote_jitter = rtp->rtcp->reported_jitter / 65536.0;
+- qual->rtt = rtp->rtcp->rtt;
+- }
+- }
+-
+- switch (qtype) {
+- case RTPQOS_SUMMARY:
+- return __ast_rtp_get_quality(rtp);
+- case RTPQOS_JITTER:
+- return __ast_rtp_get_quality_jitter(rtp);
+- case RTPQOS_LOSS:
+- return __ast_rtp_get_quality_loss(rtp);
+- case RTPQOS_RTT:
+- return __ast_rtp_get_quality_rtt(rtp);
+- }
+-
+- return NULL;
+-}
+-
+-void ast_rtp_destroy(struct ast_rtp *rtp)
+-{
+- if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) {
+- /*Print some info on the call here */
+- ast_verbose(" RTP-stats\n");
+- ast_verbose("* Our Receiver:\n");
+- ast_verbose(" SSRC: %u\n", rtp->themssrc);
+- ast_verbose(" Received packets: %u\n", rtp->rxcount);
+- ast_verbose(" Lost packets: %u\n", rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0);
+- ast_verbose(" Jitter: %.4f\n", rtp->rxjitter);
+- ast_verbose(" Transit: %.4f\n", rtp->rxtransit);
+- ast_verbose(" RR-count: %u\n", rtp->rtcp ? rtp->rtcp->rr_count : 0);
+- ast_verbose("* Our Sender:\n");
+- ast_verbose(" SSRC: %u\n", rtp->ssrc);
+- ast_verbose(" Sent packets: %u\n", rtp->txcount);
+- ast_verbose(" Lost packets: %u\n", rtp->rtcp ? rtp->rtcp->reported_lost : 0);
+- ast_verbose(" Jitter: %u\n", rtp->rtcp ? (rtp->rtcp->reported_jitter / (unsigned int)65536.0) : 0);
+- ast_verbose(" SR-count: %u\n", rtp->rtcp ? rtp->rtcp->sr_count : 0);
+- ast_verbose(" RTT: %f\n", rtp->rtcp ? rtp->rtcp->rtt : 0);
+- }
+-
+- manager_event(EVENT_FLAG_REPORTING, "RTPReceiverStat", "SSRC: %u\r\n"
+- "ReceivedPackets: %u\r\n"
+- "LostPackets: %u\r\n"
+- "Jitter: %.4f\r\n"
+- "Transit: %.4f\r\n"
+- "RRCount: %u\r\n",
+- rtp->themssrc,
+- rtp->rxcount,
+- rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0,
+- rtp->rxjitter,
+- rtp->rxtransit,
+- rtp->rtcp ? rtp->rtcp->rr_count : 0);
+- manager_event(EVENT_FLAG_REPORTING, "RTPSenderStat", "SSRC: %u\r\n"
+- "SentPackets: %u\r\n"
+- "LostPackets: %u\r\n"
+- "Jitter: %u\r\n"
+- "SRCount: %u\r\n"
+- "RTT: %f\r\n",
+- rtp->ssrc,
+- rtp->txcount,
+- rtp->rtcp ? rtp->rtcp->reported_lost : 0,
+- rtp->rtcp ? rtp->rtcp->reported_jitter : 0,
+- rtp->rtcp ? rtp->rtcp->sr_count : 0,
+- rtp->rtcp ? rtp->rtcp->rtt : 0);
+- if (rtp->smoother)
+- ast_smoother_free(rtp->smoother);
+- if (rtp->ioid)
+- ast_io_remove(rtp->io, rtp->ioid);
+- if (rtp->s > -1)
+- close(rtp->s);
+- if (rtp->rtcp) {
+- AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
+- close(rtp->rtcp->s);
+- ast_free(rtp->rtcp);
+- rtp->rtcp=NULL;
+- }
+-#ifdef P2P_INTENSE
+- ast_mutex_destroy(&rtp->bridge_lock);
+-#endif
+- ast_free(rtp);
+-}
+-
+-static unsigned int calc_txstamp(struct ast_rtp *rtp, struct timeval *delivery)
+-{
+- struct timeval t;
+- long ms;
+- if (ast_tvzero(rtp->txcore)) {
+- rtp->txcore = ast_tvnow();
+- /* Round to 20ms for nice, pretty timestamps */
+- rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
+- }
+- /* Use previous txcore if available */
+- t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
+- ms = ast_tvdiff_ms(t, rtp->txcore);
+- if (ms < 0)
+- ms = 0;
+- /* Use what we just got for next time */
+- rtp->txcore = t;
+- return (unsigned int) ms;
+-}
+-
+-/*! \brief Send begin frames for DTMF */
+-int ast_rtp_senddigit_begin(struct ast_rtp *rtp, char digit)
+-{
+- unsigned int *rtpheader;
+- int hdrlen = 12, res = 0, i = 0, payload = 0;
+- char data[256];
+-
+- if ((digit <= '9') && (digit >= '0'))
+- digit -= '0';
+- else if (digit == '*')
+- digit = 10;
+- else if (digit == '#')
+- digit = 11;
+- else if ((digit >= 'A') && (digit <= 'D'))
+- digit = digit - 'A' + 12;
+- else if ((digit >= 'a') && (digit <= 'd'))
+- digit = digit - 'a' + 12;
+- else {
+- ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
+- return 0;
+- }
+-
+- /* If we have no peer, return immediately */
+- if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
+- return 0;
+-
+- payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF);
+-
+- rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
+- rtp->send_duration = 160;
+- rtp->lastdigitts = rtp->lastts + rtp->send_duration;
+-
+- /* Get a pointer to the header */
+- rtpheader = (unsigned int *)data;
+- rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
+- rtpheader[1] = htonl(rtp->lastdigitts);
+- rtpheader[2] = htonl(rtp->ssrc);
+-
+- for (i = 0; i < 2; i++) {
+- rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
+- res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
+- if (res < 0)
+- ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n",
+- ast_inet_ntoa(rtp->them.sin_addr),
+- ntohs(rtp->them.sin_port), strerror(errno));
+- if (rtp_debug_test_addr(&rtp->them))
+- ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
+- ast_inet_ntoa(rtp->them.sin_addr),
+- ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
+- /* Increment sequence number */
+- rtp->seqno++;
+- /* Increment duration */
+- rtp->send_duration += 160;
+- /* Clear marker bit and set seqno */
+- rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
+- }
+-
+- /* Since we received a begin, we can safely store the digit and disable any compensation */
+- rtp->sending_digit = 1;
+- rtp->send_digit = digit;
+- rtp->send_payload = payload;
+-
+- return 0;
+-}
+-
+-/*! \brief Send continuation frame for DTMF */
+-static int ast_rtp_senddigit_continuation(struct ast_rtp *rtp)
+-{
+- unsigned int *rtpheader;
+- int hdrlen = 12, res = 0;
+- char data[256];
+-
+- if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
+- return 0;
+-
+- /* Setup packet to send */
+- rtpheader = (unsigned int *)data;
+- rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno));
+- rtpheader[1] = htonl(rtp->lastdigitts);
+- rtpheader[2] = htonl(rtp->ssrc);
+- rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration));
+- rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
+-
+- /* Transmit */
+- res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
+- if (res < 0)
+- ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
+- ast_inet_ntoa(rtp->them.sin_addr),
+- ntohs(rtp->them.sin_port), strerror(errno));
+- if (rtp_debug_test_addr(&rtp->them))
+- ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
+- ast_inet_ntoa(rtp->them.sin_addr),
+- ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
+-
+- /* Increment sequence number */
+- rtp->seqno++;
+- /* Increment duration */
+- rtp->send_duration += 160;
+-
+- return 0;
+-}
+-
+-/*! \brief Send end packets for DTMF */
+-int ast_rtp_senddigit_end(struct ast_rtp *rtp, char digit)
+-{
+- unsigned int *rtpheader;
+- int hdrlen = 12, res = 0, i = 0;
+- char data[256];
+-
+- /* If no address, then bail out */
+- if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
+- return 0;
+-
+- if ((digit <= '9') && (digit >= '0'))
+- digit -= '0';
+- else if (digit == '*')
+- digit = 10;
+- else if (digit == '#')
+- digit = 11;
+- else if ((digit >= 'A') && (digit <= 'D'))
+- digit = digit - 'A' + 12;
+- else if ((digit >= 'a') && (digit <= 'd'))
+- digit = digit - 'a' + 12;
+- else {
+- ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
+- return 0;
+- }
+-
+- rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
+-
+- rtpheader = (unsigned int *)data;
+- rtpheader[1] = htonl(rtp->lastdigitts);
+- rtpheader[2] = htonl(rtp->ssrc);
+- rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
+- /* Set end bit */
+- rtpheader[3] |= htonl((1 << 23));
+-
+- /* Send 3 termination packets */
+- for (i = 0; i < 3; i++) {
+- rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
+- res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
+- rtp->seqno++;
+- if (res < 0)
+- ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
+- ast_inet_ntoa(rtp->them.sin_addr),
+- ntohs(rtp->them.sin_port), strerror(errno));
+- if (rtp_debug_test_addr(&rtp->them))
+- ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
+- ast_inet_ntoa(rtp->them.sin_addr),
+- ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
+- }
+- rtp->lastts += rtp->send_duration;
+- rtp->sending_digit = 0;
+- rtp->send_digit = 0;
+-
+- return res;
+-}
+-
+-/*! \brief Public function: Send an H.261 fast update request, some devices need this rather than SIP XML */
+-int ast_rtcp_send_h261fur(void *data)
+-{
+- struct ast_rtp *rtp = data;
+- int res;
+-
+- rtp->rtcp->sendfur = 1;
+- res = ast_rtcp_write(data);
+-
+- return res;
+-}
+-
+-/*! \brief Send RTCP sender's report */
+-static int ast_rtcp_write_sr(const void *data)
+-{
+- struct ast_rtp *rtp = (struct ast_rtp *)data;
+- int res;
+- int len = 0;
+- struct timeval now;
+- unsigned int now_lsw;
+- unsigned int now_msw;
+- unsigned int *rtcpheader;
+- unsigned int lost;
+- unsigned int extended;
+- unsigned int expected;
+- unsigned int expected_interval;
+- unsigned int received_interval;
+- int lost_interval;
+- int fraction;
+- struct timeval dlsr;
+- char bdata[512];
+-
+- /* Commented condition is always not NULL if rtp->rtcp is not NULL */
+- if (!rtp || !rtp->rtcp/* || (&rtp->rtcp->them.sin_addr == 0)*/)
+- return 0;
+-
+- if (!rtp->rtcp->them.sin_addr.s_addr) { /* This'll stop rtcp for this rtp session */
+- ast_verbose("RTCP SR transmission error, rtcp halted\n");
+- AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
+- return 0;
+- }
+-
+- gettimeofday(&now, NULL);
+- timeval2ntp(now, &now_msw, &now_lsw); /* fill thses ones in from utils.c*/
+- rtcpheader = (unsigned int *)bdata;
+- rtcpheader[1] = htonl(rtp->ssrc); /* Our SSRC */
+- rtcpheader[2] = htonl(now_msw); /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970*/
+- rtcpheader[3] = htonl(now_lsw); /* now, LSW */
+- rtcpheader[4] = htonl(rtp->lastts); /* FIXME shouldn't be that, it should be now */
+- rtcpheader[5] = htonl(rtp->txcount); /* No. packets sent */
+- rtcpheader[6] = htonl(rtp->txoctetcount); /* No. bytes sent */
+- len += 28;
+-
+- extended = rtp->cycles + rtp->lastrxseqno;
+- expected = extended - rtp->seedrxseqno + 1;
+- if (rtp->rxcount > expected)
+- expected += rtp->rxcount - expected;
+- lost = expected - rtp->rxcount;
+- expected_interval = expected - rtp->rtcp->expected_prior;
+- rtp->rtcp->expected_prior = expected;
+- received_interval = rtp->rxcount - rtp->rtcp->received_prior;
+- rtp->rtcp->received_prior = rtp->rxcount;
+- lost_interval = expected_interval - received_interval;
+- if (expected_interval == 0 || lost_interval <= 0)
+- fraction = 0;
+- else
+- fraction = (lost_interval << 8) / expected_interval;
+- timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
+- rtcpheader[7] = htonl(rtp->themssrc);
+- rtcpheader[8] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff));
+- rtcpheader[9] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff)));
+- rtcpheader[10] = htonl((unsigned int)(rtp->rxjitter * 65536.));
+- rtcpheader[11] = htonl(rtp->rtcp->themrxlsr);
+- rtcpheader[12] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
+- len += 24;
+-
+- rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1));
+-
+- if (rtp->rtcp->sendfur) {
+- rtcpheader[13] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1);
+- rtcpheader[14] = htonl(rtp->ssrc); /* Our SSRC */
+- len += 8;
+- rtp->rtcp->sendfur = 0;
+- }
+-
+- /* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */
+- /* it can change mid call, and SDES can't) */
+- rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
+- rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */
+- rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */
+- len += 12;
+-
+- res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
+- if (res < 0) {
+- ast_log(LOG_ERROR, "RTCP SR transmission error to %s:%d, rtcp halted %s\n",ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port), strerror(errno));
+- AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
+- return 0;
+- }
+-
+- /* FIXME Don't need to get a new one */
+- gettimeofday(&rtp->rtcp->txlsr, NULL);
+- rtp->rtcp->sr_count++;
+-
+- rtp->rtcp->lastsrtxcount = rtp->txcount;
+-
+- if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
+- ast_verbose("* Sent RTCP SR to %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
+- ast_verbose(" Our SSRC: %u\n", rtp->ssrc);
+- ast_verbose(" Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096);
+- ast_verbose(" Sent(RTP): %u\n", rtp->lastts);
+- ast_verbose(" Sent packets: %u\n", rtp->txcount);
+- ast_verbose(" Sent octets: %u\n", rtp->txoctetcount);
+- ast_verbose(" Report block:\n");
+- ast_verbose(" Fraction lost: %u\n", fraction);
+- ast_verbose(" Cumulative loss: %u\n", lost);
+- ast_verbose(" IA jitter: %.4f\n", rtp->rxjitter);
+- ast_verbose(" Their last SR: %u\n", rtp->rtcp->themrxlsr);
+- ast_verbose(" DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0));
+- }
+- manager_event(EVENT_FLAG_REPORTING, "RTCPSent", "To: %s:%d\r\n"
+- "OurSSRC: %u\r\n"
+- "SentNTP: %u.%010u\r\n"
+- "SentRTP: %u\r\n"
+- "SentPackets: %u\r\n"
+- "SentOctets: %u\r\n"
+- "ReportBlock:\r\n"
+- "FractionLost: %u\r\n"
+- "CumulativeLoss: %u\r\n"
+- "IAJitter: %.4f\r\n"
+- "TheirLastSR: %u\r\n"
+- "DLSR: %4.4f (sec)\r\n",
+- ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port),
+- rtp->ssrc,
+- (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096,
+- rtp->lastts,
+- rtp->txcount,
+- rtp->txoctetcount,
+- fraction,
+- lost,
+- rtp->rxjitter,
+- rtp->rtcp->themrxlsr,
+- (double)(ntohl(rtcpheader[12])/65536.0));
+- return res;
+-}
+-
+-/*! \brief Send RTCP recipient's report */
+-static int ast_rtcp_write_rr(const void *data)
+-{
+- struct ast_rtp *rtp = (struct ast_rtp *)data;
+- int res;
+- int len = 32;
+- unsigned int lost;
+- unsigned int extended;
+- unsigned int expected;
+- unsigned int expected_interval;
+- unsigned int received_interval;
+- int lost_interval;
+- struct timeval now;
+- unsigned int *rtcpheader;
+- char bdata[1024];
+- struct timeval dlsr;
+- int fraction;
+-
+- double rxlost_current;
+-
+- if (!rtp || !rtp->rtcp || (&rtp->rtcp->them.sin_addr == 0))
+- return 0;
+-
+- if (!rtp->rtcp->them.sin_addr.s_addr) {
+- ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted\n");
+- AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
+- return 0;
+- }
+-
+- extended = rtp->cycles + rtp->lastrxseqno;
+- expected = extended - rtp->seedrxseqno + 1;
+- lost = expected - rtp->rxcount;
+- expected_interval = expected - rtp->rtcp->expected_prior;
+- rtp->rtcp->expected_prior = expected;
+- received_interval = rtp->rxcount - rtp->rtcp->received_prior;
+- rtp->rtcp->received_prior = rtp->rxcount;
+- lost_interval = expected_interval - received_interval;
+-
+- if (lost_interval <= 0)
+- rtp->rtcp->rxlost = 0;
+- else rtp->rtcp->rxlost = rtp->rtcp->rxlost;
+- if (rtp->rtcp->rxlost_count == 0)
+- rtp->rtcp->minrxlost = rtp->rtcp->rxlost;
+- if (lost_interval < rtp->rtcp->minrxlost)
+- rtp->rtcp->minrxlost = rtp->rtcp->rxlost;
+- if (lost_interval > rtp->rtcp->maxrxlost)
+- rtp->rtcp->maxrxlost = rtp->rtcp->rxlost;
+-
+- rxlost_current = normdev_compute(rtp->rtcp->normdev_rxlost, rtp->rtcp->rxlost, rtp->rtcp->rxlost_count);
+- rtp->rtcp->stdev_rxlost = stddev_compute(rtp->rtcp->stdev_rxlost, rtp->rtcp->rxlost, rtp->rtcp->normdev_rxlost, rxlost_current, rtp->rtcp->rxlost_count);
+- rtp->rtcp->normdev_rxlost = rxlost_current;
+- rtp->rtcp->rxlost_count++;
+-
+- if (expected_interval == 0 || lost_interval <= 0)
+- fraction = 0;
+- else
+- fraction = (lost_interval << 8) / expected_interval;
+- gettimeofday(&now, NULL);
+- timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
+- rtcpheader = (unsigned int *)bdata;
+- rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_RR << 16) | ((len/4)-1));
+- rtcpheader[1] = htonl(rtp->ssrc);
+- rtcpheader[2] = htonl(rtp->themssrc);
+- rtcpheader[3] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff));
+- rtcpheader[4] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff)));
+- rtcpheader[5] = htonl((unsigned int)(rtp->rxjitter * 65536.));
+- rtcpheader[6] = htonl(rtp->rtcp->themrxlsr);
+- rtcpheader[7] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
+-
+- if (rtp->rtcp->sendfur) {
+- rtcpheader[8] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); /* Header from page 36 in RFC 3550 */
+- rtcpheader[9] = htonl(rtp->ssrc); /* Our SSRC */
+- len += 8;
+- rtp->rtcp->sendfur = 0;
+- }
+-
+- /*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos
+- it can change mid call, and SDES can't) */
+- rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
+- rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */
+- rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */
+- len += 12;
+-
+- res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
+-
+- if (res < 0) {
+- ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno));
+- /* Remove the scheduler */
+- AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
+- return 0;
+- }
+-
+- rtp->rtcp->rr_count++;
+-
+- if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
+- ast_verbose("\n* Sending RTCP RR to %s:%d\n"
+- " Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n"
+- " IA jitter: %.4f\n"
+- " Their last SR: %u\n"
+- " DLSR: %4.4f (sec)\n\n",
+- ast_inet_ntoa(rtp->rtcp->them.sin_addr),
+- ntohs(rtp->rtcp->them.sin_port),
+- rtp->ssrc, rtp->themssrc, fraction, lost,
+- rtp->rxjitter,
+- rtp->rtcp->themrxlsr,
+- (double)(ntohl(rtcpheader[7])/65536.0));
+- }
+-
+- return res;
+-}
+-
+-/*! \brief Write and RTCP packet to the far end
+- * \note Decide if we are going to send an SR (with Reception Block) or RR
+- * RR is sent if we have not sent any rtp packets in the previous interval */
+-static int ast_rtcp_write(const void *data)
+-{
+- struct ast_rtp *rtp = (struct ast_rtp *)data;
+- int res;
+-
+- if (!rtp || !rtp->rtcp)
+- return 0;
+-
+- if (rtp->txcount > rtp->rtcp->lastsrtxcount)
+- res = ast_rtcp_write_sr(data);
+- else
+- res = ast_rtcp_write_rr(data);
+-
+- return res;
+-}
+-
+-/*! \brief generate comfort noice (CNG) */
+-int ast_rtp_sendcng(struct ast_rtp *rtp, int level)
+-{
+- unsigned int *rtpheader;
+- int hdrlen = 12;
+- int res;
+- int payload;
+- char data[256];
+- level = 127 - (level & 0x7f);
+- payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN);
+-
+- /* If we have no peer, return immediately */
+- if (!rtp->them.sin_addr.s_addr)
+- return 0;
+-
+- rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
+-
+- /* Get a pointer to the header */
+- rtpheader = (unsigned int *)data;
+- rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++));
+- rtpheader[1] = htonl(rtp->lastts);
+- rtpheader[2] = htonl(rtp->ssrc);
+- data[12] = level;
+- if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
+- res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
+- if (res <0)
+- ast_log(LOG_ERROR, "RTP Comfort Noise Transmission error to %s:%d: %s\n", ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno));
+- if (rtp_debug_test_addr(&rtp->them))
+- ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n"
+- , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen);
+-
+- }
+- return 0;
+-}
+-
+-/*! \brief Write RTP packet with audio or video media frames into UDP packet */
+-static int ast_rtp_raw_write(struct ast_rtp *rtp, struct ast_frame *f, int codec)
+-{
+- unsigned char *rtpheader;
+- int hdrlen = 12;
+- int res;
+- unsigned int ms;
+- int pred;
+- int mark = 0;
+-
+- if (rtp->sending_digit) {
+- return 0;
+- }
+-
+- ms = calc_txstamp(rtp, &f->delivery);
+- /* Default prediction */
+- if (f->frametype == AST_FRAME_VOICE) {
+- pred = rtp->lastts + f->samples;
+-
+- /* Re-calculate last TS */
+- rtp->lastts = rtp->lastts + ms * 8;
+- if (ast_tvzero(f->delivery)) {
+- /* If this isn't an absolute delivery time, Check if it is close to our prediction,
+- and if so, go with our prediction */
+- if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW)
+- rtp->lastts = pred;
+- else {
+- ast_debug(3, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms);
+- mark = 1;
+- }
+- }
+- } else if (f->frametype == AST_FRAME_VIDEO) {
+- mark = f->subclass & 0x1;
+- pred = rtp->lastovidtimestamp + f->samples;
+- /* Re-calculate last TS */
+- rtp->lastts = rtp->lastts + ms * 90;
+- /* If it's close to our prediction, go for it */
+- if (ast_tvzero(f->delivery)) {
+- if (abs(rtp->lastts - pred) < 7200) {
+- rtp->lastts = pred;
+- rtp->lastovidtimestamp += f->samples;
+- } else {
+- ast_debug(3, "Difference is %d, ms is %d (%d), pred/ts/samples %d/%d/%d\n", abs(rtp->lastts - pred), ms, ms * 90, rtp->lastts, pred, f->samples);
+- rtp->lastovidtimestamp = rtp->lastts;
+- }
+- }
+- } else {
+- pred = rtp->lastotexttimestamp + f->samples;
+- /* Re-calculate last TS */
+- rtp->lastts = rtp->lastts + ms;
+- /* If it's close to our prediction, go for it */
+- if (ast_tvzero(f->delivery)) {
+- if (abs(rtp->lastts - pred) < 7200) {
+- rtp->lastts = pred;
+- rtp->lastotexttimestamp += f->samples;
+- } else {
+- ast_debug(3, "Difference is %d, ms is %d, pred/ts/samples %d/%d/%d\n", abs(rtp->lastts - pred), ms, rtp->lastts, pred, f->samples);
+- rtp->lastotexttimestamp = rtp->lastts;
+- }
+- }
+- }
+-
+- /* If we have been explicitly told to set the marker bit do so */
+- if (rtp->set_marker_bit) {
+- mark = 1;
+- rtp->set_marker_bit = 0;
+- }
+-
+- /* If the timestamp for non-digit packets has moved beyond the timestamp
+- for digits, update the digit timestamp.
+- */
+- if (rtp->lastts > rtp->lastdigitts)
+- rtp->lastdigitts = rtp->lastts;
+-
+- if (ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO))
+- rtp->lastts = f->ts * 8;
+-
+- /* Get a pointer to the header */
+- rtpheader = (unsigned char *)(f->data.ptr - hdrlen);
+-
+- put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23)));
+- put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts));
+- put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc));
+-
+- if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
+- res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
+- if (res < 0) {
+- if (!rtp->nat || (rtp->nat && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
+- ast_debug(1, "RTP Transmission error of packet %d to %s:%d: %s\n", rtp->seqno, ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno));
+- } else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) {
+- /* Only give this error message once if we are not RTP debugging */
+- if (option_debug || rtpdebug)
+- ast_debug(0, "RTP NAT: Can't write RTP to private address %s:%d, waiting for other end to send audio...\n", ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port));
+- ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN);
+- }
+- } else {
+- rtp->txcount++;
+- rtp->txoctetcount +=(res - hdrlen);
+-
+- /* Do not schedule RR if RTCP isn't run */
+- if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) {
+- rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
+- }
+- }
+-
+- if (rtp_debug_test_addr(&rtp->them))
+- ast_verbose("Sent RTP packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
+- ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), codec, rtp->seqno, rtp->lastts,res - hdrlen);
+- }
+-
+- rtp->seqno++;
+-
+- return 0;
+-}
+-
+-void ast_rtp_codec_setpref(struct ast_rtp *rtp, struct ast_codec_pref *prefs)
+-{
+- struct ast_format_list current_format_old, current_format_new;
+-
+- /* if no packets have been sent through this session yet, then
+- * changing preferences does not require any extra work
+- */
+- if (rtp->lasttxformat == 0) {
+- rtp->pref = *prefs;
+- return;
+- }
+-
+- current_format_old = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat);
+-
+- rtp->pref = *prefs;
+-
+- current_format_new = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat);
+-
+- /* if the framing desired for the current format has changed, we may have to create
+- * or adjust the smoother for this session
+- */
+- if ((current_format_new.inc_ms != 0) &&
+- (current_format_new.cur_ms != current_format_old.cur_ms)) {
+- int new_size = (current_format_new.cur_ms * current_format_new.fr_len) / current_format_new.inc_ms;
+-
+- if (rtp->smoother) {
+- ast_smoother_reconfigure(rtp->smoother, new_size);
+- if (option_debug) {
+- ast_log(LOG_DEBUG, "Adjusted smoother to %d ms and %d bytes\n", current_format_new.cur_ms, new_size);
+- }
+- } else {
+- if (!(rtp->smoother = ast_smoother_new(new_size))) {
+- ast_log(LOG_WARNING, "Unable to create smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size);
+- return;
+- }
+- if (current_format_new.flags) {
+- ast_smoother_set_flags(rtp->smoother, current_format_new.flags);
+- }
+- if (option_debug) {
+- ast_log(LOG_DEBUG, "Created smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size);
+- }
+- }
+- }
+-
+-}
+-
+-struct ast_codec_pref *ast_rtp_codec_getpref(struct ast_rtp *rtp)
+-{
+- return &rtp->pref;
+-}
+-
+-int ast_rtp_codec_getformat(int pt)
+-{
+- if (pt < 0 || pt > MAX_RTP_PT)
+- return 0; /* bogus payload type */
+-
+- if (static_RTP_PT[pt].isAstFormat)
+- return static_RTP_PT[pt].code;
+- else
+- return 0;
+-}
+-
+-int ast_rtp_write(struct ast_rtp *rtp, struct ast_frame *_f)
+-{
+- struct ast_frame *f;
+- int codec;
+- int hdrlen = 12;
+- int subclass;
+-
+-
+- /* If we have no peer, return immediately */
+- if (!rtp->them.sin_addr.s_addr)
+- return 0;
+-
+- /* If there is no data length, return immediately */
+- if (!_f->datalen && !rtp->red)
+- return 0;
+-
+- /* Make sure we have enough space for RTP header */
+- if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO) && (_f->frametype != AST_FRAME_TEXT)) {
+- ast_log(LOG_WARNING, "RTP can only send voice, video and text\n");
+- return -1;
+- }
+-
+- if (rtp->red) {
+- /* return 0; */
+- /* no primary data or generations to send */
+- if ((_f = red_t140_to_red(rtp->red)) == NULL)
+- return 0;
+- }
+-
+- /* The bottom bit of a video subclass contains the marker bit */
+- subclass = _f->subclass;
+- if (_f->frametype == AST_FRAME_VIDEO)
+- subclass &= ~0x1;
+-
+- codec = ast_rtp_lookup_code(rtp, 1, subclass);
+- if (codec < 0) {
+- ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass));
+- return -1;
+- }
+-
+- if (rtp->lasttxformat != subclass) {
+- /* New format, reset the smoother */
+- ast_debug(1, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass));
+- rtp->lasttxformat = subclass;
+- if (rtp->smoother)
+- ast_smoother_free(rtp->smoother);
+- rtp->smoother = NULL;
+- }
+-
+- if (!rtp->smoother) {
+- struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass);
+-
+- switch (subclass) {
+- case AST_FORMAT_SPEEX:
+- case AST_FORMAT_G723_1:
+- case AST_FORMAT_SIREN7:
+- case AST_FORMAT_SIREN14:
+- /* these are all frame-based codecs and cannot be safely run through
+- a smoother */
+- break;
+- default:
+- if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */
+- if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) {
+- ast_log(LOG_WARNING, "Unable to create smoother: format: %d ms: %d len: %d\n", subclass, fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
+- return -1;
+- }
+- if (fmt.flags)
+- ast_smoother_set_flags(rtp->smoother, fmt.flags);
+- ast_debug(1, "Created smoother: format: %d ms: %d len: %d\n", subclass, fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
+- }
+- }
+- }
+- if (rtp->smoother) {
+- if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) {
+- ast_smoother_feed_be(rtp->smoother, _f);
+- } else {
+- ast_smoother_feed(rtp->smoother, _f);
+- }
+-
+- while ((f = ast_smoother_read(rtp->smoother)) && (f->data.ptr)) {
+- if (f->subclass == AST_FORMAT_G722) {
+- /* G.722 is silllllllllllllly */
+- f->samples /= 2;
+- }
+-
+- ast_rtp_raw_write(rtp, f, codec);
+- }
+- } else {
+- /* Don't buffer outgoing frames; send them one-per-packet: */
+- if (_f->offset < hdrlen)
+- f = ast_frdup(_f); /*! \bug XXX this might never be free'd. Why do we do this? */
+- else
+- f = _f;
+- if (f->data.ptr)
+- ast_rtp_raw_write(rtp, f, codec);
+- if (f != _f)
+- ast_frfree(f);
+- }
+-
+- return 0;
+-}
+-
+-/*! \brief Unregister interface to channel driver */
+-void ast_rtp_proto_unregister(struct ast_rtp_protocol *proto)
+-{
+- AST_RWLIST_WRLOCK(&protos);
+- AST_RWLIST_REMOVE(&protos, proto, list);
+- AST_RWLIST_UNLOCK(&protos);
+-}
+-
+-/*! \brief Register interface to channel driver */
+-int ast_rtp_proto_register(struct ast_rtp_protocol *proto)
+-{
+- struct ast_rtp_protocol *cur;
+-
+- AST_RWLIST_WRLOCK(&protos);
+- AST_RWLIST_TRAVERSE(&protos, cur, list) {
+- if (!strcmp(cur->type, proto->type)) {
+- ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
+- AST_RWLIST_UNLOCK(&protos);
+- return -1;
+- }
+- }
+- AST_RWLIST_INSERT_HEAD(&protos, proto, list);
+- AST_RWLIST_UNLOCK(&protos);
+-
+- return 0;
+-}
+-
+-/*! \brief Bridge loop for true native bridge (reinvite) */
+-static enum ast_bridge_result bridge_native_loop(struct ast_channel *c0, struct ast_channel *c1, struct ast_rtp *p0, struct ast_rtp *p1, struct ast_rtp *vp0, struct ast_rtp *vp1, struct ast_rtp *tp0, struct ast_rtp *tp1, struct ast_rtp_protocol *pr0, struct ast_rtp_protocol *pr1, int codec0, int codec1, int timeoutms, int flags, struct ast_frame **fo, struct ast_channel **rc, void *pvt0, void *pvt1)
+-{
+- struct ast_frame *fr = NULL;
+- struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, };
+- int oldcodec0 = codec0, oldcodec1 = codec1;
+- struct sockaddr_in ac1 = {0,}, vac1 = {0,}, tac1 = {0,}, ac0 = {0,}, vac0 = {0,}, tac0 = {0,};
+- struct sockaddr_in t1 = {0,}, vt1 = {0,}, tt1 = {0,}, t0 = {0,}, vt0 = {0,}, tt0 = {0,};
+-
+- /* Set it up so audio goes directly between the two endpoints */
+-
+- /* Test the first channel */
+- if (!(pr0->set_rtp_peer(c0, p1, vp1, tp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))) {
+- ast_rtp_get_peer(p1, &ac1);
+- if (vp1)
+- ast_rtp_get_peer(vp1, &vac1);
+- if (tp1)
+- ast_rtp_get_peer(tp1, &tac1);
+- } else
+- ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name);
+-
+- /* Test the second channel */
+- if (!(pr1->set_rtp_peer(c1, p0, vp0, tp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))) {
+- ast_rtp_get_peer(p0, &ac0);
+- if (vp0)
+- ast_rtp_get_peer(vp0, &vac0);
+- if (tp0)
+- ast_rtp_get_peer(tp0, &tac0);
+- } else
+- ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c1->name, c0->name);
+-
+- /* Now we can unlock and move into our loop */
+- ast_channel_unlock(c0);
+- ast_channel_unlock(c1);
+-
+- ast_poll_channel_add(c0, c1);
+-
+- /* Throw our channels into the structure and enter the loop */
+- cs[0] = c0;
+- cs[1] = c1;
+- cs[2] = NULL;
+- for (;;) {
+- /* Check if anything changed */
+- if ((c0->tech_pvt != pvt0) ||
+- (c1->tech_pvt != pvt1) ||
+- (c0->masq || c0->masqr || c1->masq || c1->masqr) ||
+- (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) {
+- ast_debug(1, "Oooh, something is weird, backing out\n");
+- if (c0->tech_pvt == pvt0)
+- if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0))
+- ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
+- if (c1->tech_pvt == pvt1)
+- if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0))
+- ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
+- ast_poll_channel_del(c0, c1);
+- return AST_BRIDGE_RETRY;
+- }
+-
+- /* Check if they have changed their address */
+- ast_rtp_get_peer(p1, &t1);
+- if (vp1)
+- ast_rtp_get_peer(vp1, &vt1);
+- if (tp1)
+- ast_rtp_get_peer(tp1, &tt1);
+- if (pr1->get_codec)
+- codec1 = pr1->get_codec(c1);
+- ast_rtp_get_peer(p0, &t0);
+- if (vp0)
+- ast_rtp_get_peer(vp0, &vt0);
+- if (tp0)
+- ast_rtp_get_peer(tp0, &tt0);
+- if (pr0->get_codec)
+- codec0 = pr0->get_codec(c0);
+- if ((inaddrcmp(&t1, &ac1)) ||
+- (vp1 && inaddrcmp(&vt1, &vac1)) ||
+- (tp1 && inaddrcmp(&tt1, &tac1)) ||
+- (codec1 != oldcodec1)) {
+- ast_debug(2, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
+- c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port), codec1);
+- ast_debug(2, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n",
+- c1->name, ast_inet_ntoa(vt1.sin_addr), ntohs(vt1.sin_port), codec1);
+- ast_debug(2, "Oooh, '%s' changed end taddress to %s:%d (format %d)\n",
+- c1->name, ast_inet_ntoa(tt1.sin_addr), ntohs(tt1.sin_port), codec1);
+- ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n",
+- c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1);
+- ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n",
+- c1->name, ast_inet_ntoa(vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1);
+- ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n",
+- c1->name, ast_inet_ntoa(tac1.sin_addr), ntohs(tac1.sin_port), oldcodec1);
+- if (pr0->set_rtp_peer(c0, t1.sin_addr.s_addr ? p1 : NULL, vt1.sin_addr.s_addr ? vp1 : NULL, tt1.sin_addr.s_addr ? tp1 : NULL, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))
+- ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name);
+- memcpy(&ac1, &t1, sizeof(ac1));
+- memcpy(&vac1, &vt1, sizeof(vac1));
+- memcpy(&tac1, &tt1, sizeof(tac1));
+- oldcodec1 = codec1;
+- }
+- if ((inaddrcmp(&t0, &ac0)) ||
+- (vp0 && inaddrcmp(&vt0, &vac0)) ||
+- (tp0 && inaddrcmp(&tt0, &tac0)) ||
+- (codec0 != oldcodec0)) {
+- ast_debug(2, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
+- c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port), codec0);
+- ast_debug(2, "Oooh, '%s' was %s:%d/(format %d)\n",
+- c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0);
+- if (pr1->set_rtp_peer(c1, t0.sin_addr.s_addr ? p0 : NULL, vt0.sin_addr.s_addr ? vp0 : NULL, tt0.sin_addr.s_addr ? tp0 : NULL, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))
+- ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name);
+- memcpy(&ac0, &t0, sizeof(ac0));
+- memcpy(&vac0, &vt0, sizeof(vac0));
+- memcpy(&tac0, &tt0, sizeof(tac0));
+- oldcodec0 = codec0;
+- }
+-
+- /* Wait for frame to come in on the channels */
+- if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
+- if (!timeoutms) {
+- if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0))
+- ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
+- if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0))
+- ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
+- return AST_BRIDGE_RETRY;
+- }
+- ast_debug(1, "Ooh, empty read...\n");
+- if (ast_check_hangup(c0) || ast_check_hangup(c1))
+- break;
+- continue;
+- }
+- fr = ast_read(who);
+- other = (who == c0) ? c1 : c0;
+- if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) &&
+- (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) ||
+- ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) {
+- /* Break out of bridge */
+- *fo = fr;
+- *rc = who;
+- ast_debug(1, "Oooh, got a %s\n", fr ? "digit" : "hangup");
+- if (c0->tech_pvt == pvt0)
+- if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0))
+- ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
+- if (c1->tech_pvt == pvt1)
+- if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0))
+- ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
+- ast_poll_channel_del(c0, c1);
+- return AST_BRIDGE_COMPLETE;
+- } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
+- if ((fr->subclass == AST_CONTROL_HOLD) ||
+- (fr->subclass == AST_CONTROL_UNHOLD) ||
+- (fr->subclass == AST_CONTROL_VIDUPDATE) ||
+- (fr->subclass == AST_CONTROL_T38) ||
+- (fr->subclass == AST_CONTROL_SRCUPDATE)) {
+- if (fr->subclass == AST_CONTROL_HOLD) {
+- /* If we someone went on hold we want the other side to reinvite back to us */
+- if (who == c0)
+- pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0);
+- else
+- pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0);
+- } else if (fr->subclass == AST_CONTROL_UNHOLD) {
+- /* If they went off hold they should go back to being direct */
+- if (who == c0)
+- pr1->set_rtp_peer(c1, p0, vp0, tp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE));
+- else
+- pr0->set_rtp_peer(c0, p1, vp1, tp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE));
+- }
+- /* Update local address information */
+- ast_rtp_get_peer(p0, &t0);
+- memcpy(&ac0, &t0, sizeof(ac0));
+- ast_rtp_get_peer(p1, &t1);
+- memcpy(&ac1, &t1, sizeof(ac1));
+- /* Update codec information */
+- if (pr0->get_codec && c0->tech_pvt)
+- oldcodec0 = codec0 = pr0->get_codec(c0);
+- if (pr1->get_codec && c1->tech_pvt)
+- oldcodec1 = codec1 = pr1->get_codec(c1);
+- ast_indicate_data(other, fr->subclass, fr->data.ptr, fr->datalen);
+- ast_frfree(fr);
+- } else {
+- *fo = fr;
+- *rc = who;
+- ast_debug(1, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name);
+- return AST_BRIDGE_COMPLETE;
+- }
+- } else {
+- if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
+- (fr->frametype == AST_FRAME_DTMF_END) ||
+- (fr->frametype == AST_FRAME_VOICE) ||
+- (fr->frametype == AST_FRAME_VIDEO) ||
+- (fr->frametype == AST_FRAME_IMAGE) ||
+- (fr->frametype == AST_FRAME_HTML) ||
+- (fr->frametype == AST_FRAME_MODEM) ||
+- (fr->frametype == AST_FRAME_TEXT)) {
+- ast_write(other, fr);
+- }
+- ast_frfree(fr);
+- }
+- /* Swap priority */
+-#ifndef HAVE_EPOLL
+- cs[2] = cs[0];
+- cs[0] = cs[1];
+- cs[1] = cs[2];
+-#endif
+- }
+-
+- ast_poll_channel_del(c0, c1);
+-
+- if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0))
+- ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
+- if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0))
+- ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
+-
+- return AST_BRIDGE_FAILED;
+-}
+-
+-/*! \brief P2P RTP Callback */
+-#ifdef P2P_INTENSE
+-static int p2p_rtp_callback(int *id, int fd, short events, void *cbdata)
+-{
+- int res = 0, hdrlen = 12;
+- struct sockaddr_in sin;
+- socklen_t len;
+- unsigned int *header;
+- struct ast_rtp *rtp = cbdata, *bridged = NULL;
+-
+- if (!rtp)
+- return 1;
+-
+- len = sizeof(sin);
+- if ((res = recvfrom(fd, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 0, (struct sockaddr *)&sin, &len)) < 0)
+- return 1;
+-
+- header = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET);
+-
+- /* If NAT support is turned on, then see if we need to change their address */
+- if ((rtp->nat) &&
+- ((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
+- (rtp->them.sin_port != sin.sin_port))) {
+- rtp->them = sin;
+- rtp->rxseqno = 0;
+- ast_set_flag(rtp, FLAG_NAT_ACTIVE);
+- if (option_debug || rtpdebug)
+- ast_debug(0, "P2P RTP NAT: Got audio from other end. Now sending to address %s:%d\n", ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port));
+- }
+-
+- /* Write directly out to other RTP stream if bridged */
+- if ((bridged = ast_rtp_get_bridged(rtp)))
+- bridge_p2p_rtp_write(rtp, bridged, header, res, hdrlen);
+-
+- return 1;
+-}
+-
+-/*! \brief Helper function to switch a channel and RTP stream into callback mode */
+-static int p2p_callback_enable(struct ast_channel *chan, struct ast_rtp *rtp, int **iod)
+-{
+- /* If we need DTMF, are looking for STUN, or we have no IO structure then we can't do direct callback */
+- if (ast_test_flag(rtp, FLAG_P2P_NEED_DTMF) || ast_test_flag(rtp, FLAG_HAS_STUN) || !rtp->io)
+- return 0;
+-
+- /* If the RTP structure is already in callback mode, remove it temporarily */
+- if (rtp->ioid) {
+- ast_io_remove(rtp->io, rtp->ioid);
+- rtp->ioid = NULL;
+- }
+-
+- /* Steal the file descriptors from the channel */
+- chan->fds[0] = -1;
+-
+- /* Now, fire up callback mode */
+- iod[0] = ast_io_add(rtp->io, ast_rtp_fd(rtp), p2p_rtp_callback, AST_IO_IN, rtp);
+-
+- return 1;
+-}
+-#else
+-static int p2p_callback_enable(struct ast_channel *chan, struct ast_rtp *rtp, int **iod)
+-{
+- return 0;
+-}
+-#endif
+-
+-/*! \brief Helper function to switch a channel and RTP stream out of callback mode */
+-static int p2p_callback_disable(struct ast_channel *chan, struct ast_rtp *rtp, int **iod)
+-{
+- ast_channel_lock(chan);
+-
+- /* Remove the callback from the IO context */
+- ast_io_remove(rtp->io, iod[0]);
+-
+- /* Restore file descriptors */
+- chan->fds[0] = ast_rtp_fd(rtp);
+- ast_channel_unlock(chan);
+-
+- /* Restore callback mode if previously used */
+- if (ast_test_flag(rtp, FLAG_CALLBACK_MODE))
+- rtp->ioid = ast_io_add(rtp->io, ast_rtp_fd(rtp), rtpread, AST_IO_IN, rtp);
+-
+- return 0;
+-}
+-
+-/*! \brief Helper function that sets what an RTP structure is bridged to */
+-static void p2p_set_bridge(struct ast_rtp *rtp0, struct ast_rtp *rtp1)
+-{
+- rtp_bridge_lock(rtp0);
+- rtp0->bridged = rtp1;
+- rtp_bridge_unlock(rtp0);
+-}
+-
+-/*! \brief Bridge loop for partial native bridge (packet2packet)
+-
+- In p2p mode, Asterisk is a very basic RTP proxy, just forwarding whatever
+- rtp/rtcp we get in to the channel.
+- \note this currently only works for Audio
+-*/
+-static enum ast_bridge_result bridge_p2p_loop(struct ast_channel *c0, struct ast_channel *c1, struct ast_rtp *p0, struct ast_rtp *p1, int timeoutms, int flags, struct ast_frame **fo, struct ast_channel **rc, void *pvt0, void *pvt1)
+-{
+- struct ast_frame *fr = NULL;
+- struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, };
+- int *p0_iod[2] = {NULL, NULL}, *p1_iod[2] = {NULL, NULL};
+- int p0_callback = 0, p1_callback = 0;
+- enum ast_bridge_result res = AST_BRIDGE_FAILED;
+-
+- /* Okay, setup each RTP structure to do P2P forwarding */
+- ast_clear_flag(p0, FLAG_P2P_SENT_MARK);
+- p2p_set_bridge(p0, p1);
+- ast_clear_flag(p1, FLAG_P2P_SENT_MARK);
+- p2p_set_bridge(p1, p0);
+-
+- /* Activate callback modes if possible */
+- p0_callback = p2p_callback_enable(c0, p0, &p0_iod[0]);
+- p1_callback = p2p_callback_enable(c1, p1, &p1_iod[0]);
+-
+- /* Now let go of the channel locks and be on our way */
+- ast_channel_unlock(c0);
+- ast_channel_unlock(c1);
+-
+- ast_poll_channel_add(c0, c1);
+-
+- /* Go into a loop forwarding frames until we don't need to anymore */
+- cs[0] = c0;
+- cs[1] = c1;
+- cs[2] = NULL;
+- for (;;) {
+- /* If the underlying formats have changed force this bridge to break */
+- if ((c0->rawreadformat != c1->rawwriteformat) || (c1->rawreadformat != c0->rawwriteformat)) {
+- ast_debug(3, "p2p-rtp-bridge: Oooh, formats changed, backing out\n");
+- res = AST_BRIDGE_FAILED_NOWARN;
+- break;
+- }
+- /* Check if anything changed */
+- if ((c0->tech_pvt != pvt0) ||
+- (c1->tech_pvt != pvt1) ||
+- (c0->masq || c0->masqr || c1->masq || c1->masqr) ||
+- (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) {
+- ast_debug(3, "p2p-rtp-bridge: Oooh, something is weird, backing out\n");
+- /* If a masquerade needs to happen we have to try to read in a frame so that it actually happens. Without this we risk being called again and going into a loop */
+- if ((c0->masq || c0->masqr) && (fr = ast_read(c0)))
+- ast_frfree(fr);
+- if ((c1->masq || c1->masqr) && (fr = ast_read(c1)))
+- ast_frfree(fr);
+- res = AST_BRIDGE_RETRY;
+- break;
+- }
+- /* Wait on a channel to feed us a frame */
+- if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
+- if (!timeoutms) {
+- res = AST_BRIDGE_RETRY;
+- break;
+- }
+- if (option_debug > 2)
+- ast_log(LOG_NOTICE, "p2p-rtp-bridge: Ooh, empty read...\n");
+- if (ast_check_hangup(c0) || ast_check_hangup(c1))
+- break;
+- continue;
+- }
+- /* Read in frame from channel */
+- fr = ast_read(who);
+- other = (who == c0) ? c1 : c0;
+- /* Depending on the frame we may need to break out of our bridge */
+- if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) &&
+- ((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) |
+- ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)))) {
+- /* Record received frame and who */
+- *fo = fr;
+- *rc = who;
+- ast_debug(3, "p2p-rtp-bridge: Ooh, got a %s\n", fr ? "digit" : "hangup");
+- res = AST_BRIDGE_COMPLETE;
+- break;
+- } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
+- if ((fr->subclass == AST_CONTROL_HOLD) ||
+- (fr->subclass == AST_CONTROL_UNHOLD) ||
+- (fr->subclass == AST_CONTROL_VIDUPDATE) ||
+- (fr->subclass == AST_CONTROL_T38) ||
+- (fr->subclass == AST_CONTROL_SRCUPDATE)) {
+- /* If we are going on hold, then break callback mode and P2P bridging */
+- if (fr->subclass == AST_CONTROL_HOLD) {
+- if (p0_callback)
+- p0_callback = p2p_callback_disable(c0, p0, &p0_iod[0]);
+- if (p1_callback)
+- p1_callback = p2p_callback_disable(c1, p1, &p1_iod[0]);
+- p2p_set_bridge(p0, NULL);
+- p2p_set_bridge(p1, NULL);
+- } else if (fr->subclass == AST_CONTROL_UNHOLD) {
+- /* If we are off hold, then go back to callback mode and P2P bridging */
+- ast_clear_flag(p0, FLAG_P2P_SENT_MARK);
+- p2p_set_bridge(p0, p1);
+- ast_clear_flag(p1, FLAG_P2P_SENT_MARK);
+- p2p_set_bridge(p1, p0);
+- p0_callback = p2p_callback_enable(c0, p0, &p0_iod[0]);
+- p1_callback = p2p_callback_enable(c1, p1, &p1_iod[0]);
+- }
+- ast_indicate_data(other, fr->subclass, fr->data.ptr, fr->datalen);
+- ast_frfree(fr);
+- } else {
+- *fo = fr;
+- *rc = who;
+- ast_debug(3, "p2p-rtp-bridge: Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name);
+- res = AST_BRIDGE_COMPLETE;
+- break;
+- }
+- } else {
+- if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
+- (fr->frametype == AST_FRAME_DTMF_END) ||
+- (fr->frametype == AST_FRAME_VOICE) ||
+- (fr->frametype == AST_FRAME_VIDEO) ||
+- (fr->frametype == AST_FRAME_IMAGE) ||
+- (fr->frametype == AST_FRAME_HTML) ||
+- (fr->frametype == AST_FRAME_MODEM) ||
+- (fr->frametype == AST_FRAME_TEXT)) {
+- ast_write(other, fr);
+- }
+-
+- ast_frfree(fr);
+- }
+- /* Swap priority */
+-#ifndef HAVE_EPOLL
+- cs[2] = cs[0];
+- cs[0] = cs[1];
+- cs[1] = cs[2];
+-#endif
+- }
+-
+- /* If we are totally avoiding the core, then restore our link to it */
+- if (p0_callback)
+- p0_callback = p2p_callback_disable(c0, p0, &p0_iod[0]);
+- if (p1_callback)
+- p1_callback = p2p_callback_disable(c1, p1, &p1_iod[0]);
+-
+- /* Break out of the direct bridge */
+- p2p_set_bridge(p0, NULL);
+- p2p_set_bridge(p1, NULL);
+-
+- ast_poll_channel_del(c0, c1);
+-
+- return res;
+-}
+-
+-/*! \page AstRTPbridge The Asterisk RTP bridge
+- The RTP bridge is called from the channel drivers that are using the RTP
+- subsystem in Asterisk - like SIP, H.323 and Jingle/Google Talk.
+-
+- This bridge aims to offload the Asterisk server by setting up
+- the media stream directly between the endpoints, keeping the
+- signalling in Asterisk.
+-
+- It checks with the channel driver, using a callback function, if
+- there are possibilities for a remote bridge.
+-
+- If this fails, the bridge hands off to the core bridge. Reasons
+- can be NAT support needed, DTMF features in audio needed by
+- the PBX for transfers or spying/monitoring on channels.
+-
+- If transcoding is needed - we can't do a remote bridge.
+- If only NAT support is needed, we're using Asterisk in
+- RTP proxy mode with the p2p RTP bridge, basically
+- forwarding incoming audio packets to the outbound
+- stream on a network level.
+-
+- References:
+- - ast_rtp_bridge()
+- - ast_channel_early_bridge()
+- - ast_channel_bridge()
+- - rtp.c
+- - rtp.h
+-*/
+-/*! \brief Bridge calls. If possible and allowed, initiate
+- re-invite so the peers exchange media directly outside
+- of Asterisk.
+-*/
+-enum ast_bridge_result ast_rtp_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
+-{
+- struct ast_rtp *p0 = NULL, *p1 = NULL; /* Audio RTP Channels */
+- struct ast_rtp *vp0 = NULL, *vp1 = NULL; /* Video RTP channels */
+- struct ast_rtp *tp0 = NULL, *tp1 = NULL; /* Text RTP channels */
+- struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL;
+- enum ast_rtp_get_result audio_p0_res = AST_RTP_GET_FAILED, video_p0_res = AST_RTP_GET_FAILED, text_p0_res = AST_RTP_GET_FAILED;
+- enum ast_rtp_get_result audio_p1_res = AST_RTP_GET_FAILED, video_p1_res = AST_RTP_GET_FAILED, text_p1_res = AST_RTP_GET_FAILED;
+- enum ast_bridge_result res = AST_BRIDGE_FAILED;
+- int codec0 = 0, codec1 = 0;
+- void *pvt0 = NULL, *pvt1 = NULL;
+-
+- /* Lock channels */
+- ast_channel_lock(c0);
+- while (ast_channel_trylock(c1)) {
+- ast_channel_unlock(c0);
+- usleep(1);
+- ast_channel_lock(c0);
+- }
+-
+- /* Ensure neither channel got hungup during lock avoidance */
+- if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
+- ast_log(LOG_WARNING, "Got hangup while attempting to bridge '%s' and '%s'\n", c0->name, c1->name);
+- ast_channel_unlock(c0);
+- ast_channel_unlock(c1);
+- return AST_BRIDGE_FAILED;
+- }
+-
+- /* Find channel driver interfaces */
+- if (!(pr0 = get_proto(c0))) {
+- ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name);
+- ast_channel_unlock(c0);
+- ast_channel_unlock(c1);
+- return AST_BRIDGE_FAILED;
+- }
+- if (!(pr1 = get_proto(c1))) {
+- ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name);
+- ast_channel_unlock(c0);
+- ast_channel_unlock(c1);
+- return AST_BRIDGE_FAILED;
+- }
+-
+- /* Get channel specific interface structures */
+- pvt0 = c0->tech_pvt;
+- pvt1 = c1->tech_pvt;
+-
+- /* Get audio and video interface (if native bridge is possible) */
+- audio_p0_res = pr0->get_rtp_info(c0, &p0);
+- video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED;
+- text_p0_res = pr0->get_trtp_info ? pr0->get_trtp_info(c0, &vp0) : AST_RTP_GET_FAILED;
+- audio_p1_res = pr1->get_rtp_info(c1, &p1);
+- video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED;
+- text_p1_res = pr1->get_trtp_info ? pr1->get_trtp_info(c1, &vp1) : AST_RTP_GET_FAILED;
+-
+- /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */
+- if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE))
+- audio_p0_res = AST_RTP_GET_FAILED;
+- if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE))
+- audio_p1_res = AST_RTP_GET_FAILED;
+-
+- /* Check if a bridge is possible (partial/native) */
+- if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) {
+- /* Somebody doesn't want to play... */
+- ast_channel_unlock(c0);
+- ast_channel_unlock(c1);
+- return AST_BRIDGE_FAILED_NOWARN;
+- }
+-
+- /* If we need to feed DTMF frames into the core then only do a partial native bridge */
+- if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
+- ast_set_flag(p0, FLAG_P2P_NEED_DTMF);
+- audio_p0_res = AST_RTP_TRY_PARTIAL;
+- }
+-
+- if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) {
+- ast_set_flag(p1, FLAG_P2P_NEED_DTMF);
+- audio_p1_res = AST_RTP_TRY_PARTIAL;
+- }
+-
+- /* If both sides are not using the same method of DTMF transmission
+- * (ie: one is RFC2833, other is INFO... then we can not do direct media.
+- * --------------------------------------------------
+- * | DTMF Mode | HAS_DTMF | Accepts Begin Frames |
+- * |-----------|------------|-----------------------|
+- * | Inband | False | True |
+- * | RFC2833 | True | True |
+- * | SIP INFO | False | False |
+- * --------------------------------------------------
+- * However, if DTMF from both channels is being monitored by the core, then
+- * we can still do packet-to-packet bridging, because passing through the
+- * core will handle DTMF mode translation.
+- */
+- if ((ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) ||
+- (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) {
+- if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) {
+- ast_channel_unlock(c0);
+- ast_channel_unlock(c1);
+- return AST_BRIDGE_FAILED_NOWARN;
+- }
+- audio_p0_res = AST_RTP_TRY_PARTIAL;
+- audio_p1_res = AST_RTP_TRY_PARTIAL;
+- }
+-
+- /* If we need to feed frames into the core don't do a P2P bridge */
+- if ((audio_p0_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p0, FLAG_P2P_NEED_DTMF)) ||
+- (audio_p1_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p1, FLAG_P2P_NEED_DTMF))) {
+- ast_channel_unlock(c0);
+- ast_channel_unlock(c1);
+- return AST_BRIDGE_FAILED_NOWARN;
+- }
+-
+- /* Get codecs from both sides */
+- codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0;
+- codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0;
+- if (codec0 && codec1 && !(codec0 & codec1)) {
+- /* Hey, we can't do native bridging if both parties speak different codecs */
+- ast_debug(3, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1);
+- ast_channel_unlock(c0);
+- ast_channel_unlock(c1);
+- return AST_BRIDGE_FAILED_NOWARN;
+- }
+-
+- /* If either side can only do a partial bridge, then don't try for a true native bridge */
+- if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) {
+- struct ast_format_list fmt0, fmt1;
+-
+- /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */
+- if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) {
+- ast_debug(1, "Cannot packet2packet bridge - raw formats are incompatible\n");
+- ast_channel_unlock(c0);
+- ast_channel_unlock(c1);
+- return AST_BRIDGE_FAILED_NOWARN;
+- }
+- /* They must also be using the same packetization */
+- fmt0 = ast_codec_pref_getsize(&p0->pref, c0->rawreadformat);
+- fmt1 = ast_codec_pref_getsize(&p1->pref, c1->rawreadformat);
+- if (fmt0.cur_ms != fmt1.cur_ms) {
+- ast_debug(1, "Cannot packet2packet bridge - packetization settings prevent it\n");
+- ast_channel_unlock(c0);
+- ast_channel_unlock(c1);
+- return AST_BRIDGE_FAILED_NOWARN;
+- }
+-
+- ast_verb(3, "Packet2Packet bridging %s and %s\n", c0->name, c1->name);
+- res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1);
+- } else {
+- ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
+- res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, tp0, tp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1);
+- }
+-
+- return res;
+-}
+-
+-static char *rtp_do_debug_ip(struct ast_cli_args *a)
+-{
+- struct hostent *hp;
+- struct ast_hostent ahp;
+- int port = 0;
+- char *p, *arg;
+-
+- arg = a->argv[3];
+- p = strstr(arg, ":");
+- if (p) {
+- *p = '\0';
+- p++;
+- port = atoi(p);
+- }
+- hp = ast_gethostbyname(arg, &ahp);
+- if (hp == NULL) {
+- ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
+- return CLI_FAILURE;
+- }
+- rtpdebugaddr.sin_family = AF_INET;
+- memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr));
+- rtpdebugaddr.sin_port = htons(port);
+- if (port == 0)
+- ast_cli(a->fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtpdebugaddr.sin_addr));
+- else
+- ast_cli(a->fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtpdebugaddr.sin_addr), port);
+- rtpdebug = 1;
+- return CLI_SUCCESS;
+-}
+-
+-static char *rtcp_do_debug_ip(struct ast_cli_args *a)
+-{
+- struct hostent *hp;
+- struct ast_hostent ahp;
+- int port = 0;
+- char *p, *arg;
+-
+- arg = a->argv[3];
+- p = strstr(arg, ":");
+- if (p) {
+- *p = '\0';
+- p++;
+- port = atoi(p);
+- }
+- hp = ast_gethostbyname(arg, &ahp);
+- if (hp == NULL) {
+- ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
+- return CLI_FAILURE;
+- }
+- rtcpdebugaddr.sin_family = AF_INET;
+- memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr));
+- rtcpdebugaddr.sin_port = htons(port);
+- if (port == 0)
+- ast_cli(a->fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr));
+- else
+- ast_cli(a->fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port);
+- rtcpdebug = 1;
+- return CLI_SUCCESS;
+-}
+-
+-static char *handle_cli_rtp_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+-{
+- switch (cmd) {
+- case CLI_INIT:
+- e->command = "rtp set debug {on|off|ip}";
+- e->usage =
+- "Usage: rtp set debug {on|off|ip host[:port]}\n"
+- " Enable/Disable dumping of all RTP packets. If 'ip' is\n"
+- " specified, limit the dumped packets to those to and from\n"
+- " the specified 'host' with optional port.\n";
+- return NULL;
+- case CLI_GENERATE:
+- return NULL;
+- }
+-
+- if (a->argc == e->args) { /* set on or off */
+- if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
+- rtpdebug = 1;
+- memset(&rtpdebugaddr, 0, sizeof(rtpdebugaddr));
+- ast_cli(a->fd, "RTP Debugging Enabled\n");
+- return CLI_SUCCESS;
+- } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
+- rtpdebug = 0;
+- ast_cli(a->fd, "RTP Debugging Disabled\n");
+- return CLI_SUCCESS;
+- }
+- } else if (a->argc == e->args +1) { /* ip */
+- return rtp_do_debug_ip(a);
+- }
+-
+- return CLI_SHOWUSAGE; /* default, failure */
+-}
+-
+-static char *handle_cli_rtcp_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+-{
+- switch (cmd) {
+- case CLI_INIT:
+- e->command = "rtcp set debug {on|off|ip}";
+- e->usage =
+- "Usage: rtcp set debug {on|off|ip host[:port]}\n"
+- " Enable/Disable dumping of all RTCP packets. If 'ip' is\n"
+- " specified, limit the dumped packets to those to and from\n"
+- " the specified 'host' with optional port.\n";
+- return NULL;
+- case CLI_GENERATE:
+- return NULL;
+- }
+-
+- if (a->argc == e->args) { /* set on or off */
+- if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
+- rtcpdebug = 1;
+- memset(&rtcpdebugaddr, 0, sizeof(rtcpdebugaddr));
+- ast_cli(a->fd, "RTCP Debugging Enabled\n");
+- return CLI_SUCCESS;
+- } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
+- rtcpdebug = 0;
+- ast_cli(a->fd, "RTCP Debugging Disabled\n");
+- return CLI_SUCCESS;
+- }
+- } else if (a->argc == e->args +1) { /* ip */
+- return rtcp_do_debug_ip(a);
+- }
+-
+- return CLI_SHOWUSAGE; /* default, failure */
+-}
+-
+-static char *handle_cli_rtcp_set_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+-{
+- switch (cmd) {
+- case CLI_INIT:
+- e->command = "rtcp set stats {on|off}";
+- e->usage =
+- "Usage: rtcp set stats {on|off}\n"
+- " Enable/Disable dumping of RTCP stats.\n";
+- return NULL;
+- case CLI_GENERATE:
+- return NULL;
+- }
+-
+- if (a->argc != e->args)
+- return CLI_SHOWUSAGE;
+-
+- if (!strncasecmp(a->argv[e->args-1], "on", 2))
+- rtcpstats = 1;
+- else if (!strncasecmp(a->argv[e->args-1], "off", 3))
+- rtcpstats = 0;
+- else
+- return CLI_SHOWUSAGE;
+-
+- ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled");
+- return CLI_SUCCESS;
+-}
+-
+-static char *handle_cli_stun_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+-{
+- switch (cmd) {
+- case CLI_INIT:
+- e->command = "stun set debug {on|off}";
+- e->usage =
+- "Usage: stun set debug {on|off}\n"
+- " Enable/Disable STUN (Simple Traversal of UDP through NATs)\n"
+- " debugging\n";
+- return NULL;
+- case CLI_GENERATE:
+- return NULL;
+- }
+-
+- if (a->argc != e->args)
+- return CLI_SHOWUSAGE;
+-
+- if (!strncasecmp(a->argv[e->args-1], "on", 2))
+- stundebug = 1;
+- else if (!strncasecmp(a->argv[e->args-1], "off", 3))
+- stundebug = 0;
+- else
+- return CLI_SHOWUSAGE;
+-
+- ast_cli(a->fd, "STUN Debugging %s\n", stundebug ? "Enabled" : "Disabled");
+- return CLI_SUCCESS;
+-}
+-
+-static struct ast_cli_entry cli_rtp[] = {
+- AST_CLI_DEFINE(handle_cli_rtp_set_debug, "Enable/Disable RTP debugging"),
+- AST_CLI_DEFINE(handle_cli_rtcp_set_debug, "Enable/Disable RTCP debugging"),
+- AST_CLI_DEFINE(handle_cli_rtcp_set_stats, "Enable/Disable RTCP stats"),
+- AST_CLI_DEFINE(handle_cli_stun_set_debug, "Enable/Disable STUN debugging"),
+-};
+-
+-static int __ast_rtp_reload(int reload)
+-{
+- struct ast_config *cfg;
+- const char *s;
+- struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
+-
+- cfg = ast_config_load2("rtp.conf", "rtp", config_flags);
+- if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
+- return 0;
+- }
+-
+- rtpstart = 5000;
+- rtpend = 31000;
+- dtmftimeout = DEFAULT_DTMF_TIMEOUT;
+- strictrtp = STRICT_RTP_OPEN;
+- if (cfg) {
+- if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
+- rtpstart = atoi(s);
+- if (rtpstart < 1024)
+- rtpstart = 1024;
+- if (rtpstart > 65535)
+- rtpstart = 65535;
+- }
+- if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
+- rtpend = atoi(s);
+- if (rtpend < 1024)
+- rtpend = 1024;
+- if (rtpend > 65535)
+- rtpend = 65535;
+- }
+- if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) {
+- rtcpinterval = atoi(s);
+- if (rtcpinterval == 0)
+- rtcpinterval = 0; /* Just so we're clear... it's zero */
+- if (rtcpinterval < RTCP_MIN_INTERVALMS)
+- rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */
+- if (rtcpinterval > RTCP_MAX_INTERVALMS)
+- rtcpinterval = RTCP_MAX_INTERVALMS;
+- }
+- if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
+-#ifdef SO_NO_CHECK
+- if (ast_false(s))
+- nochecksums = 1;
+- else
+- nochecksums = 0;
+-#else
+- if (ast_false(s))
+- ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
+-#endif
+- }
+- if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
+- dtmftimeout = atoi(s);
+- if ((dtmftimeout < 0) || (dtmftimeout > 64000)) {
+- ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
+- dtmftimeout, DEFAULT_DTMF_TIMEOUT);
+- dtmftimeout = DEFAULT_DTMF_TIMEOUT;
+- };
+- }
+- if ((s = ast_variable_retrieve(cfg, "general", "strictrtp"))) {
+- strictrtp = ast_true(s);
+- }
+- ast_config_destroy(cfg);
+- }
+- if (rtpstart >= rtpend) {
+- ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
+- rtpstart = 5000;
+- rtpend = 31000;
+- }
+- ast_verb(2, "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
+- return 0;
+-}
+-
+-int ast_rtp_reload(void)
+-{
+- return __ast_rtp_reload(1);
+-}
+-
+-/*! \brief Initialize the RTP system in Asterisk */
+-void ast_rtp_init(void)
+-{
+- ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry));
+- __ast_rtp_reload(0);
+-}
+-
+-/*! \brief Write t140 redundacy frame
+- * \param data primary data to be buffered
+- */
+-static int red_write(const void *data)
+-{
+- struct ast_rtp *rtp = (struct ast_rtp*) data;
+-
+- ast_rtp_write(rtp, &rtp->red->t140);
+-
+- return 1;
+-}
+-
+-/*! \brief Construct a redundant frame
+- * \param red redundant data structure
+- */
+-static struct ast_frame *red_t140_to_red(struct rtp_red *red) {
+- unsigned char *data = red->t140red.data.ptr;
+- int len = 0;
+- int i;
+-
+- /* replace most aged generation */
+- if (red->len[0]) {
+- for (i = 1; i < red->num_gen+1; i++)
+- len += red->len[i];
+-
+- memmove(&data[red->hdrlen], &data[red->hdrlen+red->len[0]], len);
+- }
+-
+- /* Store length of each generation and primary data length*/
+- for (i = 0; i < red->num_gen; i++)
+- red->len[i] = red->len[i+1];
+- red->len[i] = red->t140.datalen;
+-
+- /* write each generation length in red header */
+- len = red->hdrlen;
+- for (i = 0; i < red->num_gen; i++)
+- len += data[i*4+3] = red->len[i];
+-
+- /* add primary data to buffer */
+- memcpy(&data[len], red->t140.data.ptr, red->t140.datalen);
+- red->t140red.datalen = len + red->t140.datalen;
+-
+- /* no primary data and no generations to send */
+- if (len == red->hdrlen && !red->t140.datalen)
+- return NULL;
+-
+- /* reset t.140 buffer */
+- red->t140.datalen = 0;
+-
+- return &red->t140red;
+-}
+-
+-/*! \brief Initialize t140 redundancy
+- * \param rtp
+- * \param ti buffer t140 for ti (msecs) before sending redundant frame
+- * \param red_data_pt Payloadtypes for primary- and generation-data
+- * \param num_gen numbers of generations (primary generation not encounted)
+- *
+-*/
+-int rtp_red_init(struct ast_rtp *rtp, int ti, int *red_data_pt, int num_gen)
+-{
+- struct rtp_red *r;
+- int x;
+-
+- if (!(r = ast_calloc(1, sizeof(struct rtp_red))))
+- return -1;
+-
+- r->t140.frametype = AST_FRAME_TEXT;
+- r->t140.subclass = AST_FORMAT_T140RED;
+- r->t140.data.ptr = &r->buf_data;
+-
+- r->t140.ts = 0;
+- r->t140red = r->t140;
+- r->t140red.data.ptr = &r->t140red_data;
+- r->t140red.datalen = 0;
+- r->ti = ti;
+- r->num_gen = num_gen;
+- r->hdrlen = num_gen * 4 + 1;
+- r->prev_ts = 0;
+-
+- for (x = 0; x < num_gen; x++) {
+- r->pt[x] = red_data_pt[x];
+- r->pt[x] |= 1 << 7; /* mark redundant generations pt */
+- r->t140red_data[x*4] = r->pt[x];
+- }
+- r->t140red_data[x*4] = r->pt[x] = red_data_pt[x]; /* primary pt */
+- r->schedid = ast_sched_add(rtp->sched, ti, red_write, rtp);
+- rtp->red = r;
+-
+- r->t140.datalen = 0;
+-
+- return 0;
+-}
+-
+-/*! \brief Buffer t140 from chan_sip
+- * \param rtp
+- * \param f frame
+- */
+-void red_buffer_t140(struct ast_rtp *rtp, struct ast_frame *f)
+-{
+- if (f->datalen > -1) {
+- struct rtp_red *red = rtp->red;
+- memcpy(&red->buf_data[red->t140.datalen], f->data.ptr, f->datalen);
+- red->t140.datalen += f->datalen;
+- red->t140.ts = f->ts;
+- }
+-}
+Index: main/utils.c
+===================================================================
+--- a/main/utils.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/utils.c (.../trunk) (revision 202568)
+@@ -227,7 +227,7 @@
+ }
+
+ /*! \brief Produce 32 char MD5 hash of value. */
+-void ast_md5_hash(char *output, char *input)
++void ast_md5_hash(char *output, const char *input)
+ {
+ struct MD5Context md5;
+ unsigned char digest[16];
+@@ -235,7 +235,7 @@
+ int x;
+
+ MD5Init(&md5);
+- MD5Update(&md5, (unsigned char *)input, strlen(input));
++ MD5Update(&md5, (const unsigned char *) input, strlen(input));
+ MD5Final(digest, &md5);
+ ptr = output;
+ for (x = 0; x < 16; x++)
+@@ -243,7 +243,7 @@
+ }
+
+ /*! \brief Produce 40 char SHA1 hash of value. */
+-void ast_sha1_hash(char *output, char *input)
++void ast_sha1_hash(char *output, const char *input)
+ {
+ struct SHA1Context sha;
+ char *ptr;
+@@ -1446,7 +1446,7 @@
+ return dataPut;
+ }
+
+-void ast_join(char *s, size_t len, char * const w[])
++void ast_join(char *s, size_t len, const char * const w[])
+ {
+ int x, ofs = 0;
+ const char *src;
+@@ -1469,8 +1469,33 @@
+ * stringfields support routines.
+ */
+
+-const char __ast_string_field_empty[] = ""; /*!< the empty string */
++/* this is a little complex... string fields are stored with their
++ allocated size in the bytes preceding the string; even the
++ constant 'empty' string has to be this way, so the code that
++ checks to see if there is enough room for a new string doesn't
++ have to have any special case checks
++*/
+
++static const struct {
++ ast_string_field_allocation allocation;
++ char string[1];
++} __ast_string_field_empty_buffer;
++
++ast_string_field __ast_string_field_empty = __ast_string_field_empty_buffer.string;
++
++#define ALLOCATOR_OVERHEAD 48
++
++static size_t optimal_alloc_size(size_t size)
++{
++ unsigned int count;
++
++ size += ALLOCATOR_OVERHEAD;
++
++ for (count = 1; size; size >>= 1, count++);
++
++ return (1 << count) - ALLOCATOR_OVERHEAD;
++}
++
+ /*! \brief add a new block to the pool.
+ * We can only allocate from the topmost pool, so the
+ * fields in *mgr reflect the size of that only.
+@@ -1479,21 +1504,21 @@
+ size_t size, const char *file, int lineno, const char *func)
+ {
+ struct ast_string_field_pool *pool;
++ size_t alloc_size = optimal_alloc_size(sizeof(*pool) + size);
+
+ #if defined(__AST_DEBUG_MALLOC)
+- if (!(pool = __ast_calloc(1, sizeof(*pool) + size, file, lineno, func))) {
++ if (!(pool = __ast_calloc(1, alloc_size, file, lineno, func))) {
+ return -1;
+ }
+ #else
+- if (!(pool = ast_calloc(1, sizeof(*pool) + size))) {
++ if (!(pool = ast_calloc(1, alloc_size))) {
+ return -1;
+ }
+ #endif
+
+ pool->prev = *pool_head;
++ pool->size = alloc_size - sizeof(*pool);
+ *pool_head = pool;
+- mgr->size = size;
+- mgr->used = 0;
+ mgr->last_alloc = NULL;
+
+ return 0;
+@@ -1505,6 +1530,8 @@
+ * size > 0 means initialize the pool list with a pool of given size.
+ * This must be called right after allocating the object.
+ * size = 0 means release all pools except the most recent one.
++ * If the first pool was allocated via embedding in another
++ * object, that pool will be preserved instead.
+ * This is useful to e.g. reset an object to the initial value.
+ * size < 0 means release all pools.
+ * This must be done before destroying the object.
+@@ -1517,8 +1544,10 @@
+ struct ast_string_field_pool *preserve = NULL;
+
+ /* clear fields - this is always necessary */
+- while ((struct ast_string_field_mgr *) p != mgr)
++ while ((struct ast_string_field_mgr *) p != mgr) {
+ *p++ = __ast_string_field_empty;
++ }
++
+ mgr->last_alloc = NULL;
+ #if defined(__AST_DEBUG_MALLOC)
+ mgr->owner_file = file;
+@@ -1529,24 +1558,34 @@
+ *pool_head = NULL;
+ return add_string_pool(mgr, pool_head, needed, file, lineno, func);
+ }
++
++ /* if there is an embedded pool, we can't actually release *all*
++ * pools, we must keep the embedded one. if the caller is about
++ * to free the structure that contains the stringfield manager
++ * and embedded pool anyway, it will be freed as part of that
++ * operation.
++ */
++ if ((needed < 0) && mgr->embedded_pool) {
++ needed = 0;
++ }
++
+ if (needed < 0) { /* reset all pools */
+- if (*pool_head == NULL) {
+- ast_log(LOG_WARNING, "trying to reset empty pool\n");
+- return -1;
+- }
+ cur = *pool_head;
++ } else if (mgr->embedded_pool) { /* preserve the embedded pool */
++ preserve = mgr->embedded_pool;
++ cur = *pool_head;
+ } else { /* preserve the last pool */
+ if (*pool_head == NULL) {
+ ast_log(LOG_WARNING, "trying to reset empty pool\n");
+ return -1;
+ }
+- mgr->used = 0;
+ preserve = *pool_head;
+ cur = preserve->prev;
+ }
+
+ if (preserve) {
+ preserve->prev = NULL;
++ preserve->used = preserve->active = 0;
+ }
+
+ while (cur) {
+@@ -1567,13 +1606,15 @@
+ struct ast_string_field_pool **pool_head, size_t needed)
+ {
+ char *result = NULL;
+- size_t space = mgr->size - mgr->used;
++ size_t space = (*pool_head)->size - (*pool_head)->used;
++ size_t to_alloc = needed + sizeof(ast_string_field_allocation);
+
+- if (__builtin_expect(needed > space, 0)) {
+- size_t new_size = mgr->size * 2;
++ if (__builtin_expect(to_alloc > space, 0)) {
++ size_t new_size = (*pool_head)->size;
+
+- while (new_size < needed)
++ while (new_size < to_alloc) {
+ new_size *= 2;
++ }
+
+ #if defined(__AST_DEBUG_MALLOC)
+ if (add_string_pool(mgr, pool_head, new_size, mgr->owner_file, mgr->owner_line, mgr->owner_func))
+@@ -1584,22 +1625,23 @@
+ #endif
+ }
+
+- result = (*pool_head)->base + mgr->used;
+- mgr->used += needed;
++ result = (*pool_head)->base + (*pool_head)->used;
++ (*pool_head)->used += to_alloc;
++ (*pool_head)->active += needed;
++ result += sizeof(ast_string_field_allocation);
++ AST_STRING_FIELD_ALLOCATION(result) = needed;
+ mgr->last_alloc = result;
++
+ return result;
+ }
+
+-int __ast_string_field_ptr_grow(struct ast_string_field_mgr *mgr, size_t needed,
++int __ast_string_field_ptr_grow(struct ast_string_field_mgr *mgr,
++ struct ast_string_field_pool **pool_head, size_t needed,
+ const ast_string_field *ptr)
+ {
+- int grow = needed - (strlen(*ptr) + 1);
+- size_t space = mgr->size - mgr->used;
++ ssize_t grow = needed - AST_STRING_FIELD_ALLOCATION(*ptr);
++ size_t space = (*pool_head)->size - (*pool_head)->used;
+
+- if (grow <= 0) {
+- return 0;
+- }
+-
+ if (*ptr != mgr->last_alloc) {
+ return 1;
+ }
+@@ -1608,30 +1650,57 @@
+ return 1;
+ }
+
+- mgr->used += grow;
++ (*pool_head)->used += grow;
++ (*pool_head)->active += grow;
++ AST_STRING_FIELD_ALLOCATION(*ptr) += grow;
+
+ return 0;
+ }
+
++void __ast_string_field_release_active(struct ast_string_field_pool *pool_head,
++ const ast_string_field ptr)
++{
++ struct ast_string_field_pool *pool, *prev;
++
++ if (ptr == __ast_string_field_empty) {
++ return;
++ }
++
++ for (pool = pool_head, prev = NULL; pool; prev = pool, pool = pool->prev) {
++ if ((ptr >= pool->base) && (ptr <= (pool->base + pool->size))) {
++ pool->active -= AST_STRING_FIELD_ALLOCATION(ptr);
++ if ((pool->active == 0) && prev) {
++ prev->prev = pool->prev;
++ ast_free(pool);
++ }
++ break;
++ }
++ }
++}
++
+ void __ast_string_field_ptr_build_va(struct ast_string_field_mgr *mgr,
+ struct ast_string_field_pool **pool_head,
+ ast_string_field *ptr, const char *format, va_list ap1, va_list ap2)
+ {
+ size_t needed;
+ size_t available;
+- size_t space = mgr->size - mgr->used;
++ size_t space = (*pool_head)->size - (*pool_head)->used;
++ ssize_t grow;
+ char *target;
+
+ /* if the field already has space allocated, try to reuse it;
+- otherwise, use the empty space at the end of the current
++ otherwise, try to use the empty space at the end of the current
+ pool
+ */
+- if ((*ptr)[0] != '\0') {
++ if (*ptr != __ast_string_field_empty) {
+ target = (char *) *ptr;
+- available = strlen(target) + 1;
++ available = AST_STRING_FIELD_ALLOCATION(*ptr);
++ if (*ptr == mgr->last_alloc) {
++ available += space;
++ }
+ } else {
+- target = (*pool_head)->base + mgr->used;
+- available = space;
++ target = (*pool_head)->base + (*pool_head)->used + sizeof(ast_string_field_allocation);
++ available = space - sizeof(ast_string_field_allocation);
+ }
+
+ needed = vsnprintf(target, available, format, ap1) + 1;
+@@ -1639,33 +1708,32 @@
+ va_end(ap1);
+
+ if (needed > available) {
+- /* if the space needed can be satisfied by using the current
+- pool (which could only occur if we tried to use the field's
+- allocated space and failed), then use that space; otherwise
+- allocate a new pool
++ /* the allocation could not be satisfied using the field's current allocation
++ (if it has one), or the space available in the pool (if it does not). allocate
++ space for it, adding a new string pool if necessary.
+ */
+- if (needed > space) {
+- size_t new_size = mgr->size * 2;
+-
+- while (new_size < needed)
+- new_size *= 2;
+-
+-#if defined(__AST_DEBUG_MALLOC)
+- if (add_string_pool(mgr, pool_head, new_size, mgr->owner_file, mgr->owner_line, mgr->owner_func))
+- return;
+-#else
+- if (add_string_pool(mgr, pool_head, new_size, NULL, 0, NULL))
+- return;
+-#endif
++ if (!(target = (char *) __ast_string_field_alloc_space(mgr, pool_head, needed))) {
++ return;
+ }
+-
+- target = (*pool_head)->base + mgr->used;
+ vsprintf(target, format, ap2);
+- }
+-
+- if (*ptr != target) {
++ __ast_string_field_release_active(*pool_head, *ptr);
++ *ptr = target;
++ } else if (*ptr != target) {
++ /* the allocation was satisfied using available space in the pool, but not
++ using the space already allocated to the field
++ */
++ __ast_string_field_release_active(*pool_head, *ptr);
+ mgr->last_alloc = *ptr = target;
+- mgr->used += needed;
++ AST_STRING_FIELD_ALLOCATION(target) = needed;
++ (*pool_head)->used += needed + sizeof(ast_string_field_allocation);
++ (*pool_head)->active += needed;
++ } else if ((grow = (needed - AST_STRING_FIELD_ALLOCATION(*ptr))) > 0) {
++ /* the allocation was satisfied by using available space in the pool *and*
++ the field was the last allocated field from the pool, so it grew
++ */
++ (*pool_head)->used += grow;
++ (*pool_head)->active += grow;
++ AST_STRING_FIELD_ALLOCATION(*ptr) += grow;
+ }
+ }
+
+@@ -1683,6 +1751,50 @@
+ va_end(ap1);
+ va_end(ap2);
+ }
++
++void *__ast_calloc_with_stringfields(unsigned int num_structs, size_t struct_size, size_t field_mgr_offset,
++ size_t field_mgr_pool_offset, size_t pool_size, const char *file,
++ int lineno, const char *func)
++{
++ struct ast_string_field_mgr *mgr;
++ struct ast_string_field_pool *pool;
++ struct ast_string_field_pool **pool_head;
++ size_t pool_size_needed = sizeof(*pool) + pool_size;
++ size_t size_to_alloc = optimal_alloc_size(struct_size + pool_size_needed);
++ void *allocation;
++ unsigned int x;
++
++#if defined(__AST_DEBUG_MALLOC)
++ if (!(allocation = __ast_calloc(num_structs, size_to_alloc, file, lineno, func))) {
++ return NULL;
++ }
++#else
++ if (!(allocation = ast_calloc(num_structs, size_to_alloc))) {
++ return NULL;
++ }
++#endif
++
++ for (x = 0; x < num_structs; x++) {
++ void *base = allocation + (size_to_alloc * x);
++ const char **p;
++
++ mgr = base + field_mgr_offset;
++ pool_head = base + field_mgr_pool_offset;
++ pool = base + struct_size;
++
++ p = (const char **) pool_head + 1;
++ while ((struct ast_string_field_mgr *) p != mgr) {
++ *p++ = __ast_string_field_empty;
++ }
++
++ mgr->embedded_pool = pool;
++ *pool_head = pool;
++ pool->size = size_to_alloc - struct_size - sizeof(*pool);
++ }
++
++ return allocation;
++}
++
+ /* end of stringfields support */
+
+ AST_MUTEX_DEFINE_STATIC(fetchadd_m); /* used for all fetc&add ops */
+@@ -1809,6 +1921,126 @@
+ return 0;
+ }
+
++
++/*!
++ *\brief Parse digest authorization header.
++ *\return Returns -1 if we have no auth or something wrong with digest.
++ *\note This function may be used for Digest request and responce header.
++ * request arg is set to nonzero, if we parse Digest Request.
++ * pedantic arg can be set to nonzero if we need to do addition Digest check.
++ */
++int ast_parse_digest(const char *digest, struct ast_http_digest *d, int request, int pedantic) {
++ int i;
++ char *c, key[512], val[512], tmp[512];
++ struct ast_str *str = ast_str_create(16);
++
++ if (ast_strlen_zero(digest) || !d || !str) {
++ ast_free(str);
++ return -1;
++ }
++
++ ast_str_set(&str, 0, "%s", digest);
++
++ c = ast_skip_blanks(ast_str_buffer(str));
++
++ if (strncasecmp(tmp, "Digest ", strlen("Digest "))) {
++ ast_log(LOG_WARNING, "Missing Digest.\n");
++ ast_free(str);
++ return -1;
++ }
++ c += strlen("Digest ");
++
++ /* lookup for keys/value pair */
++ while (*c && *(c = ast_skip_blanks(c))) {
++ /* find key */
++ i = 0;
++ while (*c && *c != '=' && *c != ',' && !isspace(*c)) {
++ key[i++] = *c++;
++ }
++ key[i] = '\0';
++ c = ast_skip_blanks(c);
++ if (*c == '=') {
++ c = ast_skip_blanks(++c);
++ i = 0;
++ if (*c == '\"') {
++ /* in quotes. Skip first and look for last */
++ c++;
++ while (*c && *c != '\"') {
++ if (*c == '\\' && c[1] != '\0') { /* unescape chars */
++ c++;
++ }
++ val[i++] = *c++;
++ }
++ } else {
++ /* token */
++ while (*c && *c != ',' && !isspace(*c)) {
++ val[i++] = *c++;
++ }
++ }
++ val[i] = '\0';
++ }
++
++ while (*c && *c != ',') {
++ c++;
++ }
++ if (*c) {
++ c++;
++ }
++
++ if (!strcasecmp(key, "username")) {
++ ast_string_field_set(d, username, val);
++ } else if (!strcasecmp(key, "realm")) {
++ ast_string_field_set(d, realm, val);
++ } else if (!strcasecmp(key, "nonce")) {
++ ast_string_field_set(d, nonce, val);
++ } else if (!strcasecmp(key, "uri")) {
++ ast_string_field_set(d, uri, val);
++ } else if (!strcasecmp(key, "domain")) {
++ ast_string_field_set(d, domain, val);
++ } else if (!strcasecmp(key, "response")) {
++ ast_string_field_set(d, response, val);
++ } else if (!strcasecmp(key, "algorithm")) {
++ if (strcasecmp(val, "MD5")) {
++ ast_log(LOG_WARNING, "Digest algorithm: \"%s\" not supported.\n", val);
++ return -1;
++ }
++ } else if (!strcasecmp(key, "cnonce")) {
++ ast_string_field_set(d, cnonce, val);
++ } else if (!strcasecmp(key, "opaque")) {
++ ast_string_field_set(d, opaque, val);
++ } else if (!strcasecmp(key, "qop") && !strcasecmp(val, "auth")) {
++ d->qop = 1;
++ } else if (!strcasecmp(key, "nc")) {
++ unsigned long u;
++ if (sscanf(val, "%lx", &u) != 1) {
++ ast_log(LOG_WARNING, "Incorrect Digest nc value: \"%s\".\n", val);
++ return -1;
++ }
++ ast_string_field_set(d, nc, val);
++ }
++ }
++ ast_free(str);
++
++ /* Digest checkout */
++ if (ast_strlen_zero(d->realm) || ast_strlen_zero(d->nonce)) {
++ /* "realm" and "nonce" MUST be always exist */
++ return -1;
++ }
++
++ if (!request) {
++ /* Additional check for Digest response */
++ if (ast_strlen_zero(d->username) || ast_strlen_zero(d->uri) || ast_strlen_zero(d->response)) {
++ return -1;
++ }
++
++ if (pedantic && d->qop && (ast_strlen_zero(d->cnonce) || ast_strlen_zero(d->nc))) {
++ return -1;
++ }
++ }
++
++ return 0;
++}
++
+ #ifndef __AST_DEBUG_MALLOC
+ int _ast_asprintf(char **ret, const char *file, int lineno, const char *func, const char *fmt, ...)
+ {
+Index: main/loader.c
+===================================================================
+--- a/main/loader.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/loader.c (.../trunk) (revision 202568)
+@@ -43,7 +43,6 @@
+ #include "asterisk/manager.h"
+ #include "asterisk/cdr.h"
+ #include "asterisk/enum.h"
+-#include "asterisk/rtp.h"
+ #include "asterisk/http.h"
+ #include "asterisk/lock.h"
+ #include "asterisk/features.h"
+@@ -71,7 +70,7 @@
+
+ AST_LIST_HEAD(module_user_list, ast_module_user);
+
+-static unsigned char expected_key[] =
++static const unsigned char expected_key[] =
+ { 0x87, 0x76, 0x79, 0x35, 0x23, 0xea, 0x3a, 0xd3,
+ 0x25, 0x2a, 0xbb, 0x35, 0x87, 0xe4, 0x22, 0x24 };
+
+@@ -126,7 +125,7 @@
+ need to know what filename the module was loaded from while it
+ is being registered
+ */
+-struct ast_module *resource_being_loaded;
++static struct ast_module *resource_being_loaded;
+
+ /* XXX: should we check for duplicate resource names here? */
+
+@@ -253,7 +252,6 @@
+ { "extconfig", read_config_maps },
+ { "enum", ast_enum_reload },
+ { "manager", reload_manager },
+- { "rtp", ast_rtp_reload },
+ { "http", ast_http_reload },
+ { "logger", logger_reload },
+ { "features", ast_features_reload },
+@@ -744,10 +742,9 @@
+ mod->flags.declined = 1;
+ break;
+ case AST_MODULE_LOAD_FAILURE:
++ case AST_MODULE_LOAD_SKIP: /* modules should never return this value */
++ case AST_MODULE_LOAD_PRIORITY:
+ break;
+- case AST_MODULE_LOAD_SKIP:
+- /* modules should never return this value */
+- break;
+ }
+
+ return res;
+@@ -808,7 +805,7 @@
+
+ if (resource_heap) {
+ ast_heap_push(resource_heap, mod);
+- res = AST_MODULE_LOAD_SKIP;
++ res = AST_MODULE_LOAD_PRIORITY;
+ } else {
+ res = start_resource(mod);
+ }
+@@ -894,6 +891,9 @@
+ goto done;
+ case AST_MODULE_LOAD_SKIP:
+ break;
++ case AST_MODULE_LOAD_PRIORITY:
++ AST_LIST_REMOVE_CURRENT(entry);
++ break;
+ }
+ }
+ AST_LIST_TRAVERSE_SAFE_END;
+@@ -909,6 +909,7 @@
+ res = -1;
+ goto done;
+ case AST_MODULE_LOAD_SKIP:
++ case AST_MODULE_LOAD_PRIORITY:
+ break;
+ }
+ }
+Index: main/term.c
+===================================================================
+--- a/main/term.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/term.c (.../trunk) (revision 202568)
+@@ -43,7 +43,7 @@
+ static char enddata[80] = "";
+ static char quitdata[80] = "";
+
+-static const char *termpath[] = {
++static const char * const termpath[] = {
+ "/usr/share/terminfo",
+ "/usr/local/share/misc/terminfo",
+ "/usr/lib/terminfo",
+Index: main/cdr.c
+===================================================================
+--- a/main/cdr.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/cdr.c (.../trunk) (revision 202568)
+@@ -148,13 +148,16 @@
+ AST_RWLIST_TRAVERSE_SAFE_BEGIN(&be_list, i, list) {
+ if (!strcasecmp(name, i->name)) {
+ AST_RWLIST_REMOVE_CURRENT(list);
+- ast_verb(2, "Unregistered '%s' CDR backend\n", name);
+- ast_free(i);
+ break;
+ }
+ }
+ AST_RWLIST_TRAVERSE_SAFE_END;
+ AST_RWLIST_UNLOCK(&be_list);
++
++ if (i) {
++ ast_verb(2, "Unregistered '%s' CDR backend\n", name);
++ ast_free(i);
++ }
+ }
+
+ int ast_cdr_isset_unanswered(void)
+@@ -282,10 +285,10 @@
+ }
+
+ /* readonly cdr variables */
+-static const char *cdr_readonly_vars[] = { "clid", "src", "dst", "dcontext", "channel", "dstchannel",
+- "lastapp", "lastdata", "start", "answer", "end", "duration",
+- "billsec", "disposition", "amaflags", "accountcode", "uniqueid",
+- "userfield", NULL };
++static const char * const cdr_readonly_vars[] = { "clid", "src", "dst", "dcontext", "channel", "dstchannel",
++ "lastapp", "lastdata", "start", "answer", "end", "duration",
++ "billsec", "disposition", "amaflags", "accountcode", "uniqueid",
++ "userfield", NULL };
+ /*! Set a CDR channel variable
+ \note You can't set the CDR variables that belong to the actual CDR record, like "billsec".
+ */
+Index: main/channel.c
+===================================================================
+--- a/main/channel.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/channel.c (.../trunk) (revision 202568)
+@@ -61,6 +61,7 @@
+ #include "asterisk/slinfactory.h"
+ #include "asterisk/audiohook.h"
+ #include "asterisk/timing.h"
++#include "asterisk/autochan.h"
+
+ #ifdef HAVE_EPOLL
+ #include <sys/epoll.h>
+@@ -121,12 +122,17 @@
+ #endif
+
+ /*! \brief the list of registered channel types */
+-static AST_LIST_HEAD_NOLOCK_STATIC(backends, chanlist);
++static AST_RWLIST_HEAD_STATIC(backends, chanlist);
+
+-/*! \brief the list of channels we have. Note that the lock for this list is used for
+- both the channels list and the backends list. */
+-static AST_RWLIST_HEAD_STATIC(channels, ast_channel);
++#ifdef LOW_MEMORY
++#define NUM_CHANNEL_BUCKETS 61
++#else
++#define NUM_CHANNEL_BUCKETS 1567
++#endif
+
++/*! \brief All active channels on the system */
++static struct ao2_container *channels;
++
+ /*! \brief map AST_CAUSE's to readable string representations
+ *
+ * \ref causes.h
+@@ -185,8 +191,10 @@
+ struct ast_variable *ast_channeltype_list(void)
+ {
+ struct chanlist *cl;
+- struct ast_variable *var=NULL, *prev = NULL;
+- AST_LIST_TRAVERSE(&backends, cl, list) {
++ struct ast_variable *var = NULL, *prev = NULL;
++
++ AST_RWLIST_RDLOCK(&backends);
++ AST_RWLIST_TRAVERSE(&backends, cl, list) {
+ if (prev) {
+ if ((prev->next = ast_variable_new(cl->tech->type, cl->tech->description, "")))
+ prev = prev->next;
+@@ -195,6 +203,8 @@
+ prev = var;
+ }
+ }
++ AST_RWLIST_UNLOCK(&backends);
++
+ return var;
+ }
+
+@@ -223,18 +233,16 @@
+ ast_cli(a->fd, FORMAT, "Type", "Description", "Devicestate", "Indications", "Transfer");
+ ast_cli(a->fd, FORMAT, "----------", "-----------", "-----------", "-----------", "--------");
+
+- AST_RWLIST_RDLOCK(&channels);
+-
+- AST_LIST_TRAVERSE(&backends, cl, list) {
++ AST_RWLIST_RDLOCK(&backends);
++ AST_RWLIST_TRAVERSE(&backends, cl, list) {
+ ast_cli(a->fd, FORMAT, cl->tech->type, cl->tech->description,
+ (cl->tech->devicestate) ? "yes" : "no",
+ (cl->tech->indicate) ? "yes" : "no",
+ (cl->tech->transfer) ? "yes" : "no");
+ count_chan++;
+ }
++ AST_RWLIST_UNLOCK(&backends);
+
+- AST_RWLIST_UNLOCK(&channels);
+-
+ ast_cli(a->fd, "----------\n%d channel drivers registered.\n", count_chan);
+
+ return CLI_SUCCESS;
+@@ -254,12 +262,14 @@
+
+ wordlen = strlen(a->word);
+
+- AST_LIST_TRAVERSE(&backends, cl, list) {
++ AST_RWLIST_RDLOCK(&backends);
++ AST_RWLIST_TRAVERSE(&backends, cl, list) {
+ if (!strncasecmp(a->word, cl->tech->type, wordlen) && ++which > a->n) {
+ ret = ast_strdup(cl->tech->type);
+ break;
+ }
+ }
++ AST_RWLIST_UNLOCK(&backends);
+
+ return ret;
+ }
+@@ -283,9 +293,9 @@
+ if (a->argc != 4)
+ return CLI_SHOWUSAGE;
+
+- AST_RWLIST_RDLOCK(&channels);
++ AST_RWLIST_RDLOCK(&backends);
+
+- AST_LIST_TRAVERSE(&backends, cl, list) {
++ AST_RWLIST_TRAVERSE(&backends, cl, list) {
+ if (!strncasecmp(cl->tech->type, a->argv[3], strlen(cl->tech->type)))
+ break;
+ }
+@@ -293,7 +303,7 @@
+
+ if (!cl) {
+ ast_cli(a->fd, "\n%s is not a registered channel driver.\n", a->argv[3]);
+- AST_RWLIST_UNLOCK(&channels);
++ AST_RWLIST_UNLOCK(&backends);
+ return CLI_FAILURE;
+ }
+
+@@ -321,7 +331,8 @@
+
+ );
+
+- AST_RWLIST_UNLOCK(&channels);
++ AST_RWLIST_UNLOCK(&backends);
++
+ return CLI_SUCCESS;
+ }
+
+@@ -343,7 +354,7 @@
+ }
+
+ /*! \brief Datastore to put the linked list of ast_chan_trace and trace status */
+-const struct ast_datastore_info ast_chan_trace_datastore_info = {
++static const struct ast_datastore_info ast_chan_trace_datastore_info = {
+ .type = "ChanTrace",
+ .destroy = ast_chan_trace_destroy_cb
+ };
+@@ -469,7 +480,7 @@
+ return 1;
+ }
+
+-static int ast_check_hangup_locked(struct ast_channel *chan)
++int ast_check_hangup_locked(struct ast_channel *chan)
+ {
+ int res;
+ ast_channel_lock(chan);
+@@ -478,30 +489,28 @@
+ return res;
+ }
+
+-/*! \brief Initiate system shutdown */
++static int ast_channel_softhangup_cb(void *obj, void *arg, int flags)
++{
++ struct ast_channel *chan = obj;
++
++ ast_softhangup(chan, AST_SOFTHANGUP_SHUTDOWN);
++
++ return 0;
++}
++
+ void ast_begin_shutdown(int hangup)
+ {
+- struct ast_channel *c;
+ shutting_down = 1;
++
+ if (hangup) {
+- AST_RWLIST_RDLOCK(&channels);
+- AST_RWLIST_TRAVERSE(&channels, c, chan_list) {
+- ast_softhangup(c, AST_SOFTHANGUP_SHUTDOWN);
+- }
+- AST_RWLIST_UNLOCK(&channels);
++ ao2_callback(channels, OBJ_NODATA | OBJ_MULTIPLE, ast_channel_softhangup_cb, NULL);
+ }
+ }
+
+ /*! \brief returns number of active/allocated channels */
+ int ast_active_channels(void)
+ {
+- struct ast_channel *c;
+- int cnt = 0;
+- AST_RWLIST_RDLOCK(&channels);
+- AST_RWLIST_TRAVERSE(&channels, c, chan_list)
+- cnt++;
+- AST_RWLIST_UNLOCK(&channels);
+- return cnt;
++ return channels ? ao2_container_count(channels) : 0;
+ }
+
+ /*! \brief Cancel a shutdown in progress */
+@@ -557,28 +566,29 @@
+ {
+ struct chanlist *chan;
+
+- AST_RWLIST_WRLOCK(&channels);
++ AST_RWLIST_WRLOCK(&backends);
+
+- AST_LIST_TRAVERSE(&backends, chan, list) {
++ AST_RWLIST_TRAVERSE(&backends, chan, list) {
+ if (!strcasecmp(tech->type, chan->tech->type)) {
+ ast_log(LOG_WARNING, "Already have a handler for type '%s'\n", tech->type);
+- AST_RWLIST_UNLOCK(&channels);
++ AST_RWLIST_UNLOCK(&backends);
+ return -1;
+ }
+ }
+
+ if (!(chan = ast_calloc(1, sizeof(*chan)))) {
+- AST_RWLIST_UNLOCK(&channels);
++ AST_RWLIST_UNLOCK(&backends);
+ return -1;
+ }
+ chan->tech = tech;
+- AST_LIST_INSERT_HEAD(&backends, chan, list);
++ AST_RWLIST_INSERT_HEAD(&backends, chan, list);
+
+ ast_debug(1, "Registered handler for '%s' (%s)\n", chan->tech->type, chan->tech->description);
+
+ ast_verb(2, "Registered channel type '%s' (%s)\n", chan->tech->type, chan->tech->description);
+
+- AST_RWLIST_UNLOCK(&channels);
++ AST_RWLIST_UNLOCK(&backends);
++
+ return 0;
+ }
+
+@@ -589,9 +599,9 @@
+
+ ast_debug(1, "Unregistering channel type '%s'\n", tech->type);
+
+- AST_RWLIST_WRLOCK(&channels);
++ AST_RWLIST_WRLOCK(&backends);
+
+- AST_LIST_TRAVERSE_SAFE_BEGIN(&backends, chan, list) {
++ AST_RWLIST_TRAVERSE_SAFE_BEGIN(&backends, chan, list) {
+ if (chan->tech == tech) {
+ AST_LIST_REMOVE_CURRENT(list);
+ ast_free(chan);
+@@ -601,7 +611,7 @@
+ }
+ AST_LIST_TRAVERSE_SAFE_END;
+
+- AST_RWLIST_UNLOCK(&channels);
++ AST_RWLIST_UNLOCK(&backends);
+ }
+
+ /*! \brief Get handle to channel driver based on name */
+@@ -610,16 +620,16 @@
+ struct chanlist *chanls;
+ const struct ast_channel_tech *ret = NULL;
+
+- AST_RWLIST_RDLOCK(&channels);
++ AST_RWLIST_RDLOCK(&backends);
+
+- AST_LIST_TRAVERSE(&backends, chanls, list) {
++ AST_RWLIST_TRAVERSE(&backends, chanls, list) {
+ if (!strcasecmp(name, chanls->tech->type)) {
+ ret = chanls->tech;
+ break;
+ }
+ }
+
+- AST_RWLIST_UNLOCK(&channels);
++ AST_RWLIST_UNLOCK(&backends);
+
+ return ret;
+ }
+@@ -766,6 +776,8 @@
+ .description = "Null channel (should not see this)",
+ };
+
++static void ast_channel_destructor(void *obj);
++
+ /*! \brief Create a new channel structure */
+ static struct ast_channel * attribute_malloc __attribute__((format(printf, 12, 0)))
+ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char *cid_name,
+@@ -784,28 +796,40 @@
+ return NULL;
+ }
+
+-#if defined(__AST_DEBUG_MALLOC)
+- if (!(tmp = __ast_calloc(1, sizeof(*tmp), file, line, function))) {
++#if defined(REF_DEBUG)
++ if (!(tmp = __ao2_alloc_debug(sizeof(*tmp), ast_channel_destructor, "", file, line, function, 1))) {
+ return NULL;
+ }
++#elif defined(__AST_DEBUG_MALLOC)
++ if (!(tmp = __ao2_alloc_debug(sizeof(*tmp), ast_channel_destructor, "", file, line, function, 0))) {
++ return NULL;
++ }
+ #else
+- if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
++ if (!(tmp = ao2_alloc(sizeof(*tmp), ast_channel_destructor))) {
+ return NULL;
+ }
+ #endif
+
+ if (!(tmp->sched = sched_context_create())) {
+ ast_log(LOG_WARNING, "Channel allocation failed: Unable to create schedule context\n");
+- ast_free(tmp);
+- return NULL;
++ return ast_channel_unref(tmp);
+ }
+
+ if ((ast_string_field_init(tmp, 128))) {
+- sched_context_destroy(tmp->sched);
+- ast_free(tmp);
+- return NULL;
++ return ast_channel_unref(tmp);
+ }
+
++ if (cid_name) {
++ if (!(tmp->cid.cid_name = ast_strdup(cid_name))) {
++ return ast_channel_unref(tmp);
++ }
++ }
++ if (cid_num) {
++ if (!(tmp->cid.cid_num = ast_strdup(cid_num))) {
++ return ast_channel_unref(tmp);
++ }
++ }
++
+ #ifdef HAVE_EPOLL
+ tmp->epfd = epoll_create(25);
+ #endif
+@@ -834,6 +858,8 @@
+
+ sched_context_destroy(tmp->sched);
+ ast_string_field_free_memory(tmp);
++ ast_free(tmp->cid.cid_name);
++ ast_free(tmp->cid.cid_num);
+ ast_free(tmp);
+ return NULL;
+ } else {
+@@ -876,9 +902,6 @@
+ ast_string_field_build(tmp, uniqueid, "%s-%li.%d", ast_config_AST_SYSTEM_NAME,
+ (long) time(NULL), ast_atomic_fetchadd_int(&uniqueint, 1));
+ }
+-
+- tmp->cid.cid_name = ast_strdup(cid_name);
+- tmp->cid.cid_num = ast_strdup(cid_num);
+
+ if (!ast_strlen_zero(name_fmt)) {
+ /* Almost every channel is calling this function, and setting the name via the ast_string_field_build() call.
+@@ -923,17 +946,15 @@
+ headp = &tmp->varshead;
+ AST_LIST_HEAD_INIT_NOLOCK(headp);
+
+- ast_mutex_init(&tmp->lock_dont_use);
+-
+ AST_LIST_HEAD_INIT_NOLOCK(&tmp->datastores);
++
++ AST_LIST_HEAD_INIT_NOLOCK(&tmp->autochans);
+
+ ast_string_field_set(tmp, language, defaultlanguage);
+
+ tmp->tech = &null_tech;
+
+- AST_RWLIST_WRLOCK(&channels);
+- AST_RWLIST_INSERT_HEAD(&channels, tmp, chan_list);
+- AST_RWLIST_UNLOCK(&channels);
++ ao2_link(channels, tmp);
+
+ /*\!note
+ * and now, since the channel structure is built, and has its name, let's
+@@ -985,56 +1006,82 @@
+ return result;
+ }
+
+-/*! \brief Queue an outgoing media frame */
+-static int __ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin, int head)
++static int __ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin, int head, struct ast_frame *after)
+ {
+ struct ast_frame *f;
+ struct ast_frame *cur;
+ int blah = 1;
+- int qlen = 0;
++ unsigned int new_frames = 0;
++ unsigned int new_voice_frames = 0;
++ unsigned int queued_frames = 0;
++ unsigned int queued_voice_frames = 0;
++ AST_LIST_HEAD_NOLOCK(, ast_frame) frames;
+
+- /* Build us a copy and free the original one */
+- if (!(f = ast_frdup(fin))) {
+- return -1;
+- }
+-
+ ast_channel_lock(chan);
+
+ /* See if the last frame on the queue is a hangup, if so don't queue anything */
+- if ((cur = AST_LIST_LAST(&chan->readq)) && (cur->frametype == AST_FRAME_CONTROL) && (cur->subclass == AST_CONTROL_HANGUP)) {
+- ast_frfree(f);
++ if ((cur = AST_LIST_LAST(&chan->readq)) &&
++ (cur->frametype == AST_FRAME_CONTROL) &&
++ (cur->subclass == AST_CONTROL_HANGUP)) {
+ ast_channel_unlock(chan);
+ return 0;
+ }
+
++ /* Build copies of all the frames and count them */
++ AST_LIST_HEAD_INIT_NOLOCK(&frames);
++ for (cur = fin; cur; cur = AST_LIST_NEXT(cur, frame_list)) {
++ if (!(f = ast_frdup(cur))) {
++ ast_frfree(AST_LIST_FIRST(&frames));
++ return -1;
++ }
++
++ AST_LIST_INSERT_TAIL(&frames, f, frame_list);
++ new_frames++;
++ if (f->frametype == AST_FRAME_VOICE) {
++ new_voice_frames++;
++ }
++ }
++
+ /* Count how many frames exist on the queue */
+ AST_LIST_TRAVERSE(&chan->readq, cur, frame_list) {
+- qlen++;
++ queued_frames++;
++ if (cur->frametype == AST_FRAME_VOICE) {
++ queued_voice_frames++;
++ }
+ }
+
+- /* Allow up to 96 voice frames outstanding, and up to 128 total frames */
+- if (((fin->frametype == AST_FRAME_VOICE) && (qlen > 96)) || (qlen > 128)) {
+- if (fin->frametype != AST_FRAME_VOICE) {
+- ast_log(LOG_WARNING, "Exceptionally long queue length queuing to %s\n", chan->name);
+- ast_assert(fin->frametype == AST_FRAME_VOICE);
+- } else {
+- ast_debug(1, "Dropping voice to exceptionally long queue on %s\n", chan->name);
++ if ((queued_frames + new_frames) > 128) {
++ ast_log(LOG_WARNING, "Exceptionally long queue length queuing to %s\n", chan->name);
++ while ((f = AST_LIST_REMOVE_HEAD(&frames, frame_list))) {
+ ast_frfree(f);
+- ast_channel_unlock(chan);
+- return 0;
+ }
++ ast_channel_unlock(chan);
++ return 0;
+ }
+
+- if (head) {
+- AST_LIST_INSERT_HEAD(&chan->readq, f, frame_list);
++ if ((queued_voice_frames + new_voice_frames) > 96) {
++ ast_log(LOG_WARNING, "Exceptionally long voice queue length queuing to %s\n", chan->name);
++ while ((f = AST_LIST_REMOVE_HEAD(&frames, frame_list))) {
++ ast_frfree(f);
++ }
++ ast_channel_unlock(chan);
++ return 0;
++ }
++
++ if (after) {
++ AST_LIST_INSERT_LIST_AFTER(&chan->readq, &frames, after, frame_list);
+ } else {
+- AST_LIST_INSERT_TAIL(&chan->readq, f, frame_list);
++ if (head) {
++ AST_LIST_APPEND_LIST(&frames, &chan->readq, frame_list);
++ AST_LIST_HEAD_INIT_NOLOCK(&chan->readq);
++ }
++ AST_LIST_APPEND_LIST(&chan->readq, &frames, frame_list);
+ }
+
+ if (chan->alertpipe[1] > -1) {
+- if (write(chan->alertpipe[1], &blah, sizeof(blah)) != sizeof(blah)) {
+- ast_log(LOG_WARNING, "Unable to write to alert pipe on %s, frametype/subclass %d/%d (qlen = %d): %s!\n",
+- chan->name, f->frametype, f->subclass, qlen, strerror(errno));
++ if (write(chan->alertpipe[1], &blah, new_frames * sizeof(blah)) != (new_frames * sizeof(blah))) {
++ ast_log(LOG_WARNING, "Unable to write to alert pipe on %s (qlen = %d): %s!\n",
++ chan->name, queued_frames, strerror(errno));
+ }
+ } else if (chan->timingfd > -1) {
+ ast_timer_enable_continuous(chan->timer);
+@@ -1049,12 +1096,12 @@
+
+ int ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin)
+ {
+- return __ast_queue_frame(chan, fin, 0);
++ return __ast_queue_frame(chan, fin, 0, NULL);
+ }
+
+ int ast_queue_frame_head(struct ast_channel *chan, struct ast_frame *fin)
+ {
+- return __ast_queue_frame(chan, fin, 1);
++ return __ast_queue_frame(chan, fin, 1, NULL);
+ }
+
+ /*! \brief Queue a hangup frame for channel */
+@@ -1131,167 +1178,181 @@
+ ast_clear_flag(chan, AST_FLAG_DEFER_DTMF);
+ }
+
+-/*!
+- * \brief Helper function to find channels.
+- *
+- * It supports these modes:
+- *
+- * prev != NULL : get channel next in list after prev
+- * name != NULL : get channel with matching name
+- * name != NULL && namelen != 0 : get channel whose name starts with prefix
+- * exten != NULL : get channel whose exten or macroexten matches
+- * context != NULL && exten != NULL : get channel whose context or macrocontext
+- *
+- * It returns with the channel's lock held. If getting the individual lock fails,
+- * unlock and retry quickly up to 10 times, then give up.
+- *
+- * \note XXX Note that this code has cost O(N) because of the need to verify
+- * that the object is still on the global list.
+- *
+- * \note XXX also note that accessing fields (e.g. c->name in ast_log())
+- * can only be done with the lock held or someone could delete the
+- * object while we work on it. This causes some ugliness in the code.
+- * Note that removing the first ast_log() may be harmful, as it would
+- * shorten the retry period and possibly cause failures.
+- * We should definitely go for a better scheme that is deadlock-free.
+- */
+-static struct ast_channel *channel_find_locked(const struct ast_channel *prev,
+- const char *name, const int namelen,
+- const char *context, const char *exten)
++struct ast_channel *ast_channel_callback(ao2_callback_data_fn *cb_fn, void *arg,
++ void *data, int ao2_flags)
+ {
+- const char *msg = prev ? "deadlock" : "initial deadlock";
+- int retries;
+- struct ast_channel *c;
+- const struct ast_channel *_prev = prev;
++ return ao2_callback_data(channels, ao2_flags, cb_fn, arg, data);
++}
+
+- for (retries = 0; retries < 200; retries++) {
+- int done;
+- /* Reset prev on each retry. See note below for the reason. */
+- prev = _prev;
+- AST_RWLIST_RDLOCK(&channels);
+- AST_RWLIST_TRAVERSE(&channels, c, chan_list) {
+- if (prev) { /* look for last item, first, before any evaluation */
+- if (c != prev) /* not this one */
+- continue;
+- /* found, prepare to return c->next */
+- if ((c = AST_RWLIST_NEXT(c, chan_list)) == NULL) break;
+- /*!\note
+- * We're done searching through the list for the previous item.
+- * Any item after this point, we want to evaluate for a match.
+- * If we didn't set prev to NULL here, then we would only
+- * return matches for the first matching item (since the above
+- * "if (c != prev)" would not permit any other potential
+- * matches to reach the additional matching logic, below).
+- * Instead, it would just iterate until it once again found the
+- * original match, then iterate down to the end of the list and
+- * quit.
+- */
+- prev = NULL;
+- }
+- if (name) { /* want match by name */
+- if ((!namelen && strcasecmp(c->name, name) && strcmp(c->uniqueid, name)) ||
+- (namelen && strncasecmp(c->name, name, namelen)))
+- continue; /* name match failed */
+- } else if (exten) {
+- if (context && strcasecmp(c->context, context) &&
+- strcasecmp(c->macrocontext, context))
+- continue; /* context match failed */
+- if (strcasecmp(c->exten, exten) &&
+- strcasecmp(c->macroexten, exten))
+- continue; /* exten match failed */
+- }
+- /* if we get here, c points to the desired record */
+- break;
+- }
+- /* exit if chan not found or mutex acquired successfully */
+- /* this is slightly unsafe, as we _should_ hold the lock to access c->name */
+- done = c == NULL || ast_channel_trylock(c) == 0;
+- if (!done) {
+- ast_debug(1, "Avoiding %s for channel '%p'\n", msg, c);
+- if (retries == 199) {
+- /* We are about to fail due to a deadlock, so report this
+- * while we still have the list lock.
+- */
+- ast_debug(1, "Failure, could not lock '%p' after %d retries!\n", c, retries);
+- /* As we have deadlocked, we will skip this channel and
+- * see if there is another match.
+- * NOTE: No point doing this for a full-name match,
+- * as there can be no more matches.
+- */
+- if (!(name && !namelen)) {
+- prev = c;
+- retries = -1;
+- }
+- }
+- }
+- AST_RWLIST_UNLOCK(&channels);
+- if (done)
+- return c;
+- /* If we reach this point we basically tried to lock a channel and failed. Instead of
+- * starting from the beginning of the list we can restore our saved pointer to the previous
+- * channel and start from there.
+- */
+- prev = _prev;
+- usleep(1); /* give other threads a chance before retrying */
++struct ast_channel_iterator {
++ struct ao2_iterator i;
++ const char *name;
++ size_t name_len;
++ const char *exten;
++ const char *context;
++};
++
++struct ast_channel_iterator *ast_channel_iterator_destroy(struct ast_channel_iterator *i)
++{
++ if (i->name) {
++ ast_free((void *) i->name);
++ i->name = NULL;
+ }
+
++ if (i->exten) {
++ ast_free((void *) i->exten);
++ i->exten = NULL;
++ }
++
++ if (i->context) {
++ ast_free((void *) i->context);
++ i->context = NULL;
++ }
++
++ ast_free(i);
++
+ return NULL;
+ }
+
+-/*! \brief Browse channels in use */
+-struct ast_channel *ast_channel_walk_locked(const struct ast_channel *prev)
++static struct ast_channel_iterator *ast_channel_iterator_new(int ao2_flags, const char *name,
++ size_t name_len, const char *exten, const char *context)
+ {
+- return channel_find_locked(prev, NULL, 0, NULL, NULL);
++ struct ast_channel_iterator *i;
++
++ if (!(i = ast_calloc(1, sizeof(*i)))) {
++ return NULL;
++ }
++
++ if (!ast_strlen_zero(exten) && !(i->exten = ast_strdup(exten))) {
++ goto return_error;
++ }
++
++ if (!ast_strlen_zero(context) && !(i->context = ast_strdup(context))) {
++ goto return_error;
++ }
++
++ if (!ast_strlen_zero(name) && !(i->name = ast_strdup(name))) {
++ goto return_error;
++ }
++
++ i->name_len = name_len;
++
++ i->i = ao2_iterator_init(channels, ao2_flags);
++
++ return i;
++
++return_error:
++ if (i->exten) {
++ ast_free((void *) i->exten);
++ i->exten = NULL;
++ }
++
++ if (i->context) {
++ ast_free((void *) i->context);
++ i->context = NULL;
++ }
++
++ ast_free(i);
++
++ return NULL;
+ }
+
+-/*! \brief Get channel by name and lock it */
+-struct ast_channel *ast_get_channel_by_name_locked(const char *name)
++struct ast_channel_iterator *ast_channel_iterator_by_exten_new(int ao2_flags, const char *exten,
++ const char *context)
+ {
+- return channel_find_locked(NULL, name, 0, NULL, NULL);
++ return ast_channel_iterator_new(ao2_flags, NULL, 0, exten, context);
+ }
+
+-/*! \brief Get channel by name prefix and lock it */
+-struct ast_channel *ast_get_channel_by_name_prefix_locked(const char *name, const int namelen)
++struct ast_channel_iterator *ast_channel_iterator_by_name_new(int ao2_flags, const char *name,
++ size_t name_len)
+ {
+- return channel_find_locked(NULL, name, namelen, NULL, NULL);
++ return ast_channel_iterator_new(ao2_flags, name, name_len, NULL, NULL);
+ }
+
+-/*! \brief Get next channel by name prefix and lock it */
+-struct ast_channel *ast_walk_channel_by_name_prefix_locked(const struct ast_channel *chan, const char *name,
+- const int namelen)
++struct ast_channel_iterator *ast_channel_iterator_all_new(int ao2_flags)
+ {
+- return channel_find_locked(chan, name, namelen, NULL, NULL);
++ return ast_channel_iterator_new(ao2_flags, NULL, 0, NULL, NULL);
+ }
+
+-/*! \brief 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)
++/*!
++ * \note This function will be reduced to 1 line of code once ao2 supports
++ * returning multiple objects from an ao2_callback() using OBJ_MULTIPLE.
++ */
++struct ast_channel *ast_channel_iterator_next(struct ast_channel_iterator *i)
+ {
+- return channel_find_locked(NULL, NULL, 0, context, exten);
++ struct ast_channel *chan = NULL;
++
++ for (; (chan = ao2_iterator_next(&i->i));
++ ast_channel_unlock(chan), ast_channel_unref(chan)) {
++
++ ast_channel_lock(chan);
++
++ if (i->name) { /* match by name */
++ if (!i->name_len) {
++ if (strcasecmp(chan->name, i->name) && strcasecmp(chan->uniqueid, i->name)) {
++ continue; /* name match failed */
++ }
++ } else {
++ if (strncasecmp(chan->name, i->name, i->name_len) &&
++ strncasecmp(chan->uniqueid, i->name, i->name_len)) {
++ continue; /* name match failed */
++ }
++ }
++ } else if (i->exten) {
++ if (i->context && strcasecmp(chan->context, i->context) &&
++ strcasecmp(chan->macrocontext, i->context)) {
++ continue; /* context match failed */
++ }
++
++ if (strcasecmp(chan->exten, i->exten) &&
++ strcasecmp(chan->macroexten, i->exten)) {
++ continue; /* exten match failed */
++ }
++ }
++
++ ast_channel_unlock(chan);
++
++ break; /* chan points to the next chan desired. */
++ }
++
++ return chan;
+ }
+
+-/*! \brief Get next channel by exten (and optionally context) and lock it */
+-struct ast_channel *ast_walk_channel_by_exten_locked(const struct ast_channel *chan, const char *exten,
+- const char *context)
++static struct ast_channel *ast_channel_get_full(const char *name, size_t name_len,
++ const char *exten, const char *context)
+ {
+- return channel_find_locked(chan, NULL, 0, context, exten);
++ struct ast_channel tmp_chan = {
++ .name = name,
++ /* This is sort of a hack. Basically, we're using an arbitrary field
++ * in ast_channel to pass the name_len for a prefix match. If this
++ * gets changed, then the compare callback must be changed, too. */
++ .rings = name_len,
++ };
++
++ if (exten) {
++ ast_copy_string(tmp_chan.exten, exten, sizeof(tmp_chan.exten));
++ }
++
++ if (context) {
++ ast_copy_string(tmp_chan.context, context, sizeof(tmp_chan.context));
++ }
++
++ return ao2_find(channels, &tmp_chan, OBJ_POINTER);
+ }
+
+-/*! \brief Search for a channel based on the passed channel matching callback (first match) and return it, locked */
+-struct ast_channel *ast_channel_search_locked(int (*is_match)(struct ast_channel *, void *), void *data)
++struct ast_channel *ast_channel_get_by_name(const char *name)
+ {
+- struct ast_channel *c = NULL;
++ return ast_channel_get_full(name, 0, NULL, NULL);
++}
+
+- AST_RWLIST_RDLOCK(&channels);
+- AST_RWLIST_TRAVERSE(&channels, c, chan_list) {
+- ast_channel_lock(c);
+- if (is_match(c, data)) {
+- break;
+- }
+- ast_channel_unlock(c);
+- }
+- AST_RWLIST_UNLOCK(&channels);
++struct ast_channel *ast_channel_get_by_name_prefix(const char *name, size_t name_len)
++{
++ return ast_channel_get_full(name, name_len, NULL, NULL);
++}
+
+- return c;
++struct ast_channel *ast_channel_get_by_exten(const char *exten, const char *context)
++{
++ return ast_channel_get_full(NULL, 0, exten, context);
+ }
+
+ /*! \brief Wait, look for hangups and condition arg */
+@@ -1336,9 +1397,290 @@
+ cid->cid_dnid = cid->cid_num = cid->cid_name = cid->cid_ani = cid->cid_rdnis = NULL;
+ }
+
++struct ast_channel *ast_channel_release(struct ast_channel *chan)
++{
++ /* Safe, even if already unlinked. */
++ ao2_unlink(channels, chan);
++ return ast_channel_unref(chan);
++}
++
++/*!
++ * \internal
++ * \brief Initialize the given party id structure.
++ *
++ * \param init Party id structure to initialize.
++ *
++ * \return Nothing
++ */
++static void ast_party_id_init(struct ast_party_id *init)
++{
++ init->number = NULL;
++ init->name = NULL;
++ init->number_type = 0; /* Unknown */
++ init->number_presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
++}
++
++/*!
++ * \internal
++ * \brief Copy the source party id information to the destination party id.
++ *
++ * \param dest Destination party id
++ * \param src Source party id
++ *
++ * \return Nothing
++ */
++static void ast_party_id_copy(struct ast_party_id *dest, const struct ast_party_id *src)
++{
++ if (dest == src) {
++ /* Don't copy to self */
++ return;
++ }
++
++ if (dest->number) {
++ ast_free(dest->number);
++ }
++ dest->number = ast_strdup(src->number);
++
++ if (dest->name) {
++ ast_free(dest->name);
++ }
++ dest->name = ast_strdup(src->name);
++
++ dest->number_type = src->number_type;
++ dest->number_presentation = src->number_presentation;
++}
++
++/*!
++ * \internal
++ * \brief Initialize the given party id structure using the given guide
++ * for a set update operation.
++ *
++ * \details
++ * The initialization is needed to allow a set operation to know if a
++ * value needs to be updated. Simple integers need the guide's original
++ * value in case the set operation is not trying to set a new value.
++ * String values are simply set to NULL pointers if they are not going
++ * to be updated.
++ *
++ * \param init Party id structure to initialize.
++ * \param guide Source party id to use as a guide in initializing.
++ *
++ * \return Nothing
++ */
++static void ast_party_id_set_init(struct ast_party_id *init, const struct ast_party_id *guide)
++{
++ init->number = NULL;
++ init->name = NULL;
++ init->number_type = guide->number_type;
++ init->number_presentation = guide->number_presentation;
++}
++
++/*!
++ * \internal
++ * \brief Set the source party id information into the destination party id.
++ *
++ * \param dest Destination party id
++ * \param src Source party id
++ *
++ * \return Nothing
++ */
++static void ast_party_id_set(struct ast_party_id *dest, const struct ast_party_id *src)
++{
++ if (dest == src) {
++ /* Don't set to self */
++ return;
++ }
++
++ if (src->name && src->name != dest->name) {
++ if (dest->name) {
++ ast_free(dest->name);
++ }
++ dest->name = ast_strdup(src->name);
++ }
++
++ if (src->number && src->number != dest->number) {
++ if (dest->number) {
++ ast_free(dest->number);
++ }
++ dest->number = ast_strdup(src->number);
++ }
++
++ dest->number_type = src->number_type;
++ dest->number_presentation = src->number_presentation;
++}
++
++/*!
++ * \internal
++ * \brief Destroy the party id contents
++ *
++ * \param doomed The party id to destroy.
++ *
++ * \return Nothing
++ */
++static void ast_party_id_free(struct ast_party_id *doomed)
++{
++ if (doomed->number) {
++ ast_free(doomed->number);
++ doomed->number = NULL;
++ }
++
++ if (doomed->name) {
++ ast_free(doomed->name);
++ doomed->name = NULL;
++ }
++}
++
++void ast_party_caller_copy(struct ast_callerid *dest, const struct ast_callerid *src)
++{
++ if (dest == src) {
++ /* Don't copy to self */
++ return;
++ }
++
++#if 1
++ /* Copy caller-id specific information ONLY from struct ast_callerid */
++ if (dest->cid_num)
++ {
++ ast_free(dest->cid_num);
++ }
++ dest->cid_num = ast_strdup(src->cid_num);
++
++ if (dest->cid_name)
++ {
++ ast_free(dest->cid_name);
++ }
++ dest->cid_name = ast_strdup(src->cid_name);
++
++ dest->cid_ton = src->cid_ton;
++ dest->cid_pres = src->cid_pres;
++
++
++ if (dest->cid_ani)
++ {
++ ast_free(dest->cid_ani);
++ }
++ dest->cid_ani = ast_strdup(src->cid_ani);
++
++ dest->cid_ani2 = src->cid_ani2;
++
++#else
++
++ /* The src and dest parameter types will become struct ast_party_caller ptrs. */
++ /* This is future code */
++
++ ast_party_id_copy(&dest->id, &src->id);
++
++ if (dest->ani) {
++ ast_free(dest->ani);
++ }
++ dest->ani = ast_strdup(src->ani);
++
++ dest->ani2 = src->ani2;
++#endif
++}
++
++void ast_party_connected_line_init(struct ast_party_connected_line *init)
++{
++ ast_party_id_init(&init->id);
++ init->ani = NULL;
++ init->ani2 = 0;
++ init->source = AST_CONNECTED_LINE_UPDATE_SOURCE_UNKNOWN;
++}
++
++void ast_party_connected_line_copy(struct ast_party_connected_line *dest, const struct ast_party_connected_line *src)
++{
++ if (dest == src) {
++ /* Don't copy to self */
++ return;
++ }
++
++ ast_party_id_copy(&dest->id, &src->id);
++
++ if (dest->ani) {
++ ast_free(dest->ani);
++ }
++ dest->ani = ast_strdup(src->ani);
++
++ dest->ani2 = src->ani2;
++ dest->source = src->source;
++}
++
++void ast_party_connected_line_set_init(struct ast_party_connected_line *init, const struct ast_party_connected_line *guide)
++{
++ ast_party_id_set_init(&init->id, &guide->id);
++ init->ani = NULL;
++ init->ani2 = guide->ani2;
++ init->source = guide->source;
++}
++
++void ast_party_connected_line_set(struct ast_party_connected_line *dest, const struct ast_party_connected_line *src)
++{
++ ast_party_id_set(&dest->id, &src->id);
++
++ if (src->ani && src->ani != dest->ani) {
++ if (dest->ani) {
++ ast_free(dest->ani);
++ }
++ dest->ani = ast_strdup(src->ani);
++ }
++
++ dest->ani2 = src->ani2;
++ dest->source = src->source;
++}
++
++void ast_party_connected_line_collect_caller(struct ast_party_connected_line *connected, struct ast_callerid *cid)
++{
++ connected->id.number = cid->cid_num;
++ connected->id.name = cid->cid_name;
++ connected->id.number_type = cid->cid_ton;
++ connected->id.number_presentation = cid->cid_pres;
++
++ connected->ani = cid->cid_ani;
++ connected->ani2 = cid->cid_ani2;
++ connected->source = AST_CONNECTED_LINE_UPDATE_SOURCE_UNKNOWN;
++}
++
++void ast_party_connected_line_free(struct ast_party_connected_line *doomed)
++{
++ ast_party_id_free(&doomed->id);
++
++ if (doomed->ani) {
++ ast_free(doomed->ani);
++ doomed->ani = NULL;
++ }
++}
++
++void ast_party_redirecting_copy(struct ast_party_redirecting *dest, const struct ast_party_redirecting *src)
++{
++ if (dest == src) {
++ /* Don't copy to self */
++ return;
++ }
++
++ ast_party_id_copy(&dest->from, &src->from);
++ ast_party_id_copy(&dest->to, &src->to);
++ dest->count = src->count;
++ dest->reason = src->reason;
++}
++
++void ast_party_redirecting_set_init(struct ast_party_redirecting *init, const struct ast_party_redirecting *guide)
++{
++ ast_party_id_set_init(&init->from, &guide->from);
++ ast_party_id_set_init(&init->to, &guide->to);
++ init->count = guide->count;
++ init->reason = guide->reason;
++}
++
++void ast_party_redirecting_free(struct ast_party_redirecting *doomed)
++{
++ ast_party_id_free(&doomed->from);
++ ast_party_id_free(&doomed->to);
++}
++
+ /*! \brief Free a channel structure */
+-void ast_channel_free(struct ast_channel *chan)
++static void ast_channel_destructor(void *obj)
+ {
++ struct ast_channel *chan = obj;
+ int fd;
+ #ifdef HAVE_EPOLL
+ int i;
+@@ -1348,18 +1690,9 @@
+ struct varshead *headp;
+ struct ast_datastore *datastore = NULL;
+ char name[AST_CHANNEL_NAME], *dashptr;
+-
+- headp=&chan->varshead;
+-
+- AST_RWLIST_WRLOCK(&channels);
+- if (!AST_RWLIST_REMOVE(&channels, chan, chan_list)) {
+- ast_log(LOG_ERROR, "Unable to find channel in list to free. Assuming it has already been done.\n");
+- }
+- /* Lock and unlock the channel just to be sure nobody has it locked still
+- due to a reference retrieved from the channel list. */
+- ast_channel_lock(chan);
+- ast_channel_unlock(chan);
+
++ headp = &chan->varshead;
++
+ /* Get rid of each of the data stores on the channel */
+ while ((datastore = AST_LIST_REMOVE_HEAD(&chan->datastores, entry)))
+ /* Free the data store */
+@@ -1398,7 +1731,11 @@
+ ast_translator_free_path(chan->writetrans);
+ if (chan->pbx)
+ ast_log(LOG_WARNING, "PBX may not have been terminated properly on '%s'\n", chan->name);
++
+ free_cid(&chan->cid);
++ ast_party_connected_line_free(&chan->connected);
++ ast_party_redirecting_free(&chan->redirecting);
++
+ /* Close pipes if appropriate */
+ if ((fd = chan->alertpipe[0]) > -1)
+ close(fd);
+@@ -1437,11 +1774,7 @@
+ chan->zone = ast_tone_zone_unref(chan->zone);
+ }
+
+- ast_mutex_destroy(&chan->lock_dont_use);
+-
+ ast_string_field_free_memory(chan);
+- ast_free(chan);
+- AST_RWLIST_UNLOCK(&channels);
+
+ /* Queue an unknown state, because, while we know that this particular
+ * instance is dead, we don't know the state of all other possible
+@@ -1723,9 +2056,9 @@
+ ast_cdr_detach(chan->cdr);
+ chan->cdr = NULL;
+ }
+-
+- ast_channel_free(chan);
+
++ chan = ast_channel_release(chan);
++
+ return res;
+ }
+
+@@ -2420,6 +2753,8 @@
+ case AST_CONTROL_RINGING:
+ case AST_CONTROL_ANSWER:
+ case AST_CONTROL_SRCUPDATE:
++ case AST_CONTROL_CONNECTED_LINE:
++ case AST_CONTROL_REDIRECTING:
+ /* Unimportant */
+ break;
+ default:
+@@ -2720,13 +3055,14 @@
+ chan->fdno = -1;
+
+ if (f) {
++ struct ast_frame *readq_tail = AST_LIST_LAST(&chan->readq);
++
+ /* if the channel driver returned more than one frame, stuff the excess
+- into the readq for the next ast_read call (note that we can safely assume
+- that the readq is empty, because otherwise we would not have called into
+- the channel driver and f would be only a single frame)
++ into the readq for the next ast_read call
+ */
+ if (AST_LIST_NEXT(f, frame_list)) {
+- AST_LIST_HEAD_SET_NOLOCK(&chan->readq, AST_LIST_NEXT(f, frame_list));
++ ast_queue_frame(chan, AST_LIST_NEXT(f, frame_list));
++ ast_frfree(AST_LIST_NEXT(f, frame_list));
+ AST_LIST_NEXT(f, frame_list) = NULL;
+ }
+
+@@ -2946,12 +3282,30 @@
+ }
+ }
+
+- if (chan->readtrans && (f = ast_translate(chan->readtrans, f, 1)) == NULL)
++ if (chan->readtrans && (f = ast_translate(chan->readtrans, f, 1)) == NULL) {
+ f = &ast_null_frame;
+- else
+- /* Run generator sitting on the line if timing device not available
+- * and synchronous generation of outgoing frames is necessary */
+- ast_read_generator_actions(chan, f);
++ }
++
++ /* it is possible for the translation process on chan->readtrans to have
++ produced multiple frames from the single input frame we passed it; if
++ this happens, queue the additional frames *before* the frames we may
++ have queued earlier. if the readq was empty, put them at the head of
++ the queue, and if it was not, put them just after the frame that was
++ at the end of the queue.
++ */
++ if (AST_LIST_NEXT(f, frame_list)) {
++ if (!readq_tail) {
++ ast_queue_frame_head(chan, AST_LIST_NEXT(f, frame_list));
++ } else {
++ __ast_queue_frame(chan, AST_LIST_NEXT(f, frame_list), 0, readq_tail);
++ }
++ ast_frfree(AST_LIST_NEXT(f, frame_list));
++ AST_LIST_NEXT(f, frame_list) = NULL;
++ }
++
++ /* Run generator sitting on the line if timing device not available
++ * and synchronous generation of outgoing frames is necessary */
++ ast_read_generator_actions(chan, f);
+ }
+ default:
+ /* Just pass it on! */
+@@ -3022,7 +3376,10 @@
+ case AST_CONTROL_ANSWER:
+ case AST_CONTROL_HANGUP:
+ case AST_CONTROL_T38:
+- return 0;
++ case AST_CONTROL_CONNECTED_LINE:
++ case AST_CONTROL_REDIRECTING:
++ case AST_CONTROL_TRANSFER:
++ break;
+
+ case AST_CONTROL_CONGESTION:
+ case AST_CONTROL_BUSY:
+@@ -3043,7 +3400,7 @@
+ * in switch statements. */
+ enum ast_control_frame_type condition = _condition;
+ struct ast_tone_zone_sound *ts = NULL;
+- int res = -1;
++ int res;
+
+ ast_channel_lock(chan);
+
+@@ -3052,10 +3409,41 @@
+ ast_channel_unlock(chan);
+ return -1;
+ }
++ switch (condition) {
++ case AST_CONTROL_CONNECTED_LINE:
++ {
++ struct ast_party_connected_line connected;
+
++ ast_party_connected_line_set_init(&connected, &chan->connected);
++ res = ast_connected_line_parse_data(data, datalen, &connected);
++ if (!res) {
++ ast_channel_set_connected_line(chan, &connected);
++ }
++ ast_party_connected_line_free(&connected);
++ }
++ break;
++
++ case AST_CONTROL_REDIRECTING:
++ {
++ struct ast_party_redirecting redirecting;
++
++ ast_party_redirecting_set_init(&redirecting, &chan->redirecting);
++ res = ast_redirecting_parse_data(data, datalen, &redirecting);
++ if (!res) {
++ ast_channel_set_redirecting(chan, &redirecting);
++ }
++ ast_party_redirecting_free(&redirecting);
++ }
++ break;
++
++ default:
++ break;
++ }
+ if (chan->tech->indicate) {
+ /* See if the channel driver can handle this condition. */
+ res = chan->tech->indicate(chan, condition, data, datalen);
++ } else {
++ res = -1;
+ }
+
+ ast_channel_unlock(chan);
+@@ -3084,6 +3472,16 @@
+ switch (condition) {
+ case AST_CONTROL_RINGING:
+ ts = ast_get_indication_tone(chan->zone, "ring");
++ /* It is common practice for channel drivers to return -1 if trying
++ * to indicate ringing on a channel which is up. The idea is to let the
++ * core generate the ringing inband. However, we don't want the
++ * warning message about not being able to handle the specific indication
++ * to print nor do we want ast_indicate_data to return an "error" for this
++ * condition
++ */
++ if (chan->_state == AST_STATE_UP) {
++ res = 0;
++ }
+ break;
+ case AST_CONTROL_BUSY:
+ ts = ast_get_indication_tone(chan->zone, "busy");
+@@ -3108,6 +3506,9 @@
+ case AST_CONTROL_HOLD:
+ case AST_CONTROL_UNHOLD:
+ case AST_CONTROL_T38:
++ case AST_CONTROL_TRANSFER:
++ case AST_CONTROL_CONNECTED_LINE:
++ case AST_CONTROL_REDIRECTING:
+ /* Nothing left to do for these. */
+ res = 0;
+ break;
+@@ -3185,7 +3586,7 @@
+ {
+ /* Device does not support DTMF tones, lets fake
+ * it by doing our own generation. */
+- static const char* dtmf_tones[] = {
++ static const char * const dtmf_tones[] = {
+ "941+1336", /* 0 */
+ "697+1209", /* 1 */
+ "697+1336", /* 2 */
+@@ -3280,7 +3681,7 @@
+ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
+ {
+ int res = -1;
+- struct ast_frame *f = NULL, *f2 = NULL;
++ struct ast_frame *f = NULL;
+ int count = 0;
+
+ /*Deadlock avoidance*/
+@@ -3352,10 +3753,12 @@
+ break;
+ case AST_FRAME_DTMF_END:
+ if (chan->audiohooks) {
+- struct ast_frame *old_frame = fr;
+- fr = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_WRITE, fr);
+- if (old_frame != fr)
+- f = fr;
++ struct ast_frame *new_frame = fr;
++
++ new_frame = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_WRITE, fr);
++ if (new_frame != fr) {
++ ast_frfree(new_frame);
++ }
+ }
+ send_dtmf_event(chan, "Sent", fr->subclass, "No", "Yes");
+ ast_clear_flag(chan, AST_FLAG_BLOCKING);
+@@ -3390,14 +3793,6 @@
+ if (chan->tech->write == NULL)
+ break; /*! \todo XXX should return 0 maybe ? */
+
+- /* If audiohooks are present, write the frame out */
+- if (chan->audiohooks) {
+- struct ast_frame *old_frame = fr;
+- fr = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_WRITE, fr);
+- if (old_frame != fr)
+- f2 = fr;
+- }
+-
+ /* If the frame is in the raw write format, then it's easy... just use the frame - otherwise we will have to translate */
+ if (fr->subclass == chan->rawwriteformat)
+ f = fr;
+@@ -3409,37 +3804,82 @@
+ break;
+ }
+
++ if (chan->audiohooks) {
++ struct ast_frame *new_frame, *cur;
++
++ for (cur = f; cur; cur = AST_LIST_NEXT(cur, frame_list)) {
++ new_frame = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_WRITE, cur);
++ if (new_frame != cur) {
++ ast_frfree(new_frame);
++ }
++ }
++ }
++
+ /* If Monitor is running on this channel, then we have to write frames out there too */
++ /* the translator on chan->writetrans may have returned multiple frames
++ from the single frame we passed in; if so, feed each one of them to the
++ monitor */
+ if (chan->monitor && chan->monitor->write_stream) {
++ struct ast_frame *cur;
++
++ for (cur = f; cur; cur = AST_LIST_NEXT(cur, frame_list)) {
+ /* XXX must explain this code */
+ #ifndef MONITOR_CONSTANT_DELAY
+- int jump = chan->insmpl - chan->outsmpl - 4 * f->samples;
+- if (jump >= 0) {
+- jump = chan->insmpl - chan->outsmpl;
+- if (ast_seekstream(chan->monitor->write_stream, jump, SEEK_FORCECUR) == -1)
+- ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
+- chan->outsmpl += jump + f->samples;
+- } else
+- chan->outsmpl += f->samples;
++ int jump = chan->insmpl - chan->outsmpl - 4 * cur->samples;
++ if (jump >= 0) {
++ jump = chan->insmpl - chan->outsmpl;
++ if (ast_seekstream(chan->monitor->write_stream, jump, SEEK_FORCECUR) == -1)
++ ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
++ chan->outsmpl += jump + cur->samples;
++ } else {
++ chan->outsmpl += cur->samples;
++ }
+ #else
+- int jump = chan->insmpl - chan->outsmpl;
+- if (jump - MONITOR_DELAY >= 0) {
+- if (ast_seekstream(chan->monitor->write_stream, jump - f->samples, SEEK_FORCECUR) == -1)
+- ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
+- chan->outsmpl += jump;
+- } else
+- chan->outsmpl += f->samples;
++ int jump = chan->insmpl - chan->outsmpl;
++ if (jump - MONITOR_DELAY >= 0) {
++ if (ast_seekstream(chan->monitor->write_stream, jump - cur->samples, SEEK_FORCECUR) == -1)
++ ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
++ chan->outsmpl += jump;
++ } else {
++ chan->outsmpl += cur->samples;
++ }
+ #endif
+- if (chan->monitor->state == AST_MONITOR_RUNNING) {
+- if (ast_writestream(chan->monitor->write_stream, f) < 0)
+- ast_log(LOG_WARNING, "Failed to write data to channel monitor write stream\n");
++ if (chan->monitor->state == AST_MONITOR_RUNNING) {
++ if (ast_writestream(chan->monitor->write_stream, cur) < 0)
++ ast_log(LOG_WARNING, "Failed to write data to channel monitor write stream\n");
++ }
+ }
+ }
+
+- if (f)
+- res = chan->tech->write(chan,f);
+- else
+- res = 0;
++ /* the translator on chan->writetrans may have returned multiple frames
++ from the single frame we passed in; if so, feed each one of them to the
++ channel, freeing each one after it has been written */
++ if ((f != fr) && AST_LIST_NEXT(f, frame_list)) {
++ struct ast_frame *cur, *next;
++ unsigned int skip = 0;
++
++ for (cur = f, next = AST_LIST_NEXT(cur, frame_list);
++ cur;
++ cur = next, next = cur ? AST_LIST_NEXT(cur, frame_list) : NULL) {
++ if (!skip) {
++ if ((res = chan->tech->write(chan, cur)) < 0) {
++ chan->_softhangup |= AST_SOFTHANGUP_DEV;
++ skip = 1;
++ } else if (next) {
++ /* don't do this for the last frame in the list,
++ as the code outside the loop will do it once
++ */
++ chan->fout = FRAMECOUNT_INC(chan->fout);
++ }
++ }
++ ast_frfree(cur);
++ }
++
++ /* reset f so the code below doesn't attempt to free it */
++ f = NULL;
++ } else {
++ res = chan->tech->write(chan, f);
++ }
+ break;
+ case AST_FRAME_NULL:
+ case AST_FRAME_IAX:
+@@ -3456,13 +3896,12 @@
+
+ if (f && f != fr)
+ ast_frfree(f);
+- if (f2)
+- ast_frfree(f2);
+ ast_clear_flag(chan, AST_FLAG_BLOCKING);
++
+ /* Consider a write failure to force a soft hangup */
+- if (res < 0)
++ if (res < 0) {
+ chan->_softhangup |= AST_SOFTHANGUP_DEV;
+- else {
++ } else {
+ chan->fout = FRAMECOUNT_INC(chan->fout);
+ }
+ done:
+@@ -3473,7 +3912,7 @@
+ static int set_format(struct ast_channel *chan, int fmt, int *rawformat, int *format,
+ struct ast_trans_pvt **trans, const int direction)
+ {
+- int native;
++ int native, native_fmt = ast_best_codec(fmt);
+ int res;
+ char from[200], to[200];
+
+@@ -3484,7 +3923,19 @@
+
+ if (!fmt || !native) /* No audio requested */
+ return 0; /* Let's try a call without any sounds (video, text) */
+-
++
++ /* See if the underlying channel driver is capable of performing transcoding for us */
++ if (!ast_channel_setoption(chan, direction ? AST_OPTION_FORMAT_WRITE : AST_OPTION_FORMAT_READ, &native_fmt, sizeof(int*), 0)) {
++ ast_debug(1, "Channel driver natively set channel %s to %s format %s (%d)\n", chan->name,
++ direction ? "write" : "read", ast_getformatname(native_fmt), native_fmt);
++ chan->nativeformats = *rawformat = *format = native_fmt;
++ if (*trans) {
++ ast_translator_free_path(*trans);
++ }
++ *trans = NULL;
++ return 0;
++ }
++
+ /* Find a translation path from the native format to one of the desired formats */
+ if (!direction)
+ /* reading */
+@@ -3580,6 +4031,7 @@
+ {
+ char tmpchan[256];
+ struct ast_channel *new = NULL;
++ struct ast_party_redirecting *apr = &orig->redirecting;
+ char *data, *type;
+ int cause = 0;
+
+@@ -3604,6 +4056,8 @@
+ return NULL;
+ }
+
++ ast_channel_set_redirecting(new, apr);
++
+ /* Copy/inherit important information into new channel */
+ if (oh) {
+ if (oh->vars) {
+@@ -3613,6 +4067,7 @@
+ ast_set_callerid(new, oh->cid_num, oh->cid_name, oh->cid_num);
+ }
+ if (oh->parent_channel) {
++ ast_channel_update_redirecting(oh->parent_channel, apr);
+ ast_channel_inherit_variables(oh->parent_channel, new);
+ ast_channel_datastore_inherit(oh->parent_channel, new);
+ }
+@@ -3620,6 +4075,7 @@
+ ast_cdr_setaccount(new, oh->account);
+ }
+ } else if (caller) { /* no outgoing helper so use caller if avaliable */
++ ast_channel_update_redirecting(caller, apr);
+ ast_channel_inherit_variables(caller, new);
+ ast_channel_datastore_inherit(caller, new);
+ }
+@@ -3630,9 +4086,8 @@
+ }
+ ast_copy_flags(new->cdr, orig->cdr, AST_CDR_FLAG_ORIGINATED);
+ ast_string_field_set(new, accountcode, orig->accountcode);
+- if (!ast_strlen_zero(orig->cid.cid_num) && !ast_strlen_zero(new->cid.cid_name)) {
+- ast_set_callerid(new, orig->cid.cid_num, orig->cid.cid_name, orig->cid.cid_num);
+- }
++ ast_party_caller_copy(&new->cid, &orig->cid);
++ ast_party_connected_line_copy(&new->connected, &orig->connected);
+ ast_channel_unlock(new);
+ ast_channel_unlock(orig);
+
+@@ -3655,6 +4110,7 @@
+ struct ast_channel *chan;
+ int res = 0;
+ int last_subclass = 0;
++ struct ast_party_connected_line connected;
+
+ if (outstate)
+ *outstate = 0;
+@@ -3681,8 +4137,14 @@
+ if (oh->account)
+ ast_cdr_setaccount(chan, oh->account);
+ }
++
+ ast_set_callerid(chan, cid_num, cid_name, cid_num);
+ ast_set_flag(chan->cdr, AST_CDR_FLAG_ORIGINATED);
++ ast_party_connected_line_set_init(&connected, &chan->connected);
++ connected.id.number = (char *) cid_num;
++ connected.id.name = (char *) cid_name;
++ connected.id.number_presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
++ ast_channel_set_connected_line(chan, &connected);
+
+ if (ast_call(chan, data, 0)) { /* ast_call failed... */
+ ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
+@@ -3728,6 +4190,8 @@
+ case AST_CONTROL_UNHOLD:
+ case AST_CONTROL_VIDUPDATE:
+ case AST_CONTROL_SRCUPDATE:
++ case AST_CONTROL_CONNECTED_LINE:
++ case AST_CONTROL_REDIRECTING:
+ case -1: /* Ignore -- just stopping indications */
+ break;
+
+@@ -3794,12 +4258,12 @@
+ cause = &foo;
+ *cause = AST_CAUSE_NOTDEFINED;
+
+- if (AST_RWLIST_RDLOCK(&channels)) {
+- ast_log(LOG_WARNING, "Unable to lock channel list\n");
++ if (AST_RWLIST_RDLOCK(&backends)) {
++ ast_log(LOG_WARNING, "Unable to lock technology backend list\n");
+ return NULL;
+ }
+
+- AST_LIST_TRAVERSE(&backends, chan, list) {
++ AST_RWLIST_TRAVERSE(&backends, chan, list) {
+ if (strcasecmp(type, chan->tech->type))
+ continue;
+
+@@ -3813,11 +4277,11 @@
+ if (res < 0) {
+ ast_log(LOG_WARNING, "No translator path exists for channel type %s (native 0x%x) to 0x%x\n", type, chan->tech->capabilities, format);
+ *cause = AST_CAUSE_BEARERCAPABILITY_NOTAVAIL;
+- AST_RWLIST_UNLOCK(&channels);
++ AST_RWLIST_UNLOCK(&backends);
+ return NULL;
+ }
+ }
+- AST_RWLIST_UNLOCK(&channels);
++ AST_RWLIST_UNLOCK(&backends);
+ if (!chan->tech->requester)
+ return NULL;
+
+@@ -3830,7 +4294,7 @@
+
+ ast_log(LOG_WARNING, "No channel type registered for '%s'\n", type);
+ *cause = AST_CAUSE_NOSUCHDRIVER;
+- AST_RWLIST_UNLOCK(&channels);
++ AST_RWLIST_UNLOCK(&backends);
+
+ return NULL;
+ }
+@@ -3876,6 +4340,37 @@
+ res = 0;
+ }
+ ast_channel_unlock(chan);
++
++ if (res < 0) {
++ return res;
++ }
++
++ for (;;) {
++ struct ast_frame *fr;
++
++ res = ast_waitfor(chan, -1);
++
++ if (res < 0 || !(fr = ast_read(chan))) {
++ res = -1;
++ break;
++ }
++
++ if (fr->frametype == AST_FRAME_CONTROL && fr->subclass == AST_CONTROL_TRANSFER) {
++ enum ast_control_transfer *message = fr->data.ptr;
++
++ if (*message == AST_TRANSFER_SUCCESS) {
++ res = 1;
++ } else {
++ res = -1;
++ }
++
++ ast_frfree(fr);
++ break;
++ }
++
++ ast_frfree(fr);
++ }
++
+ return res;
+ }
+
+@@ -3955,6 +4450,12 @@
+ int src;
+ int dst;
+
++ /* See if the channel driver can natively make these two channels compatible */
++ if (from->tech->bridge && from->tech->bridge == to->tech->bridge &&
++ !ast_channel_setoption(from, AST_OPTION_MAKE_COMPATIBLE, to, sizeof(struct ast_channel *), 0)) {
++ return 0;
++ }
++
+ if (from->readformat == to->writeformat && from->writeformat == to->readformat) {
+ /* Already compatible! Moving on ... */
+ return 0;
+@@ -4087,10 +4588,16 @@
+ return res;
+ }
+
+-void ast_change_name(struct ast_channel *chan, char *newname)
++void ast_change_name(struct ast_channel *chan, const char *newname)
+ {
++ /* We must re-link, as the hash value will change here. */
++ ao2_unlink(channels, chan);
++
+ manager_event(EVENT_FLAG_CALL, "Rename", "Channel: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", chan->name, newname, chan->uniqueid);
++
+ ast_string_field_set(chan, name, newname);
++
++ ao2_link(channels, chan);
+ }
+
+ void ast_channel_inherit_variables(const struct ast_channel *parent, struct ast_channel *child)
+@@ -4160,6 +4667,26 @@
+ }
+
+ /*!
++ * \pre chan is locked
++ */
++static void report_new_callerid(const struct ast_channel *chan)
++{
++ manager_event(EVENT_FLAG_CALL, "NewCallerid",
++ "Channel: %s\r\n"
++ "CallerIDNum: %s\r\n"
++ "CallerIDName: %s\r\n"
++ "Uniqueid: %s\r\n"
++ "CID-CallingPres: %d (%s)\r\n",
++ chan->name,
++ S_OR(chan->cid.cid_num, ""),
++ S_OR(chan->cid.cid_name, ""),
++ chan->uniqueid,
++ chan->cid.cid_pres,
++ ast_describe_caller_presentation(chan->cid.cid_pres)
++ );
++}
++
++/*!
+ \brief Masquerade a channel
+
+ \note Assumes channel will be locked when called
+@@ -4172,7 +4699,11 @@
+ struct ast_frame *current;
+ const struct ast_channel_tech *t;
+ void *t_pvt;
+- struct ast_callerid tmpcid;
++ union {
++ struct ast_callerid cid;
++ struct ast_party_connected_line connected;
++ struct ast_party_redirecting redirecting;
++ } exchange;
+ struct ast_channel *clonechan = original->masq;
+ struct ast_cdr *cdr;
+ int rformat = original->readformat;
+@@ -4182,12 +4713,6 @@
+ char masqn[AST_CHANNEL_NAME];
+ char zombn[AST_CHANNEL_NAME];
+
+- ast_debug(4, "Actually Masquerading %s(%d) into the structure of %s(%d)\n",
+- clonechan->name, clonechan->_state, original->name, original->_state);
+-
+- manager_event(EVENT_FLAG_CALL, "Masquerade", "Clone: %s\r\nCloneState: %s\r\nOriginal: %s\r\nOriginalState: %s\r\n",
+- clonechan->name, ast_state2str(clonechan->_state), original->name, ast_state2str(original->_state));
+-
+ /* XXX This is a seriously wacked out operation. We're essentially putting the guts of
+ the clone channel into the original channel. Start by killing off the original
+ channel's backend. I'm not sure we're going to keep this function, because
+@@ -4196,34 +4721,33 @@
+ /* We need the clone's lock, too */
+ ast_channel_lock(clonechan);
+
+- ast_debug(2, "Got clone lock for masquerade on '%s' at %p\n", clonechan->name, &clonechan->lock_dont_use);
++ ast_debug(4, "Actually Masquerading %s(%d) into the structure of %s(%d)\n",
++ clonechan->name, clonechan->_state, original->name, original->_state);
+
++ manager_event(EVENT_FLAG_CALL, "Masquerade", "Clone: %s\r\nCloneState: %s\r\nOriginal: %s\r\nOriginalState: %s\r\n",
++ clonechan->name, ast_state2str(clonechan->_state), original->name, ast_state2str(original->_state));
++
+ /* Having remembered the original read/write formats, we turn off any translation on either
+ one */
+ free_translation(clonechan);
+ free_translation(original);
+
+-
+ /* Unlink the masquerade */
+ original->masq = NULL;
+ clonechan->masqr = NULL;
+-
++
+ /* Save the original name */
+ ast_copy_string(orig, original->name, sizeof(orig));
+ /* Save the new name */
+ ast_copy_string(newn, clonechan->name, sizeof(newn));
+ /* Create the masq name */
+ snprintf(masqn, sizeof(masqn), "%s<MASQ>", newn);
+-
++
+ /* Copy the name from the clone channel */
+- ast_string_field_set(original, name, newn);
++ ast_change_name(original, newn);
+
+ /* Mangle the name of the clone channel */
+- ast_string_field_set(clonechan, name, masqn);
+-
+- /* Notify any managers of the change, first the masq then the other */
+- manager_event(EVENT_FLAG_CALL, "Rename", "Channel: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", newn, masqn, clonechan->uniqueid);
+- manager_event(EVENT_FLAG_CALL, "Rename", "Channel: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", orig, newn, original->uniqueid);
++ ast_change_name(clonechan, masqn);
+
+ /* Swap the technologies */
+ t = original->tech;
+@@ -4309,10 +4833,9 @@
+ return -1;
+ }
+
++ /* Mangle the name of the clone channel */
+ snprintf(zombn, sizeof(zombn), "%s<ZOMBIE>", orig);
+- /* Mangle the name of the clone channel */
+- ast_string_field_set(clonechan, name, zombn);
+- manager_event(EVENT_FLAG_CALL, "Rename", "Channel: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", masqn, zombn, clonechan->uniqueid);
++ ast_change_name(clonechan, zombn);
+
+ /* Update the type. */
+ t_pvt = original->monitor;
+@@ -4332,13 +4855,19 @@
+ /* Move data stores over */
+ if (AST_LIST_FIRST(&clonechan->datastores)) {
+ struct ast_datastore *ds;
+- AST_LIST_TRAVERSE(&clonechan->datastores, ds, entry) {
++ /* We use a safe traversal here because some fixup routines actually
++ * remove the datastore from the list and free them.
++ */
++ AST_LIST_TRAVERSE_SAFE_BEGIN(&clonechan->datastores, ds, entry) {
+ if (ds->info->chan_fixup)
+ ds->info->chan_fixup(ds->data, clonechan, original);
+ }
++ AST_LIST_TRAVERSE_SAFE_END;
+ AST_LIST_APPEND_LIST(&original->datastores, &clonechan->datastores, entry);
+ }
+
++ ast_autochan_new_channel(clonechan, original);
++
+ clone_variables(original, clonechan);
+ /* Presense of ADSI capable CPE follows clone */
+ original->adsicpe = clonechan->adsicpe;
+@@ -4353,12 +4882,22 @@
+ /* Stream stuff stays the same */
+ /* Keep the original state. The fixup code will need to work with it most likely */
+
+- /* Just swap the whole structures, nevermind the allocations, they'll work themselves
+- out. */
+- tmpcid = original->cid;
++ /*
++ * Just swap the whole structures, nevermind the allocations,
++ * they'll work themselves out.
++ */
++ exchange.cid = original->cid;
+ original->cid = clonechan->cid;
+- clonechan->cid = tmpcid;
++ clonechan->cid = exchange.cid;
++ report_new_callerid(original);
+
++ exchange.connected = original->connected;
++ original->connected = clonechan->connected;
++ clonechan->connected = exchange.connected;
++ exchange.redirecting = original->redirecting;
++ original->redirecting = clonechan->redirecting;
++ clonechan->redirecting = exchange.redirecting;
++
+ /* Restore original timing file descriptor */
+ ast_channel_set_fd(original, AST_TIMING_FD, original->timingfd);
+
+@@ -4404,7 +4943,7 @@
+ if (original->visible_indication) {
+ ast_indicate(original, original->visible_indication);
+ }
+-
++
+ /* Now, at this point, the "clone" channel is totally F'd up. We mark it as
+ a zombie so nothing tries to touch it. If it's already been marked as a
+ zombie, then free it now (since it already is considered invalid). */
+@@ -4421,7 +4960,7 @@
+ clonechan->hangupcause,
+ ast_cause2str(clonechan->hangupcause)
+ );
+- ast_channel_free(clonechan);
++ clonechan = ast_channel_release(clonechan);
+ } else {
+ ast_debug(1, "Released clone lock on '%s'\n", clonechan->name);
+ ast_set_flag(clonechan, AST_FLAG_ZOMBIE);
+@@ -4455,20 +4994,9 @@
+ ast_free(chan->cid.cid_ani);
+ chan->cid.cid_ani = ast_strdup(cid_ani);
+ }
+- manager_event(EVENT_FLAG_CALL, "NewCallerid",
+- "Channel: %s\r\n"
+- "CallerIDNum: %s\r\n"
+- "CallerIDName: %s\r\n"
+- "Uniqueid: %s\r\n"
+- "CID-CallingPres: %d (%s)\r\n",
+- chan->name,
+- S_OR(chan->cid.cid_num, ""),
+- S_OR(chan->cid.cid_name, ""),
+- chan->uniqueid,
+- chan->cid.cid_pres,
+- ast_describe_caller_presentation(chan->cid.cid_pres)
+- );
+-
++
++ report_new_callerid(chan);
++
+ ast_channel_unlock(chan);
+ }
+
+@@ -4555,7 +5083,7 @@
+
+ static enum ast_bridge_result ast_generic_bridge(struct ast_channel *c0, struct ast_channel *c1,
+ struct ast_bridge_config *config, struct ast_frame **fo,
+- struct ast_channel **rc, struct timeval bridge_end)
++ struct ast_channel **rc)
+ {
+ /* Copy voice back and forth between the two channels. */
+ struct ast_channel *cs[3];
+@@ -4588,11 +5116,10 @@
+ ast_poll_channel_add(c0, c1);
+
+ if (config->feature_timer > 0 && ast_tvzero(config->nexteventts)) {
+- /* calculate when the bridge should possibly break
++ /* nexteventts is not set when the bridge is not scheduled to
++ * break, so calculate when the bridge should possibly break
+ * if a partial feature match timed out */
+- config->partialfeature_timer = ast_tvadd(ast_tvnow(), ast_samp2tv(config->feature_timer, 1000));
+- } else {
+- memset(&config->partialfeature_timer, 0, sizeof(config->partialfeature_timer));
++ config->nexteventts = ast_tvadd(ast_tvnow(), ast_samp2tv(config->feature_timer, 1000));
+ }
+
+ for (;;) {
+@@ -4605,13 +5132,17 @@
+ res = AST_BRIDGE_RETRY;
+ break;
+ }
+- if (bridge_end.tv_sec) {
+- to = ast_tvdiff_ms(bridge_end, ast_tvnow());
++ if (config->nexteventts.tv_sec) {
++ to = ast_tvdiff_ms(config->nexteventts, ast_tvnow());
+ if (to <= 0) {
+- if (config->timelimit) {
++ if (config->timelimit && !config->feature_timer && !ast_test_flag(config, AST_FEATURE_WARNING_ACTIVE)) {
+ res = AST_BRIDGE_RETRY;
+ /* generic bridge ending to play warning */
+ ast_set_flag(config, AST_FEATURE_WARNING_ACTIVE);
++ } else if (config->feature_timer) {
++ /* feature timer expired - make sure we do not play warning */
++ ast_clear_flag(config, AST_FEATURE_WARNING_ACTIVE);
++ res = AST_BRIDGE_RETRY;
+ } else {
+ res = AST_BRIDGE_COMPLETE;
+ }
+@@ -4622,8 +5153,8 @@
+ * to not break, leave the channel bridge when the feature timer
+ * time has elapsed so the DTMF will be sent to the other side.
+ */
+- if (!ast_tvzero(config->partialfeature_timer)) {
+- int diff = ast_tvdiff_ms(config->partialfeature_timer, ast_tvnow());
++ if (!ast_tvzero(config->nexteventts)) {
++ int diff = ast_tvdiff_ms(config->nexteventts, ast_tvnow());
+ if (diff <= 0) {
+ res = AST_BRIDGE_RETRY;
+ break;
+@@ -4667,11 +5198,19 @@
+ int bridge_exit = 0;
+
+ switch (f->subclass) {
++ case AST_CONTROL_REDIRECTING:
++ ast_indicate_data(other, f->subclass, f->data.ptr, f->datalen);
++ break;
++ case AST_CONTROL_CONNECTED_LINE:
++ if (ast_channel_connected_line_macro(who, other, f, other == c0, 1)) {
++ ast_indicate_data(other, f->subclass, f->data.ptr, f->datalen);
++ }
++ break;
+ case AST_CONTROL_HOLD:
+ case AST_CONTROL_UNHOLD:
+ case AST_CONTROL_VIDUPDATE:
++ case AST_CONTROL_T38:
+ case AST_CONTROL_SRCUPDATE:
+- case AST_CONTROL_T38:
+ ast_indicate_data(other, f->subclass, f->data.ptr, f->datalen);
+ if (jb_in_use) {
+ ast_jb_empty_and_reset(c0, c1);
+@@ -4698,8 +5237,8 @@
+ /* monitored dtmf causes exit from bridge */
+ int monitored_source = (who == c0) ? watch_c0_dtmf : watch_c1_dtmf;
+
+- if (monitored_source &&
+- (f->frametype == AST_FRAME_DTMF_END ||
++ if (monitored_source &&
++ (f->frametype == AST_FRAME_DTMF_END ||
+ f->frametype == AST_FRAME_DTMF_BEGIN)) {
+ *fo = f;
+ *rc = who;
+@@ -4753,13 +5292,13 @@
+ {
+ manager_event(EVENT_FLAG_CALL, "Bridge",
+ "Bridgestate: %s\r\n"
+- "Bridgetype: %s\r\n"
+- "Channel1: %s\r\n"
+- "Channel2: %s\r\n"
+- "Uniqueid1: %s\r\n"
+- "Uniqueid2: %s\r\n"
+- "CallerID1: %s\r\n"
+- "CallerID2: %s\r\n",
++ "Bridgetype: %s\r\n"
++ "Channel1: %s\r\n"
++ "Channel2: %s\r\n"
++ "Uniqueid1: %s\r\n"
++ "Uniqueid2: %s\r\n"
++ "CallerID1: %s\r\n"
++ "CallerID2: %s\r\n",
+ onoff ? "Link" : "Unlink",
+ type == 1 ? "core" : "native",
+ c0->name, c1->name, c0->uniqueid, c1->uniqueid,
+@@ -4838,7 +5377,6 @@
+ struct ast_channel *who = NULL;
+ enum ast_bridge_result res = AST_BRIDGE_COMPLETE;
+ int nativefailed=0;
+- int firstpass;
+ int o0nativeformats;
+ int o1nativeformats;
+ long time_left_ms=0;
+@@ -4862,21 +5400,17 @@
+ return -1;
+
+ *fo = NULL;
+- firstpass = config->firstpass;
+- config->firstpass = 0;
+
+- if (ast_tvzero(config->start_time))
++ if (ast_tvzero(config->start_time)) {
+ config->start_time = ast_tvnow();
+- time_left_ms = config->timelimit;
+-
+- caller_warning = ast_test_flag(&config->features_caller, AST_FEATURE_PLAY_WARNING);
+- callee_warning = ast_test_flag(&config->features_callee, AST_FEATURE_PLAY_WARNING);
+-
+- if (config->start_sound && firstpass) {
+- if (caller_warning)
+- bridge_playfile(c0, c1, config->start_sound, time_left_ms / 1000);
+- if (callee_warning)
+- bridge_playfile(c1, c0, config->start_sound, time_left_ms / 1000);
++ if (config->start_sound) {
++ if (caller_warning) {
++ bridge_playfile(c0, c1, config->start_sound, config->timelimit / 1000);
++ }
++ if (callee_warning) {
++ bridge_playfile(c1, c0, config->start_sound, config->timelimit / 1000);
++ }
++ }
+ }
+
+ /* Keep track of bridge */
+@@ -4888,11 +5422,26 @@
+ o1nativeformats = c1->nativeformats;
+
+ if (config->feature_timer && !ast_tvzero(config->nexteventts)) {
+- config->nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->feature_timer, 1000));
+- } else if (config->timelimit && firstpass) {
++ config->nexteventts = ast_tvadd(config->feature_start_time, ast_samp2tv(config->feature_timer, 1000));
++ } else if (config->timelimit) {
++ time_left_ms = config->timelimit - ast_tvdiff_ms(ast_tvnow(), config->start_time);
++ caller_warning = ast_test_flag(&config->features_caller, AST_FEATURE_PLAY_WARNING);
++ callee_warning = ast_test_flag(&config->features_callee, AST_FEATURE_PLAY_WARNING);
+ config->nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->timelimit, 1000));
+- if (caller_warning || callee_warning)
+- config->nexteventts = ast_tvsub(config->nexteventts, ast_samp2tv(config->play_warning, 1000));
++ if ((caller_warning || callee_warning) && config->play_warning) {
++ long next_warn = config->play_warning;
++ if (time_left_ms < config->play_warning) {
++ /* At least one warning was played, which means we are returning after feature */
++ long warns_passed = (config->play_warning - time_left_ms) / config->warning_freq;
++ /* It is 'warns_passed * warning_freq' NOT '(warns_passed + 1) * warning_freq',
++ because nexteventts will be updated once again in the 'if (!to)' block */
++ next_warn = config->play_warning - warns_passed * config->warning_freq;
++ }
++ config->nexteventts = ast_tvsub(config->nexteventts, ast_samp2tv(next_warn, 1000));
++ }
++ } else {
++ config->nexteventts.tv_sec = 0;
++ config->nexteventts.tv_usec = 0;
+ }
+
+ if (!c0->tech->send_digit_begin)
+@@ -4948,10 +5497,12 @@
+ if (callee_warning)
+ bridge_playfile(c1, c0, config->warning_sound, t);
+ }
+- if (config->warning_freq && (time_left_ms > (config->warning_freq + 5000)))
++
++ if (config->warning_freq && (time_left_ms > (config->warning_freq + 5000))) {
+ config->nexteventts = ast_tvadd(config->nexteventts, ast_samp2tv(config->warning_freq, 1000));
+- else
++ } else {
+ config->nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->timelimit, 1000));
++ }
+ }
+ ast_clear_flag(config, AST_FEATURE_WARNING_ACTIVE);
+ }
+@@ -4996,7 +5547,6 @@
+ ast_set_flag(c0, AST_FLAG_NBRIDGE);
+ ast_set_flag(c1, AST_FLAG_NBRIDGE);
+ if ((res = c0->tech->bridge(c0, c1, config->flags, fo, rc, to)) == AST_BRIDGE_COMPLETE) {
+- /* \todo XXX here should check that cid_num is not NULL */
+ manager_event(EVENT_FLAG_CALL, "Unlink",
+ "Channel1: %s\r\n"
+ "Channel2: %s\r\n"
+@@ -5004,7 +5554,7 @@
+ "Uniqueid2: %s\r\n"
+ "CallerID1: %s\r\n"
+ "CallerID2: %s\r\n",
+- c0->name, c1->name, c0->uniqueid, c1->uniqueid, c0->cid.cid_num, c1->cid.cid_num);
++ c0->name, c1->name, c0->uniqueid, c1->uniqueid, S_OR(c0->cid.cid_num, "<unknown>"), S_OR(c1->cid.cid_num, "<unknown>"));
+ ast_debug(1, "Returning from native bridge, channels: %s, %s\n", c0->name, c1->name);
+
+ ast_clear_flag(c0, AST_FLAG_NBRIDGE);
+@@ -5050,7 +5600,7 @@
+
+ update_bridge_vars(c0, c1);
+
+- res = ast_generic_bridge(c0, c1, config, fo, rc, config->nexteventts);
++ res = ast_generic_bridge(c0, c1, config, fo, rc);
+ if (res != AST_BRIDGE_RETRY) {
+ break;
+ } else if (config->feature_timer) {
+@@ -5069,7 +5619,6 @@
+ c0->_bridge = NULL;
+ c1->_bridge = NULL;
+
+- /* \todo XXX here should check that cid_num is not NULL */
+ manager_event(EVENT_FLAG_CALL, "Unlink",
+ "Channel1: %s\r\n"
+ "Channel2: %s\r\n"
+@@ -5077,7 +5626,7 @@
+ "Uniqueid2: %s\r\n"
+ "CallerID1: %s\r\n"
+ "CallerID2: %s\r\n",
+- c0->name, c1->name, c0->uniqueid, c1->uniqueid, c0->cid.cid_num, c1->cid.cid_num);
++ c0->name, c1->name, c0->uniqueid, c1->uniqueid, S_OR(c0->cid.cid_num, "<unknown>"), S_OR(c1->cid.cid_num, "<unknown>"));
+ ast_debug(1, "Bridge stops bridging channels %s and %s\n", c0->name, c1->name);
+
+ return res;
+@@ -5338,8 +5887,58 @@
+ ast_moh_cleanup_ptr(chan);
+ }
+
++static int ast_channel_hash_cb(const void *obj, const int flags)
++{
++ const struct ast_channel *chan = obj;
++
++ /* If the name isn't set, return 0 so that the ao2_find() search will
++ * start in the first bucket. */
++ if (ast_strlen_zero(chan->name)) {
++ return 0;
++ }
++
++ return ast_str_case_hash(chan->name);
++}
++
++static int ast_channel_cmp_cb(void *obj, void *arg, int flags)
++{
++ struct ast_channel *chan = obj, *cmp_args = arg;
++ size_t name_len;
++ int ret = CMP_MATCH;
++
++ /* This is sort of a hack. Basically, we're using an arbitrary field
++ * in ast_channel to pass the name_len for a prefix match. If this
++ * gets changed, then the uses of ao2_find() must be changed, too. */
++ name_len = cmp_args->rings;
++
++ ast_channel_lock(chan);
++
++ if (cmp_args->name) { /* match by name */
++ if ((!name_len && strcasecmp(chan->name, cmp_args->name)) ||
++ (name_len && strncasecmp(chan->name, cmp_args->name, name_len))) {
++ ret = 0; /* name match failed */
++ }
++ } else if (cmp_args->exten) {
++ if (cmp_args->context && strcasecmp(chan->context, cmp_args->context) &&
++ strcasecmp(chan->macrocontext, cmp_args->context)) {
++ ret = 0; /* context match failed */
++ }
++ if (ret && strcasecmp(chan->exten, cmp_args->exten) &&
++ strcasecmp(chan->macroexten, cmp_args->exten)) {
++ ret = 0; /* exten match failed */
++ }
++ }
++
++ ast_channel_unlock(chan);
++
++ return ret;
++}
++
+ void ast_channels_init(void)
+ {
++ channels = ao2_container_alloc(NUM_CHANNEL_BUCKETS,
++ ast_channel_hash_cb, ast_channel_cmp_cb);
++
+ ast_cli_register_multiple(cli_channel, ARRAY_LEN(cli_channel));
+ }
+
+@@ -5474,116 +6073,6 @@
+ }
+ };
+
+-#ifdef DEBUG_CHANNEL_LOCKS
+-
+-/*! \brief Unlock AST channel (and print debugging output)
+-\note You need to enable DEBUG_CHANNEL_LOCKS for this function
+-*/
+-int __ast_channel_unlock(struct ast_channel *chan, const char *filename, int lineno, const char *func)
+-{
+- int res = 0;
+- ast_debug(3, "::::==== Unlocking AST channel %s\n", chan->name);
+-
+- if (!chan) {
+- ast_debug(1, "::::==== Unlocking non-existing channel \n");
+- return 0;
+- }
+-#ifdef DEBUG_THREADS
+- res = __ast_pthread_mutex_unlock(filename, lineno, func, "(channel lock)", &chan->lock_dont_use);
+-#else
+- res = ast_mutex_unlock(&chan->lock_dont_use);
+-#endif
+-
+- if (option_debug > 2) {
+-#ifdef DEBUG_THREADS
+- int count = 0;
+- if ((count = chan->lock_dont_use.track.reentrancy))
+- ast_debug(3, ":::=== Still have %d locks (recursive)\n", count);
+-#endif
+- if (!res)
+- ast_debug(3, "::::==== Channel %s was unlocked\n", chan->name);
+- if (res == EINVAL) {
+- ast_debug(3, "::::==== Channel %s had no lock by this thread. Failed unlocking\n", chan->name);
+- }
+- }
+- if (res == EPERM) {
+- /* We had no lock, so okay any way*/
+- ast_debug(4, "::::==== Channel %s was not locked at all \n", chan->name);
+- res = 0;
+- }
+- return res;
+-}
+-
+-/*! \brief Lock AST channel (and print debugging output)
+-\note You need to enable DEBUG_CHANNEL_LOCKS for this function */
+-int __ast_channel_lock(struct ast_channel *chan, const char *filename, int lineno, const char *func)
+-{
+- int res;
+-
+- ast_debug(4, "====:::: Locking AST channel %s\n", chan->name);
+-
+-#ifdef DEBUG_THREADS
+- res = __ast_pthread_mutex_lock(filename, lineno, func, "(channel lock)", &chan->lock_dont_use);
+-#else
+- res = ast_mutex_lock(&chan->lock_dont_use);
+-#endif
+-
+- if (option_debug > 3) {
+-#ifdef DEBUG_THREADS
+- int count = 0;
+- if ((count = chan->lock_dont_use.track.reentrancy))
+- ast_debug(4, ":::=== Now have %d locks (recursive)\n", count);
+-#endif
+- if (!res)
+- ast_debug(4, "::::==== Channel %s was locked\n", chan->name);
+- if (res == EDEADLK) {
+- /* We had no lock, so okey any way */
+- ast_debug(4, "::::==== Channel %s was not locked by us. Lock would cause deadlock.\n", chan->name);
+- }
+- if (res == EINVAL) {
+- ast_debug(4, "::::==== Channel %s lock failed. No mutex.\n", chan->name);
+- }
+- }
+- return res;
+-}
+-
+-/*! \brief Lock AST channel (and print debugging output)
+-\note You need to enable DEBUG_CHANNEL_LOCKS for this function */
+-int __ast_channel_trylock(struct ast_channel *chan, const char *filename, int lineno, const char *func)
+-{
+- int res;
+-
+- ast_debug(3, "====:::: Trying to lock AST channel %s\n", chan->name);
+-#ifdef DEBUG_THREADS
+- res = __ast_pthread_mutex_trylock(filename, lineno, func, "(channel lock)", &chan->lock_dont_use);
+-#else
+- res = ast_mutex_trylock(&chan->lock_dont_use);
+-#endif
+-
+- if (option_debug > 2) {
+-#ifdef DEBUG_THREADS
+- int count = 0;
+- if ((count = chan->lock_dont_use.track.reentrancy))
+- ast_debug(3, ":::=== Now have %d locks (recursive)\n", count);
+-#endif
+- if (!res)
+- ast_debug(3, "::::==== Channel %s was locked\n", chan->name);
+- if (res == EBUSY) {
+- /* We failed to lock */
+- ast_debug(3, "::::==== Channel %s failed to lock. Not waiting around...\n", chan->name);
+- }
+- if (res == EDEADLK) {
+- /* We had no lock, so okey any way*/
+- ast_debug(3, "::::==== Channel %s was not locked. Lock would cause deadlock.\n", chan->name);
+- }
+- if (res == EINVAL)
+- ast_debug(3, "::::==== Channel %s lock failed. No mutex.\n", chan->name);
+- }
+- return res;
+-}
+-
+-#endif
+-
+ /*
+ * Wrappers for various ast_say_*() functions that call the full version
+ * of the same functions.
+@@ -5638,6 +6127,616 @@
+ return ast_say_digit_str_full(chan, buf, ints, lang, audiofd, ctrlfd);
+ }
+
++void ast_connected_line_copy_from_caller(struct ast_party_connected_line *dest, const struct ast_callerid *src)
++{
++#if 1
++ /* Must manually fill in struct ast_party_id until struct ast_callerid goes away */
++ if (dest->id.number) {
++ ast_free(dest->id.number);
++ }
++ dest->id.number = ast_strdup(src->cid_num);
++
++ if (dest->id.name) {
++ ast_free(dest->id.name);
++ }
++ dest->id.name = ast_strdup(src->cid_name);
++
++ dest->id.number_type = src->cid_ton;
++ dest->id.number_presentation = src->cid_pres;
++
++
++ if (dest->ani) {
++ ast_free(dest->ani);
++ }
++ dest->ani = ast_strdup(src->cid_ani);
++
++ dest->ani2 = src->cid_ani2;
++
++#else
++
++ /* The src parameter type will become a struct ast_party_caller ptr. */
++ /* This is future code */
++
++ ast_party_id_copy(&dest->id, &src->id);
++
++ if (dest->ani) {
++ ast_free(dest->ani);
++ }
++ dest->ani = ast_strdup(src->ani);
++
++ dest->ani2 = src->ani2;
++#endif
++}
++
++void ast_connected_line_copy_to_caller(struct ast_callerid *dest, const struct ast_party_connected_line *src)
++{
++#if 1
++ /* Must manually extract from struct ast_party_id until struct ast_callerid goes away */
++ if (dest->cid_num) {
++ ast_free(dest->cid_num);
++ }
++ dest->cid_num = ast_strdup(src->id.number);
++
++ if (dest->cid_name) {
++ ast_free(dest->cid_name);
++ }
++ dest->cid_name = ast_strdup(src->id.name);
++
++ dest->cid_ton = src->id.number_type;
++ dest->cid_pres = src->id.number_presentation;
++
++
++ if (dest->cid_ani) {
++ ast_free(dest->cid_ani);
++ }
++ dest->cid_ani = ast_strdup(src->ani);
++
++ dest->cid_ani2 = src->ani2;
++
++#else
++
++ /* The dest parameter type will become a struct ast_party_caller ptr. */
++ /* This is future code */
++
++ ast_party_id_copy(&dest->id, &src->id);
++
++ if (dest->ani) {
++ ast_free(dest->ani);
++ }
++ dest->ani = ast_strdup(src->ani);
++
++ dest->ani2 = src->ani2;
++#endif
++}
++
++void ast_channel_set_connected_line(struct ast_channel *chan, const struct ast_party_connected_line *connected)
++{
++ if (&chan->connected == connected) {
++ /* Don't set to self */
++ return;
++ }
++
++ ast_channel_lock(chan);
++ ast_party_connected_line_set(&chan->connected, connected);
++ ast_channel_unlock(chan);
++}
++
++/*!
++ * \brief Element identifiers for connected line indication frame data
++ * \note Only add to the end of this enum.
++ */
++enum {
++ AST_CONNECTED_LINE_NUMBER,
++ AST_CONNECTED_LINE_NAME,
++ AST_CONNECTED_LINE_NUMBER_TYPE,
++ AST_CONNECTED_LINE_NUMBER_PRESENTATION,
++ AST_CONNECTED_LINE_SOURCE
++};
++
++int ast_connected_line_build_data(unsigned char *data, size_t datalen, const struct ast_party_connected_line *connected)
++{
++ int32_t value;
++ size_t length;
++ size_t pos = 0;
++
++ /*
++ * The size of integer values must be fixed in case the frame is
++ * shipped to another machine.
++ */
++
++ /* *************** Connected line party id *************** */
++ if (connected->id.number) {
++ length = strlen(connected->id.number);
++ if (datalen < pos + (sizeof(data[0]) * 2) + length) {
++ ast_log(LOG_WARNING, "No space left for connected line number\n");
++ return -1;
++ }
++ data[pos++] = AST_CONNECTED_LINE_NUMBER;
++ data[pos++] = length;
++ memcpy(data + pos, connected->id.number, length);
++ pos += length;
++ }
++
++ if (connected->id.name) {
++ length = strlen(connected->id.name);
++ if (datalen < pos + (sizeof(data[0]) * 2) + length) {
++ ast_log(LOG_WARNING, "No space left for connected line name\n");
++ return -1;
++ }
++ data[pos++] = AST_CONNECTED_LINE_NAME;
++ data[pos++] = length;
++ memcpy(data + pos, connected->id.name, length);
++ pos += length;
++ }
++
++ if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
++ ast_log(LOG_WARNING, "No space left for connected line type of number\n");
++ return -1;
++ }
++ data[pos++] = AST_CONNECTED_LINE_NUMBER_TYPE;
++ data[pos++] = 1;
++ data[pos++] = connected->id.number_type;
++
++ if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
++ ast_log(LOG_WARNING, "No space left for connected line presentation\n");
++ return -1;
++ }
++ data[pos++] = AST_CONNECTED_LINE_NUMBER_PRESENTATION;
++ data[pos++] = 1;
++ data[pos++] = connected->id.number_presentation;
++
++ /* Connected line source */
++ if (datalen < pos + (sizeof(data[0]) * 2) + sizeof(value)) {
++ ast_log(LOG_WARNING, "No space left for connected line source\n");
++ return -1;
++ }
++ data[pos++] = AST_CONNECTED_LINE_SOURCE;
++ data[pos++] = sizeof(value);
++ value = htonl(connected->source);
++ memcpy(data + pos, &value, sizeof(value));
++ pos += sizeof(value);
++
++ return pos;
++}
++
++int ast_connected_line_parse_data(const unsigned char *data, size_t datalen, struct ast_party_connected_line *connected)
++{
++ size_t pos;
++ unsigned char ie_len;
++ unsigned char ie_id;
++ int32_t value;
++
++ for (pos = 0; pos < datalen; pos += ie_len) {
++ if (datalen < pos + sizeof(ie_id) + sizeof(ie_len)) {
++ ast_log(LOG_WARNING, "Invalid connected line update\n");
++ return -1;
++ }
++ ie_id = data[pos++];
++ ie_len = data[pos++];
++ if (datalen < pos + ie_len) {
++ ast_log(LOG_WARNING, "Invalid connected line update\n");
++ return -1;
++ }
++
++ switch (ie_id) {
++ case AST_CONNECTED_LINE_NUMBER:
++ if (connected->id.number) {
++ ast_free(connected->id.number);
++ }
++ connected->id.number = ast_malloc(ie_len + 1);
++ if (connected->id.number) {
++ memcpy(connected->id.number, data + pos, ie_len);
++ connected->id.number[ie_len] = 0;
++ }
++ break;
++ case AST_CONNECTED_LINE_NAME:
++ if (connected->id.name) {
++ ast_free(connected->id.name);
++ }
++ connected->id.name = ast_malloc(ie_len + 1);
++ if (connected->id.name) {
++ memcpy(connected->id.name, data + pos, ie_len);
++ connected->id.name[ie_len] = 0;
++ }
++ break;
++ case AST_CONNECTED_LINE_NUMBER_TYPE:
++ if (ie_len != 1) {
++ ast_log(LOG_WARNING, "Invalid connected line type of number (%u)\n", (unsigned) ie_len);
++ break;
++ }
++ connected->id.number_type = data[pos];
++ break;
++ case AST_CONNECTED_LINE_NUMBER_PRESENTATION:
++ if (ie_len != 1) {
++ ast_log(LOG_WARNING, "Invalid connected line presentation (%u)\n", (unsigned) ie_len);
++ break;
++ }
++ connected->id.number_presentation = data[pos];
++ break;
++ case AST_CONNECTED_LINE_SOURCE:
++ if (ie_len != sizeof(value)) {
++ ast_log(LOG_WARNING, "Invalid connected line source (%u)\n", (unsigned) ie_len);
++ break;
++ }
++ memcpy(&value, data + pos, sizeof(value));
++ connected->source = ntohl(value);
++ break;
++ default:
++ ast_log(LOG_DEBUG, "Unknown connected line element: %u (%u)\n", (unsigned) ie_id, (unsigned) ie_len);
++ break;
++ }
++ }
++
++ return 0;
++}
++
++void ast_channel_update_connected_line(struct ast_channel *chan, const struct ast_party_connected_line *connected)
++{
++ unsigned char data[1024]; /* This should be large enough */
++ size_t datalen;
++
++ datalen = ast_connected_line_build_data(data, sizeof(data), connected);
++ if (datalen == (size_t) -1) {
++ return;
++ }
++
++ ast_indicate_data(chan, AST_CONTROL_CONNECTED_LINE, data, datalen);
++}
++
++void ast_channel_queue_connected_line_update(struct ast_channel *chan, const struct ast_party_connected_line *connected)
++{
++ unsigned char data[1024]; /* This should be large enough */
++ size_t datalen;
++
++ datalen = ast_connected_line_build_data(data, sizeof(data), connected);
++ if (datalen == (size_t) -1) {
++ return;
++ }
++
++ ast_queue_control_data(chan, AST_CONTROL_CONNECTED_LINE, data, datalen);
++}
++
++void ast_channel_set_redirecting(struct ast_channel *chan, const struct ast_party_redirecting *redirecting)
++{
++ if (&chan->redirecting == redirecting) {
++ /* Don't set to self */
++ return;
++ }
++
++ ast_channel_lock(chan);
++
++ ast_party_id_set(&chan->redirecting.from, &redirecting->from);
++ if (redirecting->from.number
++ && redirecting->from.number != chan->redirecting.from.number) {
++ /*
++ * Must move string to ast_channel.cid.cid_rdnis until it goes away.
++ */
++ if (chan->cid.cid_rdnis) {
++ ast_free(chan->cid.cid_rdnis);
++ }
++ chan->cid.cid_rdnis = chan->redirecting.from.number;
++ chan->redirecting.from.number = NULL;
++ }
++
++ ast_party_id_set(&chan->redirecting.to, &redirecting->to);
++ chan->redirecting.reason = redirecting->reason;
++ chan->redirecting.count = redirecting->count;
++
++ ast_channel_unlock(chan);
++}
++
++/*!
++ * \brief Element identifiers for redirecting indication frame data
++ * \note Only add to the end of this enum.
++ */
++enum {
++ AST_REDIRECTING_FROM_NUMBER,
++ AST_REDIRECTING_FROM_NAME,
++ AST_REDIRECTING_FROM_NUMBER_TYPE,
++ AST_REDIRECTING_FROM_NUMBER_PRESENTATION,
++ AST_REDIRECTING_TO_NUMBER,
++ AST_REDIRECTING_TO_NAME,
++ AST_REDIRECTING_TO_NUMBER_TYPE,
++ AST_REDIRECTING_TO_NUMBER_PRESENTATION,
++ AST_REDIRECTING_REASON,
++ AST_REDIRECTING_COUNT
++};
++
++int ast_redirecting_build_data(unsigned char *data, size_t datalen, const struct ast_party_redirecting *redirecting)
++{
++ int32_t value;
++ size_t length;
++ size_t pos = 0;
++
++ /*
++ * The size of integer values must be fixed in case the frame is
++ * shipped to another machine.
++ */
++
++ /* *************** Redirecting from party id *************** */
++ if (redirecting->from.number) {
++ length = strlen(redirecting->from.number);
++ if (datalen < pos + (sizeof(data[0]) * 2) + length) {
++ ast_log(LOG_WARNING, "No space left for redirecting from number\n");
++ return -1;
++ }
++ data[pos++] = AST_REDIRECTING_FROM_NUMBER;
++ data[pos++] = length;
++ memcpy(data + pos, redirecting->from.number, length);
++ pos += length;
++ }
++
++ if (redirecting->from.name) {
++ length = strlen(redirecting->from.name);
++ if (datalen < pos + (sizeof(data[0]) * 2) + length) {
++ ast_log(LOG_WARNING, "No space left for redirecting from name\n");
++ return -1;
++ }
++ data[pos++] = AST_REDIRECTING_FROM_NAME;
++ data[pos++] = length;
++ memcpy(data + pos, redirecting->from.name, length);
++ pos += length;
++ }
++
++ if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
++ ast_log(LOG_WARNING, "No space left for redirecting from type of number\n");
++ return -1;
++ }
++ data[pos++] = AST_REDIRECTING_FROM_NUMBER_TYPE;
++ data[pos++] = 1;
++ data[pos++] = redirecting->from.number_type;
++
++ if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
++ ast_log(LOG_WARNING, "No space left for redirecting from presentation\n");
++ return -1;
++ }
++ data[pos++] = AST_REDIRECTING_FROM_NUMBER_PRESENTATION;
++ data[pos++] = 1;
++ data[pos++] = redirecting->from.number_presentation;
++
++ /* *************** Redirecting to party id *************** */
++ if (redirecting->to.number) {
++ length = strlen(redirecting->to.number);
++ if (datalen < pos + (sizeof(data[0]) * 2) + length) {
++ ast_log(LOG_WARNING, "No space left for redirecting to number\n");
++ return -1;
++ }
++ data[pos++] = AST_REDIRECTING_TO_NUMBER;
++ data[pos++] = length;
++ memcpy(data + pos, redirecting->to.number, length);
++ pos += length;
++ }
++
++ if (redirecting->to.name) {
++ length = strlen(redirecting->to.name);
++ if (datalen < pos + (sizeof(data[0]) * 2) + length) {
++ ast_log(LOG_WARNING, "No space left for redirecting to name\n");
++ return -1;
++ }
++ data[pos++] = AST_REDIRECTING_TO_NAME;
++ data[pos++] = length;
++ memcpy(data + pos, redirecting->to.name, length);
++ pos += length;
++ }
++
++ if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
++ ast_log(LOG_WARNING, "No space left for redirecting to type of number\n");
++ return -1;
++ }
++ data[pos++] = AST_REDIRECTING_TO_NUMBER_TYPE;
++ data[pos++] = 1;
++ data[pos++] = redirecting->to.number_type;
++
++ if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
++ ast_log(LOG_WARNING, "No space left for redirecting to presentation\n");
++ return -1;
++ }
++ data[pos++] = AST_REDIRECTING_TO_NUMBER_PRESENTATION;
++ data[pos++] = 1;
++ data[pos++] = redirecting->to.number_presentation;
++
++ /* Redirecting reason */
++ if (datalen < pos + (sizeof(data[0]) * 2) + sizeof(value)) {
++ ast_log(LOG_WARNING, "No space left for redirecting reason\n");
++ return -1;
++ }
++ data[pos++] = AST_REDIRECTING_REASON;
++ data[pos++] = sizeof(value);
++ value = htonl(redirecting->reason);
++ memcpy(data + pos, &value, sizeof(value));
++ pos += sizeof(value);
++
++ /* Redirecting count */
++ if (datalen < pos + (sizeof(data[0]) * 2) + sizeof(value)) {
++ ast_log(LOG_WARNING, "No space left for redirecting count\n");
++ return -1;
++ }
++ data[pos++] = AST_REDIRECTING_COUNT;
++ data[pos++] = sizeof(value);
++ value = htonl(redirecting->count);
++ memcpy(data + pos, &value, sizeof(value));
++ pos += sizeof(value);
++
++ return pos;
++}
++
++int ast_redirecting_parse_data(const unsigned char *data, size_t datalen, struct ast_party_redirecting *redirecting)
++{
++ size_t pos;
++ unsigned char ie_len;
++ unsigned char ie_id;
++ int32_t value;
++
++ for (pos = 0; pos < datalen; pos += ie_len) {
++ if (datalen < pos + sizeof(ie_id) + sizeof(ie_len)) {
++ ast_log(LOG_WARNING, "Invalid redirecting update\n");
++ return -1;
++ }
++ ie_id = data[pos++];
++ ie_len = data[pos++];
++ if (datalen < pos + ie_len) {
++ ast_log(LOG_WARNING, "Invalid redirecting update\n");
++ return -1;
++ }
++
++ switch (ie_id) {
++ case AST_REDIRECTING_FROM_NUMBER:
++ if (redirecting->from.number) {
++ ast_free(redirecting->from.number);
++ }
++ redirecting->from.number = ast_malloc(ie_len + 1);
++ if (redirecting->from.number) {
++ memcpy(redirecting->from.number, data + pos, ie_len);
++ redirecting->from.number[ie_len] = 0;
++ }
++ break;
++ case AST_REDIRECTING_FROM_NAME:
++ if (redirecting->from.name) {
++ ast_free(redirecting->from.name);
++ }
++ redirecting->from.name = ast_malloc(ie_len + 1);
++ if (redirecting->from.name) {
++ memcpy(redirecting->from.name, data + pos, ie_len);
++ redirecting->from.name[ie_len] = 0;
++ }
++ break;
++ case AST_REDIRECTING_FROM_NUMBER_TYPE:
++ if (ie_len != 1) {
++ ast_log(LOG_WARNING, "Invalid redirecting from type of number (%u)\n", (unsigned) ie_len);
++ break;
++ }
++ redirecting->from.number_type = data[pos];
++ break;
++ case AST_REDIRECTING_FROM_NUMBER_PRESENTATION:
++ if (ie_len != 1) {
++ ast_log(LOG_WARNING, "Invalid redirecting from presentation (%u)\n", (unsigned) ie_len);
++ break;
++ }
++ redirecting->from.number_presentation = data[pos];
++ break;
++ case AST_REDIRECTING_TO_NUMBER:
++ if (redirecting->to.number) {
++ ast_free(redirecting->to.number);
++ }
++ redirecting->to.number = ast_malloc(ie_len + 1);
++ if (redirecting->to.number) {
++ memcpy(redirecting->to.number, data + pos, ie_len);
++ redirecting->to.number[ie_len] = 0;
++ }
++ break;
++ case AST_REDIRECTING_TO_NAME:
++ if (redirecting->to.name) {
++ ast_free(redirecting->to.name);
++ }
++ redirecting->to.name = ast_malloc(ie_len + 1);
++ if (redirecting->to.name) {
++ memcpy(redirecting->to.name, data + pos, ie_len);
++ redirecting->to.name[ie_len] = 0;
++ }
++ break;
++ case AST_REDIRECTING_TO_NUMBER_TYPE:
++ if (ie_len != 1) {
++ ast_log(LOG_WARNING, "Invalid redirecting to type of number (%u)\n", (unsigned) ie_len);
++ break;
++ }
++ redirecting->to.number_type = data[pos];
++ break;
++ case AST_REDIRECTING_TO_NUMBER_PRESENTATION:
++ if (ie_len != 1) {
++ ast_log(LOG_WARNING, "Invalid redirecting to presentation (%u)\n", (unsigned) ie_len);
++ break;
++ }
++ redirecting->to.number_presentation = data[pos];
++ break;
++ case AST_REDIRECTING_REASON:
++ if (ie_len != sizeof(value)) {
++ ast_log(LOG_WARNING, "Invalid redirecting reason (%u)\n", (unsigned) ie_len);
++ break;
++ }
++ memcpy(&value, data + pos, sizeof(value));
++ redirecting->reason = ntohl(value);
++ break;
++ case AST_REDIRECTING_COUNT:
++ if (ie_len != sizeof(value)) {
++ ast_log(LOG_WARNING, "Invalid redirecting count (%u)\n", (unsigned) ie_len);
++ break;
++ }
++ memcpy(&value, data + pos, sizeof(value));
++ redirecting->count = ntohl(value);
++ break;
++ default:
++ ast_log(LOG_DEBUG, "Unknown redirecting element: %u (%u)\n", (unsigned) ie_id, (unsigned) ie_len);
++ break;
++ }
++ }
++
++ return 0;
++}
++
++void ast_channel_update_redirecting(struct ast_channel *chan, const struct ast_party_redirecting *redirecting)
++{
++ unsigned char data[1024]; /* This should be large enough */
++ size_t datalen;
++
++ datalen = ast_redirecting_build_data(data, sizeof(data), redirecting);
++ if (datalen == (size_t) -1) {
++ return;
++ }
++
++ ast_indicate_data(chan, AST_CONTROL_REDIRECTING, data, datalen);
++}
++
++void ast_channel_queue_redirecting_update(struct ast_channel *chan, const struct ast_party_redirecting *redirecting)
++{
++ unsigned char data[1024]; /* This should be large enough */
++ size_t datalen;
++
++ datalen = ast_redirecting_build_data(data, sizeof(data), redirecting);
++ if (datalen == (size_t) -1) {
++ return;
++ }
++
++ ast_queue_control_data(chan, AST_CONTROL_REDIRECTING, data, datalen);
++}
++
++int ast_channel_connected_line_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *connected_info, int caller, int frame)
++{
++ const char *macro;
++ const char *macro_args;
++ union {
++ const struct ast_frame *frame;
++ const struct ast_party_connected_line *connected;
++ } pointer;
++ int retval;
++
++ if (frame) {
++ pointer.frame = connected_info;
++ } else {
++ pointer.connected = connected_info;
++ }
++
++ ast_channel_lock(macro_chan);
++ macro = ast_strdupa(S_OR(pbx_builtin_getvar_helper(macro_chan, caller ? "CONNECTED_LINE_CALLER_SEND_MACRO" : "CONNECTED_LINE_CALLEE_SEND_MACRO"), ""));
++ macro_args = ast_strdupa(S_OR(pbx_builtin_getvar_helper(macro_chan, caller ? "CONNECTED_LINE_CALLER_SEND_MACRO_ARGS" : "CONNECTED_LINE_CALLEE_SEND_MACRO_ARGS"), ""));
++ ast_channel_unlock(macro_chan);
++
++ if (ast_strlen_zero(macro)) {
++ return -1;
++ }
++
++ if (frame) {
++ ast_connected_line_parse_data(pointer.frame->data.ptr, pointer.frame->datalen, &macro_chan->connected);
++ } else {
++ ast_party_connected_line_copy(&macro_chan->connected, pointer.connected);
++ }
++
++ if (!(retval = ast_app_run_macro(autoservice_chan, macro_chan, macro, macro_args))) {
++ ast_channel_update_connected_line(macro_chan, &macro_chan->connected);
++ }
++
++ return retval;
++}
++
+ /* DO NOT PUT ADDITIONAL FUNCTIONS BELOW THIS BOUNDARY
+ *
+ * ONLY FUNCTIONS FOR PROVIDING BACKWARDS ABI COMPATIBILITY BELONG HERE
+Index: main/manager.c
+===================================================================
+--- a/main/manager.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/manager.c (.../trunk) (revision 202568)
+@@ -22,7 +22,7 @@
+ *
+ * \author Mark Spencer <markster@digium.com>
+ *
+- * \extref OpenSSL http://www.openssl.org - for AMI/SSL
++ * \extref OpenSSL http://www.openssl.org - for AMI/SSL
+ *
+ * At the moment this file contains a number of functions, namely:
+ *
+@@ -75,6 +75,618 @@
+ #include "asterisk/astobj2.h"
+ #include "asterisk/features.h"
+
++/*** DOCUMENTATION
++ <manager name="Ping" language="en_US">
++ <synopsis>
++ Keepalive command.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ </syntax>
++ <description>
++ <para>A 'Ping' action will ellicit a 'Pong' response. Used to keep the
++ manager connection open.</para>
++ </description>
++ </manager>
++ <manager name="Events" language="en_US">
++ <synopsis>
++ Control Event Flow.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="EventMask" required="true">
++ <enumlist>
++ <enum name="on">
++ <para>If all events should be sent.</para>
++ </enum>
++ <enum name="off">
++ <para>If no events should be sent.</para>
++ </enum>
++ <enum name="system,call,log,...">
++ <para>To select which flags events should have to be sent.</para>
++ </enum>
++ </enumlist>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Enable/Disable sending of events to this manager client.</para>
++ </description>
++ </manager>
++ <manager name="Logoff" language="en_US">
++ <synopsis>
++ Logoff Manager.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ </syntax>
++ <description>
++ <para>Logoff the current manager session.</para>
++ </description>
++ </manager>
++ <manager name="Login" language="en_US">
++ <synopsis>
++ Login Manager.
++ </synopsis>
++ <syntax>
++ <parameter name="ActionID">
++ <para>ActionID for this transaction. Will be returned.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Login Manager.</para>
++ </description>
++ </manager>
++ <manager name="Challenge" language="en_US">
++ <synopsis>
++ Generate Challenge for MD5 Auth.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ </syntax>
++ <description>
++ <para>Generate a challenge for MD5 authentication.</para>
++ </description>
++ </manager>
++ <manager name="Hangup" language="en_US">
++ <synopsis>
++ Hangup channel.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Channel" required="true">
++ <para>The channel name to be hangup.</para>
++ </parameter>
++ <parameter name="Cause">
++ <para>Numeric hangup cause.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Hangup a channel.</para>
++ </description>
++ </manager>
++ <manager name="Status" language="en_US">
++ <synopsis>
++ List channel status.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Channel" required="true">
++ <para>The name of the channel to query for status.</para>
++ </parameter>
++ <parameter name="Variables">
++ <para>Comma <literal>,</literal> separated list of variable to include.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Will return the status information of each channel along with the
++ value for the specified channel variables.</para>
++ </description>
++ </manager>
++ <manager name="Setvar" language="en_US">
++ <synopsis>
++ Set a channel variable.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Channel">
++ <para>Channel to set variable for.</para>
++ </parameter>
++ <parameter name="Variable" required="true">
++ <para>Variable name.</para>
++ </parameter>
++ <parameter name="Value" required="true">
++ <para>Variable value.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Set a global or local channel variable.</para>
++ </description>
++ </manager>
++ <manager name="Getvar" language="en_US">
++ <synopsis>
++ Gets a channel variable.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Channel">
++ <para>Channel to read variable from.</para>
++ </parameter>
++ <parameter name="Variable" required="true">
++ <para>Variable name.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Get the value of a global or local channel variable.</para>
++ </description>
++ </manager>
++ <manager name="GetConfig" language="en_US">
++ <synopsis>
++ Retrieve configuration.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Filename" required="true">
++ <para>Configuration filename (e.g. <filename>foo.conf</filename>).</para>
++ </parameter>
++ <parameter name="Category">
++ <para>Category in configuration file.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>This action will dump the contents of a configuration
++ file by category and contents or optionally by specified category only.</para>
++ </description>
++ </manager>
++ <manager name="GetConfigJSON" language="en_US">
++ <synopsis>
++ Retrieve configuration (JSON format).
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Filename" required="true">
++ <para>Configuration filename (e.g. <filename>foo.conf</filename>).</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>This action will dump the contents of a configuration file by category
++ and contents in JSON format. This only makes sense to be used using rawman over
++ the HTTP interface.</para>
++ </description>
++ </manager>
++ <manager name="UpdateConfig" language="en_US">
++ <synopsis>
++ Update basic configuration.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="SrcFilename" required="true">
++ <para>Configuration filename to read (e.g. <filename>foo.conf</filename>).</para>
++ </parameter>
++ <parameter name="DstFilename" required="true">
++ <para>Configuration filename to write (e.g. <filename>foo.conf</filename>)</para>
++ </parameter>
++ <parameter name="Reload">
++ <para>Whether or not a reload should take place (or name of specific module).</para>
++ </parameter>
++ <parameter name="Action-XXXXXX">
++ <para>Action to take.</para>
++ <para>X's represent 6 digit number beginning with 000000.</para>
++ <enumlist>
++ <enum name="NewCat" />
++ <enum name="RenameCat" />
++ <enum name="DelCat" />
++ <enum name="EmptyCat" />
++ <enum name="Update" />
++ <enum name="Delete" />
++ <enum name="Append" />
++ <enum name="Insert" />
++ </enumlist>
++ </parameter>
++ <parameter name="Cat-XXXXXX">
++ <para>Category to operate on.</para>
++ <xi:include xpointer="xpointer(/docs/manager[@name='UpdateConfig']/syntax/parameter[@name='Action-XXXXXX']/para[2])" />
++ </parameter>
++ <parameter name="Var-XXXXXX">
++ <para>Variable to work on.</para>
++ <xi:include xpointer="xpointer(/docs/manager[@name='UpdateConfig']/syntax/parameter[@name='Action-XXXXXX']/para[2])" />
++ </parameter>
++ <parameter name="Value-XXXXXX">
++ <para>Value to work on.</para>
++ <xi:include xpointer="xpointer(/docs/manager[@name='UpdateConfig']/syntax/parameter[@name='Action-XXXXXX']/para[2])" />
++ </parameter>
++ <parameter name="Match-XXXXXX">
++ <para>Extra match required to match line.</para>
++ <xi:include xpointer="xpointer(/docs/manager[@name='UpdateConfig']/syntax/parameter[@name='Action-XXXXXX']/para[2])" />
++ </parameter>
++ <parameter name="Line-XXXXXX">
++ <para>Line in category to operate on (used with delete and insert actions).</para>
++ <xi:include xpointer="xpointer(/docs/manager[@name='UpdateConfig']/syntax/parameter[@name='Action-XXXXXX']/para[2])" />
++ </parameter>
++ </syntax>
++ <description>
++ <para>This action will modify, create, or delete configuration elements
++ in Asterisk configuration files.</para>
++ </description>
++ </manager>
++ <manager name="CreateConfig" language="en_US">
++ <synopsis>
++ Creates an empty file in the configuration directory.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Filename" required="true">
++ <para>The configuration filename to create (e.g. <filename>foo.conf</filename>).</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>This action will create an empty file in the configuration
++ directory. This action is intended to be used before an UpdateConfig
++ action.</para>
++ </description>
++ </manager>
++ <manager name="ListCategories" language="en_US">
++ <synopsis>
++ List categories in configuration file.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Filename" required="true">
++ <para>Configuration filename (e.g. <filename>foo.conf</filename>).</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>This action will dump the categories in a given file.</para>
++ </description>
++ </manager>
++ <manager name="Redirect" language="en_US">
++ <synopsis>
++ Redirect (transfer) a call.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Channel" required="true">
++ <para>Channel to redirect.</para>
++ </parameter>
++ <parameter name="ExtraChannel">
++ <para>Second call leg to transfer (optional).</para>
++ </parameter>
++ <parameter name="Exten" required="true">
++ <para>Extension to transfer to.</para>
++ </parameter>
++ <parameter name="Context" required="true">
++ <para>Context to transfer to.</para>
++ </parameter>
++ <parameter name="Priority" required="true">
++ <para>Priority to transfer to.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Redirect (transfer) a call.</para>
++ </description>
++ </manager>
++ <manager name="Atxfer" language="en_US">
++ <synopsis>
++ Attended transfer.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Channel" required="true">
++ <para>Transferer's channel.</para>
++ </parameter>
++ <parameter name="Exten" required="true">
++ <para>Extension to transfer to.</para>
++ </parameter>
++ <parameter name="Context" required="true">
++ <para>Context to transfer to.</para>
++ </parameter>
++ <parameter name="Priority" required="true">
++ <para>Priority to transfer to.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Attended transfer.</para>
++ </description>
++ </manager>
++ <manager name="Originate" language="en_US">
++ <synopsis>
++ Originate a call.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Channel" required="true">
++ <para>Channel name to call.</para>
++ </parameter>
++ <parameter name="Exten">
++ <para>Extension to use (requires <literal>Context</literal> and
++ <literal>Priority</literal>)</para>
++ </parameter>
++ <parameter name="Context">
++ <para>Context to use (requires <literal>Exten</literal> and
++ <literal>Priority</literal>)</para>
++ </parameter>
++ <parameter name="Priority">
++ <para>Priority to use (requires <literal>Exten</literal> and
++ <literal>Context</literal>)</para>
++ </parameter>
++ <parameter name="Application">
++ <para>Application to execute.</para>
++ </parameter>
++ <parameter name="Data">
++ <para>Data to use (requires <literal>Application</literal>).</para>
++ </parameter>
++ <parameter name="Timeout">
++ <para>How long to wait for call to be answered (in ms).</para>
++ </parameter>
++ <parameter name="CallerID">
++ <para>Caller ID to be set on the outgoing channel.</para>
++ </parameter>
++ <parameter name="Variable">
++ <para>Channel variable to set, multiple Variable: headers are allowed.</para>
++ </parameter>
++ <parameter name="Account">
++ <para>Account code.</para>
++ </parameter>
++ <parameter name="Async">
++ <para>Set to <literal>true</literal> for fast origination.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Generates an outgoing call to a
++ <replaceable>Extension</replaceable>/<replaceable>Context</replaceable>/<replaceable>Priority</replaceable>
++ or <replaceable>Application</replaceable>/<replaceable>Data</replaceable></para>
++ </description>
++ </manager>
++ <manager name="Command" language="en_US">
++ <synopsis>
++ Execute Asterisk CLI Command.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Command" required="true">
++ <para>Asterisk CLI command to run.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Run a CLI command.</para>
++ </description>
++ </manager>
++ <manager name="ExtensionState" language="en_US">
++ <synopsis>
++ Check Extension Status.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Exten" required="true">
++ <para>Extension to check state on.</para>
++ </parameter>
++ <parameter name="Context" required="true">
++ <para>Context for extension.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Report the extension state for given extension. If the extension has a hint,
++ will use devicestate to check the status of the device connected to the extension.</para>
++ <para>Will return an <literal>Extension Status</literal> message. The response will include
++ the hint for the extension and the status.</para>
++ </description>
++ </manager>
++ <manager name="AbsoluteTimeout" language="en_US">
++ <synopsis>
++ Set absolute timeout.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Channel" required="true">
++ <para>Channel name to hangup.</para>
++ </parameter>
++ <parameter name="Timeout" required="true">
++ <para>Maximum duration of the call (sec).</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Hangup a channel after a certain time. Acknowledges set time with
++ <literal>Timeout Set</literal> message.</para>
++ </description>
++ </manager>
++ <manager name="MailboxStatus" language="en_US">
++ <synopsis>
++ Check mailbox.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Mailbox" required="true">
++ <para>Full mailbox ID <replaceable>mailbox</replaceable>@<replaceable>vm-context</replaceable>.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Checks a voicemail account for status.</para>
++ <para>Returns number of messages.</para>
++ <para>Message: Mailbox Status.</para>
++ <para>Mailbox: <replaceable>mailboxid</replaceable>.</para>
++ <para>Waiting: <replaceable>count</replaceable>.</para>
++ </description>
++ </manager>
++ <manager name="MailboxCount" language="en_US">
++ <synopsis>
++ Check Mailbox Message Count.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Mailbox" required="true">
++ <para>Full mailbox ID <replaceable>mailbox</replaceable>@<replaceable>vm-context</replaceable>.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Checks a voicemail account for new messages.</para>
++ <para>Returns number of urgent, new and old messages.</para>
++ <para>Message: Mailbox Message Count</para>
++ <para>Mailbox: <replaceable>mailboxid</replaceable></para>
++ <para>UrgentMessages: <replaceable>count</replaceable></para>
++ <para>NewMessages: <replaceable>count</replaceable></para>
++ <para>OldMessages: <replaceable>count</replaceable></para>
++ </description>
++ </manager>
++ <manager name="ListCommands" language="en_US">
++ <synopsis>
++ List available manager commands.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ </syntax>
++ <description>
++ <para>Returns the action name and synopsis for every action that
++ is available to the user.</para>
++ </description>
++ </manager>
++ <manager name="SendText" language="en_US">
++ <synopsis>
++ Send text message to channel.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Channel" required="true">
++ <para>Channel to send message to.</para>
++ </parameter>
++ <parameter name="Message" required="true">
++ <para>Message to send.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Sends A Text Message to a channel while in a call.</para>
++ </description>
++ </manager>
++ <manager name="UserEvent" language="en_US">
++ <synopsis>
++ Send an arbitrary event.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="UserEvent" required="true">
++ <para>Event string to send.</para>
++ </parameter>
++ <parameter name="Header1">
++ <para>Content1.</para>
++ </parameter>
++ <parameter name="HeaderN">
++ <para>ContentN.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Send an event to manager sessions.</para>
++ </description>
++ </manager>
++ <manager name="WaitEvent" language="en_US">
++ <synopsis>
++ Wait for an event to occur.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Timeout" required="true">
++ <para>Maximum time (in seconds) to wait for events, <literal>-1</literal> means forever.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>This action will ellicit a <literal>Success</literal> response. Whenever
++ a manager event is queued. Once WaitEvent has been called on an HTTP manager
++ session, events will be generated and queued.</para>
++ </description>
++ </manager>
++ <manager name="CoreSettings" language="en_US">
++ <synopsis>
++ Show PBX core settings (version etc).
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ </syntax>
++ <description>
++ <para>Query for Core PBX settings.</para>
++ </description>
++ </manager>
++ <manager name="CoreStatus" language="en_US">
++ <synopsis>
++ Show PBX core status variables.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ </syntax>
++ <description>
++ <para>Query for Core PBX status.</para>
++ </description>
++ </manager>
++ <manager name="Reload" language="en_US">
++ <synopsis>
++ Send a reload event.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Module">
++ <para>Name of the module to reload.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Send a reload event.</para>
++ </description>
++ </manager>
++ <manager name="CoreShowChannels" language="en_US">
++ <synopsis>
++ List currently active channels.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ </syntax>
++ <description>
++ <para>List currently defined channels and some information about them.</para>
++ </description>
++ </manager>
++ <manager name="ModuleLoad" language="en_US">
++ <synopsis>
++ Module management.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Module">
++ <para>Asterisk module name (including .so extension) or subsystem identifier:</para>
++ <enumlist>
++ <enum name="cdr" />
++ <enum name="enum" />
++ <enum name="dnsmgr" />
++ <enum name="extconfig" />
++ <enum name="manager" />
++ <enum name="rtp" />
++ <enum name="http" />
++ </enumlist>
++ </parameter>
++ <parameter name="LoadType" required="true">
++ <para>The operation to be done on module.</para>
++ <enumlist>
++ <enum name="load" />
++ <enum name="unload" />
++ <enum name="reload" />
++ </enumlist>
++ <para>If no module is specified for a <literal>reload</literal> loadtype,
++ all modules are reloaded.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Loads, unloads or reloads an Asterisk module in a running system.</para>
++ </description>
++ </manager>
++ <manager name="ModuleCheck" language="en_US">
++ <synopsis>
++ Check if module is loaded.
++ </synopsis>
++ <syntax>
++ <parameter name="Module" required="true">
++ <para>Asterisk module name (not including extension).</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Checks if Asterisk module is loaded. Will return Success/Failure.
++ For success returns, the module revision number is included.</para>
++ </description>
++ </manager>
++ ***/
++
+ enum error_type {
+ UNKNOWN_ACTION = 1,
+ UNKNOWN_CATEGORY,
+@@ -126,8 +738,10 @@
+ static int manager_enabled = 0;
+ static int webmanager_enabled = 0;
+
++#define DEFAULT_REALM "asterisk"
++static char global_realm[MAXHOSTNAMELEN]; /*!< Default realm */
++
+ static int block_sockets;
+-static int num_sessions;
+
+ static int manager_debug; /*!< enable some debugging code in the manager */
+
+@@ -138,11 +752,12 @@
+ * AMI session have managerid == 0; the entry is created upon a connect,
+ * and destroyed with the socket.
+ * HTTP sessions have managerid != 0, the value is used as a search key
+- * to lookup sessions (using the mansession_id cookie).
++ * to lookup sessions (using the mansession_id cookie, or nonce key from
++ * Digest Authentication http header).
+ */
+ #define MAX_BLACKLIST_CMD_LEN 2
+-static struct {
+- char *words[AST_MAX_CMD_LEN];
++static const struct {
++ const char *words[AST_MAX_CMD_LEN];
+ } command_blacklist[] = {
+ {{ "module", "load", NULL }},
+ {{ "module", "unload", NULL }},
+@@ -183,7 +798,6 @@
+ */
+ struct mansession_session {
+ pthread_t ms_t; /*!< Execution thread, basically useless */
+- ast_mutex_t __lock; /*!< Thread lock -- don't use in action callbacks, it's already taken care of */
+ /* XXX need to document which fields it is protecting */
+ struct sockaddr_in sin; /*!< address we are connecting from */
+ FILE *f; /*!< fdopen() on the underlying fd */
+@@ -206,6 +820,9 @@
+ struct eventqent *last_ev; /*!< last event processed. */
+ int writetimeout; /*!< Timeout for ast_carefulwrite() */
+ int pending_event; /*!< Pending events indicator in case when waiting_thread is NULL */
++ time_t noncetime; /*!< Timer for nonce value expiration */
++ unsigned long oldnonce; /*!< Stale nonce value */
++ unsigned long nc; /*!< incremental nonce counter */
+ AST_LIST_HEAD_NOLOCK(mansession_datastores, ast_datastore) datastores; /*!< Data stores on the session */
+ AST_LIST_ENTRY(mansession_session) list;
+ };
+@@ -219,12 +836,13 @@
+ struct mansession_session *session;
+ FILE *f;
+ int fd;
++ ast_mutex_t lock;
+ };
+
++static struct ao2_container *sessions = NULL;
++
+ #define NEW_EVENT(m) (AST_LIST_NEXT(m->session->last_ev, eq_next))
+
+-static AST_LIST_HEAD_STATIC(sessions, mansession_session);
+-
+ /*! \brief user descriptor, as read from the config file.
+ *
+ * \note It is still missing some fields -- e.g. we can have multiple permit and deny
+@@ -238,8 +856,9 @@
+ int readperm; /*! Authorization for reading */
+ int writeperm; /*! Authorization for writing */
+ int writetimeout; /*! Per user Timeout for ast_carefulwrite() */
+- int displayconnects; /*!< XXX unused */
+- int keep; /*!< mark entries created on a reload */
++ int displayconnects; /*!< XXX unused */
++ int keep; /*!< mark entries created on a reload */
++ char *a1_hash; /*!< precalculated A1 for Digest auth */
+ AST_RWLIST_ENTRY(ast_manager_user) list;
+ };
+
+@@ -252,13 +871,15 @@
+ /*! \brief list of hooks registered */
+ static AST_RWLIST_HEAD_STATIC(manager_hooks, manager_custom_hook);
+
++static struct eventqent *unref_event(struct eventqent *e);
++static void ref_event(struct eventqent *e);
++
+ /*! \brief Add a custom hook to be called when an event is fired */
+ void ast_manager_register_hook(struct manager_custom_hook *hook)
+ {
+ AST_RWLIST_WRLOCK(&manager_hooks);
+ AST_RWLIST_INSERT_TAIL(&manager_hooks, hook, list);
+ AST_RWLIST_UNLOCK(&manager_hooks);
+- return;
+ }
+
+ /*! \brief Delete a custom hook to be called when an event is fired */
+@@ -267,52 +888,8 @@
+ AST_RWLIST_WRLOCK(&manager_hooks);
+ AST_RWLIST_REMOVE(&manager_hooks, hook, list);
+ AST_RWLIST_UNLOCK(&manager_hooks);
+- return;
+ }
+
+-/*! \brief
+- * Event list management functions.
+- * We assume that the event list always has at least one element,
+- * and the delete code will not remove the last entry even if the
+- *
+- */
+-#if 0
+-static time_t __deb(time_t start, const char *msg)
+-{
+- time_t now = time(NULL);
+- ast_verbose("%4d th %p %s\n", (int)(now % 3600), pthread_self(), msg);
+- if (start != 0 && now - start > 5)
+- ast_verbose("+++ WOW, %s took %d seconds\n", msg, (int)(now - start));
+- return now;
+-}
+-
+-static void LOCK_EVENTS(void)
+-{
+- time_t start = __deb(0, "about to lock events");
+- AST_LIST_LOCK(&all_events);
+- __deb(start, "done lock events");
+-}
+-
+-static void UNLOCK_EVENTS(void)
+-{
+- __deb(0, "about to unlock events");
+- AST_LIST_UNLOCK(&all_events);
+-}
+-
+-static void LOCK_SESS(void)
+-{
+- time_t start = __deb(0, "about to lock sessions");
+- AST_LIST_LOCK(&sessions);
+- __deb(start, "done lock sessions");
+-}
+-
+-static void UNLOCK_SESS(void)
+-{
+- __deb(0, "about to unlock sessions");
+- AST_LIST_UNLOCK(&sessions);
+-}
+-#endif
+-
+ int check_manager_enabled()
+ {
+ return manager_enabled;
+@@ -336,8 +913,9 @@
+ /* the list is never empty now, but may become so when
+ * we optimize it in the future, so be prepared.
+ */
+- if (ret)
++ if (ret) {
+ ast_atomic_fetchadd_int(&ret->usecount, 1);
++ }
+ AST_LIST_UNLOCK(&all_events);
+ return ret;
+ }
+@@ -363,9 +941,9 @@
+ * helper functions to convert back and forth between
+ * string and numeric representation of set of flags
+ */
+-static struct permalias {
++static const struct permalias {
+ int num;
+- char *label;
++ const char *label;
+ } perms[] = {
+ { EVENT_FLAG_SYSTEM, "system" },
+ { EVENT_FLAG_CALL, "call" },
+@@ -386,7 +964,7 @@
+ };
+
+ /*! \brief Convert authority code to a list of options */
+-static char *authority_to_str(int authority, struct ast_str **res)
++static const char *authority_to_str(int authority, struct ast_str **res)
+ {
+ int i;
+ char *sep = "";
+@@ -416,12 +994,14 @@
+
+ do {
+ if ((next = strchr(val, delim))) {
+- if (!strncmp(val, smallstr, (next - val)))
++ if (!strncmp(val, smallstr, (next - val))) {
+ return 1;
+- else
++ } else {
+ continue;
+- } else
++ }
++ } else {
+ return !strcmp(smallstr, val);
++ }
+ } while (*(val = (next + 1)));
+
+ return 0;
+@@ -431,12 +1011,14 @@
+ {
+ int x = 0, ret = 0;
+
+- if (!instr)
++ if (!instr) {
+ return 0;
++ }
+
+ for (x = 0; x < ARRAY_LEN(perms); x++) {
+- if (ast_instring(instr, perms[x].label, ','))
++ if (ast_instring(instr, perms[x].label, ',')) {
+ ret |= perms[x].num;
++ }
+ }
+
+ return ret;
+@@ -450,40 +1032,106 @@
+ {
+ const char *p;
+
+- if (ast_strlen_zero(string))
++ if (ast_strlen_zero(string)) {
+ return -1;
++ }
+
+- for (p = string; *p; p++)
+- if (*p < '0' || *p > '9')
++ for (p = string; *p; p++) {
++ if (*p < '0' || *p > '9') {
+ break;
+- if (!p) /* all digits */
++ }
++ }
++ if (!p) { /* all digits */
+ return atoi(string);
+- if (ast_false(string))
++ }
++ if (ast_false(string)) {
+ return 0;
++ }
+ if (ast_true(string)) { /* all permissions */
+ int x, ret = 0;
+- for (x = 0; x < ARRAY_LEN(perms); x++)
++ for (x = 0; x < ARRAY_LEN(perms); x++) {
+ ret |= perms[x].num;
++ }
+ return ret;
+ }
+ return get_perm(string);
+ }
+
+-static int check_manager_session_inuse(const char *name)
++/*! \brief Unreference manager session object.
++ If no more references, then go ahead and delete it */
++static struct mansession_session *unref_mansession(struct mansession_session *s)
+ {
+- struct mansession_session *session = NULL;
++ int refcount = ao2_ref(s, -1);
++ if (manager_debug) {
++ ast_log(LOG_DEBUG, "Mansession: %p refcount now %d\n", s, refcount - 1);
++ }
++ return s;
++}
+
+- AST_LIST_LOCK(&sessions);
+- AST_LIST_TRAVERSE(&sessions, session, list) {
+- if (!strcasecmp(session->username, name))
+- break;
++static void session_destructor(void *obj)
++{
++ struct mansession_session *session = obj;
++ struct eventqent *eqe = session->last_ev;
++ struct ast_datastore *datastore;
++
++ /* Get rid of each of the data stores on the session */
++ while ((datastore = AST_LIST_REMOVE_HEAD(&session->datastores, entry))) {
++ /* Free the data store */
++ ast_datastore_free(datastore);
+ }
+- AST_LIST_UNLOCK(&sessions);
+
+- return session ? 1 : 0;
++ if (session->f != NULL) {
++ fclose(session->f);
++ }
++ unref_event(eqe);
+ }
+
++/*! \brief Allocate manager session structure and add it to the list of sessions */
++static struct mansession_session *build_mansession(struct sockaddr_in sin)
++{
++ struct mansession_session *newsession;
+
++ if (!(newsession = ao2_alloc(sizeof(*newsession), session_destructor))) {
++ return NULL;
++ }
++ newsession->fd = -1;
++ newsession->waiting_thread = AST_PTHREADT_NULL;
++ newsession->writetimeout = 100;
++ newsession->send_events = -1;
++ newsession->sin = sin;
++
++ ao2_link(sessions, newsession);
++
++ return newsession;
++}
++
++static int mansession_cmp_fn(void *obj, void *arg, int flags)
++{
++ struct mansession_session *s = obj;
++ char *str = arg;
++ return !strcasecmp(s->username, str) ? CMP_MATCH : 0;
++}
++
++static void session_destroy(struct mansession_session *s)
++{
++ unref_mansession(s);
++ ao2_unlink(sessions, s);
++}
++
++
++static int check_manager_session_inuse(const char *name)
++{
++ struct mansession_session *session = ao2_find(sessions, (char *) name, 0);
++ int inuse = 0;
++
++ if (session) {
++ inuse = 1;
++ unref_mansession(session);
++ }
++ return inuse;
++}
++
++
+ /*!
+ * lookup an entry in the list of registered users.
+ * must be called with the list lock held.
+@@ -493,8 +1141,9 @@
+ struct ast_manager_user *user = NULL;
+
+ AST_RWLIST_TRAVERSE(&users, user, list)
+- if (!strcasecmp(user->username, name))
++ if (!strcasecmp(user->username, name)) {
+ break;
++ }
+ return user;
+ }
+
+@@ -508,10 +1157,11 @@
+ int ret = 0;
+
+ AST_RWLIST_RDLOCK(&users);
+- if ((user = get_manager_by_name_locked (session->username)))
++ if ((user = get_manager_by_name_locked (session->username))) {
+ ret = user->displayconnects;
++ }
+ AST_RWLIST_UNLOCK(&users);
+-
++
+ return ret;
+ }
+
+@@ -521,10 +1171,14 @@
+ struct ast_str *authority;
+ int num, l, which;
+ char *ret = NULL;
++#ifdef AST_XML_DOCS
++ char syntax_title[64], description_title[64], synopsis_title[64], seealso_title[64], arguments_title[64];
++#endif
++
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "manager show command";
+- e->usage =
++ e->usage =
+ "Usage: manager show command <actionname> [<actionname> [<actionname> [...]]]\n"
+ " Shows the detailed description for a specific Asterisk manager interface command.\n";
+ return NULL;
+@@ -546,14 +1200,41 @@
+ return CLI_SHOWUSAGE;
+ }
+
++#ifdef AST_XML_DOCS
++ /* setup the titles */
++ term_color(synopsis_title, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
++ term_color(description_title, "[Description]\n", COLOR_MAGENTA, 0, 40);
++ term_color(syntax_title, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
++ term_color(seealso_title, "[See Also]\n", COLOR_MAGENTA, 0, 40);
++ term_color(arguments_title, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
++#endif
++
+ AST_RWLIST_RDLOCK(&actions);
+ AST_RWLIST_TRAVERSE(&actions, cur, list) {
+ for (num = 3; num < a->argc; num++) {
+ if (!strcasecmp(cur->action, a->argv[num])) {
+- ast_cli(a->fd, "Action: %s\nSynopsis: %s\nPrivilege: %s\n%s\n",
+- cur->action, cur->synopsis,
+- authority_to_str(cur->authority, &authority),
+- S_OR(cur->description, ""));
++#ifdef AST_XML_DOCS
++ if (cur->docsrc == AST_XML_DOC) {
++ ast_cli(a->fd, "%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n",
++ syntax_title,
++ ast_xmldoc_printable(S_OR(cur->syntax, "Not available"), 1),
++ synopsis_title,
++ ast_xmldoc_printable(S_OR(cur->synopsis, "Not available"), 1),
++ description_title,
++ ast_xmldoc_printable(S_OR(cur->description, "Not available"), 1),
++ arguments_title,
++ ast_xmldoc_printable(S_OR(cur->arguments, "Not available"), 1),
++ seealso_title,
++ ast_xmldoc_printable(S_OR(cur->seealso, "Not available"), 1));
++ } else {
++#endif
++ ast_cli(a->fd, "Action: %s\nSynopsis: %s\nPrivilege: %s\n%s\n",
++ cur->action, cur->synopsis,
++ authority_to_str(cur->authority, &authority),
++ S_OR(cur->description, ""));
++#ifdef AST_XML_DOCS
++ }
++#endif
+ }
+ }
+ }
+@@ -570,17 +1251,19 @@
+ e->usage = "Usage: manager set debug [on|off]\n Show, enable, disable debugging of the manager code.\n";
+ return NULL;
+ case CLI_GENERATE:
+- return NULL;
++ return NULL;
+ }
+- if (a->argc == 3)
++
++ if (a->argc == 3) {
+ ast_cli(a->fd, "manager debug is %s\n", manager_debug? "on" : "off");
+- else if (a->argc == 4) {
+- if (!strcasecmp(a->argv[3], "on"))
++ } else if (a->argc == 4) {
++ if (!strcasecmp(a->argv[3], "on")) {
+ manager_debug = 1;
+- else if (!strcasecmp(a->argv[3], "off"))
++ } else if (!strcasecmp(a->argv[3], "off")) {
+ manager_debug = 0;
+- else
++ } else {
+ return CLI_SHOWUSAGE;
++ }
+ }
+ return CLI_SUCCESS;
+ }
+@@ -596,15 +1279,16 @@
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "manager show user";
+- e->usage =
++ e->usage =
+ " Usage: manager show user <user>\n"
+ " Display all information related to the manager user specified.\n";
+ return NULL;
+ case CLI_GENERATE:
+ l = strlen(a->word);
+ which = 0;
+- if (a->pos != 3)
++ if (a->pos != 3) {
+ return NULL;
++ }
+ AST_RWLIST_RDLOCK(&users);
+ AST_RWLIST_TRAVERSE(&users, user, list) {
+ if ( !strncasecmp(a->word, user->username, l) && ++which > a->n ) {
+@@ -616,8 +1300,9 @@
+ return ret;
+ }
+
+- if (a->argc != 4)
++ if (a->argc != 4) {
+ return CLI_SHOWUSAGE;
++ }
+
+ AST_RWLIST_RDLOCK(&users);
+
+@@ -655,7 +1340,7 @@
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "manager show users";
+- e->usage =
++ e->usage =
+ "Usage: manager show users\n"
+ " Prints a listing of all managers that are currently configured on that\n"
+ " system.\n";
+@@ -663,8 +1348,9 @@
+ case CLI_GENERATE:
+ return NULL;
+ }
+- if (a->argc != 3)
++ if (a->argc != 3) {
+ return CLI_SHOWUSAGE;
++ }
+
+ AST_RWLIST_RDLOCK(&users);
+
+@@ -684,9 +1370,8 @@
+
+ AST_RWLIST_UNLOCK(&users);
+
+- ast_cli(a->fd, "-------------------\n");
+- ast_cli(a->fd, "%d manager users configured.\n", count_amu);
+-
++ ast_cli(a->fd,"-------------------\n"
++ "%d manager users configured.\n", count_amu);
+ return CLI_SUCCESS;
+ }
+
+@@ -700,13 +1385,13 @@
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "manager show commands";
+- e->usage =
++ e->usage =
+ "Usage: manager show commands\n"
+ " Prints a listing of all the available Asterisk manager interface commands.\n";
+ return NULL;
+ case CLI_GENERATE:
+- return NULL;
+- }
++ return NULL;
++ }
+ authority = ast_str_alloca(80);
+ ast_cli(a->fd, HSMC_FORMAT, "Action", "Privilege", "Synopsis");
+ ast_cli(a->fd, HSMC_FORMAT, "------", "---------", "--------");
+@@ -727,26 +1412,30 @@
+ #define HSMCONN_FORMAT1 " %-15.15s %-15.15s %-10.10s %-10.10s %-8.8s %-8.8s %-5.5s %-5.5s\n"
+ #define HSMCONN_FORMAT2 " %-15.15s %-15.15s %-10d %-10d %-8d %-8d %-5.5d %-5.5d\n"
+ int count = 0;
++ struct ao2_iterator i;
++
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "manager show connected";
+- e->usage =
++ e->usage =
+ "Usage: manager show connected\n"
+ " Prints a listing of the users that are currently connected to the\n"
+ "Asterisk manager interface.\n";
+ return NULL;
+ case CLI_GENERATE:
+- return NULL;
++ return NULL;
+ }
+
+ ast_cli(a->fd, HSMCONN_FORMAT1, "Username", "IP Address", "Start", "Elapsed", "FileDes", "HttpCnt", "Read", "Write");
+
+- AST_LIST_LOCK(&sessions);
+- AST_LIST_TRAVERSE(&sessions, session, list) {
++ i = ao2_iterator_init(sessions, 0);
++ while ((session = ao2_iterator_next(&i))) {
++ ao2_lock(session);
+ ast_cli(a->fd, HSMCONN_FORMAT2, session->username, ast_inet_ntoa(session->sin.sin_addr), (int)(session->sessionstart), (int)(now - session->sessionstart), session->fd, session->inuse, session->readperm, session->writeperm);
+ count++;
++ ao2_unlock(session);
++ unref_mansession(session);
+ }
+- AST_LIST_UNLOCK(&sessions);
+
+ ast_cli(a->fd, "%d users connected.\n", count);
+
+@@ -761,7 +1450,7 @@
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "manager show eventq";
+- e->usage =
++ e->usage =
+ "Usage: manager show eventq\n"
+ " Prints a listing of all events pending in the Asterisk manger\n"
+ "event queue.\n";
+@@ -793,8 +1482,9 @@
+ case CLI_GENERATE:
+ return NULL;
+ }
+- if (a->argc > 2)
++ if (a->argc > 2) {
+ return CLI_SHOWUSAGE;
++ }
+ reload_manager();
+ return CLI_SUCCESS;
+ }
+@@ -811,12 +1501,6 @@
+ AST_CLI_DEFINE(handle_manager_reload, "Reload manager configurations"),
+ };
+
+-/*
+- * Decrement the usecount for the event; if it goes to zero,
+- * (why check for e->next ?) wakeup the
+- * main thread, which is in charge of freeing the record.
+- * Returns the next record.
+- */
+ static struct eventqent *unref_event(struct eventqent *e)
+ {
+ ast_atomic_fetchadd_int(&e->usecount, -1);
+@@ -829,36 +1513,6 @@
+ }
+
+ /*
+- * destroy a session, leaving the usecount
+- */
+-static void free_session(struct mansession_session *session)
+-{
+- struct eventqent *eqe = session->last_ev;
+- struct ast_datastore *datastore;
+-
+- /* Get rid of each of the data stores on the session */
+- while ((datastore = AST_LIST_REMOVE_HEAD(&session->datastores, entry))) {
+- /* Free the data store */
+- ast_datastore_free(datastore);
+- }
+-
+- if (session->f != NULL)
+- fclose(session->f);
+- ast_mutex_destroy(&session->__lock);
+- ast_free(session);
+- unref_event(eqe);
+-}
+-
+-static void destroy_session(struct mansession_session *session)
+-{
+- AST_LIST_LOCK(&sessions);
+- AST_LIST_REMOVE(&sessions, session, list);
+- ast_atomic_fetchadd_int(&num_sessions, -1);
+- free_session(session);
+- AST_LIST_UNLOCK(&sessions);
+-}
+-
+-/*
+ * Generic function to return either the first or the last matching header
+ * from a list of variables, possibly skipping empty strings.
+ * At the moment there is only one use of this function in this file,
+@@ -914,20 +1568,24 @@
+ for (x = 0; x < m->hdrcount; x++) {
+ char *parse, *var, *val;
+
+- if (strncasecmp("Variable: ", m->headers[x], varlen))
++ if (strncasecmp("Variable: ", m->headers[x], varlen)) {
+ continue;
++ }
+ parse = ast_strdupa(m->headers[x] + varlen);
+
+ AST_STANDARD_APP_ARGS(args, parse);
+- if (!args.argc)
++ if (!args.argc) {
+ continue;
++ }
+ for (y = 0; y < args.argc; y++) {
+- if (!args.vars[y])
++ if (!args.vars[y]) {
+ continue;
++ }
+ var = val = ast_strdupa(args.vars[y]);
+ strsep(&val, "=");
+- if (!val || ast_strlen_zero(var))
++ if (!val || ast_strlen_zero(var)) {
+ continue;
++ }
+ cur = ast_variable_new(var, val, "");
+ cur->next = head;
+ head = cur;
+@@ -971,8 +1629,9 @@
+ va_list ap;
+ struct ast_str *buf;
+
+- if (!(buf = ast_str_thread_get(&astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE)))
++ if (!(buf = ast_str_thread_get(&astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE))) {
+ return;
++ }
+
+ va_start(ap, fmt);
+ ast_str_set_va(&buf, 0, fmt, ap);
+@@ -1007,16 +1666,19 @@
+ const char *id = astman_get_header(m, "ActionID");
+
+ astman_append(s, "Response: %s\r\n", resp);
+- if (!ast_strlen_zero(id))
++ if (!ast_strlen_zero(id)) {
+ astman_append(s, "ActionID: %s\r\n", id);
+- if (listflag)
++ }
++ if (listflag) {
+ astman_append(s, "Eventlist: %s\r\n", listflag); /* Start, complete, cancelled */
+- if (msg == MSG_MOREDATA)
++ }
++ if (msg == MSG_MOREDATA) {
+ return;
+- else if (msg)
++ } else if (msg) {
+ astman_append(s, "Message: %s\r\n\r\n", msg);
+- else
++ } else {
+ astman_append(s, "\r\n");
++ }
+ }
+
+ void astman_send_response(struct mansession *s, const struct message *m, char *resp, char *msg)
+@@ -1044,7 +1706,18 @@
+ astman_send_response_full(s, m, "Success", msg, listflag);
+ }
+
++/*! \brief Lock the 'mansession' structure. */
++static void mansession_lock(struct mansession *s)
++{
++ ast_mutex_lock(&s->lock);
++}
+
++/*! \brief Unlock the 'mansession' structure. */
++static void mansession_unlock(struct mansession *s)
++{
++ ast_mutex_unlock(&s->lock);
++}
++
+ /*! \brief
+ Rather than braindead on,off this now can also accept a specific int mask value
+ or a ',' delim list of mask strings (the same as manager.conf) -anthm
+@@ -1053,10 +1726,11 @@
+ {
+ int maskint = strings_to_mask(eventmask);
+
+- ast_mutex_lock(&s->session->__lock);
+- if (maskint >= 0)
++ mansession_lock(s);
++ if (maskint >= 0) {
+ s->session->send_events = maskint;
+- ast_mutex_unlock(&s->session->__lock);
++ }
++ mansession_unlock(s);
+
+ return maskint;
+ }
+@@ -1075,8 +1749,9 @@
+ int error = -1;
+ struct ast_manager_user *user = NULL;
+
+- if (ast_strlen_zero(username)) /* missing username */
++ if (ast_strlen_zero(username)) { /* missing username */
+ return -1;
++ }
+
+ /* locate user in locked state */
+ AST_RWLIST_WRLOCK(&users);
+@@ -1100,14 +1775,16 @@
+ MD5Final(digest, &md5);
+ for (x = 0; x < 16; x++)
+ len += sprintf(md5key + len, "%2.2x", digest[x]);
+- if (!strcmp(md5key, key))
++ if (!strcmp(md5key, key)) {
+ error = 0;
++ }
+ } else {
+- ast_debug(1, "MD5 authentication is not possible. challenge: '%s'\n",
++ ast_debug(1, "MD5 authentication is not possible. challenge: '%s'\n",
+ S_OR(s->session->challenge, ""));
+ }
+- } else if (password && user->secret && !strcmp(password, user->secret))
++ } else if (password && user->secret && !strcmp(password, user->secret)) {
+ error = 0;
++ }
+
+ if (error) {
+ ast_log(LOG_NOTICE, "%s failed to authenticate as '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username);
+@@ -1116,24 +1793,18 @@
+ }
+
+ /* auth complete */
+-
++
+ ast_copy_string(s->session->username, username, sizeof(s->session->username));
+ s->session->readperm = user->readperm;
+ s->session->writeperm = user->writeperm;
+ s->session->writetimeout = user->writetimeout;
+ s->session->sessionstart = time(NULL);
+ set_eventmask(s, astman_get_header(m, "Events"));
+-
++
+ AST_RWLIST_UNLOCK(&users);
+ return 0;
+ }
+
+-/*! \brief Manager PING */
+-static char mandescr_ping[] =
+-"Description: A 'Ping' action will ellicit a 'Pong' response. Used to keep the\n"
+-" manager connection open.\n"
+-"Variables: NONE\n";
+-
+ static int action_ping(struct mansession *s, const struct message *m)
+ {
+ const char *actionid = astman_get_header(m, "ActionID");
+@@ -1146,13 +1817,6 @@
+ return 0;
+ }
+
+-static char mandescr_getconfig[] =
+-"Description: A 'GetConfig' action will dump the contents of a configuration\n"
+-"file by category and contents or optionally by specified category only.\n"
+-"Variables: (Names marked with * are required)\n"
+-" *Filename: Configuration filename (e.g. foo.conf)\n"
+-" Category: Category in configuration file\n";
+-
+ static int action_getconfig(struct mansession *s, const struct message *m)
+ {
+ struct ast_config *cfg;
+@@ -1179,25 +1843,21 @@
+ if (ast_strlen_zero(category) || (!ast_strlen_zero(category) && !strcmp(category, cur_category))) {
+ lineno = 0;
+ astman_append(s, "Category-%06d: %s\r\n", catcount, cur_category);
+- for (v = ast_variable_browse(cfg, cur_category); v; v = v->next)
++ for (v = ast_variable_browse(cfg, cur_category); v; v = v->next) {
+ astman_append(s, "Line-%06d-%06d: %s=%s\r\n", catcount, lineno++, v->name, v->value);
++ }
+ catcount++;
+ }
+ }
+- if (!ast_strlen_zero(category) && catcount == 0) /* TODO: actually, a config with no categories doesn't even get loaded */
++ if (!ast_strlen_zero(category) && catcount == 0) { /* TODO: actually, a config with no categories doesn't even get loaded */
+ astman_append(s, "No categories found\r\n");
++ }
+ ast_config_destroy(cfg);
+ astman_append(s, "\r\n");
+
+ return 0;
+ }
+
+-static char mandescr_listcategories[] =
+-"Description: A 'ListCategories' action will dump the categories in\n"
+-"a given file.\n"
+-"Variables:\n"
+-" Filename: Configuration filename (e.g. foo.conf)\n";
+-
+ static int action_listcategories(struct mansession *s, const struct message *m)
+ {
+ struct ast_config *cfg;
+@@ -1219,8 +1879,9 @@
+ astman_append(s, "Category-%06d: %s\r\n", catcount, category);
+ catcount++;
+ }
+- if (catcount == 0) /* TODO: actually, a config with no categories doesn't even get loaded */
++ if (catcount == 0) { /* TODO: actually, a config with no categories doesn't even get loaded */
+ astman_append(s, "Error: no categories found\r\n");
++ }
+ ast_config_destroy(cfg);
+ astman_append(s, "\r\n");
+
+@@ -1228,26 +1889,20 @@
+ }
+
+
+-
+
++
+ /*! The amount of space in out must be at least ( 2 * strlen(in) + 1 ) */
+ static void json_escape(char *out, const char *in)
+ {
+ for (; *in; in++) {
+- if (*in == '\\' || *in == '\"')
++ if (*in == '\\' || *in == '\"') {
+ *out++ = '\\';
++ }
+ *out++ = *in;
+ }
+ *out = '\0';
+ }
+
+-static char mandescr_getconfigjson[] =
+-"Description: A 'GetConfigJSON' action will dump the contents of a configuration\n"
+-"file by category and contents in JSON format. This only makes sense to be used\n"
+-"using rawman over the HTTP interface.\n"
+-"Variables:\n"
+-" Filename: Configuration filename (e.g. foo.conf)\n";
+-
+ static int action_getconfigjson(struct mansession *s, const struct message *m)
+ {
+ struct ast_config *cfg;
+@@ -1282,11 +1937,13 @@
+ }
+ json_escape(buf, category);
+ astman_append(s, "%s\"%s\":[", comma1 ? "," : "", buf);
+- if (!comma1)
++ if (!comma1) {
+ comma1 = 1;
++ }
+ for (v = ast_variable_browse(cfg, category); v; v = v->next) {
+- if (comma2)
++ if (comma2) {
+ astman_append(s, ",");
++ }
+ if (buf_len < 2 * strlen(v->name) + 1) {
+ buf_len *= 2;
+ buf = alloca(buf_len);
+@@ -1299,8 +1956,9 @@
+ }
+ json_escape(buf, v->value);
+ astman_append(s, "%s\"", buf);
+- if (!comma2)
++ if (!comma2) {
+ comma2 = 1;
++ }
+ }
+ astman_append(s, "]");
+ }
+@@ -1347,7 +2005,7 @@
+ object = 1;
+ value++;
+ }
+-
++
+ snprintf(hdr, sizeof(hdr), "Match-%06d", x);
+ match = astman_get_header(m, hdr);
+
+@@ -1365,8 +2023,9 @@
+ }
+ if (ast_strlen_zero(match)) {
+ ast_category_append(cfg, category);
+- } else
++ } else {
+ ast_category_insert(cfg, category, match);
++ }
+ } else if (!strcasecmp(action, "renamecat")) {
+ if (ast_strlen_zero(value)) {
+ result = UNSPECIFIED_ARGUMENT;
+@@ -1419,15 +2078,16 @@
+ break;
+ }
+ if (!(category = ast_category_get(cfg, cat))) {
+- result = UNKNOWN_CATEGORY;
++ result = UNKNOWN_CATEGORY;
+ break;
+ }
+ if (!(v = ast_variable_new(var, value, dfn))) {
+ result = FAILURE_ALLOCATION;
+ break;
+ }
+- if (object || (match && !strcasecmp(match, "object")))
++ if (object || (match && !strcasecmp(match, "object"))) {
+ v->object = 1;
++ }
+ ast_variable_append(category, v);
+ } else if (!strcasecmp(action, "insert")) {
+ if (ast_strlen_zero(var) || ast_strlen_zero(line)) {
+@@ -1455,20 +2115,6 @@
+ return result;
+ }
+
+-static char mandescr_updateconfig[] =
+-"Description: A 'UpdateConfig' action will modify, create, or delete\n"
+-"configuration elements in Asterisk configuration files.\n"
+-"Variables (X's represent 6 digit number beginning with 000000):\n"
+-" SrcFilename: Configuration filename to read(e.g. foo.conf)\n"
+-" DstFilename: Configuration filename to write(e.g. foo.conf)\n"
+-" Reload: Whether or not a reload should take place (or name of specific module)\n"
+-" Action-XXXXXX: Action to Take (NewCat,RenameCat,DelCat,EmptyCat,Update,Delete,Append,Insert)\n"
+-" Cat-XXXXXX: Category to operate on\n"
+-" Var-XXXXXX: Variable to work on\n"
+-" Value-XXXXXX: Value to work on\n"
+-" Match-XXXXXX: Extra match required to match line\n"
+-" Line-XXXXXX: Line in category to operate on (used with delete and insert actions)\n";
+-
+ static int action_updateconfig(struct mansession *s, const struct message *m)
+ {
+ struct ast_config *cfg;
+@@ -1498,8 +2144,9 @@
+ }
+ astman_send_ack(s, m, NULL);
+ if (!ast_strlen_zero(rld)) {
+- if (ast_true(rld))
++ if (ast_true(rld)) {
+ rld = NULL;
++ }
+ ast_module_reload(rld);
+ }
+ } else {
+@@ -1543,13 +2190,6 @@
+ return 0;
+ }
+
+-static char mandescr_createconfig[] =
+-"Description: A 'CreateConfig' action will create an empty file in the\n"
+-"configuration directory. This action is intended to be used before an\n"
+-"UpdateConfig action.\n"
+-"Variables\n"
+-" Filename: The configuration filename to create (e.g. foo.conf)\n";
+-
+ static int action_createconfig(struct mansession *s, const struct message *m)
+ {
+ int fd;
+@@ -1568,14 +2208,6 @@
+ return 0;
+ }
+
+-/*! \brief Manager WAITEVENT */
+-static char mandescr_waitevent[] =
+-"Description: A 'WaitEvent' action will ellicit a 'Success' response. Whenever\n"
+-"a manager event is queued. Once WaitEvent has been called on an HTTP manager\n"
+-"session, events will be generated and queued.\n"
+-"Variables: \n"
+-" Timeout: Maximum time (in seconds) to wait for events, -1 means forever.\n";
+-
+ static int action_waitevent(struct mansession *s, const struct message *m)
+ {
+ const char *timeouts = astman_get_header(m, "Timeout");
+@@ -1585,21 +2217,24 @@
+ const char *id = astman_get_header(m, "ActionID");
+ char idText[256];
+
+- if (!ast_strlen_zero(id))
++ if (!ast_strlen_zero(id)) {
+ snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
+- else
++ } else {
+ idText[0] = '\0';
++ }
+
+ if (!ast_strlen_zero(timeouts)) {
+ sscanf(timeouts, "%i", &timeout);
+- if (timeout < -1)
++ if (timeout < -1) {
+ timeout = -1;
++ }
+ /* XXX maybe put an upper bound, or prevent the use of 0 ? */
+ }
+
+- ast_mutex_lock(&s->session->__lock);
+- if (s->session->waiting_thread != AST_PTHREADT_NULL)
++ mansession_lock(s);
++ if (s->session->waiting_thread != AST_PTHREADT_NULL) {
+ pthread_kill(s->session->waiting_thread, SIGURG);
++ }
+
+ if (s->session->managerid) { /* AMI-over-HTTP session */
+ /*
+@@ -1610,43 +2245,52 @@
+ time_t now = time(NULL);
+ int max = s->session->sessiontimeout - now - 10;
+
+- if (max < 0) /* We are already late. Strange but possible. */
++ if (max < 0) { /* We are already late. Strange but possible. */
+ max = 0;
+- if (timeout < 0 || timeout > max)
++ }
++ if (timeout < 0 || timeout > max) {
+ timeout = max;
+- if (!s->session->send_events) /* make sure we record events */
++ }
++ if (!s->session->send_events) { /* make sure we record events */
+ s->session->send_events = -1;
++ }
+ }
+- ast_mutex_unlock(&s->session->__lock);
++ mansession_unlock(s);
+
+ /* XXX should this go inside the lock ? */
+ s->session->waiting_thread = pthread_self(); /* let new events wake up this thread */
+ ast_debug(1, "Starting waiting for an event!\n");
+
+ for (x = 0; x < timeout || timeout < 0; x++) {
+- ast_mutex_lock(&s->session->__lock);
+- if (NEW_EVENT(s))
++ mansession_lock(s);
++ if (NEW_EVENT(s)) {
+ needexit = 1;
++ }
+ /* We can have multiple HTTP session point to the same mansession entry.
+ * The way we deal with it is not very nice: newcomers kick out the previous
+ * HTTP session. XXX this needs to be improved.
+ */
+- if (s->session->waiting_thread != pthread_self())
++ if (s->session->waiting_thread != pthread_self()) {
+ needexit = 1;
+- if (s->session->needdestroy)
++ }
++ if (s->session->needdestroy) {
+ needexit = 1;
+- ast_mutex_unlock(&s->session->__lock);
+- if (needexit)
++ }
++ mansession_unlock(s);
++ if (needexit) {
+ break;
++ }
+ if (s->session->managerid == 0) { /* AMI session */
+- if (ast_wait_for_input(s->session->fd, 1000))
++ if (ast_wait_for_input(s->session->fd, 1000)) {
+ break;
++ }
+ } else { /* HTTP session */
+ sleep(1);
+ }
+ }
+ ast_debug(1, "Finished waiting for an event!\n");
+- ast_mutex_lock(&s->session->__lock);
++
++ mansession_lock(s);
+ if (s->session->waiting_thread == pthread_self()) {
+ struct eventqent *eqe;
+ astman_send_response(s, m, "Success", "Waiting for Event completed.");
+@@ -1666,15 +2310,10 @@
+ } else {
+ ast_debug(1, "Abandoning event request!\n");
+ }
+- ast_mutex_unlock(&s->session->__lock);
++ mansession_unlock(s);
+ return 0;
+ }
+
+-static char mandescr_listcommands[] =
+-"Description: Returns the action name and synopsis for every\n"
+-" action that is available to the user\n"
+-"Variables: NONE\n";
+-
+ /*! \note The actionlock is read-locked by the caller of this function */
+ static int action_listcommands(struct mansession *s, const struct message *m)
+ {
+@@ -1683,23 +2322,16 @@
+
+ astman_start_ack(s, m);
+ AST_RWLIST_TRAVERSE(&actions, cur, list) {
+- if (s->session->writeperm & cur->authority || cur->authority == 0)
++ if (s->session->writeperm & cur->authority || cur->authority == 0) {
+ astman_append(s, "%s: %s (Priv: %s)\r\n",
+ cur->action, cur->synopsis, authority_to_str(cur->authority, &temp));
++ }
+ }
+ astman_append(s, "\r\n");
+
+ return 0;
+ }
+
+-static char mandescr_events[] =
+-"Description: Enable/Disable sending of events to this manager\n"
+-" client.\n"
+-"Variables:\n"
+-" EventMask: 'on' if all events should be sent,\n"
+-" 'off' if no events should be sent,\n"
+-" 'system,call,log' to select which flags events should have to be sent.\n";
+-
+ static int action_events(struct mansession *s, const struct message *m)
+ {
+ const char *mask = astman_get_header(m, "EventMask");
+@@ -1715,10 +2347,6 @@
+ return 0;
+ }
+
+-static char mandescr_logoff[] =
+-"Description: Logoff this manager session\n"
+-"Variables: NONE\n";
+-
+ static int action_logoff(struct mansession *s, const struct message *m)
+ {
+ astman_send_response(s, m, "Goodbye", "Thanks for all the fish.");
+@@ -1727,15 +2355,22 @@
+
+ static int action_login(struct mansession *s, const struct message *m)
+ {
++
++ /* still authenticated - don't process again */
++ if (s->session->authenticated) {
++ astman_send_ack(s, m, "Already authenticated");
++ return 0;
++ }
++
+ if (authenticate(s, m)) {
+ sleep(1);
+ astman_send_error(s, m, "Authentication failed");
+ return -1;
+ }
+ s->session->authenticated = 1;
+- if (manager_displayconnects(s->session))
++ if (manager_displayconnects(s->session)) {
+ ast_verb(2, "%sManager '%s' logged on from %s\n", (s->session->managerid ? "HTTP " : ""), s->session->username, ast_inet_ntoa(s->session->sin.sin_addr));
+- ast_log(LOG_EVENT, "%sManager '%s' logged on from %s\n", (s->session->managerid ? "HTTP " : ""), s->session->username, ast_inet_ntoa(s->session->sin.sin_addr));
++ }
+ astman_send_ack(s, m, "Authentication accepted");
+ return 0;
+ }
+@@ -1745,49 +2380,62 @@
+ const char *authtype = astman_get_header(m, "AuthType");
+
+ if (!strcasecmp(authtype, "MD5")) {
+- if (ast_strlen_zero(s->session->challenge))
++ if (ast_strlen_zero(s->session->challenge)) {
+ snprintf(s->session->challenge, sizeof(s->session->challenge), "%ld", ast_random());
+- ast_mutex_lock(&s->session->__lock);
++ }
++ mansession_lock(s);
+ astman_start_ack(s, m);
+ astman_append(s, "Challenge: %s\r\n\r\n", s->session->challenge);
+- ast_mutex_unlock(&s->session->__lock);
++ mansession_unlock(s);
+ } else {
+ astman_send_error(s, m, "Must specify AuthType");
+ }
+ return 0;
+ }
+
+-static char mandescr_hangup[] =
+-"Description: Hangup a channel\n"
+-"Variables: \n"
+-" Channel: The channel name to be hungup\n";
+-
+ static int action_hangup(struct mansession *s, const struct message *m)
+ {
+ struct ast_channel *c = NULL;
++ int causecode = 0; /* all values <= 0 mean 'do not set hangupcause in channel' */
+ const char *name = astman_get_header(m, "Channel");
++ const char *cause = astman_get_header(m, "Cause");
++
+ if (ast_strlen_zero(name)) {
+ astman_send_error(s, m, "No channel specified");
+ return 0;
+ }
+- c = ast_get_channel_by_name_locked(name);
+- if (!c) {
++
++ if (!ast_strlen_zero(cause)) {
++ char *endptr;
++ causecode = strtol(cause, &endptr, 10);
++ if (causecode < 0 || causecode > 127 || *endptr != '\0') {
++ ast_log(LOG_NOTICE, "Invalid 'Cause: %s' in manager action Hangup\n", cause);
++ /* keep going, better to hangup without cause than to not hang up at all */
++ causecode = 0; /* do not set channel's hangupcause */
++ }
++ }
++
++ if (!(c = ast_channel_get_by_name(name))) {
+ astman_send_error(s, m, "No such channel");
+ return 0;
+ }
+- ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
++
++ ast_channel_lock(c);
++ if (causecode > 0) {
++ ast_debug(1, "Setting hangupcause of channel %s to %d (is %d now)\n",
++ c->name, causecode, c->hangupcause);
++ c->hangupcause = causecode;
++ }
++ ast_softhangup_nolock(c, AST_SOFTHANGUP_EXPLICIT);
+ ast_channel_unlock(c);
++
++ c = ast_channel_unref(c);
++
+ astman_send_ack(s, m, "Channel Hungup");
++
+ return 0;
+ }
+
+-static char mandescr_setvar[] =
+-"Description: Set a global or local channel variable.\n"
+-"Variables: (Names marked with * are required)\n"
+-" Channel: Channel to set variable for\n"
+-" *Variable: Variable name\n"
+-" *Value: Value\n";
+-
+ static int action_setvar(struct mansession *s, const struct message *m)
+ {
+ struct ast_channel *c = NULL;
+@@ -1801,8 +2449,7 @@
+ }
+
+ if (!ast_strlen_zero(name)) {
+- c = ast_get_channel_by_name_locked(name);
+- if (!c) {
++ if (!(c = ast_channel_get_by_name(name))) {
+ astman_send_error(s, m, "No such channel");
+ return 0;
+ }
+@@ -1810,21 +2457,15 @@
+
+ pbx_builtin_setvar_helper(c, varname, S_OR(varval, ""));
+
+- if (c)
+- ast_channel_unlock(c);
++ if (c) {
++ c = ast_channel_unref(c);
++ }
+
+ astman_send_ack(s, m, "Variable Set");
+
+ return 0;
+ }
+
+-static char mandescr_getvar[] =
+-"Description: Get the value of a global or local channel variable.\n"
+-"Variables: (Names marked with * are required)\n"
+-" Channel: Channel to read variable from\n"
+-" *Variable: Variable name\n"
+-" ActionID: Optional Action id for message matching.\n";
+-
+ static int action_getvar(struct mansession *s, const struct message *m)
+ {
+ struct ast_channel *c = NULL;
+@@ -1839,8 +2480,7 @@
+ }
+
+ if (!ast_strlen_zero(name)) {
+- c = ast_get_channel_by_name_locked(name);
+- if (!c) {
++ if (!(c = ast_channel_get_by_name(name))) {
+ astman_send_error(s, m, "No such channel");
+ return 0;
+ }
+@@ -1851,35 +2491,27 @@
+ c = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Bogus/manager");
+ if (c) {
+ ast_func_read(c, (char *) varname, workspace, sizeof(workspace));
+- ast_channel_free(c);
+- c = NULL;
++ c = ast_channel_release(c);
+ } else
+ ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n");
+- } else
++ } else {
+ ast_func_read(c, (char *) varname, workspace, sizeof(workspace));
++ }
+ varval = workspace;
+ } else {
+ pbx_retrieve_variable(c, varname, &varval, workspace, sizeof(workspace), NULL);
+ }
+
+- if (c)
+- ast_channel_unlock(c);
++ if (c) {
++ c = ast_channel_unref(c);
++ }
++
+ astman_start_ack(s, m);
+ astman_append(s, "Variable: %s\r\nValue: %s\r\n\r\n", varname, varval);
+
+ return 0;
+ }
+
+-static char mandescr_status[] =
+-"Description: Lists channel status along with requested channel vars.\n"
+-"Variables: (Names marked with * are required)\n"
+-" *Channel: Name of the channel to query for status\n"
+-" Variables: Comma ',' separated list of variables to include\n"
+-" ActionID: Optional ID for this transaction\n"
+-"Will return the status information of each channel along with the\n"
+-"value for the specified channel variables.\n";
+-
+-
+ /*! \brief Manager "status" command to show channels */
+ /* Needs documentation... */
+ static int action_status(struct mansession *s, const struct message *m)
+@@ -1899,22 +2531,29 @@
+ AST_APP_ARG(name)[100];
+ );
+ struct ast_str *str = ast_str_create(1000);
++ struct ast_channel_iterator *iter = NULL;
+
+- if (!ast_strlen_zero(id))
++ if (!ast_strlen_zero(id)) {
+ snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
+- else
++ } else {
+ idText[0] = '\0';
++ }
+
+- if (all)
+- c = ast_channel_walk_locked(NULL);
+- else {
+- c = ast_get_channel_by_name_locked(name);
+- if (!c) {
++ if (all) {
++ if (!(iter = ast_channel_iterator_all_new(0))) {
++ ast_free(str);
++ astman_send_error(s, m, "Memory Allocation Failure");
++ return 1;
++ }
++ c = ast_channel_iterator_next(iter);
++ } else {
++ if (!(c = ast_channel_get_by_name(name))) {
+ astman_send_error(s, m, "No such channel");
+ ast_free(str);
+ return 0;
+ }
+ }
++
+ astman_send_ack(s, m, "Channel status will follow");
+
+ if (!ast_strlen_zero(cvariables)) {
+@@ -1922,7 +2561,9 @@
+ }
+
+ /* if we look by name, we break after the first iteration */
+- while (c) {
++ for (; c; c = ast_channel_iterator_next(iter)) {
++ ast_channel_lock(c);
++
+ if (!ast_strlen_zero(cvariables)) {
+ int i;
+ ast_str_reset(str);
+@@ -1943,10 +2584,11 @@
+ }
+
+ channels++;
+- if (c->_bridge)
++ if (c->_bridge) {
+ snprintf(bridge, sizeof(bridge), "BridgedChannel: %s\r\nBridgedUniqueid: %s\r\n", c->_bridge->name, c->_bridge->uniqueid);
+- else
++ } else {
+ bridge[0] = '\0';
++ }
+ if (c->pbx) {
+ if (c->cdr) {
+ elapsed_seconds = now.tv_sec - c->cdr->start.tv_sec;
+@@ -1978,45 +2620,45 @@
+ c->exten, c->priority, (long)elapsed_seconds, bridge, c->uniqueid, ast_str_buffer(str), idText);
+ } else {
+ astman_append(s,
+- "Event: Status\r\n"
+- "Privilege: Call\r\n"
+- "Channel: %s\r\n"
+- "CallerIDNum: %s\r\n"
+- "CallerIDName: %s\r\n"
+- "Account: %s\r\n"
+- "State: %s\r\n"
+- "%s"
+- "Uniqueid: %s\r\n"
+- "%s"
+- "%s"
+- "\r\n",
+- c->name,
+- S_OR(c->cid.cid_num, "<unknown>"),
+- S_OR(c->cid.cid_name, "<unknown>"),
+- c->accountcode,
+- ast_state2str(c->_state), bridge, c->uniqueid, ast_str_buffer(str), idText);
++ "Event: Status\r\n"
++ "Privilege: Call\r\n"
++ "Channel: %s\r\n"
++ "CallerIDNum: %s\r\n"
++ "CallerIDName: %s\r\n"
++ "Account: %s\r\n"
++ "State: %s\r\n"
++ "%s"
++ "Uniqueid: %s\r\n"
++ "%s"
++ "%s"
++ "\r\n",
++ c->name,
++ S_OR(c->cid.cid_num, "<unknown>"),
++ S_OR(c->cid.cid_name, "<unknown>"),
++ c->accountcode,
++ ast_state2str(c->_state), bridge, c->uniqueid,
++ ast_str_buffer(str), idText);
+ }
++
+ ast_channel_unlock(c);
+- if (!all)
++ c = ast_channel_unref(c);
++
++ if (!all) {
+ break;
+- c = ast_channel_walk_locked(c);
++ }
+ }
++
+ astman_append(s,
+- "Event: StatusComplete\r\n"
+- "%s"
+- "Items: %d\r\n"
+- "\r\n", idText, channels);
++ "Event: StatusComplete\r\n"
++ "%s"
++ "Items: %d\r\n"
++ "\r\n", idText, channels);
++
+ ast_free(str);
++
+ return 0;
+ }
+
+-static char mandescr_sendtext[] =
+-"Description: Sends A Text Message while in a call.\n"
+-"Variables: (Names marked with * are required)\n"
+-" *Channel: Channel to send message to\n"
+-" *Message: Message to send\n"
+-" ActionID: Optional Action id for message matching.\n";
+-
+ static int action_sendtext(struct mansession *s, const struct message *m)
+ {
+ struct ast_channel *c = NULL;
+@@ -2034,33 +2676,25 @@
+ return 0;
+ }
+
+- c = ast_get_channel_by_name_locked(name);
+- if (!c) {
++ if (!(c = ast_channel_get_by_name(name))) {
+ astman_send_error(s, m, "No such channel");
+ return 0;
+ }
+
++ ast_channel_lock(c);
+ res = ast_sendtext(c, textmsg);
+ ast_channel_unlock(c);
+-
+- if (res > 0)
++ c = ast_channel_unref(c);
++
++ if (res > 0) {
+ astman_send_ack(s, m, "Success");
+- else
++ } else {
+ astman_send_error(s, m, "Failure");
+-
++ }
++
+ return res;
+ }
+
+-static char mandescr_redirect[] =
+-"Description: Redirect (transfer) a call.\n"
+-"Variables: (Names marked with * are required)\n"
+-" *Channel: Channel to redirect\n"
+-" ExtraChannel: Second call leg to transfer (optional)\n"
+-" *Exten: Extension to transfer to\n"
+-" *Context: Context to transfer to\n"
+-" *Priority: Priority to transfer to\n"
+-" ActionID: Optional Action id for message matching.\n";
+-
+ /*! \brief action_redirect: The redirect manager command */
+ static int action_redirect(struct mansession *s, const struct message *m)
+ {
+@@ -2077,38 +2711,44 @@
+ astman_send_error(s, m, "Channel not specified");
+ return 0;
+ }
++
+ if (!ast_strlen_zero(priority) && (sscanf(priority, "%d", &pi) != 1)) {
+ if ((pi = ast_findlabel_extension(NULL, context, exten, priority, NULL)) < 1) {
+ astman_send_error(s, m, "Invalid priority");
+ return 0;
+ }
+ }
+- /* XXX watch out, possible deadlock - we are trying to get two channels!!! */
+- chan = ast_get_channel_by_name_locked(name);
+- if (!chan) {
++
++ if (!(chan = ast_channel_get_by_name(name))) {
+ char buf[256];
+ snprintf(buf, sizeof(buf), "Channel does not exist: %s", name);
+ astman_send_error(s, m, buf);
+ return 0;
+ }
+- if (ast_check_hangup(chan)) {
++
++ if (ast_check_hangup_locked(chan)) {
+ astman_send_error(s, m, "Redirect failed, channel not up.");
+- ast_channel_unlock(chan);
++ chan = ast_channel_unref(chan);
+ return 0;
+ }
+- if (!ast_strlen_zero(name2))
+- chan2 = ast_get_channel_by_name_locked(name2);
+- if (chan2 && ast_check_hangup(chan2)) {
++
++ if (!ast_strlen_zero(name2)) {
++ chan2 = ast_channel_get_by_name(name2);
++ }
++
++ if (chan2 && ast_check_hangup_locked(chan2)) {
+ astman_send_error(s, m, "Redirect failed, extra channel not up.");
+- ast_channel_unlock(chan);
+- ast_channel_unlock(chan2);
++ chan = ast_channel_unref(chan);
++ chan2 = ast_channel_unref(chan2);
+ return 0;
+ }
++
+ if (chan->pbx) {
+ ast_channel_lock(chan);
+ ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
+ ast_channel_unlock(chan);
+ }
++
+ res = ast_async_goto(chan, context, exten, pi);
+ if (!res) {
+ if (!ast_strlen_zero(name2)) {
+@@ -2122,30 +2762,29 @@
+ } else {
+ res = -1;
+ }
+- if (!res)
++ if (!res) {
+ astman_send_ack(s, m, "Dual Redirect successful");
+- else
++ } else {
+ astman_send_error(s, m, "Secondary redirect failed");
+- } else
++ }
++ } else {
+ astman_send_ack(s, m, "Redirect successful");
+- } else
++ }
++ } else {
+ astman_send_error(s, m, "Redirect failed");
+- if (chan)
+- ast_channel_unlock(chan);
+- if (chan2)
+- ast_channel_unlock(chan2);
++ }
++
++ if (chan) {
++ chan = ast_channel_unref(chan);
++ }
++
++ if (chan2) {
++ chan2 = ast_channel_unref(chan2);
++ }
++
+ return 0;
+ }
+
+-static char mandescr_atxfer[] =
+-"Description: Attended transfer.\n"
+-"Variables: (Names marked with * are required)\n"
+-" *Channel: Transferer's channel\n"
+-" *Exten: Extension to transfer to\n"
+-" *Context: Context to transfer to\n"
+-" *Priority: Priority to transfer to\n"
+-" ActionID: Optional Action id for message matching.\n";
+-
+ static int action_atxfer(struct mansession *s, const struct message *m)
+ {
+ const char *name = astman_get_header(m, "Channel");
+@@ -2155,7 +2794,7 @@
+ struct ast_call_feature *atxfer_feature = NULL;
+ char *feature_code = NULL;
+
+- if (ast_strlen_zero(name)) {
++ if (ast_strlen_zero(name)) {
+ astman_send_error(s, m, "No channel specified");
+ return 0;
+ }
+@@ -2169,7 +2808,7 @@
+ return 0;
+ }
+
+- if (!(chan = ast_get_channel_by_name_locked(name))) {
++ if (!(chan = ast_channel_get_by_name(name))) {
+ astman_send_error(s, m, "Channel specified does not exist");
+ return 0;
+ }
+@@ -2179,17 +2818,18 @@
+ }
+
+ for (feature_code = atxfer_feature->exten; feature_code && *feature_code; ++feature_code) {
+- struct ast_frame f = {AST_FRAME_DTMF, *feature_code};
++ struct ast_frame f = { AST_FRAME_DTMF, *feature_code };
+ ast_queue_frame(chan, &f);
+ }
+
+ for (feature_code = (char *)exten; feature_code && *feature_code; ++feature_code) {
+- struct ast_frame f = {AST_FRAME_DTMF, *feature_code};
++ struct ast_frame f = { AST_FRAME_DTMF, *feature_code };
+ ast_queue_frame(chan, &f);
+ }
+
++ chan = ast_channel_unref(chan);
++
+ astman_send_ack(s, m, "Atxfer successfully queued");
+- ast_channel_unlock(chan);
+
+ return 0;
+ }
+@@ -2229,12 +2869,6 @@
+ return 0;
+ }
+
+-static char mandescr_command[] =
+-"Description: Run a CLI command.\n"
+-"Variables: (Names marked with * are required)\n"
+-" *Command: Asterisk CLI command to run\n"
+-" ActionID: Optional Action id for message matching.\n";
+-
+ /*! \brief Manager command "command" - execute CLI command */
+ static int action_command(struct mansession *s, const struct message *m)
+ {
+@@ -2256,8 +2890,9 @@
+ }
+
+ astman_append(s, "Response: Follows\r\nPrivilege: Command\r\n");
+- if (!ast_strlen_zero(id))
++ if (!ast_strlen_zero(id)) {
+ astman_append(s, "ActionID: %s\r\n", id);
++ }
+ /* FIXME: Wedge a ActionID response in here, waiting for later changes */
+ ast_cli_command(fd, cmd); /* XXX need to change this to use a FILE * */
+ l = lseek(fd, 0, SEEK_END); /* how many chars available */
+@@ -2281,8 +2916,9 @@
+ close(fd);
+ unlink(template);
+ astman_append(s, "--END COMMAND--\r\n\r\n");
+- if (final_buf)
++ if (final_buf) {
+ ast_free(final_buf);
++ }
+ return 0;
+ }
+
+@@ -2325,8 +2961,9 @@
+ in->vars, in->account, &chan);
+ }
+
+- if (!chan)
+- snprintf(requested_channel, AST_CHANNEL_NAME, "%s/%s", in->tech, in->data);
++ if (!chan) {
++ snprintf(requested_channel, AST_CHANNEL_NAME, "%s/%s", in->tech, in->data);
++ }
+ /* Tell the manager what happened with the channel */
+ manager_event(EVENT_FLAG_CALL, "OriginateResponse",
+ "%s%s"
+@@ -2338,36 +2975,21 @@
+ "Uniqueid: %s\r\n"
+ "CallerIDNum: %s\r\n"
+ "CallerIDName: %s\r\n",
+- in->idtext, ast_strlen_zero(in->idtext) ? "" : "\r\n", res ? "Failure" : "Success",
+- chan ? chan->name : requested_channel, in->context, in->exten, reason,
++ in->idtext, ast_strlen_zero(in->idtext) ? "" : "\r\n", res ? "Failure" : "Success",
++ chan ? chan->name : requested_channel, in->context, in->exten, reason,
+ chan ? chan->uniqueid : "<null>",
+ S_OR(in->cid_num, "<unknown>"),
+ S_OR(in->cid_name, "<unknown>")
+ );
+
+ /* Locked by ast_pbx_outgoing_exten or ast_pbx_outgoing_app */
+- if (chan)
++ if (chan) {
+ ast_channel_unlock(chan);
++ }
+ ast_free(in);
+ return NULL;
+ }
+
+-static char mandescr_originate[] =
+-"Description: Generates an outgoing call to a Extension/Context/Priority or\n"
+-" Application/Data\n"
+-"Variables: (Names marked with * are required)\n"
+-" *Channel: Channel name to call\n"
+-" Exten: Extension to use (requires 'Context' and 'Priority')\n"
+-" Context: Context to use (requires 'Exten' and 'Priority')\n"
+-" Priority: Priority to use (requires 'Exten' and 'Context')\n"
+-" Application: Application to use\n"
+-" Data: Data to use (requires 'Application')\n"
+-" Timeout: How long to wait for call to be answered (in ms)\n"
+-" CallerID: Caller ID to be set on the outgoing channel\n"
+-" Variable: Channel variable to set, multiple Variable: headers are allowed\n"
+-" Account: Account code\n"
+-" Async: Set to 'true' for fast origination\n";
+-
+ static int action_originate(struct mansession *s, const struct message *m)
+ {
+ const char *name = astman_get_header(m, "Channel");
+@@ -2419,13 +3041,15 @@
+ ast_copy_string(tmp2, callerid, sizeof(tmp2));
+ ast_callerid_parse(tmp2, &n, &l);
+ if (n) {
+- if (ast_strlen_zero(n))
++ if (ast_strlen_zero(n)) {
+ n = NULL;
++ }
+ }
+ if (l) {
+ ast_shrink_phone_number(l);
+- if (ast_strlen_zero(l))
++ if (ast_strlen_zero(l)) {
+ l = NULL;
++ }
+ }
+ if (!ast_strlen_zero(codecs)) {
+ format = 0;
+@@ -2439,13 +3063,15 @@
+ if (!ast_strlen_zero(id))
+ snprintf(fast->idtext, sizeof(fast->idtext), "ActionID: %s", id);
+ ast_copy_string(fast->tech, tech, sizeof(fast->tech));
+- ast_copy_string(fast->data, data, sizeof(fast->data));
++ ast_copy_string(fast->data, data, sizeof(fast->data));
+ ast_copy_string(fast->app, app, sizeof(fast->app));
+ ast_copy_string(fast->appdata, appdata, sizeof(fast->appdata));
+- if (l)
++ if (l) {
+ ast_copy_string(fast->cid_num, l, sizeof(fast->cid_num));
+- if (n)
++ }
++ if (n) {
+ ast_copy_string(fast->cid_name, n, sizeof(fast->cid_name));
++ }
+ fast->vars = vars;
+ ast_copy_string(fast->context, context, sizeof(fast->context));
+ ast_copy_string(fast->exten, exten, sizeof(fast->exten));
+@@ -2478,33 +3104,21 @@
+ }
+ res = ast_pbx_outgoing_app(tech, format, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL);
+ } else {
+- if (exten && context && pi)
++ if (exten && context && pi) {
+ res = ast_pbx_outgoing_exten(tech, format, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL);
+- else {
++ } else {
+ astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'");
+ return 0;
+ }
+ }
+- if (!res)
++ if (!res) {
+ astman_send_ack(s, m, "Originate successfully queued");
+- else
++ } else {
+ astman_send_error(s, m, "Originate failed");
++ }
+ return 0;
+ }
+
+-/*! \brief Help text for manager command mailboxstatus
+- */
+-static char mandescr_mailboxstatus[] =
+-"Description: Checks a voicemail account for status.\n"
+-"Variables: (Names marked with * are required)\n"
+-" *Mailbox: Full mailbox ID <mailbox>@<vm-context>\n"
+-" ActionID: Optional ActionID for message matching.\n"
+-"Returns number of messages.\n"
+-" Message: Mailbox Status\n"
+-" Mailbox: <mailboxid>\n"
+-" Waiting: <count>\n"
+-"\n";
+-
+ static int action_mailboxstatus(struct mansession *s, const struct message *m)
+ {
+ const char *mailbox = astman_get_header(m, "Mailbox");
+@@ -2522,18 +3136,6 @@
+ return 0;
+ }
+
+-static char mandescr_mailboxcount[] =
+-"Description: Checks a voicemail account for new messages.\n"
+-"Variables: (Names marked with * are required)\n"
+-" *Mailbox: Full mailbox ID <mailbox>@<vm-context>\n"
+-" ActionID: Optional ActionID for message matching.\n"
+-"Returns number of urgent, new and old messages.\n"
+-" Message: Mailbox Message Count\n"
+-" Mailbox: <mailboxid>\n"
+-" UrgentMessages: <count>\n"
+-" NewMessages: <count>\n"
+-" OldMessages: <count>\n"
+-"\n";
+ static int action_mailboxcount(struct mansession *s, const struct message *m)
+ {
+ const char *mailbox = astman_get_header(m, "Mailbox");
+@@ -2555,17 +3157,6 @@
+ return 0;
+ }
+
+-static char mandescr_extensionstate[] =
+-"Description: Report the extension state for given extension.\n"
+-" If the extension has a hint, will use devicestate to check\n"
+-" the status of the device connected to the extension.\n"
+-"Variables: (Names marked with * are required)\n"
+-" *Exten: Extension to check state on\n"
+-" *Context: Context for extension\n"
+-" ActionId: Optional ID for this transaction\n"
+-"Will return an \"Extension Status\" message.\n"
+-"The response will include the hint for the extension and the status.\n";
+-
+ static int action_extensionstate(struct mansession *s, const struct message *m)
+ {
+ const char *exten = astman_get_header(m, "Exten");
+@@ -2576,8 +3167,9 @@
+ astman_send_error(s, m, "Extension not specified");
+ return 0;
+ }
+- if (ast_strlen_zero(context))
++ if (ast_strlen_zero(context)) {
+ context = "default";
++ }
+ status = ast_extension_state(NULL, context, exten);
+ ast_get_hint(hint, sizeof(hint) - 1, NULL, 0, NULL, context, exten);
+ astman_start_ack(s, m);
+@@ -2590,13 +3182,6 @@
+ return 0;
+ }
+
+-static char mandescr_timeout[] =
+-"Description: Hangup a channel after a certain time.\n"
+-"Variables: (Names marked with * are required)\n"
+-" *Channel: Channel name to hangup\n"
+-" *Timeout: Maximum duration of the call (sec)\n"
+-"Acknowledges set time with 'Timeout Set' message\n";
+-
+ static int action_timeout(struct mansession *s, const struct message *m)
+ {
+ struct ast_channel *c;
+@@ -2608,20 +3193,26 @@
+ astman_send_error(s, m, "No channel specified");
+ return 0;
+ }
++
+ if (!timeout || timeout < 0) {
+ astman_send_error(s, m, "No timeout specified");
+ return 0;
+ }
+- c = ast_get_channel_by_name_locked(name);
+- if (!c) {
++
++ if (!(c = ast_channel_get_by_name(name))) {
+ astman_send_error(s, m, "No such channel");
+ return 0;
+ }
+
+ when.tv_usec = (timeout - when.tv_sec) * 1000000.0;
++
++ ast_channel_lock(c);
+ ast_channel_setwhentohangup_tv(c, when);
+ ast_channel_unlock(c);
++ c = ast_channel_unref(c);
++
+ astman_send_ack(s, m, "Timeout Set");
++
+ return 0;
+ }
+
+@@ -2634,7 +3225,7 @@
+ {
+ int ret = 0;
+
+- ast_mutex_lock(&s->session->__lock);
++ ao2_lock(s->session);
+ if (s->session->f != NULL) {
+ struct eventqent *eqe;
+
+@@ -2649,17 +3240,10 @@
+ s->session->last_ev = unref_event(s->session->last_ev);
+ }
+ }
+- ast_mutex_unlock(&s->session->__lock);
++ ao2_unlock(s->session);
+ return ret;
+ }
+
+-static char mandescr_userevent[] =
+-"Description: Send an event to manager sessions.\n"
+-"Variables: (Names marked with * are required)\n"
+-" *UserEvent: EventStringToSend\n"
+-" Header1: Content1\n"
+-" HeaderN: ContentN\n";
+-
+ static int action_userevent(struct mansession *s, const struct message *m)
+ {
+ const char *event = astman_get_header(m, "UserEvent");
+@@ -2678,21 +3262,17 @@
+ return 0;
+ }
+
+-static char mandescr_coresettings[] =
+-"Description: Query for Core PBX settings.\n"
+-"Variables: (Names marked with * are optional)\n"
+-" *ActionID: ActionID of this transaction\n";
+-
+ /*! \brief Show PBX core settings information */
+ static int action_coresettings(struct mansession *s, const struct message *m)
+ {
+ const char *actionid = astman_get_header(m, "ActionID");
+ char idText[150];
+
+- if (!ast_strlen_zero(actionid))
++ if (!ast_strlen_zero(actionid)) {
+ snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid);
+- else
++ } else {
+ idText[0] = '\0';
++ }
+
+ astman_append(s, "Response: Success\r\n"
+ "%s"
+@@ -2703,14 +3283,14 @@
+ "CoreMaxLoadAvg: %f\r\n"
+ "CoreRunUser: %s\r\n"
+ "CoreRunGroup: %s\r\n"
+- "CoreMaxFilehandles: %d\r\n"
++ "CoreMaxFilehandles: %d\r\n"
+ "CoreRealTimeEnabled: %s\r\n"
+ "CoreCDRenabled: %s\r\n"
+ "CoreHTTPenabled: %s\r\n"
+ "\r\n",
+ idText,
+ AMI_VERSION,
+- ast_get_version(),
++ ast_get_version(),
+ ast_config_AST_SYSTEM_NAME,
+ option_maxcalls,
+ option_maxload,
+@@ -2724,70 +3304,61 @@
+ return 0;
+ }
+
+-static char mandescr_corestatus[] =
+-"Description: Query for Core PBX status.\n"
+-"Variables: (Names marked with * are optional)\n"
+-" *ActionID: ActionID of this transaction\n";
+-
+ /*! \brief Show PBX core status information */
+ static int action_corestatus(struct mansession *s, const struct message *m)
+ {
+ const char *actionid = astman_get_header(m, "ActionID");
+ char idText[150];
+- char startuptime[150];
+- char reloadtime[150];
++ char startuptime[150], startupdate[150];
++ char reloadtime[150], reloaddate[150];
+ struct ast_tm tm;
+
+- if (!ast_strlen_zero(actionid))
++ if (!ast_strlen_zero(actionid)) {
+ snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid);
+- else
++ } else {
+ idText[0] = '\0';
++ }
+
+ ast_localtime(&ast_startuptime, &tm, NULL);
+ ast_strftime(startuptime, sizeof(startuptime), "%H:%M:%S", &tm);
++ ast_strftime(startupdate, sizeof(startupdate), "%Y-%m-%d", &tm);
+ ast_localtime(&ast_lastreloadtime, &tm, NULL);
+ ast_strftime(reloadtime, sizeof(reloadtime), "%H:%M:%S", &tm);
++ ast_strftime(reloaddate, sizeof(reloaddate), "%Y-%m-%d", &tm);
+
+ astman_append(s, "Response: Success\r\n"
+ "%s"
++ "CoreStartupDate: %s\r\n"
+ "CoreStartupTime: %s\r\n"
++ "CoreReloadDate: %s\r\n"
+ "CoreReloadTime: %s\r\n"
+ "CoreCurrentCalls: %d\r\n"
+ "\r\n",
+ idText,
++ startupdate,
+ startuptime,
++ reloaddate,
+ reloadtime,
+ ast_active_channels()
+ );
+ return 0;
+ }
+
+-static char mandescr_reload[] =
+-"Description: Send a reload event.\n"
+-"Variables: (Names marked with * are optional)\n"
+-" *ActionID: ActionID of this transaction\n"
+-" *Module: Name of the module to reload\n";
+-
+ /*! \brief Send a reload event */
+ static int action_reload(struct mansession *s, const struct message *m)
+ {
+ const char *module = astman_get_header(m, "Module");
+ int res = ast_module_reload(S_OR(module, NULL));
+
+- if (res == 2)
++ if (res == 2) {
+ astman_send_ack(s, m, "Module Reloaded");
+- else
++ } else {
+ astman_send_error(s, m, s == 0 ? "No such module" : "Module does not support reload");
++ }
+ return 0;
+ }
+
+-static char mandescr_coreshowchannels[] =
+-"Description: List currently defined channels and some information\n"
+-" about them.\n"
+-"Variables:\n"
+-" ActionID: Optional Action id for message matching.\n";
+-
+-/*! \brief Manager command "CoreShowChannels" - List currently defined channels
++/*! \brief Manager command "CoreShowChannels" - List currently defined channels
+ * and some information about them. */
+ static int action_coreshowchannels(struct mansession *s, const struct message *m)
+ {
+@@ -2796,18 +3367,28 @@
+ struct ast_channel *c = NULL;
+ int numchans = 0;
+ int duration, durh, durm, durs;
++ struct ast_channel_iterator *iter;
+
+- if (!ast_strlen_zero(actionid))
++ if (!ast_strlen_zero(actionid)) {
+ snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid);
+- else
++ } else {
+ idText[0] = '\0';
++ }
+
+- astman_send_listack(s, m, "Channels will follow", "start");
++ if (!(iter = ast_channel_iterator_all_new(0))) {
++ astman_send_error(s, m, "Memory Allocation Failure");
++ return 1;
++ }
+
+- while ((c = ast_channel_walk_locked(c)) != NULL) {
+- struct ast_channel *bc = ast_bridged_channel(c);
++ astman_send_listack(s, m, "Channels will follow", "start");
++
++ for (; (c = ast_channel_iterator_next(iter)); ast_channel_unref(c)) {
++ struct ast_channel *bc;
+ char durbuf[10] = "";
+
++ ast_channel_lock(c);
++
++ bc = ast_bridged_channel(c);
+ if (c->cdr && !ast_tvzero(c->cdr->start)) {
+ duration = (int)(ast_tvdiff_ms(ast_tvnow(), c->cdr->start) / 1000);
+ durh = duration / 3600;
+@@ -2836,7 +3417,9 @@
+ "\r\n", idText, c->name, c->uniqueid, c->context, c->exten, c->priority, c->_state,
+ ast_state2str(c->_state), c->appl ? c->appl : "", c->data ? S_OR(c->data, "") : "",
+ S_OR(c->cid.cid_num, ""), durbuf, S_OR(c->accountcode, ""), bc ? bc->name : "", bc ? bc->uniqueid : "");
++
+ ast_channel_unlock(c);
++
+ numchans++;
+ }
+
+@@ -2847,18 +3430,11 @@
+ "%s"
+ "\r\n", numchans, idText);
+
++ ast_channel_iterator_destroy(iter);
++
+ return 0;
+ }
+
+-static char mandescr_modulecheck[] =
+-"Description: Checks if Asterisk module is loaded\n"
+-"Variables: \n"
+-" ActionID: <id> Action ID for this transaction. Will be returned.\n"
+-" Module: <name> Asterisk module name (not including extension)\n"
+-"\n"
+-"Will return Success/Failure\n"
+-"For success returns, the module revision number is included.\n";
+-
+ /* Manager function to check if module is loaded */
+ static int manager_modulecheck(struct mansession *s, const struct message *m)
+ {
+@@ -2891,10 +3467,11 @@
+ version = ast_file_version_find(filename);
+ #endif
+
+- if (!ast_strlen_zero(id))
++ if (!ast_strlen_zero(id)) {
+ snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
+- else
++ } else {
+ idText[0] = '\0';
++ }
+ astman_append(s, "Response: Success\r\n%s", idText);
+ #if !defined(LOW_MEMORY)
+ astman_append(s, "Version: %s\r\n\r\n", version ? version : "");
+@@ -2902,54 +3479,48 @@
+ return 0;
+ }
+
+-static char mandescr_moduleload[] =
+-"Description: Loads, unloads or reloads an Asterisk module in a running system.\n"
+-"Variables: \n"
+-" ActionID: <id> Action ID for this transaction. Will be returned.\n"
+-" Module: <name> Asterisk module name (including .so extension)\n"
+-" or subsystem identifier:\n"
+-" cdr, enum, dnsmgr, extconfig, manager, rtp, http\n"
+-" LoadType: load | unload | reload\n"
+-" The operation to be done on module\n"
+-" If no module is specified for a reload loadtype, all modules are reloaded";
+-
+ static int manager_moduleload(struct mansession *s, const struct message *m)
+ {
+ int res;
+ const char *module = astman_get_header(m, "Module");
+ const char *loadtype = astman_get_header(m, "LoadType");
+
+- if (!loadtype || strlen(loadtype) == 0)
++ if (!loadtype || strlen(loadtype) == 0) {
+ astman_send_error(s, m, "Incomplete ModuleLoad action.");
+- if ((!module || strlen(module) == 0) && strcasecmp(loadtype, "reload") != 0)
++ }
++ if ((!module || strlen(module) == 0) && strcasecmp(loadtype, "reload") != 0) {
+ astman_send_error(s, m, "Need module name");
++ }
+
+ if (!strcasecmp(loadtype, "load")) {
+ res = ast_load_resource(module);
+- if (res)
++ if (res) {
+ astman_send_error(s, m, "Could not load module.");
+- else
++ } else {
+ astman_send_ack(s, m, "Module loaded.");
++ }
+ } else if (!strcasecmp(loadtype, "unload")) {
+ res = ast_unload_resource(module, AST_FORCE_SOFT);
+- if (res)
++ if (res) {
+ astman_send_error(s, m, "Could not unload module.");
+- else
++ } else {
+ astman_send_ack(s, m, "Module unloaded.");
++ }
+ } else if (!strcasecmp(loadtype, "reload")) {
+ if (module != NULL) {
+ res = ast_module_reload(module);
+- if (res == 0)
++ if (res == 0) {
+ astman_send_error(s, m, "No such module.");
+- else if (res == 1)
++ } else if (res == 1) {
+ astman_send_error(s, m, "Module does not support reload action.");
+- else
++ } else {
+ astman_send_ack(s, m, "Module reloaded.");
++ }
+ } else {
+ ast_module_reload(NULL); /* Reload all modules */
+ astman_send_ack(s, m, "All modules reloaded");
+ }
+- } else
++ } else
+ astman_send_error(s, m, "Incomplete ModuleLoad action.");
+ return 0;
+ }
+@@ -2973,21 +3544,21 @@
+ int ret = 0;
+ struct manager_action *tmp;
+ const char *user = astman_get_header(m, "Username");
++ int (*call_func)(struct mansession *s, const struct message *m) = NULL;
+
+ ast_copy_string(action, __astman_get_header(m, "Action", GET_HEADER_SKIP_EMPTY), sizeof(action));
+- ast_debug(1, "Manager received command '%s'\n", action);
+
+ if (ast_strlen_zero(action)) {
+- ast_mutex_lock(&s->session->__lock);
++ mansession_lock(s);
+ astman_send_error(s, m, "Missing action in request");
+- ast_mutex_unlock(&s->session->__lock);
++ mansession_unlock(s);
+ return 0;
+ }
+
+ if (!s->session->authenticated && strcasecmp(action, "Login") && strcasecmp(action, "Logoff") && strcasecmp(action, "Challenge")) {
+- ast_mutex_lock(&s->session->__lock);
++ mansession_lock(s);
+ astman_send_error(s, m, "Permission denied");
+- ast_mutex_unlock(&s->session->__lock);
++ mansession_unlock(s);
+ return 0;
+ }
+
+@@ -2995,34 +3566,42 @@
+ (!strcasecmp(action, "Login") || !strcasecmp(action, "Challenge"))) {
+ if (check_manager_session_inuse(user)) {
+ sleep(1);
+- ast_mutex_lock(&s->session->__lock);
++ mansession_lock(s);
+ astman_send_error(s, m, "Login Already In Use");
+- ast_mutex_unlock(&s->session->__lock);
++ mansession_unlock(s);
+ return -1;
+ }
+ }
+
+ AST_RWLIST_RDLOCK(&actions);
+ AST_RWLIST_TRAVERSE(&actions, tmp, list) {
+- if (strcasecmp(action, tmp->action))
++ if (strcasecmp(action, tmp->action)) {
+ continue;
+- if (s->session->writeperm & tmp->authority || tmp->authority == 0)
+- ret = tmp->func(s, m);
+- else
++ }
++ if (s->session->writeperm & tmp->authority || tmp->authority == 0) {
++ call_func = tmp->func;
++ } else {
+ astman_send_error(s, m, "Permission denied");
++ tmp = NULL;
++ }
+ break;
+ }
+ AST_RWLIST_UNLOCK(&actions);
+
+- if (!tmp) {
++ if (tmp && call_func) {
++ /* call AMI function after actions list are unlocked */
++ ast_debug(1, "Running action '%s'\n", tmp->action);
++ ret = call_func(s, m);
++ } else {
+ char buf[512];
+ snprintf(buf, sizeof(buf), "Invalid/unknown command: %s. Use Action: ListCommands to show available commands.", action);
+- ast_mutex_lock(&s->session->__lock);
++ mansession_lock(s);
+ astman_send_error(s, m, buf);
+- ast_mutex_unlock(&s->session->__lock);
++ mansession_unlock(s);
+ }
+- if (ret)
++ if (ret) {
+ return ret;
++ }
+ /* Once done with our message, deliver any pending events unless the
+ requester doesn't want them as part of this response.
+ */
+@@ -3054,12 +3633,13 @@
+ */
+ for (x = 0; x < s->session->inlen; x++) {
+ int cr; /* set if we have \r */
+- if (src[x] == '\r' && x+1 < s->session->inlen && src[x+1] == '\n')
++ if (src[x] == '\r' && x+1 < s->session->inlen && src[x + 1] == '\n') {
+ cr = 2; /* Found. Update length to include \r\n */
+- else if (src[x] == '\n')
++ } else if (src[x] == '\n') {
+ cr = 1; /* also accept \n only */
+- else
++ } else {
+ continue;
++ }
+ memmove(output, src, x); /*... but trim \r\n */
+ output[x] = '\0'; /* terminate the string */
+ x += cr; /* number of bytes used */
+@@ -3075,40 +3655,42 @@
+ res = 0;
+ while (res == 0) {
+ /* XXX do we really need this locking ? */
+- ast_mutex_lock(&s->session->__lock);
++ mansession_lock(s);
+ if (s->session->pending_event) {
+ s->session->pending_event = 0;
+- ast_mutex_unlock(&s->session->__lock);
++ mansession_unlock(s);
+ return 0;
+ }
+ s->session->waiting_thread = pthread_self();
+- ast_mutex_unlock(&s->session->__lock);
++ mansession_unlock(s);
+
+ res = ast_wait_for_input(s->session->fd, -1); /* return 0 on timeout ? */
+
+- ast_mutex_lock(&s->session->__lock);
++ mansession_lock(s);
+ s->session->waiting_thread = AST_PTHREADT_NULL;
+- ast_mutex_unlock(&s->session->__lock);
++ mansession_unlock(s);
+ }
+ if (res < 0) {
+ /* If we get a signal from some other thread (typically because
+ * there are new events queued), return 0 to notify the caller.
+ */
+- if (errno == EINTR || errno == EAGAIN)
++ if (errno == EINTR || errno == EAGAIN) {
+ return 0;
++ }
+ ast_log(LOG_WARNING, "poll() returned error: %s\n", strerror(errno));
+ return -1;
+ }
+- ast_mutex_lock(&s->session->__lock);
++
++ mansession_lock(s);
+ res = fread(src + s->session->inlen, 1, maxlen - s->session->inlen, s->session->f);
+- if (res < 1)
++ if (res < 1) {
+ res = -1; /* error return */
+- else {
++ } else {
+ s->session->inlen += res;
+ src[s->session->inlen] = '\0';
+ res = 0;
+ }
+- ast_mutex_unlock(&s->session->__lock);
++ mansession_unlock(s);
+ return res;
+ }
+
+@@ -3120,16 +3702,18 @@
+
+ for (;;) {
+ /* Check if any events are pending and do them if needed */
+- if (process_events(s))
++ if (process_events(s)) {
+ return -1;
++ }
+ res = get_input(s, header_buf);
+ if (res == 0) {
+ continue;
+ } else if (res > 0) {
+- if (ast_strlen_zero(header_buf))
++ if (ast_strlen_zero(header_buf)) {
+ return process_message(s, &m) ? -1 : 0;
+- else if (m.hdrcount < (AST_MAX_MANHEADERS - 1))
++ } else if (m.hdrcount < (AST_MAX_MANHEADERS - 1)) {
+ m.headers[m.hdrcount++] = ast_strdupa(header_buf);
++ }
+ } else {
+ return res;
+ }
+@@ -3147,56 +3731,53 @@
+ static void *session_do(void *data)
+ {
+ struct ast_tcptls_session_instance *ser = data;
+- struct mansession_session *session = ast_calloc(1, sizeof(*session));
+- struct mansession s = {.session = NULL, };
++ struct mansession_session *session = build_mansession(ser->remote_address);
++ struct mansession s = { NULL, };
+ int flags;
+ int res;
+
+- if (session == NULL)
++ if (session == NULL) {
+ goto done;
++ }
+
+- session->writetimeout = 100;
+- session->waiting_thread = AST_PTHREADT_NULL;
+-
+ flags = fcntl(ser->fd, F_GETFL);
+- if (!block_sockets) /* make sure socket is non-blocking */
++ if (!block_sockets) { /* make sure socket is non-blocking */
+ flags |= O_NONBLOCK;
+- else
++ } else {
+ flags &= ~O_NONBLOCK;
++ }
+ fcntl(ser->fd, F_SETFL, flags);
+
+- ast_mutex_init(&session->__lock);
+- session->send_events = -1;
++ ao2_lock(session);
+ /* Hook to the tail of the event queue */
+ session->last_ev = grab_last();
+
++ ast_mutex_init(&s.lock);
++
+ /* these fields duplicate those in the 'ser' structure */
+- session->fd = ser->fd;
+- session->f = ser->f;
++ session->fd = s.fd = ser->fd;
++ session->f = s.f = ser->f;
+ session->sin = ser->remote_address;
+ s.session = session;
+
+ AST_LIST_HEAD_INIT_NOLOCK(&session->datastores);
+
+- AST_LIST_LOCK(&sessions);
+- AST_LIST_INSERT_HEAD(&sessions, session, list);
+- ast_atomic_fetchadd_int(&num_sessions, 1);
+- AST_LIST_UNLOCK(&sessions);
+-
++ ao2_unlock(session);
+ astman_append(&s, "Asterisk Call Manager/%s\r\n", AMI_VERSION); /* welcome prompt */
+ for (;;) {
+- if ((res = do_message(&s)) < 0)
++ if ((res = do_message(&s)) < 0) {
+ break;
++ }
+ }
+ /* session is over, explain why and terminate */
+ if (session->authenticated) {
+- if (manager_displayconnects(session))
++ if (manager_displayconnects(session)) {
+ ast_verb(2, "Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr));
+- ast_log(LOG_EVENT, "Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr));
++ }
+ } else {
+- if (displayconnects)
++ if (displayconnects) {
+ ast_verb(2, "Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(session->sin.sin_addr));
+- ast_log(LOG_EVENT, "Failed attempt from %s\n", ast_inet_ntoa(session->sin.sin_addr));
++ }
+ }
+
+ /* It is possible under certain circumstances for this session thread
+@@ -3212,8 +3793,9 @@
+ */
+ usleep(1);
+
+- destroy_session(session);
++ session_destroy(session);
+
++ ast_mutex_destroy(&s.lock);
+ done:
+ ao2_ref(ser, -1);
+ ser = NULL;
+@@ -3225,23 +3807,24 @@
+ {
+ struct mansession_session *session;
+ time_t now = time(NULL);
++ struct ao2_iterator i;
+
+- AST_LIST_LOCK(&sessions);
+- AST_LIST_TRAVERSE_SAFE_BEGIN(&sessions, session, list) {
++ i = ao2_iterator_init(sessions, 0);
++ while ((session = ao2_iterator_next(&i)) && n_max > 0) {
++ ao2_lock(session);
+ if (session->sessiontimeout && (now > session->sessiontimeout) && !session->inuse) {
+- AST_LIST_REMOVE_CURRENT(list);
+- ast_atomic_fetchadd_int(&num_sessions, -1);
+ if (session->authenticated && (VERBOSITY_ATLEAST(2)) && manager_displayconnects(session)) {
+ ast_verb(2, "HTTP Manager '%s' timed out from %s\n",
+ session->username, ast_inet_ntoa(session->sin.sin_addr));
+ }
+- free_session(session); /* XXX outside ? */
+- if (--n_max <= 0)
+- break;
++ ao2_unlock(session);
++ session_destroy(session);
++ n_max--;
++ } else {
++ ao2_unlock(session);
++ unref_mansession(session);
+ }
+ }
+- AST_LIST_TRAVERSE_SAFE_END;
+- AST_LIST_UNLOCK(&sessions);
+ }
+
+ /*
+@@ -3253,8 +3836,9 @@
+ struct eventqent *tmp = ast_malloc(sizeof(*tmp) + strlen(str));
+ static int seq; /* sequence number */
+
+- if (!tmp)
++ if (!tmp) {
+ return -1;
++ }
+
+ /* need to init all fields, because ast_malloc() does not */
+ tmp->usecount = 0;
+@@ -3286,12 +3870,9 @@
+ struct timeval now;
+ struct ast_str *buf;
+
+- /* Abort if there aren't any manager sessions */
+- if (!num_sessions)
+- return 0;
+-
+- if (!(buf = ast_str_thread_get(&manager_event_buf, MANAGER_EVENT_BUF_INITSIZE)))
++ if (!(buf = ast_str_thread_get(&manager_event_buf, MANAGER_EVENT_BUF_INITSIZE))) {
+ return -1;
++ }
+
+ cat_str = authority_to_str(category, &auth);
+ ast_str_set(&buf, 0,
+@@ -3322,21 +3903,25 @@
+ append_event(ast_str_buffer(buf), category);
+
+ /* Wake up any sleeping sessions */
+- AST_LIST_LOCK(&sessions);
+- AST_LIST_TRAVERSE(&sessions, session, list) {
+- ast_mutex_lock(&session->__lock);
+- if (session->waiting_thread != AST_PTHREADT_NULL)
+- pthread_kill(session->waiting_thread, SIGURG);
+- else
+- /* We have an event to process, but the mansession is
+- * not waiting for it. We still need to indicate that there
+- * is an event waiting so that get_input processes the pending
+- * event instead of polling.
+- */
+- session->pending_event = 1;
+- ast_mutex_unlock(&session->__lock);
++ if (sessions) {
++ struct ao2_iterator i;
++ i = ao2_iterator_init(sessions, 0);
++ while ((session = ao2_iterator_next(&i))) {
++ ao2_lock(session);
++ if (session->waiting_thread != AST_PTHREADT_NULL) {
++ pthread_kill(session->waiting_thread, SIGURG);
++ } else {
++ /* We have an event to process, but the mansession is
++ * not waiting for it. We still need to indicate that there
++ * is an event waiting so that get_input processes the pending
++ * event instead of polling.
++ */
++ session->pending_event = 1;
++ }
++ ao2_unlock(session);
++ unref_mansession(session);
++ }
+ }
+- AST_LIST_UNLOCK(&sessions);
+
+ AST_RWLIST_RDLOCK(&manager_hooks);
+ AST_RWLIST_TRAVERSE(&manager_hooks, hook, list) {
+@@ -3362,6 +3947,7 @@
+ AST_RWLIST_TRAVERSE_SAFE_BEGIN(&actions, cur, list) {
+ if (!strcasecmp(action, cur->action)) {
+ AST_RWLIST_REMOVE_CURRENT(list);
++ ast_string_field_free_memory(cur);
+ ast_free(cur);
+ ast_verb(2, "Manager unregistered action %s\n", action);
+ break;
+@@ -3405,10 +3991,11 @@
+ }
+ }
+
+- if (prev)
++ if (prev) {
+ AST_RWLIST_INSERT_AFTER(&actions, prev, act, list);
+- else
++ } else {
+ AST_RWLIST_INSERT_HEAD(&actions, act, list);
++ }
+
+ ast_verb(2, "Manager registered action %s\n", act->action);
+
+@@ -3422,16 +4009,53 @@
+ int ast_manager_register2(const char *action, int auth, int (*func)(struct mansession *s, const struct message *m), const char *synopsis, const char *description)
+ {
+ struct manager_action *cur = NULL;
++#ifdef AST_XML_DOCS
++ char *tmpxml;
++#endif
+
+- if (!(cur = ast_calloc(1, sizeof(*cur))))
++ if (!(cur = ast_calloc(1, sizeof(*cur)))) {
+ return -1;
++ }
+
++ if (ast_string_field_init(cur, 128)) {
++ ast_free(cur);
++ return -1;
++ }
++
+ cur->action = action;
+ cur->authority = auth;
+ cur->func = func;
+- cur->synopsis = synopsis;
+- cur->description = description;
++#ifdef AST_XML_DOCS
++ if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) {
++ tmpxml = ast_xmldoc_build_synopsis("manager", action);
++ ast_string_field_set(cur, synopsis, tmpxml);
++ ast_free(tmpxml);
+
++ tmpxml = ast_xmldoc_build_syntax("manager", action);
++ ast_string_field_set(cur, syntax, tmpxml);
++ ast_free(tmpxml);
++
++ tmpxml = ast_xmldoc_build_description("manager", action);
++ ast_string_field_set(cur, description, tmpxml);
++ ast_free(tmpxml);
++
++ tmpxml = ast_xmldoc_build_seealso("manager", action);
++ ast_string_field_set(cur, seealso, tmpxml);
++ ast_free(tmpxml);
++
++ tmpxml = ast_xmldoc_build_arguments("manager", action);
++ ast_string_field_set(cur, arguments, tmpxml);
++ ast_free(tmpxml);
++
++ cur->docsrc = AST_XML_DOC;
++ } else {
++#endif
++ ast_string_field_set(cur, synopsis, synopsis);
++ ast_string_field_set(cur, description, description);
++#ifdef AST_XML_DOCS
++ cur->docsrc = AST_STATIC_DOC;
++ }
++#endif
+ if (ast_manager_register_struct(cur)) {
+ ast_free(cur);
+ return -1;
+@@ -3460,7 +4084,7 @@
+ FORMAT_XML,
+ };
+
+-static char *contenttype[] = {
++static const char * const contenttype[] = {
+ [FORMAT_RAW] = "plain",
+ [FORMAT_HTML] = "html",
+ [FORMAT_XML] = "xml",
+@@ -3474,26 +4098,62 @@
+ static struct mansession_session *find_session(uint32_t ident, int incinuse)
+ {
+ struct mansession_session *session;
++ struct ao2_iterator i;
+
+- if (ident == 0)
++ if (ident == 0) {
+ return NULL;
++ }
+
+- AST_LIST_LOCK(&sessions);
+- AST_LIST_TRAVERSE(&sessions, session, list) {
+- ast_mutex_lock(&session->__lock);
++ i = ao2_iterator_init(sessions, 0);
++ while ((session = ao2_iterator_next(&i))) {
++ ao2_lock(session);
+ if (session->managerid == ident && !session->needdestroy) {
+ ast_atomic_fetchadd_int(&session->inuse, incinuse ? 1 : 0);
+ break;
+ }
+- ast_mutex_unlock(&session->__lock);
++ ao2_unlock(session);
++ unref_mansession(session);
+ }
+- AST_LIST_UNLOCK(&sessions);
+
+ return session;
+ }
+
+-int astman_is_authed(uint32_t ident)
++/*!
++ * locate an http session in the list.
++ * The search keys (nonce) and (username) is value from received
++ * "Authorization" http header.
++ * As well as in find_session() function, the value of the nonce can't be zero.
++ * (0 meansi, that the session used for AMI socket connection).
++ * Flag (stale) is set, if client used valid, but old, nonce value.
++ *
++ */
++static struct mansession_session *find_session_by_nonce(const char *username, unsigned long nonce, int *stale)
+ {
++ struct mansession_session *session;
++ struct ao2_iterator i;
++
++ if (nonce == 0 || username == NULL || stale == NULL) {
++ return NULL;
++ }
++
++ i = ao2_iterator_init(sessions, 0);
++ while ((session = ao2_iterator_next(&i))) {
++ ao2_lock(session);
++ if (!strcasecmp(session->username, username) && session->managerid == nonce) {
++ *stale = 0;
++ break;
++ } else if (!strcasecmp(session->username, username) && session->oldnonce == nonce) {
++ *stale = 1;
++ break;
++ }
++ ao2_unlock(session);
++ unref_mansession(session);
++ }
++ return session;
++}
++
++int astman_is_authed(uint32_t ident)
++{
+ int authed;
+ struct mansession_session *session;
+
+@@ -3502,7 +4162,8 @@
+
+ authed = (session->authenticated != 0);
+
+- ast_mutex_unlock(&session->__lock);
++ ao2_unlock(session);
++ unref_mansession(session);
+
+ return authed;
+ }
+@@ -3511,18 +4172,24 @@
+ {
+ int result = 0;
+ struct mansession_session *session;
++ struct ao2_iterator i;
+
+- AST_LIST_LOCK(&sessions);
+- AST_LIST_TRAVERSE(&sessions, session, list) {
+- ast_mutex_lock(&session->__lock);
++ if (ident == 0) {
++ return 0;
++ }
++
++ i = ao2_iterator_init(sessions, 0);
++ while ((session = ao2_iterator_next(&i))) {
++ ao2_lock(session);
+ if ((session->managerid == ident) && (session->readperm & perm)) {
+ result = 1;
+- ast_mutex_unlock(&session->__lock);
++ ao2_unlock(session);
++ unref_mansession(session);
+ break;
+ }
+- ast_mutex_unlock(&session->__lock);
++ ao2_unlock(session);
++ unref_mansession(session);
+ }
+- AST_LIST_UNLOCK(&sessions);
+ return result;
+ }
+
+@@ -3530,18 +4197,24 @@
+ {
+ int result = 0;
+ struct mansession_session *session;
++ struct ao2_iterator i;
+
+- AST_LIST_LOCK(&sessions);
+- AST_LIST_TRAVERSE(&sessions, session, list) {
+- ast_mutex_lock(&session->__lock);
++ if (ident == 0) {
++ return 0;
++ }
++
++ i = ao2_iterator_init(sessions, 0);
++ while ((session = ao2_iterator_next(&i))) {
++ ao2_lock(session);
+ if ((session->managerid == ident) && (session->writeperm & perm)) {
+ result = 1;
+- ast_mutex_unlock(&session->__lock);
++ ao2_unlock(session);
++ unref_mansession(session);
+ break;
+ }
+- ast_mutex_unlock(&session->__lock);
++ ao2_unlock(session);
++ unref_mansession(session);
+ }
+- AST_LIST_UNLOCK(&sessions);
+ return result;
+ }
+
+@@ -3563,10 +4236,11 @@
+ ast_str_append(out, 0, "%s", buf);
+ dst = buf;
+ space = sizeof(buf);
+- if (*src == '\0')
++ if (*src == '\0') {
+ break;
++ }
+ }
+-
++
+ if ( (mode & 2) && !isalnum(*src)) {
+ *dst++ = '_';
+ space--;
+@@ -3611,29 +4285,11 @@
+ int count;
+ };
+
+-static int compress_char(char c)
+-{
+- c &= 0x7f;
+- if (c < 32)
+- return 0;
+- else if (c >= 'a' && c <= 'z')
+- return c - 64;
+- else if (c > 'z')
+- return '_';
+- else
+- return c - 32;
+-}
+-
+ static int variable_count_hash_fn(const void *vvc, const int flags)
+ {
+ const struct variable_count *vc = vvc;
+- int res = 0, i;
+- for (i = 0; i < 5; i++) {
+- if (vc->varname[i] == '\0')
+- break;
+- res += compress_char(vc->varname[i]) << (i * 6);
+- }
+- return res;
++
++ return ast_str_hash(vc->varname);
+ }
+
+ static int variable_count_cmp_fn(void *obj, void *vstr, int flags)
+@@ -3662,7 +4318,7 @@
+ *
+ * General: the unformatted text is used as a value of
+ * XML output: to be completed
+- *
++ *
+ * \verbatim
+ * Each section is within <response type="object" id="xxx">
+ * where xxx is taken from ajaxdest variable or defaults to unknown
+@@ -3675,7 +4331,7 @@
+ * Sections (blank lines in the input) are separated by a <HR>
+ *
+ */
+-static void xml_translate(struct ast_str **out, char *in, struct ast_variable *vars, enum output_format format)
++static void xml_translate(struct ast_str **out, char *in, struct ast_variable *get_vars, enum output_format format)
+ {
+ struct ast_variable *v;
+ const char *dest = NULL;
+@@ -3687,30 +4343,41 @@
+ struct variable_count *vc = NULL;
+ struct ao2_container *vco = NULL;
+
+- for (v = vars; v; v = v->next) {
+- if (!dest && !strcasecmp(v->name, "ajaxdest"))
+- dest = v->value;
+- else if (!objtype && !strcasecmp(v->name, "ajaxobjtype"))
+- objtype = v->value;
++ if (xml) {
++ /* dest and objtype need only for XML format */
++ for (v = get_vars; v; v = v->next) {
++ if (!strcasecmp(v->name, "ajaxdest")) {
++ dest = v->value;
++ } else if (!strcasecmp(v->name, "ajaxobjtype")) {
++ objtype = v->value;
++ }
++ }
++ if (ast_strlen_zero(dest)) {
++ dest = "unknown";
++ }
++ if (ast_strlen_zero(objtype)) {
++ objtype = "generic";
++ }
+ }
+- if (!dest)
+- dest = "unknown";
+- if (!objtype)
+- objtype = "generic";
+
+ /* we want to stop when we find an empty line */
+ while (in && *in) {
+ val = strsep(&in, "\r\n"); /* mark start and end of line */
+- if (in && *in == '\n') /* remove trailing \n if any */
++ if (in && *in == '\n') { /* remove trailing \n if any */
+ in++;
++ }
+ ast_trim_blanks(val);
+ ast_debug(5, "inobj %d in_data %d line <%s>\n", inobj, in_data, val);
+ if (ast_strlen_zero(val)) {
+- if (in_data) { /* close data */
++ /* empty line */
++ if (in_data) {
++ /* close data in Opaque mode */
+ ast_str_append(out, 0, xml ? "'" : "</td></tr>\n");
+ in_data = 0;
+ }
++
+ if (inobj) {
++ /* close block */
+ ast_str_append(out, 0, xml ? " /></response>\n" :
+ "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
+ inobj = 0;
+@@ -3720,54 +4387,57 @@
+ continue;
+ }
+
+- /* we expect Name: value lines */
+- if (in_data) {
+- var = NULL;
+- } else {
+- var = strsep(&val, ":");
+- if (val) { /* found the field name */
+- val = ast_skip_blanks(val);
+- ast_trim_blanks(var);
+- } else { /* field name not found, move to opaque mode */
+- val = var;
+- var = "Opaque-data";
+- }
+- }
+-
+ if (!inobj) {
+- if (xml)
++ /* start new block */
++ if (xml) {
+ ast_str_append(out, 0, "<response type='object' id='%s'><%s", dest, objtype);
+- else
+- ast_str_append(out, 0, "<body>\n");
++ }
+ vco = ao2_container_alloc(37, variable_count_hash_fn, variable_count_cmp_fn);
+ inobj = 1;
+ }
+
+- if (!in_data) { /* build appropriate line start */
+- ast_str_append(out, 0, xml ? " " : "<tr><td>");
+- if ((vc = ao2_find(vco, var, 0)))
+- vc->count++;
+- else {
+- /* Create a new entry for this one */
+- vc = ao2_alloc(sizeof(*vc), NULL);
+- vc->varname = var;
+- vc->count = 1;
+- ao2_link(vco, vc);
+- }
+- xml_copy_escape(out, var, xml ? 1 | 2 : 0);
+- if (vc->count > 1)
+- ast_str_append(out, 0, "-%d", vc->count);
+- ao2_ref(vc, -1);
+- ast_str_append(out, 0, xml ? "='" : "</td><td>");
+- if (!strcmp(var, "Opaque-data"))
+- in_data = 1;
++ if (in_data) {
++ /* Process data field in Opaque mode */
++ xml_copy_escape(out, val, 0); /* data field */
++ ast_str_append(out, 0, xml ? "\n" : "<br>\n");
++ continue;
+ }
++
++ /* We expect "Name: value" line here */
++ var = strsep(&val, ":");
++ if (val) {
++ /* found the field name */
++ val = ast_skip_blanks(val);
++ ast_trim_blanks(var);
++ } else {
++ /* field name not found, switch to opaque mode */
++ val = var;
++ var = "Opaque-data";
++ in_data = 1;
++ }
++
++
++ ast_str_append(out, 0, xml ? " " : "<tr><td>");
++ if ((vc = ao2_find(vco, var, 0))) {
++ vc->count++;
++ } else {
++ /* Create a new entry for this one */
++ vc = ao2_alloc(sizeof(*vc), NULL);
++ vc->varname = var;
++ vc->count = 1;
++ ao2_link(vco, vc);
++ }
++
++ xml_copy_escape(out, var, xml ? 1 | 2 : 0); /* data name */
++ if (vc->count > 1) {
++ ast_str_append(out, 0, "-%d", vc->count);
++ }
++ ao2_ref(vc, -1);
++ ast_str_append(out, 0, xml ? "='" : "</td><td>");
+ xml_copy_escape(out, val, 0); /* data field */
+- if (!in_data)
+- ast_str_append(out, 0, xml ? "'" : "</td></tr>\n");
+- else
+- ast_str_append(out, 0, xml ? "\n" : "<br>\n");
++ ast_str_append(out, 0, xml ? "'" : "</td></tr>\n");
+ }
++
+ if (inobj) {
+ ast_str_append(out, 0, xml ? " /></response>\n" :
+ "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
+@@ -3775,43 +4445,55 @@
+ }
+ }
+
+-static struct ast_str *generic_http_callback(enum output_format format,
+- struct sockaddr_in *remote_address, const char *uri, enum ast_http_method method,
+- struct ast_variable *params, int *status,
+- char **title, int *contentlength)
++static int generic_http_callback(struct ast_tcptls_session_instance *ser,
++ enum ast_http_method method,
++ enum output_format format,
++ struct sockaddr_in *remote_address, const char *uri,
++ struct ast_variable *get_params,
++ struct ast_variable *headers)
+ {
+ struct mansession s = {.session = NULL, };
+ struct mansession_session *session = NULL;
+ uint32_t ident = 0;
+ int blastaway = 0;
+- struct ast_variable *v;
++ struct ast_variable *v, *cookies, *params = get_params;
+ char template[] = "/tmp/ast-http-XXXXXX"; /* template for temporary file */
+- struct ast_str *out = NULL;
++ struct ast_str *http_header = NULL, *out = NULL;
+ struct message m = { 0 };
+ unsigned int x;
+ size_t hdrlen;
+
+- for (v = params; v; v = v->next) {
++ if (method != AST_HTTP_GET && method != AST_HTTP_HEAD && method != AST_HTTP_POST) {
++ ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method");
++ return -1;
++ }
++
++ cookies = ast_http_get_cookies(headers);
++ for (v = cookies; v; v = v->next) {
+ if (!strcasecmp(v->name, "mansession_id")) {
+ sscanf(v->value, "%x", &ident);
+ break;
+ }
+ }
++ if (cookies) {
++ ast_variables_destroy(cookies);
++ }
+
+ if (!(session = find_session(ident, 1))) {
++
++ /**/
+ /* Create new session.
+ * While it is not in the list we don't need any locking
+ */
+- if (!(session = ast_calloc(1, sizeof(*session)))) {
+- *status = 500;
+- goto generic_callback_out;
++ if (!(session = build_mansession(*remote_address))) {
++ ast_http_error(ser, 500, "Server Error", "Internal Server Error (out of memory)\n");
++ return -1;
+ }
++ ao2_lock(session);
+ session->sin = *remote_address;
+ session->fd = -1;
+ session->waiting_thread = AST_PTHREADT_NULL;
+ session->send_events = 0;
+- ast_mutex_init(&session->__lock);
+- ast_mutex_lock(&session->__lock);
+ session->inuse = 1;
+ /*!\note There is approximately a 1 in 1.8E19 chance that the following
+ * calculation will produce 0, which is an invalid ID, but due to the
+@@ -3821,25 +4503,38 @@
+ while ((session->managerid = ast_random() ^ (unsigned long) session) == 0);
+ session->last_ev = grab_last();
+ AST_LIST_HEAD_INIT_NOLOCK(&session->datastores);
+- AST_LIST_LOCK(&sessions);
+- AST_LIST_INSERT_HEAD(&sessions, session, list);
+- ast_atomic_fetchadd_int(&num_sessions, 1);
+- AST_LIST_UNLOCK(&sessions);
+ }
++ ao2_unlock(session);
+
+- s.session = session;
++ http_header = ast_str_create(128);
++ out = ast_str_create(2048);
+
+- ast_mutex_unlock(&session->__lock);
++ ast_mutex_init(&s.lock);
+
+- if (!(out = ast_str_create(1024))) {
+- *status = 500;
++ if (http_header == NULL || out == NULL) {
++ ast_http_error(ser, 500, "Server Error", "Internal Server Error (ast_str_create() out of memory)\n");
+ goto generic_callback_out;
+ }
+
++ s.session = session;
+ s.fd = mkstemp(template); /* create a temporary file for command output */
+ unlink(template);
++ if (s.fd <= -1) {
++ ast_http_error(ser, 500, "Server Error", "Internal Server Error (mkstemp failed)\n");
++ goto generic_callback_out;
++ }
+ s.f = fdopen(s.fd, "w+");
++ if (!s.f) {
++ ast_log(LOG_WARNING, "HTTP Manager, fdopen failed: %s!\n", strerror(errno));
++ ast_http_error(ser, 500, "Server Error", "Internal Server Error (fdopen failed)\n");
++ close(s.fd);
++ goto generic_callback_out;
++ }
+
++ if (method == AST_HTTP_POST) {
++ params = ast_http_get_post_vars(ser, headers);
++ }
++
+ for (x = 0, v = params; v && (x < AST_MAX_MANHEADERS); x++, v = v->next) {
+ hdrlen = strlen(v->name) + strlen(v->value) + 3;
+ m.headers[m.hdrcount] = alloca(hdrlen);
+@@ -3853,24 +4548,21 @@
+ if (manager_displayconnects(session)) {
+ ast_verb(2, "HTTP Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr));
+ }
+- ast_log(LOG_EVENT, "HTTP Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr));
+ } else {
+ if (displayconnects) {
+ ast_verb(2, "HTTP Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(session->sin.sin_addr));
+ }
+- ast_log(LOG_EVENT, "HTTP Failed attempt from %s\n", ast_inet_ntoa(session->sin.sin_addr));
+ }
+ session->needdestroy = 1;
+ }
+
+- ast_str_append(&out, 0,
+- "Content-type: text/%s\r\n"
+- "Cache-Control: no-cache;\r\n"
+- "Set-Cookie: mansession_id=\"%08x\"; Version=\"1\"; Max-Age=%d\r\n"
+- "Pragma: SuppressEvents\r\n"
+- "\r\n",
+- contenttype[format],
+- session->managerid, httptimeout);
++ ast_str_append(&http_header, 0,
++ "Content-type: text/%s\r\n"
++ "Cache-Control: no-cache;\r\n"
++ "Set-Cookie: mansession_id=\"%08x\"; Version=\"1\"; Max-Age=%d"
++ "Pragma: SuppressEvents\r\n",
++ contenttype[format],
++ session->managerid, httptimeout);
+
+ if (format == FORMAT_XML) {
+ ast_str_append(&out, 0, "<ajax-response>\n");
+@@ -3883,7 +4575,7 @@
+
+ #define ROW_FMT "<tr><td colspan=\"2\" bgcolor=\"#f1f1ff\">%s</td></tr>\r\n"
+ #define TEST_STRING \
+- "<form action=\"manager\">\n\
++ "<form action=\"manager\" method=\"post\">\n\
+ Action: <select name=\"action\">\n\
+ <option value=\"\">-----&gt;</option>\n\
+ <option value=\"login\">login</option>\n\
+@@ -3905,13 +4597,16 @@
+ if (s.f != NULL) { /* have temporary output */
+ char *buf;
+ size_t l = ftell(s.f);
+-
++
+ if (l) {
+- if ((buf = mmap(NULL, l, PROT_READ | PROT_WRITE, MAP_SHARED, s.fd, 0))) {
+- if (format == FORMAT_XML || format == FORMAT_HTML)
++ if (MAP_FAILED == (buf = mmap(NULL, l, PROT_READ | PROT_WRITE, MAP_PRIVATE, s.fd, 0))) {
++ ast_log(LOG_WARNING, "mmap failed. Manager output was not processed\n");
++ } else {
++ if (format == FORMAT_XML || format == FORMAT_HTML) {
+ xml_translate(&out, buf, params, format);
+- else
++ } else {
+ ast_str_append(&out, 0, "%s", buf);
++ }
+ munmap(buf, l);
+ }
+ } else if (format == FORMAT_XML || format == FORMAT_HTML) {
+@@ -3924,10 +4619,11 @@
+
+ if (format == FORMAT_XML) {
+ ast_str_append(&out, 0, "</ajax-response>\n");
+- } else if (format == FORMAT_HTML)
++ } else if (format == FORMAT_HTML) {
+ ast_str_append(&out, 0, "</table></body>\r\n");
++ }
+
+- ast_mutex_lock(&session->__lock);
++ ao2_lock(session);
+ /* Reset HTTP timeout. If we're not authenticated, keep it extremely short */
+ session->sessiontimeout = time(NULL) + ((session->authenticated || httptimeout < 5) ? httptimeout : 5);
+
+@@ -3937,64 +4633,447 @@
+ blastaway = 1;
+ } else {
+ ast_debug(1, "Need destroy, but can't do it yet!\n");
+- if (session->waiting_thread != AST_PTHREADT_NULL)
++ if (session->waiting_thread != AST_PTHREADT_NULL) {
+ pthread_kill(session->waiting_thread, SIGURG);
++ }
+ session->inuse--;
+ }
+- } else
++ } else {
+ session->inuse--;
+- ast_mutex_unlock(&session->__lock);
++ }
++ ao2_unlock(session);
+
+- if (blastaway)
+- destroy_session(session);
++ ast_http_send(ser, method, 200, NULL, http_header, out, 0, 0);
++ http_header = out = NULL;
++
+ generic_callback_out:
+- if (*status != 200)
+- return ast_http_error(500, "Server Error", NULL, "Internal Server Error (out of memory)\n");
+- return out;
++ ast_mutex_destroy(&s.lock);
++
++ /* Clear resource */
++
++ if (method == AST_HTTP_POST && params) {
++ ast_variables_destroy(params);
++ }
++ if (http_header) {
++ ast_free(http_header);
++ }
++ if (out) {
++ ast_free(out);
++ }
++
++ if (session && blastaway) {
++ session_destroy(session);
++ } else if (session && session->f) {
++ fclose(session->f);
++ session->f = NULL;
++ }
++
++ return 0;
+ }
+
+-static struct ast_str *manager_http_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *params, struct ast_variable *headers, int *status, char **title, int *contentlength)
++static int auth_http_callback(struct ast_tcptls_session_instance *ser,
++ enum ast_http_method method,
++ enum output_format format,
++ struct sockaddr_in *remote_address, const char *uri,
++ struct ast_variable *get_params,
++ struct ast_variable *headers)
+ {
+- return generic_http_callback(FORMAT_HTML, &ser->remote_address, uri, method, params, status, title, contentlength);
++ struct mansession_session *session = NULL;
++ struct mansession s = { NULL, };
++ struct ast_variable *v, *params = get_params;
++ char template[] = "/tmp/ast-http-XXXXXX"; /* template for temporary file */
++ struct ast_str *http_header = NULL, *out = NULL;
++ size_t result_size = 512;
++ struct message m = { 0 };
++ unsigned int x;
++ size_t hdrlen;
++
++ time_t time_now = time(NULL);
++ unsigned long nonce = 0, nc;
++ struct ast_http_digest d = { NULL, };
++ struct ast_manager_user *user = NULL;
++ int stale = 0;
++ char resp_hash[256]="";
++ /* Cache for user data */
++ char u_username[80];
++ int u_readperm;
++ int u_writeperm;
++ int u_writetimeout;
++ int u_displayconnects;
++
++ if (method != AST_HTTP_GET && method != AST_HTTP_HEAD && method != AST_HTTP_POST) {
++ ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method");
++ return -1;
++ }
++
++ /* Find "Authorization: " header */
++ for (v = headers; v; v = v->next) {
++ if (!strcasecmp(v->name, "Authorization")) {
++ break;
++ }
++ }
++
++ if (!v || ast_strlen_zero(v->value)) {
++ goto out_401; /* Authorization Header not present - send auth request */
++ }
++
++ /* Digest found - parse */
++ if (ast_string_field_init(&d, 128)) {
++ ast_http_error(ser, 500, "Server Error", "Internal Server Error (out of memory)\n");
++ return -1;
++ }
++
++ if (ast_parse_digest(v->value, &d, 0, 1)) {
++ /* Error in Digest - send new one */
++ nonce = 0;
++ goto out_401;
++ }
++ if (sscanf(d.nonce, "%lx", &nonce) != 1) {
++ ast_log(LOG_WARNING, "Received incorrect nonce in Digest <%s>\n", d.nonce);
++ nonce = 0;
++ goto out_401;
++ }
++
++ AST_RWLIST_WRLOCK(&users);
++ user = get_manager_by_name_locked(d.username);
++ if(!user) {
++ AST_RWLIST_UNLOCK(&users);
++ ast_log(LOG_NOTICE, "%s tried to authenticate with nonexistent user '%s'\n", ast_inet_ntoa(remote_address->sin_addr), d.username);
++ nonce = 0;
++ goto out_401;
++ }
++
++ /* --- We have User for this auth, now check ACL */
++ if (user->ha && !ast_apply_ha(user->ha, remote_address)) {
++ AST_RWLIST_UNLOCK(&users);
++ ast_log(LOG_NOTICE, "%s failed to pass IP ACL as '%s'\n", ast_inet_ntoa(remote_address->sin_addr), d.username);
++ ast_http_error(ser, 403, "Permission denied", "Permission denied\n");
++ return -1;
++ }
++
++ /* --- We have auth, so check it */
++
++ /* compute the expected response to compare with what we received */
++ {
++ char a2[256];
++ char a2_hash[256];
++ char resp[256];
++
++ /* XXX Now request method are hardcoded in A2 */
++ snprintf(a2, sizeof(a2), "%s:%s", ast_get_http_method(method), d.uri);
++ ast_md5_hash(a2_hash, a2);
++
++ if (d.qop) {
++ /* RFC 2617 */
++ snprintf(resp, sizeof(resp), "%s:%08lx:%s:%s:auth:%s", user->a1_hash, nonce, d.nc, d.cnonce, a2_hash);
++ } else {
++ /* RFC 2069 */
++ snprintf(resp, sizeof(resp), "%s:%08lx:%s", user->a1_hash, nonce, a2_hash);
++ }
++ ast_md5_hash(resp_hash, resp);
++ }
++
++ if (!d.nonce || strncasecmp(d.response, resp_hash, strlen(resp_hash))) {
++ /* Something was wrong, so give the client to try with a new challenge */
++ AST_RWLIST_UNLOCK(&users);
++ nonce = 0;
++ goto out_401;
++ }
++
++ /*
++ * User are pass Digest authentication.
++ * Now, cache the user data and unlock user list.
++ */
++ ast_copy_string(u_username, user->username, sizeof(u_username));
++ u_readperm = user->readperm;
++ u_writeperm = user->writeperm;
++ u_displayconnects = user->displayconnects;
++ u_writetimeout = user->writetimeout;
++ AST_RWLIST_UNLOCK(&users);
++
++ if (!(session = find_session_by_nonce(d.username, nonce, &stale))) {
++ /*
++ * Create new session.
++ * While it is not in the list we don't need any locking
++ */
++ if (!(session = build_mansession(*remote_address))) {
++ ast_http_error(ser, 500, "Server Error", "Internal Server Error (out of memory)\n");
++ return -1;
++ }
++ ao2_lock(session);
++
++ ast_copy_string(session->username, u_username, sizeof(session->username));
++ session->managerid = nonce;
++ session->last_ev = grab_last();
++ AST_LIST_HEAD_INIT_NOLOCK(&session->datastores);
++
++ session->readperm = u_readperm;
++ session->writeperm = u_writeperm;
++ session->writetimeout = u_writetimeout;
++
++ if (u_displayconnects) {
++ ast_verb(2, "HTTP Manager '%s' logged in from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr));
++ }
++ session->noncetime = session->sessionstart = time_now;
++ session->authenticated = 1;
++ } else if (stale) {
++ /*
++ * Session found, but nonce is stale.
++ *
++ * This could be because an old request (w/old nonce) arrived.
++ *
++ * This may be as the result of http proxy usage (separate delay or
++ * multipath) or in a situation where a page was refreshed too quickly
++ * (seen in Firefox).
++ *
++ * In this situation, we repeat the 401 auth with the current nonce
++ * value.
++ */
++ nonce = session->managerid;
++ ao2_unlock(session);
++ stale = 1;
++ goto out_401;
++ } else {
++ sscanf(d.nc, "%lx", &nc);
++ if (session->nc >= nc || ((time_now - session->noncetime) > 62) ) {
++ /*
++ * Nonce time expired (> 2 minutes) or something wrong with nonce
++ * counter.
++ *
++ * Create new nonce key and resend Digest auth request. Old nonce
++ * is saved for stale checking...
++ */
++ session->nc = 0; /* Reset nonce counter */
++ session->oldnonce = session->managerid;
++ nonce = session->managerid = ast_random();
++ session->noncetime = time_now;
++ ao2_unlock(session);
++ stale = 1;
++ goto out_401;
++ } else {
++ session->nc = nc; /* All OK, save nonce counter */
++ }
++ }
++
++
++ /* Reset session timeout. */
++ session->sessiontimeout = time(NULL) + (httptimeout > 5 ? httptimeout : 5);
++ ao2_unlock(session);
++
++ ast_mutex_init(&s.lock);
++ s.session = session;
++ s.fd = mkstemp(template); /* create a temporary file for command output */
++ unlink(template);
++ if (s.fd <= -1) {
++ ast_http_error(ser, 500, "Server Error", "Internal Server Error (mkstemp failed)\n");
++ goto auth_callback_out;
++ }
++ s.f = fdopen(s.fd, "w+");
++ if (!s.f) {
++ ast_log(LOG_WARNING, "HTTP Manager, fdopen failed: %s!\n", strerror(errno));
++ ast_http_error(ser, 500, "Server Error", "Internal Server Error (fdopen failed)\n");
++ close(s.fd);
++ goto auth_callback_out;
++ }
++
++ if (method == AST_HTTP_POST) {
++ params = ast_http_get_post_vars(ser, headers);
++ }
++
++ for (x = 0, v = params; v && (x < AST_MAX_MANHEADERS); x++, v = v->next) {
++ hdrlen = strlen(v->name) + strlen(v->value) + 3;
++ m.headers[m.hdrcount] = alloca(hdrlen);
++ snprintf((char *) m.headers[m.hdrcount], hdrlen, "%s: %s", v->name, v->value);
++ ast_verb(4, "HTTP Manager add header %s\n", m.headers[m.hdrcount]);
++ m.hdrcount = x + 1;
++ }
++
++ if (process_message(&s, &m)) {
++ if (u_displayconnects) {
++ ast_verb(2, "HTTP Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr));
++ }
++
++ session->needdestroy = 1;
++ }
++
++ if (s.f) {
++ result_size = ftell(s.f); /* Calculate approx. size of result */
++ }
++
++ http_header = ast_str_create(80);
++ out = ast_str_create(result_size * 2 + 512);
++
++ if (http_header == NULL || out == NULL) {
++ ast_http_error(ser, 500, "Server Error", "Internal Server Error (ast_str_create() out of memory)\n");
++ goto auth_callback_out;
++ }
++
++ ast_str_append(&http_header, 0, "Content-type: text/%s", contenttype[format]);
++
++ if (format == FORMAT_XML) {
++ ast_str_append(&out, 0, "<ajax-response>\n");
++ } else if (format == FORMAT_HTML) {
++ ast_str_append(&out, 0,
++ "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n"
++ "<html><head>\r\n"
++ "<title>Asterisk&trade; Manager Interface</title>\r\n"
++ "</head><body style=\"background-color: #ffffff;\">\r\n"
++ "<form method=\"POST\">\r\n"
++ "<table align=\"center\" style=\"background-color: #f1f1f1;\" width=\"500\">\r\n"
++ "<tr><th colspan=\"2\" style=\"background-color: #f1f1ff;\"><h1>Manager Tester</h1></th></tr>\r\n"
++ "<tr><th colspan=\"2\" style=\"background-color: #f1f1ff;\">Action: <input name=\"action\" /> Cmd: <input name=\"command\" /><br>"
++ "<input type=\"submit\" value=\"Send request\" /></th></tr>\r\n");
++ }
++
++ if (s.f != NULL) { /* have temporary output */
++ char *buf;
++ size_t l = ftell(s.f);
++
++ if (l) {
++ if ((buf = mmap(NULL, l, PROT_READ | PROT_WRITE, MAP_SHARED, s.fd, 0))) {
++ if (format == FORMAT_XML || format == FORMAT_HTML) {
++ xml_translate(&out, buf, params, format);
++ } else {
++ ast_str_append(&out, 0, "%s", buf);
++ }
++ munmap(buf, l);
++ }
++ } else if (format == FORMAT_XML || format == FORMAT_HTML) {
++ xml_translate(&out, "", params, format);
++ }
++ fclose(s.f);
++ s.f = NULL;
++ s.fd = -1;
++ }
++
++ if (format == FORMAT_XML) {
++ ast_str_append(&out, 0, "</ajax-response>\n");
++ } else if (format == FORMAT_HTML) {
++ ast_str_append(&out, 0, "</table></form></body></html>\r\n");
++ }
++
++ ast_http_send(ser, method, 200, NULL, http_header, out, 0, 0);
++ http_header = out = NULL;
++
++auth_callback_out:
++ ast_mutex_destroy(&s.lock);
++
++ /* Clear resources and unlock manager session */
++ if (method == AST_HTTP_POST && params) {
++ ast_variables_destroy(params);
++ }
++
++ ast_free(http_header);
++ ast_free(out);
++
++ ao2_lock(session);
++ if (session->f) {
++ fclose(session->f);
++ }
++ session->f = NULL;
++ session->fd = -1;
++ ao2_unlock(session);
++
++ if (session->needdestroy) {
++ ast_debug(1, "Need destroy, doing it now!\n");
++ session_destroy(session);
++ }
++ ast_string_field_free_memory(&d);
++ return 0;
++
++out_401:
++ if (!nonce) {
++ nonce = ast_random();
++ }
++
++ ast_http_auth(ser, global_realm, nonce, nonce, stale, NULL);
++ ast_string_field_free_memory(&d);
++ return 0;
+ }
+
+-static struct ast_str *mxml_http_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *params, struct ast_variable *headers, int *status, char **title, int *contentlength)
++static int manager_http_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers)
+ {
+- return generic_http_callback(FORMAT_XML, &ser->remote_address, uri, method, params, status, title, contentlength);
++ return generic_http_callback(ser, method, FORMAT_HTML, &ser->remote_address, uri, get_params, headers);
+ }
+
+-static struct ast_str *rawman_http_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *params, struct ast_variable *headers, int *status, char **title, int *contentlength)
++static int mxml_http_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers)
+ {
+- return generic_http_callback(FORMAT_RAW, &ser->remote_address, uri, method, params, status, title, contentlength);
++ return generic_http_callback(ser, method, FORMAT_XML, &ser->remote_address, uri, get_params, headers);
+ }
+
+-struct ast_http_uri rawmanuri = {
++static int rawman_http_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers)
++{
++ return generic_http_callback(ser, method, FORMAT_RAW, &ser->remote_address, uri, get_params, headers);
++}
++
++static struct ast_http_uri rawmanuri = {
+ .description = "Raw HTTP Manager Event Interface",
+ .uri = "rawman",
+ .callback = rawman_http_callback,
+- .supports_get = 1,
+ .data = NULL,
+ .key = __FILE__,
+ };
+
+-struct ast_http_uri manageruri = {
++static struct ast_http_uri manageruri = {
+ .description = "HTML Manager Event Interface",
+ .uri = "manager",
+ .callback = manager_http_callback,
+- .supports_get = 1,
+ .data = NULL,
+ .key = __FILE__,
+ };
+
+-struct ast_http_uri managerxmluri = {
++static struct ast_http_uri managerxmluri = {
+ .description = "XML Manager Event Interface",
+ .uri = "mxml",
+ .callback = mxml_http_callback,
+- .supports_get = 1,
+ .data = NULL,
+ .key = __FILE__,
+ };
+
++
++/* Callback with Digest authentication */
++static int auth_manager_http_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers)
++{
++ return auth_http_callback(ser, method, FORMAT_HTML, &ser->remote_address, uri, get_params, headers);
++}
++
++static int auth_mxml_http_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers)
++{
++ return auth_http_callback(ser, method, FORMAT_XML, &ser->remote_address, uri, get_params, headers);
++}
++
++static int auth_rawman_http_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers)
++{
++ return auth_http_callback(ser, method, FORMAT_RAW, &ser->remote_address, uri, get_params, headers);
++}
++
++static struct ast_http_uri arawmanuri = {
++ .description = "Raw HTTP Manager Event Interface w/Digest authentication",
++ .uri = "arawman",
++ .has_subtree = 0,
++ .callback = auth_rawman_http_callback,
++ .data = NULL,
++ .key = __FILE__,
++};
++
++static struct ast_http_uri amanageruri = {
++ .description = "HTML Manager Event Interface w/Digest authentication",
++ .uri = "amanager",
++ .has_subtree = 0,
++ .callback = auth_manager_http_callback,
++ .data = NULL,
++ .key = __FILE__,
++};
++
++static struct ast_http_uri amanagerxmluri = {
++ .description = "XML Manager Event Interface w/Digest authentication",
++ .uri = "amxml",
++ .has_subtree = 0,
++ .callback = auth_mxml_http_callback,
++ .data = NULL,
++ .key = __FILE__,
++};
++
+ static int registered = 0;
+ static int webregged = 0;
+
+@@ -4007,11 +5086,11 @@
+ purge_events();
+ }
+
+-struct ast_tls_config ami_tls_cfg;
++static struct ast_tls_config ami_tls_cfg;
+ static struct ast_tcptls_session_args ami_desc = {
+ .accept_fd = -1,
+ .master = AST_PTHREADT_NULL,
+- .tls_cfg = NULL,
++ .tls_cfg = NULL,
+ .poll_timeout = 5000, /* wake up every 5 seconds */
+ .periodic_fn = purge_old_stuff,
+ .name = "AMI server",
+@@ -4022,7 +5101,7 @@
+ static struct ast_tcptls_session_args amis_desc = {
+ .accept_fd = -1,
+ .master = AST_PTHREADT_NULL,
+- .tls_cfg = &ami_tls_cfg,
++ .tls_cfg = &ami_tls_cfg,
+ .poll_timeout = -1, /* the other does the periodic cleanup */
+ .name = "AMI TLS server",
+ .accept_fn = ast_tcptls_server_root, /* thread doing the accept() */
+@@ -4035,49 +5114,48 @@
+ const char *val;
+ char *cat = NULL;
+ int newhttptimeout = 60;
+- int have_sslbindaddr = 0;
+- struct hostent *hp;
+- struct ast_hostent ahp;
+ struct ast_manager_user *user = NULL;
+ struct ast_variable *var;
+ struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
++ char a1[256];
++ char a1_hash[256];
+
+ manager_enabled = 0;
+
+ if (!registered) {
+ /* Register default actions */
+- ast_manager_register2("Ping", 0, action_ping, "Keepalive command", mandescr_ping);
+- ast_manager_register2("Events", 0, action_events, "Control Event Flow", mandescr_events);
+- ast_manager_register2("Logoff", 0, action_logoff, "Logoff Manager", mandescr_logoff);
+- ast_manager_register2("Login", 0, action_login, "Login Manager", NULL);
+- ast_manager_register2("Challenge", 0, action_challenge, "Generate Challenge for MD5 Auth", NULL);
+- ast_manager_register2("Hangup", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL, action_hangup, "Hangup Channel", mandescr_hangup);
+- ast_manager_register2("Status", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_status, "Lists channel status", mandescr_status);
+- ast_manager_register2("Setvar", EVENT_FLAG_CALL, action_setvar, "Set Channel Variable", mandescr_setvar);
+- ast_manager_register2("Getvar", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_getvar, "Gets a Channel Variable", mandescr_getvar);
+- ast_manager_register2("GetConfig", EVENT_FLAG_SYSTEM | EVENT_FLAG_CONFIG, action_getconfig, "Retrieve configuration", mandescr_getconfig);
+- ast_manager_register2("GetConfigJSON", EVENT_FLAG_SYSTEM | EVENT_FLAG_CONFIG, action_getconfigjson, "Retrieve configuration (JSON format)", mandescr_getconfigjson);
+- ast_manager_register2("UpdateConfig", EVENT_FLAG_CONFIG, action_updateconfig, "Update basic configuration", mandescr_updateconfig);
+- ast_manager_register2("CreateConfig", EVENT_FLAG_CONFIG, action_createconfig, "Creates an empty file in the configuration directory", mandescr_createconfig);
+- ast_manager_register2("ListCategories", EVENT_FLAG_CONFIG, action_listcategories, "List categories in configuration file", mandescr_listcategories);
+- ast_manager_register2("Redirect", EVENT_FLAG_CALL, action_redirect, "Redirect (transfer) a call", mandescr_redirect );
+- ast_manager_register2("Atxfer", EVENT_FLAG_CALL, action_atxfer, "Attended transfer", mandescr_atxfer);
+- ast_manager_register2("Originate", EVENT_FLAG_ORIGINATE, action_originate, "Originate Call", mandescr_originate);
+- ast_manager_register2("Command", EVENT_FLAG_COMMAND, action_command, "Execute Asterisk CLI Command", mandescr_command );
+- ast_manager_register2("ExtensionState", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_extensionstate, "Check Extension Status", mandescr_extensionstate );
+- ast_manager_register2("AbsoluteTimeout", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL, action_timeout, "Set Absolute Timeout", mandescr_timeout );
+- ast_manager_register2("MailboxStatus", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_mailboxstatus, "Check Mailbox", mandescr_mailboxstatus );
+- ast_manager_register2("MailboxCount", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_mailboxcount, "Check Mailbox Message Count", mandescr_mailboxcount );
+- ast_manager_register2("ListCommands", 0, action_listcommands, "List available manager commands", mandescr_listcommands);
+- ast_manager_register2("SendText", EVENT_FLAG_CALL, action_sendtext, "Send text message to channel", mandescr_sendtext);
+- ast_manager_register2("UserEvent", EVENT_FLAG_USER, action_userevent, "Send an arbitrary event", mandescr_userevent);
+- ast_manager_register2("WaitEvent", 0, action_waitevent, "Wait for an event to occur", mandescr_waitevent);
+- ast_manager_register2("CoreSettings", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, action_coresettings, "Show PBX core settings (version etc)", mandescr_coresettings);
+- ast_manager_register2("CoreStatus", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, action_corestatus, "Show PBX core status variables", mandescr_corestatus);
+- ast_manager_register2("Reload", EVENT_FLAG_CONFIG | EVENT_FLAG_SYSTEM, action_reload, "Send a reload event", mandescr_reload);
+- ast_manager_register2("CoreShowChannels", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, action_coreshowchannels, "List currently active channels", mandescr_coreshowchannels);
+- ast_manager_register2("ModuleLoad", EVENT_FLAG_SYSTEM, manager_moduleload, "Module management", mandescr_moduleload);
+- ast_manager_register2("ModuleCheck", EVENT_FLAG_SYSTEM, manager_modulecheck, "Check if module is loaded", mandescr_modulecheck);
++ ast_manager_register_xml("Ping", 0, action_ping);
++ ast_manager_register_xml("Events", 0, action_events);
++ ast_manager_register_xml("Logoff", 0, action_logoff);
++ ast_manager_register_xml("Login", 0, action_login);
++ ast_manager_register_xml("Challenge", 0, action_challenge);
++ ast_manager_register_xml("Hangup", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL, action_hangup);
++ ast_manager_register_xml("Status", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_status);
++ ast_manager_register_xml("Setvar", EVENT_FLAG_CALL, action_setvar);
++ ast_manager_register_xml("Getvar", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_getvar);
++ ast_manager_register_xml("GetConfig", EVENT_FLAG_SYSTEM | EVENT_FLAG_CONFIG, action_getconfig);
++ ast_manager_register_xml("GetConfigJSON", EVENT_FLAG_SYSTEM | EVENT_FLAG_CONFIG, action_getconfigjson);
++ ast_manager_register_xml("UpdateConfig", EVENT_FLAG_CONFIG, action_updateconfig);
++ ast_manager_register_xml("CreateConfig", EVENT_FLAG_CONFIG, action_createconfig);
++ ast_manager_register_xml("ListCategories", EVENT_FLAG_CONFIG, action_listcategories);
++ ast_manager_register_xml("Redirect", EVENT_FLAG_CALL, action_redirect);
++ ast_manager_register_xml("Atxfer", EVENT_FLAG_CALL, action_atxfer);
++ ast_manager_register_xml("Originate", EVENT_FLAG_ORIGINATE, action_originate);
++ ast_manager_register_xml("Command", EVENT_FLAG_COMMAND, action_command);
++ ast_manager_register_xml("ExtensionState", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_extensionstate);
++ ast_manager_register_xml("AbsoluteTimeout", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL, action_timeout);
++ ast_manager_register_xml("MailboxStatus", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_mailboxstatus);
++ ast_manager_register_xml("MailboxCount", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_mailboxcount);
++ ast_manager_register_xml("ListCommands", 0, action_listcommands);
++ ast_manager_register_xml("SendText", EVENT_FLAG_CALL, action_sendtext);
++ ast_manager_register_xml("UserEvent", EVENT_FLAG_USER, action_userevent);
++ ast_manager_register_xml("WaitEvent", 0, action_waitevent);
++ ast_manager_register_xml("CoreSettings", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, action_coresettings);
++ ast_manager_register_xml("CoreStatus", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, action_corestatus);
++ ast_manager_register_xml("Reload", EVENT_FLAG_CONFIG | EVENT_FLAG_SYSTEM, action_reload);
++ ast_manager_register_xml("CoreShowChannels", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, action_coreshowchannels);
++ ast_manager_register_xml("ModuleLoad", EVENT_FLAG_SYSTEM, manager_moduleload);
++ ast_manager_register_xml("ModuleCheck", EVENT_FLAG_SYSTEM, manager_modulecheck);
+
+ ast_cli_register_multiple(cli_manager, ARRAY_LEN(cli_manager));
+ ast_extension_state_add(NULL, NULL, manager_state_cb, NULL);
+@@ -4085,8 +5163,9 @@
+ /* Append placeholder event so master_eventq never runs dry */
+ append_event("Event: Placeholder\r\n\r\n", 0);
+ }
+- if ((cfg = ast_config_load2("manager.conf", "manager", config_flags)) == CONFIG_STATUS_FILEUNCHANGED)
++ if ((cfg = ast_config_load2("manager.conf", "manager", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
+ return 0;
++ }
+
+ displayconnects = 1;
+ if (!cfg) {
+@@ -4095,39 +5174,34 @@
+ }
+
+ /* default values */
++ ast_copy_string(global_realm, S_OR(ast_config_AST_SYSTEM_NAME, DEFAULT_REALM), sizeof(global_realm));
+ memset(&ami_desc.local_address, 0, sizeof(struct sockaddr_in));
+ memset(&amis_desc.local_address, 0, sizeof(amis_desc.local_address));
+ amis_desc.local_address.sin_port = htons(5039);
+ ami_desc.local_address.sin_port = htons(DEFAULT_MANAGER_PORT);
+
+ ami_tls_cfg.enabled = 0;
+- if (ami_tls_cfg.certfile)
++ if (ami_tls_cfg.certfile) {
+ ast_free(ami_tls_cfg.certfile);
++ }
+ ami_tls_cfg.certfile = ast_strdup(AST_CERTFILE);
+- if (ami_tls_cfg.cipher)
++ if (ami_tls_cfg.pvtfile) {
++ ast_free(ami_tls_cfg.pvtfile);
++ }
++ ami_tls_cfg.pvtfile = ast_strdup("");
++ if (ami_tls_cfg.cipher) {
+ ast_free(ami_tls_cfg.cipher);
++ }
+ ami_tls_cfg.cipher = ast_strdup("");
+
+ for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
+ val = var->value;
+- if (!strcasecmp(var->name, "sslenable"))
+- ami_tls_cfg.enabled = ast_true(val);
+- else if (!strcasecmp(var->name, "sslbindport"))
+- amis_desc.local_address.sin_port = htons(atoi(val));
+- else if (!strcasecmp(var->name, "sslbindaddr")) {
+- if ((hp = ast_gethostbyname(val, &ahp))) {
+- memcpy(&amis_desc.local_address.sin_addr, hp->h_addr, sizeof(amis_desc.local_address.sin_addr));
+- have_sslbindaddr = 1;
+- } else {
+- ast_log(LOG_WARNING, "Invalid bind address '%s'\n", val);
+- }
+- } else if (!strcasecmp(var->name, "sslcert")) {
+- ast_free(ami_tls_cfg.certfile);
+- ami_tls_cfg.certfile = ast_strdup(val);
+- } else if (!strcasecmp(var->name, "sslcipher")) {
+- ast_free(ami_tls_cfg.cipher);
+- ami_tls_cfg.cipher = ast_strdup(val);
+- } else if (!strcasecmp(var->name, "enabled")) {
++
++ if (!ast_tls_read_conf(&ami_tls_cfg, &amis_desc, var->name, val)) {
++ continue;
++ }
++
++ if (!strcasecmp(var->name, "enabled")) {
+ manager_enabled = ast_true(val);
+ } else if (!strcasecmp(var->name, "block-sockets")) {
+ block_sockets = ast_true(val);
+@@ -4140,7 +5214,7 @@
+ ast_log(LOG_WARNING, "Invalid address '%s' specified, using 0.0.0.0\n", val);
+ memset(&ami_desc.local_address.sin_addr, 0, sizeof(ami_desc.local_address.sin_addr));
+ }
+- } else if (!strcasecmp(var->name, "allowmultiplelogin")) {
++ } else if (!strcasecmp(var->name, "allowmultiplelogin")) {
+ allowmultiplelogin = ast_true(val);
+ } else if (!strcasecmp(var->name, "displayconnects")) {
+ displayconnects = ast_true(val);
+@@ -4153,17 +5227,20 @@
+ } else {
+ ast_log(LOG_NOTICE, "Invalid keyword <%s> = <%s> in manager.conf [general]\n",
+ var->name, val);
+- }
++ }
+ }
+
+- if (manager_enabled)
++ if (manager_enabled) {
+ ami_desc.local_address.sin_family = AF_INET;
+- if (!have_sslbindaddr)
++ }
++ /* if the amis address has not been set, default is the same as non secure ami */
++ if (!amis_desc.local_address.sin_addr.s_addr) {
+ amis_desc.local_address.sin_addr = ami_desc.local_address.sin_addr;
+- if (ami_tls_cfg.enabled)
++ }
++ if (ami_tls_cfg.enabled) {
+ amis_desc.local_address.sin_family = AF_INET;
++ }
+
+-
+ AST_RWLIST_WRLOCK(&users);
+
+ /* First, get users from users.conf */
+@@ -4173,9 +5250,10 @@
+ int genhasmanager = ast_true(ast_variable_retrieve(ucfg, "general", "hasmanager"));
+
+ while ((cat = ast_category_browse(ucfg, cat))) {
+- if (!strcasecmp(cat, "general"))
++ if (!strcasecmp(cat, "general")) {
+ continue;
+-
++ }
++
+ hasmanager = ast_variable_retrieve(ucfg, cat, "hasmanager");
+ if ((!hasmanager && genhasmanager) || ast_true(hasmanager)) {
+ const char *user_secret = ast_variable_retrieve(ucfg, cat, "secret");
+@@ -4183,13 +5261,14 @@
+ const char *user_write = ast_variable_retrieve(ucfg, cat, "write");
+ const char *user_displayconnects = ast_variable_retrieve(ucfg, cat, "displayconnects");
+ const char *user_writetimeout = ast_variable_retrieve(ucfg, cat, "writetimeout");
+-
++
+ /* Look for an existing entry,
+ * if none found - create one and add it to the list
+ */
+ if (!(user = get_manager_by_name_locked(cat))) {
+- if (!(user = ast_calloc(1, sizeof(*user))))
++ if (!(user = ast_calloc(1, sizeof(*user)))) {
+ break;
++ }
+
+ /* Copy name over */
+ ast_copy_string(user->username, cat, sizeof(user->username));
+@@ -4204,36 +5283,45 @@
+ user->writetimeout = 100;
+ }
+
+- if (!user_secret)
++ if (!user_secret) {
+ user_secret = ast_variable_retrieve(ucfg, "general", "secret");
+- if (!user_read)
++ }
++ if (!user_read) {
+ user_read = ast_variable_retrieve(ucfg, "general", "read");
+- if (!user_write)
++ }
++ if (!user_write) {
+ user_write = ast_variable_retrieve(ucfg, "general", "write");
+- if (!user_displayconnects)
++ }
++ if (!user_displayconnects) {
+ user_displayconnects = ast_variable_retrieve(ucfg, "general", "displayconnects");
+- if (!user_writetimeout)
++ }
++ if (!user_writetimeout) {
+ user_writetimeout = ast_variable_retrieve(ucfg, "general", "writetimeout");
++ }
+
+ if (!ast_strlen_zero(user_secret)) {
+- if (user->secret)
++ if (user->secret) {
+ ast_free(user->secret);
++ }
+ user->secret = ast_strdup(user_secret);
+ }
+
+- if (user_read)
++ if (user_read) {
+ user->readperm = get_perm(user_read);
+- if (user_write)
++ }
++ if (user_write) {
+ user->writeperm = get_perm(user_write);
+- if (user_displayconnects)
++ }
++ if (user_displayconnects) {
+ user->displayconnects = ast_true(user_displayconnects);
+-
++ }
+ if (user_writetimeout) {
+ int value = atoi(user_writetimeout);
+- if (value < 100)
++ if (value < 100) {
+ ast_log(LOG_WARNING, "Invalid writetimeout value '%s' at users.conf line %d\n", var->value, var->lineno);
+- else
++ } else {
+ user->writetimeout = value;
++ }
+ }
+ }
+ }
+@@ -4245,13 +5333,15 @@
+ while ((cat = ast_category_browse(cfg, cat))) {
+ struct ast_ha *oldha;
+
+- if (!strcasecmp(cat, "general"))
++ if (!strcasecmp(cat, "general")) {
+ continue;
++ }
+
+ /* Look for an existing entry, if none found - create one and add it to the list */
+ if (!(user = get_manager_by_name_locked(cat))) {
+- if (!(user = ast_calloc(1, sizeof(*user))))
++ if (!(user = ast_calloc(1, sizeof(*user)))) {
+ break;
++ }
+ /* Copy name over */
+ ast_copy_string(user->username, cat, sizeof(user->username));
+
+@@ -4274,8 +5364,9 @@
+ var = ast_variable_browse(cfg, cat);
+ for (; var; var = var->next) {
+ if (!strcasecmp(var->name, "secret")) {
+- if (user->secret)
++ if (user->secret) {
+ ast_free(user->secret);
++ }
+ user->secret = ast_strdup(var->value);
+ } else if (!strcasecmp(var->name, "deny") ||
+ !strcasecmp(var->name, "permit")) {
+@@ -4288,12 +5379,14 @@
+ user->displayconnects = ast_true(var->value);
+ } else if (!strcasecmp(var->name, "writetimeout")) {
+ int value = atoi(var->value);
+- if (value < 100)
++ if (value < 100) {
+ ast_log(LOG_WARNING, "Invalid writetimeout value '%s' at line %d\n", var->value, var->lineno);
+- else
++ } else {
+ user->writetimeout = value;
+- } else
++ }
++ } else {
+ ast_debug(1, "%s is an unknown option.\n", var->name);
++ }
+ }
+ ast_free_ha(oldha);
+ }
+@@ -4303,13 +5396,25 @@
+ AST_RWLIST_TRAVERSE_SAFE_BEGIN(&users, user, list) {
+ if (user->keep) { /* valid record. clear flag for the next round */
+ user->keep = 0;
++
++ /* Calculate A1 for Digest auth */
++ snprintf(a1, sizeof(a1), "%s:%s:%s", user->username, global_realm, user->secret);
++ ast_md5_hash(a1_hash,a1);
++ if (user->a1_hash) {
++ ast_free(user->a1_hash);
++ }
++ user->a1_hash = ast_strdup(a1_hash);
+ continue;
+ }
+ /* We do not need to keep this user so take them out of the list */
+ AST_RWLIST_REMOVE_CURRENT(list);
+ /* Free their memory now */
+- if (user->secret)
++ if (user->a1_hash) {
++ ast_free(user->a1_hash);
++ }
++ if (user->secret) {
+ ast_free(user->secret);
++ }
+ ast_free_ha(user->ha);
+ ast_free(user);
+ }
+@@ -4317,11 +5422,21 @@
+
+ AST_RWLIST_UNLOCK(&users);
+
++ if (!reload) {
++ /* If you have a NULL hash fn, you only need a single bucket */
++ sessions = ao2_container_alloc(1, NULL, mansession_cmp_fn);
++ }
++
+ if (webmanager_enabled && manager_enabled) {
+ if (!webregged) {
++
+ ast_http_uri_link(&rawmanuri);
+ ast_http_uri_link(&manageruri);
+ ast_http_uri_link(&managerxmluri);
++
++ ast_http_uri_link(&arawmanuri);
++ ast_http_uri_link(&amanageruri);
++ ast_http_uri_link(&amanagerxmluri);
+ webregged = 1;
+ }
+ } else {
+@@ -4329,18 +5444,24 @@
+ ast_http_uri_unlink(&rawmanuri);
+ ast_http_uri_unlink(&manageruri);
+ ast_http_uri_unlink(&managerxmluri);
++
++ ast_http_uri_unlink(&arawmanuri);
++ ast_http_uri_unlink(&amanageruri);
++ ast_http_uri_unlink(&amanagerxmluri);
+ webregged = 0;
+ }
+ }
+
+- if (newhttptimeout > 0)
++ if (newhttptimeout > 0) {
+ httptimeout = newhttptimeout;
++ }
+
+ manager_event(EVENT_FLAG_SYSTEM, "Reload", "Module: Manager\r\nStatus: %s\r\nMessage: Manager reload Requested\r\n", manager_enabled ? "Enabled" : "Disabled");
+
+ ast_tcptls_server_start(&ami_desc);
+- if (ast_ssl_setup(amis_desc.tls_cfg))
++ if (ast_ssl_setup(amis_desc.tls_cfg)) {
+ ast_tcptls_server_start(&amis_desc);
++ }
+ return 0;
+ }
+
+@@ -4369,7 +5490,7 @@
+ struct ast_datastore *astman_datastore_find(struct mansession *s, const struct ast_datastore_info *info, const char *uid)
+ {
+ struct ast_datastore *datastore = NULL;
+-
++
+ if (info == NULL)
+ return NULL;
+
+Index: main/ast_expr2f.c
+===================================================================
+--- a/main/ast_expr2f.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/ast_expr2f.c (.../trunk) (revision 202568)
+@@ -2379,7 +2379,7 @@
+
+ void ast_yyfree(void *ptr, yyscan_t yyscanner)
+ {
+- if (ptr) /* the normal generated ast_yyfree func just frees its first arg;
++ /* the normal generated ast_yyfree func just frees its first arg;
+ this get complaints on some systems, as sometimes this
+ arg is a nil ptr! It's usually not fatal, but is irritating! */
+ free( (char *) ptr );
+@@ -2416,15 +2416,40 @@
+ else
+ buf[0] = 0;
+ return_value = strlen(buf);
+- if (io.val->u.s)
+- free(io.val->u.s);
++ free(io.val->u.s);
+ }
+ free(io.val);
+ }
+ return return_value;
+ }
+
++#if !defined(STANDALONE)
++int ast_str_expr(struct ast_str **str, ssize_t maxlen, struct ast_channel *chan, char *expr)
++{
++ struct parse_io io = { .string = expr, .chan = chan };
+
++ ast_yylex_init(&io.scanner);
++ ast_yy_scan_string(expr, io.scanner);
++ ast_yyparse ((void *) &io);
++ ast_yylex_destroy(io.scanner);
++
++ if (!io.val) {
++ ast_str_set(str, maxlen, "0");
++ } else {
++ if (io.val->type == AST_EXPR_number) {
++ int res_length;
++ ast_str_set(str, maxlen, FP___PRINTF, io.val->u.i);
++ } else if (io.val->u.s) {
++ ast_str_set(str, maxlen, "%s", io.val->u.s);
++ free(io.val->u.s);
++ }
++ free(io.val);
++ }
++ return ast_str_strlen(*str);
++}
++#endif
++
++
+ char extra_error_message[4095];
+ int extra_error_message_supplied = 0;
+ void ast_expr_register_extra_error_info(char *message);
+Index: main/features.c
+===================================================================
+--- a/main/features.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/features.c (.../trunk) (revision 202568)
+@@ -154,6 +154,61 @@
+ <ref type="application">ParkedCall</ref>
+ </see-also>
+ </application>
++ <manager name="ParkedCalls" language="en_US">
++ <synopsis>
++ List parked calls.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ </syntax>
++ <description>
++ <para>List parked calls.</para>
++ </description>
++ </manager>
++ <manager name="Park" language="en_US">
++ <synopsis>
++ Park a channel.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Channel" required="true">
++ <para>Channel name to park.</para>
++ </parameter>
++ <parameter name="Channel2" required="true">
++ <para>Channel to announce park info to (and return to if timeout).</para>
++ </parameter>
++ <parameter name="Timeout">
++ <para>Number of milliseconds to wait before callback.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Park a channel.</para>
++ </description>
++ </manager>
++ <manager name="Bridge" language="en_US">
++ <synopsis>
++ Bridge two channels already in the PBX.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Channel1" required="true">
++ <para>Channel to Bridge to Channel2.</para>
++ </parameter>
++ <parameter name="Channel2" required="true">
++ <para>Channel to Bridge to Channel1.</para>
++ </parameter>
++ <parameter name="Tone">
++ <para>Play courtesy tone to Channel 2.</para>
++ <enumlist>
++ <enum name="yes" />
++ <enum name="no" />
++ </enumlist>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Bridge together two channels already in the PBX.</para>
++ </description>
++ </manager>
+ ***/
+
+ #define DEFAULT_PARK_TIME 45000
+@@ -284,17 +339,17 @@
+ memcpy(df_copy, df, sizeof(*df));
+
+ return df_copy;
+- }
+-
+- static void dial_features_destroy(void *data)
+- {
++}
++
++static void dial_features_destroy(void *data)
++{
+ struct ast_dial_features *df = data;
+ if (df) {
+ ast_free(df);
+ }
+- }
+-
+- const struct ast_datastore_info dial_features_info = {
++}
++
++static const struct ast_datastore_info dial_features_info = {
+ .type = "dial-features",
+ .destroy = dial_features_destroy,
+ .duplicate = dial_features_duplicate,
+@@ -720,11 +775,13 @@
+ if ((c = strrchr(other_side, ';'))) {
+ *++c = '1';
+ }
+- if ((tmpchan = ast_get_channel_by_name_locked(other_side))) {
++ if ((tmpchan = ast_channel_get_by_name(other_side))) {
++ ast_channel_lock(tmpchan);
+ if ((base_peer = ast_bridged_channel(tmpchan))) {
+ ast_copy_string(pu->peername, base_peer->name, sizeof(pu->peername));
+ }
+ ast_channel_unlock(tmpchan);
++ tmpchan = ast_channel_unref(tmpchan);
+ }
+ } else {
+ ast_copy_string(pu->peername, S_OR(args->orig_chan_name, peer->name), sizeof(pu->peername));
+@@ -889,9 +946,6 @@
+ return masq_park_call(rchan, peer, timeout, extout, 1, NULL);
+ }
+
+-#define FEATURE_SENSE_CHAN (1 << 0)
+-#define FEATURE_SENSE_PEER (1 << 1)
+-
+ /*!
+ * \brief set caller and callee according to the direction
+ * \param caller, callee, peer, chan, sense
+@@ -922,7 +976,7 @@
+ * Setup channel, set return exten,priority to 's,1'
+ * answer chan, sleep chan, park call
+ */
+-static int builtin_parkcall(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
++static int builtin_parkcall(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
+ {
+ struct ast_channel *parker;
+ struct ast_channel *parkee;
+@@ -992,7 +1046,7 @@
+ * \retval AST_FEATURE_RETURN_SUCCESS on success.
+ * \retval -1 on error.
+ */
+-static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
++static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
+ {
+ char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
+ int x = 0;
+@@ -1085,7 +1139,7 @@
+ return -1;
+ }
+
+-static int builtin_automixmonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
++static int builtin_automixmonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
+ {
+ char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
+ int x = 0;
+@@ -1195,7 +1249,7 @@
+
+ }
+
+-static int builtin_disconnect(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
++static int builtin_disconnect(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
+ {
+ ast_verb(4, "User hit '%s' to disconnect call.\n", code);
+ return AST_FEATURE_RETURN_HANGUP;
+@@ -1245,7 +1299,7 @@
+ * \retval AST_FEATURE_RETURN_SUCCESS.
+ * \retval -1 on failure.
+ */
+-static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
++static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
+ {
+ struct ast_channel *transferer;
+ struct ast_channel *transferee;
+@@ -1323,6 +1377,9 @@
+ /* Set the channel's new extension, since it exists, using transferer context */
+ ast_set_flag(transferee, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
+ ast_log(LOG_DEBUG,"ABOUT TO AST_ASYNC_GOTO, have a pbx... set HANGUP_DONT on chan=%s\n", transferee->name);
++ if (ast_channel_connected_line_macro(transferee, transferer, &transferer->connected, 1, 0)) {
++ ast_channel_update_connected_line(transferee, &transferer->connected);
++ }
+ set_c_e_p(transferee, transferer_real_context, xferto, 0);
+ }
+ check_goto_on_transfer(transferer);
+@@ -1376,7 +1433,7 @@
+ *
+ * \return -1 on failure
+ */
+-static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
++static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
+ {
+ struct ast_channel *transferer;
+ struct ast_channel *transferee;
+@@ -1390,6 +1447,7 @@
+ struct ast_bridge_config bconfig;
+ struct ast_frame *f;
+ int l;
++ struct ast_party_connected_line connected_line;
+ struct ast_datastore *features_datastore;
+ struct ast_dial_features *dialfeatures = NULL;
+
+@@ -1459,6 +1517,7 @@
+ newchan = feature_request_and_dial(transferer, transferee, "Local", ast_best_codec(transferer->nativeformats),
+ xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name, 1, transferer->language);
+
++ ast_party_connected_line_init(&connected_line);
+ if (!ast_check_hangup(transferer)) {
+ /* Transferer is up - old behaviour */
+ ast_indicate(transferer, -1);
+@@ -1481,6 +1540,17 @@
+ memset(&bconfig,0,sizeof(struct ast_bridge_config));
+ ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
+ ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
++ /* We need to get the transferer's connected line information copied
++ * at this point because he is likely to hang up during the bridge with
++ * newchan. This info will be used down below before bridging the
++ * transferee and newchan
++ *
++ * As a result, we need to be sure to free this data before returning
++ * or overwriting it.
++ */
++ ast_channel_lock(transferer);
++ ast_party_connected_line_copy(&connected_line, &transferer->connected);
++ ast_channel_unlock(transferer);
+ res = ast_bridge_call(transferer, newchan, &bconfig);
+ if (ast_check_hangup(newchan) || !ast_check_hangup(transferer)) {
+ ast_hangup(newchan);
+@@ -1488,10 +1558,12 @@
+ ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
+ finishup(transferee);
+ transferer->_softhangup = 0;
++ ast_party_connected_line_free(&connected_line);
+ return AST_FEATURE_RETURN_SUCCESS;
+ }
+ if (check_compat(transferee, newchan)) {
+ finishup(transferee);
++ ast_party_connected_line_free(&connected_line);
+ return -1;
+ }
+ ast_indicate(transferee, AST_CONTROL_UNHOLD);
+@@ -1502,11 +1574,13 @@
+ || ast_check_hangup(transferee)
+ || ast_check_hangup(newchan)) {
+ ast_hangup(newchan);
++ ast_party_connected_line_free(&connected_line);
+ return -1;
+ }
+ xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
+ if (!xferchan) {
+ ast_hangup(newchan);
++ ast_party_connected_line_free(&connected_line);
+ return -1;
+ }
+ /* Make formats okay */
+@@ -1526,6 +1600,7 @@
+ if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
+ ast_hangup(xferchan);
+ ast_hangup(newchan);
++ ast_party_connected_line_free(&connected_line);
+ return -1;
+ }
+
+@@ -1560,6 +1635,48 @@
+ tobj->bconfig.end_bridge_callback_data_fixup(&tobj->bconfig, tobj->peer, tobj->chan);
+ }
+
++ /* Due to a limitation regarding when callerID is set on a Local channel,
++ * we use the transferer's connected line information here.
++ */
++
++ /* xferchan is transferee, and newchan is the transfer target
++ * So...in a transfer, who is the caller and who is the callee?
++ *
++ * When the call is originally made, it is clear who is caller and callee.
++ * When a transfer occurs, it is my humble opinion that the transferee becomes
++ * the caller, and the transfer target is the callee.
++ *
++ * The problem is that these macros were set with the intention of the original
++ * caller and callee taking those roles. A transfer can totally mess things up,
++ * to be technical. What sucks even more is that you can't effectively change
++ * the macros in the dialplan during the call from the transferer to the transfer
++ * target because the transferee is stuck with whatever role he originally had.
++ *
++ * I think the answer here is just to make sure that it is well documented that
++ * during a transfer, the transferee is the "caller" and the transfer target
++ * is the "callee."
++ *
++ * This means that if party A calls party B, and party A transfers party B to
++ * party C, then B has switched roles for the call. Now party B will have the
++ * caller macro called on his channel instead of the callee macro.
++ *
++ * Luckily, the method by which the bridge is launched here ensures that the
++ * transferee is the "chan" on the bridge and the transfer target is the "peer,"
++ * so my idea for the roles post-transfer does not require extensive code changes.
++ */
++ connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
++ if (ast_channel_connected_line_macro(newchan, xferchan, &connected_line, 1, 0)) {
++ ast_channel_update_connected_line(xferchan, &connected_line);
++ }
++ ast_channel_lock(xferchan);
++ ast_connected_line_copy_from_caller(&connected_line, &xferchan->cid);
++ ast_channel_unlock(xferchan);
++ connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
++ if (ast_channel_connected_line_macro(xferchan, newchan, &connected_line, 0, 0)) {
++ ast_channel_update_connected_line(newchan, &connected_line);
++ }
++ ast_party_connected_line_free(&connected_line);
++
+ if (ast_stream_and_wait(newchan, xfersound, ""))
+ ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
+ bridge_call_thread_launch(tobj);
+@@ -1656,11 +1773,28 @@
+ tobj->chan = newchan;
+ tobj->peer = xferchan;
+ tobj->bconfig = *config;
+-
++
+ if (tobj->bconfig.end_bridge_callback_data_fixup) {
+ tobj->bconfig.end_bridge_callback_data_fixup(&tobj->bconfig, tobj->peer, tobj->chan);
+ }
+
++ ast_channel_lock(newchan);
++ ast_connected_line_copy_from_caller(&connected_line, &newchan->cid);
++ ast_channel_unlock(newchan);
++ connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
++ if (ast_channel_connected_line_macro(newchan, xferchan, &connected_line, 1, 0)) {
++ ast_channel_update_connected_line(xferchan, &connected_line);
++ }
++ ast_channel_lock(xferchan);
++ ast_connected_line_copy_from_caller(&connected_line, &xferchan->cid);
++ ast_channel_unlock(xferchan);
++ connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
++ if (ast_channel_connected_line_macro(xferchan, newchan, &connected_line, 0, 0)) {
++ ast_channel_update_connected_line(newchan, &connected_line);
++ }
++
++ ast_party_connected_line_free(&connected_line);
++
+ if (ast_stream_and_wait(newchan, xfersound, ""))
+ ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
+ bridge_call_thread_launch(tobj);
+@@ -1677,8 +1811,7 @@
+
+ AST_RWLOCK_DEFINE_STATIC(features_lock);
+
+-static struct ast_call_feature builtin_features[] =
+-{
++static struct ast_call_feature builtin_features[] = {
+ { AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
+ { AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
+ { AST_FEATURE_AUTOMON, "One Touch Monitor", "automon", "", "", builtin_automonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
+@@ -1883,7 +2016,7 @@
+ * \retval -1 error.
+ * \retval -2 when an application cannot be found.
+ */
+-static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
++static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
+ {
+ struct ast_app *app;
+ struct ast_call_feature *feature = data;
+@@ -1969,53 +2102,42 @@
+ }
+
+ /*!
+- * \brief Check the dynamic features
+- * \param chan,peer,config,code,sense
++ * \brief Helper function for feature_interpret and ast_feature_detect
++ * \param chan,peer,config,code,sense,dynamic_features char buf,feature flags,operation,feature
+ *
+ * Lock features list, browse for code, unlock list
++ * If a feature is found and the operation variable is set, that feature's
++ * operation is executed. The first feature found is copied to the feature parameter.
+ * \retval res on success.
+ * \retval -1 on failure.
+ */
+-static int feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
++static int feature_interpret_helper(struct ast_channel *chan, struct ast_channel *peer,
++ struct ast_bridge_config *config, const char *code, int sense, char *dynamic_features_buf,
++ struct ast_flags *features, int operation, struct ast_call_feature *feature)
+ {
+ int x;
+- struct ast_flags features;
+- struct ast_call_feature *feature;
+ struct feature_group *fg = NULL;
+ struct feature_group_exten *fge;
+- const char *peer_dynamic_features, *chan_dynamic_features;
+- char dynamic_features_buf[128];
++ struct ast_call_feature *tmpfeature;
+ char *tmp, *tok;
+ int res = AST_FEATURE_RETURN_PASSDIGITS;
+ int feature_detected = 0;
+
+- if (sense == FEATURE_SENSE_CHAN) {
+- ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
++ if (!(peer && chan && config) && operation) {
++ return -1; /* can not run feature operation */
+ }
+- else {
+- ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
+- }
+
+- ast_channel_lock(peer);
+- peer_dynamic_features = ast_strdupa(S_OR(pbx_builtin_getvar_helper(peer, "DYNAMIC_FEATURES"),""));
+- ast_channel_unlock(peer);
+-
+- ast_channel_lock(chan);
+- chan_dynamic_features = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES"),""));
+- ast_channel_unlock(chan);
+-
+- snprintf(dynamic_features_buf, sizeof(dynamic_features_buf), "%s%s%s", S_OR(chan_dynamic_features, ""), chan_dynamic_features && peer_dynamic_features ? "#" : "", S_OR(peer_dynamic_features,""));
+-
+- ast_debug(3, "Feature interpret: chan=%s, peer=%s, code=%s, sense=%d, features=%d, dynamic=%s\n", chan->name, peer->name, code, sense, features.flags, dynamic_features_buf);
+-
+ ast_rwlock_rdlock(&features_lock);
+ for (x = 0; x < FEATURES_COUNT; x++) {
+- if ((ast_test_flag(&features, builtin_features[x].feature_mask)) &&
++ if ((ast_test_flag(features, builtin_features[x].feature_mask)) &&
+ !ast_strlen_zero(builtin_features[x].exten)) {
+ /* Feature is up for consideration */
+ if (!strcmp(builtin_features[x].exten, code)) {
+ ast_debug(3, "Feature detected: fname=%s sname=%s exten=%s\n", builtin_features[x].fname, builtin_features[x].sname, builtin_features[x].exten);
+- res = builtin_features[x].operation(chan, peer, config, code, sense, NULL);
++ if (operation) {
++ res = builtin_features[x].operation(chan, peer, config, code, sense, NULL);
++ }
++ memcpy(feature, &builtin_features[x], sizeof(feature));
+ feature_detected = 1;
+ break;
+ } else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
+@@ -2026,8 +2148,9 @@
+ }
+ ast_rwlock_unlock(&features_lock);
+
+- if (ast_strlen_zero(dynamic_features_buf) || feature_detected)
++ if (ast_strlen_zero(dynamic_features_buf) || feature_detected) {
+ return res;
++ }
+
+ tmp = dynamic_features_buf;
+
+@@ -2040,8 +2163,10 @@
+ AST_LIST_TRAVERSE(&fg->features, fge, entry) {
+ if (strcasecmp(fge->exten, code))
+ continue;
+-
+- res = fge->feature->operation(chan, peer, config, code, sense, fge->feature);
++ if (operation) {
++ res = fge->feature->operation(chan, peer, config, code, sense, fge->feature);
++ }
++ memcpy(feature, fge->feature, sizeof(feature));
+ if (res != AST_FEATURE_RETURN_KEEPTRYING) {
+ AST_RWLIST_UNLOCK(&feature_groups);
+ break;
+@@ -2056,33 +2181,78 @@
+
+ AST_RWLIST_RDLOCK(&feature_list);
+
+- if (!(feature = find_dynamic_feature(tok))) {
++ if (!(tmpfeature = find_dynamic_feature(tok))) {
+ AST_RWLIST_UNLOCK(&feature_list);
+ continue;
+ }
+-
++
+ /* Feature is up for consideration */
+- if (!strcmp(feature->exten, code)) {
+- ast_verb(3, " Feature Found: %s exten: %s\n",feature->sname, tok);
+- res = feature->operation(chan, peer, config, code, sense, feature);
++ if (!strcmp(tmpfeature->exten, code)) {
++ ast_verb(3, " Feature Found: %s exten: %s\n",tmpfeature->sname, tok);
++ if (operation) {
++ res = tmpfeature->operation(chan, peer, config, code, sense, tmpfeature);
++ }
++ memcpy(feature, tmpfeature, sizeof(feature));
+ if (res != AST_FEATURE_RETURN_KEEPTRYING) {
+ AST_RWLIST_UNLOCK(&feature_list);
+ break;
+ }
+ res = AST_FEATURE_RETURN_PASSDIGITS;
+- } else if (!strncmp(feature->exten, code, strlen(code)))
++ } else if (!strncmp(tmpfeature->exten, code, strlen(code)))
+ res = AST_FEATURE_RETURN_STOREDIGITS;
+
+ AST_RWLIST_UNLOCK(&feature_list);
+ }
+-
++
+ return res;
+ }
+
++/*!
++ * \brief Check the dynamic features
++ * \param chan,peer,config,code,sense
++ *
++ * \retval res on success.
++ * \retval -1 on failure.
++*/
++
++static int feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense) {
++
++ char dynamic_features_buf[128];
++ const char *peer_dynamic_features, *chan_dynamic_features;
++ struct ast_flags features;
++ struct ast_call_feature feature;
++ if (sense == FEATURE_SENSE_CHAN) {
++ ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
++ }
++ else {
++ ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
++ }
++
++ ast_channel_lock(peer);
++ peer_dynamic_features = ast_strdupa(S_OR(pbx_builtin_getvar_helper(peer, "DYNAMIC_FEATURES"),""));
++ ast_channel_unlock(peer);
++
++ ast_channel_lock(chan);
++ chan_dynamic_features = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES"),""));
++ ast_channel_unlock(chan);
++
++ snprintf(dynamic_features_buf, sizeof(dynamic_features_buf), "%s%s%s", S_OR(chan_dynamic_features, ""), chan_dynamic_features && peer_dynamic_features ? "#" : "", S_OR(peer_dynamic_features,""));
++
++ ast_debug(3, "Feature interpret: chan=%s, peer=%s, code=%s, sense=%d, features=%d, dynamic=%s\n", chan->name, peer->name, code, sense, features.flags, dynamic_features_buf);
++
++ return feature_interpret_helper(chan, peer, config, code, sense, dynamic_features_buf, &features, 1, &feature);
++}
++
++
++int ast_feature_detect(struct ast_channel *chan, struct ast_flags *features, const char *code, struct ast_call_feature *feature) {
++
++ return feature_interpret_helper(chan, NULL, NULL, code, 0, NULL, features, 0, feature);
++}
++
+ static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
+ {
+ int x;
+-
++
+ ast_clear_flag(config, AST_FLAGS_ALL);
+
+ ast_rwlock_rdlock(&features_lock);
+@@ -2097,7 +2267,7 @@
+ ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
+ }
+ ast_rwlock_unlock(&features_lock);
+-
++
+ if (chan && peer && !(ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_0) && ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_1))) {
+ const char *dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
+
+@@ -2163,6 +2333,10 @@
+ ast_channel_inherit_variables(caller, chan);
+ pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", caller->name);
+
++ ast_channel_lock(chan);
++ ast_connected_line_copy_from_caller(&chan->connected, &caller->cid);
++ ast_channel_unlock(chan);
++
+ if (ast_call(chan, data, timeout)) {
+ ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
+ goto done;
+@@ -2238,6 +2412,10 @@
+ f = NULL;
+ ready=1;
+ break;
++ } else if (f->subclass == AST_CONTROL_CONNECTED_LINE) {
++ if (ast_channel_connected_line_macro(chan, caller, f, 1, 1)) {
++ ast_indicate_data(caller, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen);
++ }
+ } else if (f->subclass != -1) {
+ ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass);
+ }
+@@ -2433,7 +2611,6 @@
+ int hadfeatures=0;
+ int autoloopflag;
+ struct ast_option_header *aoh;
+- struct ast_bridge_config backup_config;
+ struct ast_cdr *bridge_cdr = NULL;
+ struct ast_cdr *orig_peer_cdr = NULL;
+ struct ast_cdr *chan_cdr = pick_unlocked_cdr(chan->cdr); /* the proper chan cdr, if there are forked cdrs */
+@@ -2441,10 +2618,6 @@
+ struct ast_cdr *new_chan_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */
+ struct ast_cdr *new_peer_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */
+
+- memset(&backup_config, 0, sizeof(backup_config));
+-
+- config->start_time = ast_tvnow();
+-
+ if (chan && peer) {
+ pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
+ pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
+@@ -2465,7 +2638,7 @@
+ if (monitor_ok) {
+ const char *monitor_exec;
+ struct ast_channel *src = NULL;
+- if (!monitor_app) {
++ if (!monitor_app) {
+ if (!(monitor_app = pbx_findapp("Monitor")))
+ monitor_ok=0;
+ }
+@@ -2480,7 +2653,6 @@
+ }
+
+ set_config_flags(chan, peer, config);
+- config->firstpass = 1;
+
+ /* Answer if need be */
+ if (chan->_state != AST_STATE_UP) {
+@@ -2565,8 +2737,8 @@
+ feature_timer. Not good!
+ */
+ if (config->feature_timer && (!f || f->frametype == AST_FRAME_DTMF_END)) {
+- /* Update time limit for next pass */
+- diff = ast_tvdiff_ms(ast_tvnow(), config->start_time);
++ /* Update feature timer for next pass */
++ diff = ast_tvdiff_ms(ast_tvnow(), config->feature_start_time);
+ if (res == AST_BRIDGE_RETRY) {
+ /* The feature fully timed out but has not been updated. Skip
+ * the potential round error from the diff calculation and
+@@ -2577,18 +2749,7 @@
+ }
+
+ if (hasfeatures) {
+- /* Running on backup config, meaning a feature might be being
+- activated, but that's no excuse to keep things going
+- indefinitely! */
+- if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) {
+- ast_debug(1, "Timed out, realtime this time!\n");
+- config->feature_timer = 0;
+- who = chan;
+- if (f)
+- ast_frfree(f);
+- f = NULL;
+- res = 0;
+- } else if (config->feature_timer <= 0) {
++ if (config->feature_timer <= 0) {
+ /* Not *really* out of time, just out of time for
+ digits to come in for features. */
+ ast_debug(1, "Timed out for feature!\n");
+@@ -2604,9 +2765,8 @@
+ ast_frfree(f);
+ hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
+ if (!hasfeatures) {
+- /* Restore original (possibly time modified) bridge config */
+- memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
+- memset(&backup_config, 0, sizeof(backup_config));
++ /* No more digits expected - reset the timer */
++ config->feature_timer = 0;
+ }
+ hadfeatures = hasfeatures;
+ /* Continue as we were */
+@@ -2630,13 +2790,14 @@
+ }
+ }
+ if (res < 0) {
+- if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_test_flag(peer, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan) && !ast_check_hangup(peer))
++ if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_test_flag(peer, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan) && !ast_check_hangup(peer)) {
+ ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
++ }
+ goto before_you_go;
+ }
+
+ if (!f || (f->frametype == AST_FRAME_CONTROL &&
+- (f->subclass == AST_CONTROL_HANGUP || f->subclass == AST_CONTROL_BUSY ||
++ (f->subclass == AST_CONTROL_HANGUP || f->subclass == AST_CONTROL_BUSY ||
+ f->subclass == AST_CONTROL_CONGESTION))) {
+ res = -1;
+ break;
+@@ -2650,6 +2811,11 @@
+ case -1:
+ ast_indicate(other, f->subclass);
+ break;
++ case AST_CONTROL_CONNECTED_LINE:
++ if (!ast_channel_connected_line_macro(who, other, f, who != chan, 1)) {
++ break;
++ }
++ /* The implied "else" falls through purposely */
+ case AST_CONTROL_HOLD:
+ case AST_CONTROL_UNHOLD:
+ ast_indicate_data(other, f->subclass, f->data.ptr, f->datalen);
+@@ -2686,7 +2852,7 @@
+ /* Get rid of the frame before we start doing "stuff" with the channels */
+ ast_frfree(f);
+ f = NULL;
+- config->feature_timer = backup_config.feature_timer;
++ config->feature_timer = 0;
+ res = feature_interpret(chan, peer, config, featurecode, sense);
+ switch(res) {
+ case AST_FEATURE_RETURN_PASSDIGITS:
+@@ -2698,30 +2864,21 @@
+ }
+ if (res >= AST_FEATURE_RETURN_PASSDIGITS) {
+ res = 0;
+- } else
++ } else {
+ break;
++ }
+ hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
+ if (hadfeatures && !hasfeatures) {
+- /* Restore backup */
+- memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
+- memset(&backup_config, 0, sizeof(struct ast_bridge_config));
++ /* Feature completed or timed out */
++ config->feature_timer = 0;
+ } else if (hasfeatures) {
+- if (!hadfeatures) {
+- /* Backup configuration */
+- memcpy(&backup_config, config, sizeof(struct ast_bridge_config));
+- /* Setup temporary config options */
+- config->play_warning = 0;
+- ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
+- ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
+- config->warning_freq = 0;
+- config->warning_sound = NULL;
+- config->end_sound = NULL;
+- config->start_sound = NULL;
+- config->firstpass = 0;
++ if (config->timelimit) {
++ /* No warning next time - we are waiting for future */
++ ast_set_flag(config, AST_FEATURE_WARNING_ACTIVE);
+ }
+- config->start_time = ast_tvnow();
++ config->feature_start_time = ast_tvnow();
+ config->feature_timer = featuredigittimeout;
+- ast_debug(1, "Set time limit to %ld\n", config->feature_timer);
++ ast_debug(1, "Set feature timer to %ld\n", config->feature_timer);
+ }
+ }
+ if (f)
+@@ -2795,7 +2952,9 @@
+ bridge_cdr = NULL;
+ }
+ }
+- ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_RUN);
++ if (chan->priority != 1 || !spawn_error) {
++ ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_RUN);
++ }
+ ast_channel_unlock(chan);
+ /* protect the lastapp/lastdata against the effects of the hangup/dialplan code */
+ if (bridge_cdr) {
+@@ -2839,33 +2998,35 @@
+ to attend to; if the chan or peer changed names,
+ we have the before and after attached CDR's.
+ */
+-
++
+ if (new_chan_cdr) {
+ struct ast_channel *chan_ptr = NULL;
+-
+- if (strcasecmp(orig_channame, chan->name) != 0) {
+- /* old channel */
+- chan_ptr = ast_get_channel_by_name_locked(orig_channame);
+- if (chan_ptr) {
+- if (!ast_bridged_channel(chan_ptr)) {
+- struct ast_cdr *cur;
+- for (cur = chan_ptr->cdr; cur; cur = cur->next) {
+- if (cur == chan_cdr) {
+- break;
+- }
+- }
+- if (cur)
+- ast_cdr_specialized_reset(chan_cdr,0);
+- }
+- ast_channel_unlock(chan_ptr);
+- }
+- /* new channel */
+- ast_cdr_specialized_reset(new_chan_cdr,0);
+- } else {
+- ast_cdr_specialized_reset(chan_cdr,0); /* nothing changed, reset the chan_cdr */
+- }
++
++ if (strcasecmp(orig_channame, chan->name) != 0) {
++ /* old channel */
++ if ((chan_ptr = ast_channel_get_by_name(orig_channame))) {
++ ast_channel_lock(chan_ptr);
++ if (!ast_bridged_channel(chan_ptr)) {
++ struct ast_cdr *cur;
++ for (cur = chan_ptr->cdr; cur; cur = cur->next) {
++ if (cur == chan_cdr) {
++ break;
++ }
++ }
++ if (cur) {
++ ast_cdr_specialized_reset(chan_cdr, 0);
++ }
++ }
++ ast_channel_unlock(chan_ptr);
++ chan_ptr = ast_channel_unref(chan_ptr);
++ }
++ /* new channel */
++ ast_cdr_specialized_reset(new_chan_cdr, 0);
++ } else {
++ ast_cdr_specialized_reset(chan_cdr, 0); /* nothing changed, reset the chan_cdr */
++ }
+ }
+-
++
+ {
+ struct ast_channel *chan_ptr = NULL;
+ new_peer_cdr = pick_unlocked_cdr(peer->cdr); /* the proper chan cdr, if there are forked cdrs */
+@@ -2873,8 +3034,8 @@
+ ast_set_flag(new_peer_cdr, AST_CDR_FLAG_POST_DISABLED); /* DISABLED is viral-- it will propagate across a bridge */
+ if (strcasecmp(orig_peername, peer->name) != 0) {
+ /* old channel */
+- chan_ptr = ast_get_channel_by_name_locked(orig_peername);
+- if (chan_ptr) {
++ if ((chan_ptr = ast_channel_get_by_name(orig_peername))) {
++ ast_channel_lock(chan_ptr);
+ if (!ast_bridged_channel(chan_ptr)) {
+ struct ast_cdr *cur;
+ for (cur = chan_ptr->cdr; cur; cur = cur->next) {
+@@ -2882,15 +3043,17 @@
+ break;
+ }
+ }
+- if (cur)
+- ast_cdr_specialized_reset(peer_cdr,0);
++ if (cur) {
++ ast_cdr_specialized_reset(peer_cdr, 0);
++ }
+ }
+ ast_channel_unlock(chan_ptr);
++ chan_ptr = ast_channel_unref(chan_ptr);
+ }
+ /* new channel */
+- ast_cdr_specialized_reset(new_peer_cdr,0);
++ ast_cdr_specialized_reset(new_peer_cdr, 0);
+ } else {
+- ast_cdr_specialized_reset(peer_cdr,0); /* nothing changed, reset the peer_cdr */
++ ast_cdr_specialized_reset(peer_cdr, 0); /* nothing changed, reset the peer_cdr */
+ }
+ }
+
+@@ -3196,7 +3359,7 @@
+ END_OPTIONS );
+
+ /*! \brief Park a call */
+-static int park_call_exec(struct ast_channel *chan, void *data)
++static int park_call_exec(struct ast_channel *chan, const char *data)
+ {
+ /* Cache the original channel name in case we get masqueraded in the middle
+ * of a park--it is still theoretically possible for a transfer to happen before
+@@ -3282,7 +3445,7 @@
+ }
+
+ /*! \brief Pickup parked call */
+-static int park_exec_full(struct ast_channel *chan, void *data, struct ast_parkinglot *parkinglot)
++static int park_exec_full(struct ast_channel *chan, const char *data, struct ast_parkinglot *parkinglot)
+ {
+ int res = 0;
+ struct ast_channel *peer=NULL;
+@@ -3292,7 +3455,7 @@
+ struct ast_bridge_config config;
+
+ if (data)
+- park = atoi((char *)data);
++ park = atoi((char *) data);
+
+ parkinglot = find_parkinglot(findparkinglotname(chan));
+ if (!parkinglot)
+@@ -3445,7 +3608,7 @@
+ return -1;
+ }
+
+-static int park_exec(struct ast_channel *chan, void *data)
++static int park_exec(struct ast_channel *chan, const char *data)
+ {
+ return park_exec_full(chan, data, default_parkinglot);
+ }
+@@ -3627,7 +3790,7 @@
+ char old_parking_ext[AST_MAX_EXTENSION];
+ char old_parking_con[AST_MAX_EXTENSION] = "";
+ char *ctg;
+- static const char *categories[] = {
++ static const char * const categories[] = {
+ /* Categories in features.conf that are not
+ * to be parsed as group categories
+ */
+@@ -4052,14 +4215,6 @@
+ return CLI_SUCCESS;
+ }
+
+-static char mandescr_bridge[] =
+-"Description: Bridge together two channels already in the PBX\n"
+-"Variables: ( Headers marked with * are required )\n"
+-" *Channel1: Channel to Bridge to Channel2\n"
+-" *Channel2: Channel to Bridge to Channel1\n"
+-" Tone: (Yes|No) Play courtesy tone to Channel 2\n"
+-"\n";
+-
+ /*!
+ * \brief Actual bridge
+ * \param chan
+@@ -4113,12 +4268,8 @@
+ return 0;
+ }
+
+- /* The same code must be executed for chana and chanb. To avoid a
+- * theoretical deadlock, this code is separated so both chana and chanb will
+- * not hold locks at the same time. */
+-
+ /* Start with chana */
+- chana = ast_get_channel_by_name_prefix_locked(channela, strlen(channela));
++ chana = ast_channel_get_by_name_prefix(channela, strlen(channela));
+
+ /* send errors if any of the channels could not be found/locked */
+ if (!chana) {
+@@ -4136,16 +4287,16 @@
+ if (!(tmpchana = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
+ NULL, NULL, 0, "Bridge/%s", chana->name))) {
+ astman_send_error(s, m, "Unable to create temporary channel!");
+- ast_channel_unlock(chana);
++ chana = ast_channel_unref(chana);
+ return 1;
+ }
+
+ do_bridge_masquerade(chana, tmpchana);
+- ast_channel_unlock(chana);
+- chana = NULL;
+
++ chana = ast_channel_unref(chana);
++
+ /* now do chanb */
+- chanb = ast_get_channel_by_name_prefix_locked(channelb, strlen(channelb));
++ chanb = ast_channel_get_by_name_prefix(channelb, strlen(channelb));
+ /* send errors if any of the channels could not be found/locked */
+ if (!chanb) {
+ char buf[256];
+@@ -4164,13 +4315,14 @@
+ NULL, NULL, 0, "Bridge/%s", chanb->name))) {
+ astman_send_error(s, m, "Unable to create temporary channels!");
+ ast_hangup(tmpchana);
+- ast_channel_unlock(chanb);
++ chanb = ast_channel_unref(chanb);
+ return 1;
+ }
++
+ do_bridge_masquerade(chanb, tmpchanb);
+- ast_channel_unlock(chanb);
+- chanb = NULL;
+
++ chanb = ast_channel_unref(chanb);
++
+ /* make the channels compatible, send error if we fail doing so */
+ if (ast_channel_make_compatible(tmpchana, tmpchanb)) {
+ ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for manager bridge\n", tmpchana->name, tmpchanb->name);
+@@ -4328,13 +4480,6 @@
+ return RESULT_SUCCESS;
+ }
+
+-static char mandescr_park[] =
+-"Description: Park a channel.\n"
+-"Variables: (Names marked with * are required)\n"
+-" *Channel: Channel name to park\n"
+-" *Channel2: Channel to announce park info to (and return to if timeout)\n"
+-" Timeout: Number of milliseconds to wait before callback.\n";
+-
+ /*!
+ * \brief Create manager event for parked calls
+ * \param s
+@@ -4364,21 +4509,24 @@
+ return 0;
+ }
+
+- ch1 = ast_get_channel_by_name_locked(channel);
+- if (!ch1) {
++ if (!(ch1 = ast_channel_get_by_name(channel))) {
+ snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel);
+ astman_send_error(s, m, buf);
+ return 0;
+ }
+
+- ch2 = ast_get_channel_by_name_locked(channel2);
+- if (!ch2) {
++ if (!(ch2 = ast_channel_get_by_name(channel2))) {
+ snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel2);
+ astman_send_error(s, m, buf);
+- ast_channel_unlock(ch1);
++ ast_channel_unref(ch1);
+ return 0;
+ }
+
++ ast_channel_lock(ch1);
++ while (ast_channel_trylock(ch2)) {
++ CHANNEL_DEADLOCK_AVOIDANCE(ch1);
++ }
++
+ if (!ast_strlen_zero(timeout)) {
+ sscanf(timeout, "%d", &to);
+ }
+@@ -4394,19 +4542,26 @@
+ ast_channel_unlock(ch1);
+ ast_channel_unlock(ch2);
+
++ ch1 = ast_channel_unref(ch1);
++ ch2 = ast_channel_unref(ch2);
++
+ return 0;
+ }
+
+-static int find_channel_by_group(struct ast_channel *c, void *data) {
+- struct ast_channel *chan = data;
++static int find_channel_by_group(void *obj, void *arg, void *data, int flags)
++{
++ struct ast_channel *c = data;
++ struct ast_channel *chan = obj;
+
+- return !c->pbx &&
++ int i = !c->pbx &&
+ /* Accessing 'chan' here is safe without locking, because there is no way for
+ the channel do disappear from under us at this point. pickupgroup *could*
+ change while we're here, but that isn't a problem. */
+ (c != chan) &&
+ (chan->pickupgroup & c->callgroup) &&
+ ((c->_state == AST_STATE_RINGING) || (c->_state == AST_STATE_RING));
++
++ return i ? CMP_MATCH | CMP_STOP : 0;
+ }
+
+ /*!
+@@ -4419,32 +4574,59 @@
+ */
+ int ast_pickup_call(struct ast_channel *chan)
+ {
+- struct ast_channel *cur = ast_channel_search_locked(find_channel_by_group, chan);
++ struct ast_channel *cur;
++ struct ast_party_connected_line connected_caller;
++ int res;
++ const char *chan_name;
++ const char *cur_name;
+
+- if (cur) {
+- int res = -1;
+- ast_debug(1, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name);
+- res = ast_answer(chan);
+- if (res)
+- ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
+- res = ast_queue_control(chan, AST_CONTROL_ANSWER);
+- if (res)
+- ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
+- res = ast_channel_masquerade(cur, chan);
+- if (res)
+- ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name); /* Done */
+- if (!ast_strlen_zero(pickupsound)) {
+- ast_stream_and_wait(cur, pickupsound, "");
+- }
+- ast_channel_unlock(cur);
+- return res;
+- } else {
++ if (!(cur = ast_channel_callback(find_channel_by_group, NULL, chan, 0))) {
+ ast_debug(1, "No call pickup possible...\n");
+ if (!ast_strlen_zero(pickupfailsound)) {
+ ast_stream_and_wait(chan, pickupfailsound, "");
+ }
++ return -1;
+ }
+- return -1;
++
++ ast_channel_lock_both(cur, chan);
++
++ cur_name = ast_strdupa(cur->name);
++ chan_name = ast_strdupa(chan->name);
++
++ ast_debug(1, "Call pickup on chan '%s' by '%s'\n", cur_name, chan_name);
++
++ connected_caller = cur->connected;
++ connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
++ if (ast_channel_connected_line_macro(NULL, chan, &connected_caller, 0, 0)) {
++ ast_channel_update_connected_line(chan, &connected_caller);
++ }
++
++ ast_party_connected_line_collect_caller(&connected_caller, &chan->cid);
++ connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
++ ast_channel_queue_connected_line_update(chan, &connected_caller);
++
++ ast_channel_unlock(cur);
++ ast_channel_unlock(chan);
++
++ if (ast_answer(chan)) {
++ ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan_name);
++ }
++
++ if (ast_queue_control(chan, AST_CONTROL_ANSWER)) {
++ ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan_name);
++ }
++
++ if ((res = ast_channel_masquerade(cur, chan))) {
++ ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan_name, cur_name);
++ }
++
++ if (!ast_strlen_zero(pickupsound)) {
++ ast_stream_and_wait(cur, pickupsound, "");
++ }
++
++ cur = ast_channel_unref(cur);
++
++ return res;
+ }
+
+ static char *app_bridge = "Bridge";
+@@ -4466,7 +4648,7 @@
+ * answer call if not already, check compatible channels, setup bridge config
+ * now bridge call, if transfered party hangs up return to PBX extension.
+ */
+-static int bridge_exec(struct ast_channel *chan, void *data)
++static int bridge_exec(struct ast_channel *chan, const char *data)
+ {
+ struct ast_channel *current_dest_chan, *final_dest_chan;
+ char *tmp_data = NULL;
+@@ -4504,8 +4686,8 @@
+ }
+
+ /* make sure we have a valid end point */
+- if (!(current_dest_chan = ast_get_channel_by_name_prefix_locked(args.dest_chan,
+- strlen(args.dest_chan)))) {
++ if (!(current_dest_chan = ast_channel_get_by_name_prefix(args.dest_chan,
++ strlen(args.dest_chan)))) {
+ ast_log(LOG_WARNING, "Bridge failed because channel %s does not exists or we "
+ "cannot get its lock\n", args.dest_chan);
+ manager_event(EVENT_FLAG_CALL, "BridgeExec",
+@@ -4518,8 +4700,9 @@
+ }
+
+ /* answer the channel if needed */
+- if (current_dest_chan->_state != AST_STATE_UP)
++ if (current_dest_chan->_state != AST_STATE_UP) {
+ ast_answer(current_dest_chan);
++ }
+
+ /* try to allocate a place holder where current_dest_chan will be placed */
+ if (!(final_dest_chan = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
+@@ -4546,6 +4729,7 @@
+ "Channel2: %s\r\n", chan->name, final_dest_chan->name);
+ ast_hangup(final_dest_chan); /* may be we should return this channel to the PBX? */
+ pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "INCOMPATIBLE");
++ current_dest_chan = ast_channel_unref(current_dest_chan);
+ return 0;
+ }
+
+@@ -4563,6 +4747,8 @@
+ }
+ }
+
++ current_dest_chan = ast_channel_unref(current_dest_chan);
++
+ /* do the bridge */
+ ast_bridge_call(chan, final_dest_chan, &bconfig);
+
+@@ -4602,9 +4788,9 @@
+ if (!res)
+ res = ast_register_application2(parkcall, park_call_exec, NULL, NULL, NULL);
+ if (!res) {
+- ast_manager_register("ParkedCalls", 0, manager_parking_status, "List parked calls");
+- ast_manager_register2("Park", EVENT_FLAG_CALL, manager_park, "Park a channel", mandescr_park);
+- ast_manager_register2("Bridge", EVENT_FLAG_CALL, action_bridge, "Bridge two channels already in the PBX", mandescr_bridge);
++ ast_manager_register_xml("ParkedCalls", 0, manager_parking_status);
++ ast_manager_register_xml("Park", EVENT_FLAG_CALL, manager_park);
++ ast_manager_register_xml("Bridge", EVENT_FLAG_CALL, action_bridge);
+ }
+
+ res |= ast_devstate_prov_add("Park", metermaidstate);
+Index: main/http.c
+===================================================================
+--- a/main/http.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/http.c (.../trunk) (revision 202568)
+@@ -17,14 +17,14 @@
+ */
+
+ /*!
+- * \file
++ * \file
+ * \brief http server for AMI access
+ *
+ * \author Mark Spencer <markster@digium.com>
+ *
+ * This program implements a tiny http server
+- * and was inspired by micro-httpd by Jef Poskanzer
+- *
++ * and was inspired by micro-httpd by Jef Poskanzer
++ *
+ * \ref AstHTTP - AMI over the http protocol
+ */
+
+@@ -98,6 +98,7 @@
+ const char *mtype;
+ } mimetypes[] = {
+ { "png", "image/png" },
++ { "xml", "text/xml" },
+ { "jpg", "image/jpeg" },
+ { "js", "application/x-javascript" },
+ { "wav", "audio/x-wav" },
+@@ -115,8 +116,24 @@
+
+ static AST_RWLIST_HEAD_STATIC(uri_redirects, http_uri_redirect);
+
+-static const char *ftype2mtype(const char *ftype, char *wkspace, int wkspacelen)
++static const struct ast_cfhttp_methods_text {
++ enum ast_http_method method;
++ const char text[];
++} ast_http_methods_text[] = {
++ { AST_HTTP_UNKNOWN, "UNKNOWN" },
++ { AST_HTTP_GET, "GET" },
++ { AST_HTTP_POST, "POST" },
++ { AST_HTTP_HEAD, "HEAD" },
++ { AST_HTTP_PUT, "PUT" },
++};
++
++const char *ast_get_http_method(enum ast_http_method method)
+ {
++ return ast_http_methods_text[method].text;
++}
++
++const char *ast_http_ftype2mtype(const char *ftype)
++{
+ int x;
+
+ if (ftype) {
+@@ -126,21 +143,24 @@
+ }
+ }
+ }
+-
+- snprintf(wkspace, wkspacelen, "text/%s", S_OR(ftype, "plain"));
+-
+- return wkspace;
++ return NULL;
+ }
+
+-static uint32_t manid_from_vars(struct ast_variable *sid) {
+- uint32_t mngid;
++uint32_t ast_http_manid_from_vars(struct ast_variable *headers)
++{
++ uint32_t mngid = 0;
++ struct ast_variable *v, *cookies;
+
+- while (sid && strcmp(sid->name, "mansession_id"))
+- sid = sid->next;
+-
+- if (!sid || sscanf(sid->value, "%x", &mngid) != 1)
+- return 0;
+-
++ cookies = ast_http_get_cookies(headers);
++ for (v = cookies; v; v = v->next) {
++ if (!strcasecmp(v->name, "mansession_id")) {
++ sscanf(v->value, "%x", &mngid);
++ break;
++ }
++ }
++ if (cookies) {
++ ast_variables_destroy(cookies);
++ }
+ return mngid;
+ }
+
+@@ -151,20 +171,31 @@
+ }
+ }
+
+-static struct ast_str *static_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *vars, struct ast_variable *headers, int *status, char **title, int *contentlength)
++static int static_callback(struct ast_tcptls_session_instance *ser,
++ const struct ast_http_uri *urih, const char *uri,
++ enum ast_http_method method, struct ast_variable *get_vars,
++ struct ast_variable *headers)
+ {
+ char *path;
+- char *ftype;
++ const char *ftype;
+ const char *mtype;
+ char wkspace[80];
+ struct stat st;
+ int len;
+ int fd;
+- struct timeval now = ast_tvnow();
+- char buf[256];
++ struct ast_str *http_header;
++ struct timeval tv;
+ struct ast_tm tm;
++ char timebuf[80], etag[23];
++ struct ast_variable *v;
++ int not_modified = 0;
+
+- /* Yuck. I'm not really sold on this, but if you don't deliver static content it makes your configuration
++ if (method != AST_HTTP_GET && method != AST_HTTP_HEAD) {
++ ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method");
++ return -1;
++ }
++
++ /* Yuck. I'm not really sold on this, but if you don't deliver static content it makes your configuration
+ substantially more challenging, but this seems like a rather irritating feature creep on Asterisk. */
+ if (!enablestatic || ast_strlen_zero(uri)) {
+ goto out403;
+@@ -178,18 +209,20 @@
+ if (strstr(uri, "/..")) {
+ goto out403;
+ }
+-
++
+ if ((ftype = strrchr(uri, '.'))) {
+ ftype++;
+ }
+
+- mtype = ftype2mtype(ftype, wkspace, sizeof(wkspace));
+-
++ if (!(mtype = ast_http_ftype2mtype(ftype))) {
++ snprintf(wkspace, sizeof(wkspace), "text/%s", S_OR(ftype, "plain"));
++ }
++
+ /* Cap maximum length */
+ if ((len = strlen(uri) + strlen(ast_config_AST_DATA_DIR) + strlen("/static-http/") + 5) > 1024) {
+ goto out403;
+ }
+-
++
+ path = alloca(len);
+ sprintf(path, "%s/static-http/%s", ast_config_AST_DATA_DIR, uri);
+ if (stat(path, &st)) {
+@@ -198,142 +231,275 @@
+
+ if (S_ISDIR(st.st_mode)) {
+ goto out404;
+- }
++ }
+
+- if ((fd = open(path, O_RDONLY)) < 0) {
++ fd = open(path, O_RDONLY);
++ if (fd < 0) {
+ goto out403;
+ }
+
+- if (strstr(path, "/private/") && !astman_is_authed(manid_from_vars(vars))) {
++ if (strstr(path, "/private/") && !astman_is_authed(ast_http_manid_from_vars(headers))) {
+ goto out403;
+ }
+
+- ast_strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S %Z", ast_localtime(&now, &tm, "GMT"));
+- fprintf(ser->f, "HTTP/1.1 200 OK\r\n"
+- "Server: Asterisk/%s\r\n"
+- "Date: %s\r\n"
+- "Connection: close\r\n"
+- "Cache-Control: private\r\n"
+- "Content-Length: %d\r\n"
+- "Content-type: %s\r\n\r\n",
+- ast_get_version(), buf, (int) st.st_size, mtype);
++ /* make "Etag:" http header value */
++ snprintf(etag, sizeof(etag), "\"%ld\"", (long)st.st_mtime);
+
+- while ((len = read(fd, buf, sizeof(buf))) > 0) {
+- if (fwrite(buf, 1, len, ser->f) != len) {
+- ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno));
++ /* make "Last-Modified:" http header value */
++ tv.tv_sec = st.st_mtime;
++ tv.tv_usec = 0;
++ ast_strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", ast_localtime(&tv, &tm, "GMT"));
++
++ /* check received "If-None-Match" request header and Etag value for file */
++ for (v = headers; v; v = v->next) {
++ if (!strcasecmp(v->name, "If-None-Match")) {
++ if (!strcasecmp(v->value, etag)) {
++ not_modified = 1;
++ }
++ break;
+ }
+ }
+
++ if ( (http_header = ast_str_create(255)) == NULL) {
++ return -1;
++ }
++
++ ast_str_set(&http_header, 0, "Content-type: %s\r\n"
++ "ETag: %s\r\n"
++ "Last-Modified: %s",
++ mtype,
++ etag,
++ timebuf);
++
++ /* ast_http_send() frees http_header, so we don't need to do it before returning */
++ if (not_modified) {
++ ast_http_send(ser, method, 304, "Not Modified", http_header, NULL, 0, 1);
++ } else {
++ ast_http_send(ser, method, 200, NULL, http_header, NULL, fd, 1); /* static content flag is set */
++ }
+ close(fd);
++ return 0;
+
+- return NULL;
+-
+ out404:
+- return ast_http_error((*status = 404),
+- (*title = ast_strdup("Not Found")),
+- NULL, "The requested URL was not found on this server.");
++ ast_http_error(ser, 404, "Not Found", "The requested URL was not found on this server.");
++ return -1;
+
+ out403:
+- return ast_http_error((*status = 403),
+- (*title = ast_strdup("Access Denied")),
+- NULL, "You do not have permission to access the requested URL.");
++ ast_http_error(ser, 403, "Access Denied", "You do not have permission to access the requested URL.");
++ return -1;
+ }
+
+-
+-static struct ast_str *httpstatus_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *vars, struct ast_variable *headers, int *status, char **title, int *contentlength)
++static int httpstatus_callback(struct ast_tcptls_session_instance *ser,
++ const struct ast_http_uri *urih, const char *uri,
++ enum ast_http_method method, struct ast_variable *get_vars,
++ struct ast_variable *headers)
+ {
+- struct ast_str *out = ast_str_create(512);
+- struct ast_variable *v;
++ struct ast_str *out;
++ struct ast_variable *v, *cookies = NULL;
+
+- if (out == NULL) {
+- return out;
++ if (method != AST_HTTP_GET && method != AST_HTTP_HEAD) {
++ ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method");
++ return -1;
+ }
+
++ if ( (out = ast_str_create(512)) == NULL) {
++ return -1;
++ }
++
+ ast_str_append(&out, 0,
+- "\r\n"
+- "<title>Asterisk HTTP Status</title>\r\n"
+- "<body bgcolor=\"#ffffff\">\r\n"
+- "<table bgcolor=\"#f1f1f1\" align=\"center\"><tr><td bgcolor=\"#e0e0ff\" colspan=\"2\" width=\"500\">\r\n"
+- "<h2>&nbsp;&nbsp;Asterisk&trade; HTTP Status</h2></td></tr>\r\n");
++ "<title>Asterisk HTTP Status</title>\r\n"
++ "<body bgcolor=\"#ffffff\">\r\n"
++ "<table bgcolor=\"#f1f1f1\" align=\"center\"><tr><td bgcolor=\"#e0e0ff\" colspan=\"2\" width=\"500\">\r\n"
++ "<h2>&nbsp;&nbsp;Asterisk&trade; HTTP Status</h2></td></tr>\r\n");
++
+ ast_str_append(&out, 0, "<tr><td><i>Prefix</i></td><td><b>%s</b></td></tr>\r\n", prefix);
+ ast_str_append(&out, 0, "<tr><td><i>Bind Address</i></td><td><b>%s</b></td></tr>\r\n",
+ ast_inet_ntoa(http_desc.old_address.sin_addr));
+ ast_str_append(&out, 0, "<tr><td><i>Bind Port</i></td><td><b>%d</b></td></tr>\r\n",
+ ntohs(http_desc.old_address.sin_port));
+-
+ if (http_tls_cfg.enabled) {
+ ast_str_append(&out, 0, "<tr><td><i>SSL Bind Port</i></td><td><b>%d</b></td></tr>\r\n",
+ ntohs(https_desc.old_address.sin_port));
+ }
+-
+ ast_str_append(&out, 0, "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
+-
+- for (v = vars; v; v = v->next) {
+- if (strncasecmp(v->name, "cookie_", 7)) {
+- ast_str_append(&out, 0, "<tr><td><i>Submitted Variable '%s'</i></td><td>%s</td></tr>\r\n", v->name, v->value);
+- }
++ for (v = get_vars; v; v = v->next) {
++ ast_str_append(&out, 0, "<tr><td><i>Submitted GET Variable '%s'</i></td><td>%s</td></tr>\r\n", v->name, v->value);
+ }
+-
+ ast_str_append(&out, 0, "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
+
+- for (v = vars; v; v = v->next) {
+- if (!strncasecmp(v->name, "cookie_", 7)) {
+- ast_str_append(&out, 0, "<tr><td><i>Cookie '%s'</i></td><td>%s</td></tr>\r\n", v->name, v->value);
+- }
++ cookies = ast_http_get_cookies(headers);
++ for (v = cookies; v; v = v->next) {
++ ast_str_append(&out, 0, "<tr><td><i>Cookie '%s'</i></td><td>%s</td></tr>\r\n", v->name, v->value);
+ }
++ ast_variables_destroy(cookies);
+
+ ast_str_append(&out, 0, "</table><center><font size=\"-1\"><i>Asterisk and Digium are registered trademarks of Digium, Inc.</i></font></center></body>\r\n");
+- return out;
++ ast_http_send(ser, method, 200, NULL, NULL, out, 0, 0);
++ return 0;
+ }
+
+ static struct ast_http_uri statusuri = {
+ .callback = httpstatus_callback,
+ .description = "Asterisk HTTP General Status",
+ .uri = "httpstatus",
+- .supports_get = 1,
++ .has_subtree = 0,
+ .data = NULL,
+ .key = __FILE__,
+ };
+-
++
+ static struct ast_http_uri staticuri = {
+ .callback = static_callback,
+ .description = "Asterisk HTTP Static Delivery",
+ .uri = "static",
+ .has_subtree = 1,
+- .static_content = 1,
+- .supports_get = 1,
+ .data = NULL,
+ .key= __FILE__,
+ };
+-
+-struct ast_str *ast_http_error(int status, const char *title, const char *extra_header, const char *text)
++
++
++/* send http/1.1 responce */
++/* free content variable and close socket*/
++void ast_http_send(struct ast_tcptls_session_instance *ser,
++ enum ast_http_method method, int status_code, const char *status_title,
++ struct ast_str *http_header, struct ast_str *out, const int fd,
++ unsigned int static_content)
+ {
++ struct timeval now = ast_tvnow();
++ struct ast_tm tm;
++ char timebuf[80];
++ int content_length = 0;
++
++ if (!ser || 0 == ser->f) {
++ return;
++ }
++
++ ast_strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", ast_localtime(&now, &tm, "GMT"));
++
++ /* calc conetnt length */
++ if (out) {
++ content_length += strlen(ast_str_buffer(out));
++ }
++
++ if (fd) {
++ content_length += lseek(fd, 0, SEEK_END);
++ lseek(fd, 0, SEEK_SET);
++ }
++
++ /* send http header */
++ fprintf(ser->f, "HTTP/1.1 %d %s\r\n"
++ "Server: Asterisk/%s\r\n"
++ "Date: %s\r\n"
++ "Connection: close\r\n"
++ "%s"
++ "Content-Length: %d\r\n"
++ "%s\r\n\r\n",
++ status_code, status_title ? status_title : "OK",
++ ast_get_version(),
++ timebuf,
++ static_content ? "" : "Cache-Control: no-cache, no-store\r\n",
++ content_length,
++ http_header ? ast_str_buffer(http_header) : ""
++ );
++
++ /* send content */
++ if (method != AST_HTTP_HEAD || status_code >= 400) {
++ if (out) {
++ fprintf(ser->f, "%s", ast_str_buffer(out));
++ }
++
++ if (fd) {
++ char buf[256];
++ int len;
++ while ((len = read(fd, buf, sizeof(buf))) > 0) {
++ if (fwrite(buf, len, 1, ser->f) != len) {
++ ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno));
++ }
++ }
++ }
++ }
++
++ if (http_header) {
++ ast_free(http_header);
++ }
++ if (out) {
++ ast_free(out);
++ }
++
++ fclose(ser->f);
++ ser->f = 0;
++ return;
++}
++
++/* Send http "401 Unauthorized" responce and close socket*/
++void ast_http_auth(struct ast_tcptls_session_instance *ser, const char *realm,
++ const unsigned long nonce, const unsigned long opaque, int stale,
++ const char *text)
++{
++ struct ast_str *http_headers = ast_str_create(128);
+ struct ast_str *out = ast_str_create(512);
+
+- if (out == NULL) {
+- return out;
++ if (!http_headers || !out) {
++ ast_free(http_headers);
++ ast_free(out);
++ return;
+ }
+
++ ast_str_set(&http_headers, 0,
++ "WWW-authenticate: Digest algorithm=MD5, realm=\"%s\", nonce=\"%08lx\", qop=\"auth\", opaque=\"%08lx\"%s\r\n"
++ "Content-type: text/html",
++ realm ? realm : "Asterisk",
++ nonce,
++ opaque,
++ stale ? ", stale=true" : "");
++
+ ast_str_set(&out, 0,
+- "Content-type: text/html\r\n"
+- "%s"
+- "\r\n"
+- "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n"
+- "<html><head>\r\n"
+- "<title>%d %s</title>\r\n"
+- "</head><body>\r\n"
+- "<h1>%s</h1>\r\n"
+- "<p>%s</p>\r\n"
+- "<hr />\r\n"
+- "<address>Asterisk Server</address>\r\n"
+- "</body></html>\r\n",
+- (extra_header ? extra_header : ""), status, title, title, text);
++ "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n"
++ "<html><head>\r\n"
++ "<title>401 Unauthorized</title>\r\n"
++ "</head><body>\r\n"
++ "<h1>401 Unauthorized</h1>\r\n"
++ "<p>%s</p>\r\n"
++ "<hr />\r\n"
++ "<address>Asterisk Server</address>\r\n"
++ "</body></html>\r\n",
++ text ? text : "");
+
+- return out;
++ ast_http_send(ser, AST_HTTP_UNKNOWN, 401, "Unauthorized", http_headers, out, 0, 0);
++ return;
+ }
+
+-/*! \brief
+- * Link the new uri into the list.
++/* send http error responce and close socket*/
++void ast_http_error(struct ast_tcptls_session_instance *ser, int status_code, const char *status_title, const char *text)
++{
++ struct ast_str *http_headers = ast_str_create(40);
++ struct ast_str *out = ast_str_create(256);
++
++ if (!http_headers || !out) {
++ ast_free(http_headers);
++ ast_free(out);
++ return;
++ }
++
++ ast_str_set(&http_headers, 0, "Content-type: text/html");
++
++ ast_str_set(&out, 0,
++ "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n"
++ "<html><head>\r\n"
++ "<title>%d %s</title>\r\n"
++ "</head><body>\r\n"
++ "<h1>%s</h1>\r\n"
++ "<p>%s</p>\r\n"
++ "<hr />\r\n"
++ "<address>Asterisk Server</address>\r\n"
++ "</body></html>\r\n",
++ status_code, status_title, status_title, text);
++
++ ast_http_send(ser, AST_HTTP_UNKNOWN, status_code, status_title, http_headers, out, 0, 0);
++ return;
++}
++
++/*! \brief
++ * Link the new uri into the list.
+ *
+ * They are sorted by length of
+ * the string, not alphabetically. Duplicate entries are not replaced,
+@@ -346,25 +512,19 @@
+ struct ast_http_uri *uri;
+ int len = strlen(urih->uri);
+
+- if (!(urih->supports_get || urih->supports_post)) {
+- ast_log(LOG_WARNING, "URI handler does not provide either GET or POST method: %s (%s)\n", urih->uri, urih->description);
+- return -1;
+- }
+-
+ AST_RWLIST_WRLOCK(&uris);
+
+- if (AST_RWLIST_EMPTY(&uris) || strlen(AST_RWLIST_FIRST(&uris)->uri) <= len) {
++ if ( AST_RWLIST_EMPTY(&uris) || strlen(AST_RWLIST_FIRST(&uris)->uri) <= len ) {
+ AST_RWLIST_INSERT_HEAD(&uris, urih, entry);
+ AST_RWLIST_UNLOCK(&uris);
+-
+ return 0;
+ }
+
+ AST_RWLIST_TRAVERSE(&uris, uri, entry) {
+ if (AST_RWLIST_NEXT(uri, entry) &&
+- strlen(AST_RWLIST_NEXT(uri, entry)->uri) <= len) {
++ strlen(AST_RWLIST_NEXT(uri, entry)->uri) <= len) {
+ AST_RWLIST_INSERT_AFTER(&uris, uri, urih, entry);
+- AST_RWLIST_UNLOCK(&uris);
++ AST_RWLIST_UNLOCK(&uris);
+
+ return 0;
+ }
+@@ -373,9 +533,9 @@
+ AST_RWLIST_INSERT_TAIL(&uris, urih, entry);
+
+ AST_RWLIST_UNLOCK(&uris);
+-
++
+ return 0;
+-}
++}
+
+ void ast_http_uri_unlink(struct ast_http_uri *urih)
+ {
+@@ -411,91 +571,121 @@
+ static void http_decode(char *s)
+ {
+ char *t;
+-
++
+ for (t = s; *t; t++) {
+- if (*t == '+')
++ if (*t == '+') {
+ *t = ' ';
++ }
+ }
+
+ ast_uri_decode(s);
+ }
+
+-static struct ast_str *handle_uri(struct ast_tcptls_session_instance *ser, char *uri, enum ast_http_method method,
+- int *status, char **title, int *contentlength, struct ast_variable **cookies, struct ast_variable *headers,
+- unsigned int *static_content)
++/*
++ * get post variables from client Request Entity-Body, if content type is
++ * application/x-www-form-urlencoded
++ */
++struct ast_variable *ast_http_get_post_vars(
++ struct ast_tcptls_session_instance *ser, struct ast_variable *headers)
+ {
++ int content_length = 0;
++ struct ast_variable *v, *post_vars=NULL, *prev = NULL;
++ char *buf, *var, *val;
++
++ for (v = headers; v; v = v->next) {
++ if (!strcasecmp(v->name, "Content-Type")) {
++ if (strcasecmp(v->value, "application/x-www-form-urlencoded")) {
++ return NULL;
++ }
++ break;
++ }
++ }
++
++ for (v = headers; v; v = v->next) {
++ if (!strcasecmp(v->name, "Content-Length")) {
++ content_length = atoi(v->value) + 1;
++ break;
++ }
++ }
++
++ if (!content_length) {
++ return NULL;
++ }
++
++ if (!(buf = alloca(content_length))) {
++ return NULL;
++ }
++ if (!fgets(buf, content_length, ser->f)) {
++ return NULL;
++ }
++
++ while ((val = strsep(&buf, "&"))) {
++ var = strsep(&val, "=");
++ if (val) {
++ http_decode(val);
++ } else {
++ val = "";
++ }
++ http_decode(var);
++ if ((v = ast_variable_new(var, val, ""))) {
++ if (post_vars) {
++ prev->next = v;
++ } else {
++ post_vars = v;
++ }
++ prev = v;
++ }
++ }
++ return post_vars;
++}
++
++static int handle_uri(struct ast_tcptls_session_instance *ser, char *uri,
++ enum ast_http_method method, struct ast_variable *headers)
++{
+ char *c;
+- struct ast_str *out = NULL;
++ int res = -1;
+ char *params = uri;
+ struct ast_http_uri *urih = NULL;
+ int l;
+- struct ast_variable *vars = NULL, *v, *prev = NULL;
++ struct ast_variable *get_vars = NULL, *v, *prev = NULL;
+ struct http_uri_redirect *redirect;
+- int saw_method = 0;
+
+- /* preserve previous behavior of only support URI parameters on GET requests */
+- if (method == AST_HTTP_GET) {
+- strsep(&params, "?");
+-
+- /* Extract arguments from the request and store them in variables.
+- * Note that a request can have multiple arguments with the same
+- * name, and we store them all in the list of variables.
+- * It is up to the application to handle multiple values.
+- */
+- if (params) {
+- char *var, *val;
+-
+- while ((val = strsep(&params, "&"))) {
+- var = strsep(&val, "=");
+- if (val) {
+- http_decode(val);
++ strsep(&params, "?");
++ /* Extract arguments from the request and store them in variables. */
++ if (params) {
++ char *var, *val;
++
++ while ((val = strsep(&params, "&"))) {
++ var = strsep(&val, "=");
++ if (val) {
++ http_decode(val);
++ } else {
++ val = "";
++ }
++ http_decode(var);
++ if ((v = ast_variable_new(var, val, ""))) {
++ if (get_vars) {
++ prev->next = v;
+ } else {
+- val = "";
++ get_vars = v;
+ }
+- http_decode(var);
+- if ((v = ast_variable_new(var, val, ""))) {
+- if (vars) {
+- prev->next = v;
+- } else {
+- vars = v;
+- }
+- prev = v;
+- }
++ prev = v;
+ }
+ }
+ }
+-
+- /*
+- * Append the cookies to the list of variables.
+- * This saves a pass in the cookies list, but has the side effect
+- * that a variable might mask a cookie with the same name if the
+- * application stops at the first match.
+- * Note that this is the same behaviour as $_REQUEST variables in PHP.
+- */
+- if (prev) {
+- prev->next = *cookies;
+- } else {
+- vars = *cookies;
+- }
+- *cookies = NULL;
+-
+ http_decode(uri);
+
+ AST_RWLIST_RDLOCK(&uri_redirects);
+ AST_RWLIST_TRAVERSE(&uri_redirects, redirect, entry) {
+ if (!strcasecmp(uri, redirect->target)) {
+- char buf[512];
++ struct ast_str *http_header = ast_str_create(128);
++ ast_str_set(&http_header, 0, "Location: %s\r\n", redirect->dest);
++ ast_http_send(ser, method, 302, "Moved Temporarily", http_header, NULL, 0, 0);
+
+- snprintf(buf, sizeof(buf), "Location: %s\r\n", redirect->dest);
+- out = ast_http_error((*status = 302),
+- (*title = ast_strdup("Moved Temporarily")),
+- buf, "Redirecting...");
+-
+ break;
+ }
+ }
+ AST_RWLIST_UNLOCK(&uri_redirects);
+-
+ if (redirect) {
+ goto cleanup;
+ }
+@@ -508,70 +698,31 @@
+ AST_RWLIST_RDLOCK(&uris);
+ AST_RWLIST_TRAVERSE(&uris, urih, entry) {
+ ast_debug(2, "match request [%s] with handler [%s] len %d\n", uri, urih->uri, l);
+- if (!saw_method) {
+- switch (method) {
+- case AST_HTTP_GET:
+- if (urih->supports_get) {
+- saw_method = 1;
+- }
+- break;
+- case AST_HTTP_POST:
+- if (urih->supports_post) {
+- saw_method = 1;
+- }
+- break;
+- }
+- }
+-
+ l = strlen(urih->uri);
+ c = uri + l; /* candidate */
+-
+- if (strncasecmp(urih->uri, uri, l) || /* no match */
+- (*c && *c != '/')) { /* substring */
++ if (strncasecmp(urih->uri, uri, l) /* no match */
++ || (*c && *c != '/')) { /* substring */
+ continue;
+ }
+-
+ if (*c == '/') {
+ c++;
+ }
+-
+ if (!*c || urih->has_subtree) {
+- if (((method == AST_HTTP_GET) && urih->supports_get) ||
+- ((method == AST_HTTP_POST) && urih->supports_post)) {
+- uri = c;
+-
+- break;
+- }
++ uri = c;
++ break;
+ }
+ }
+-
+- if (!urih) {
+- AST_RWLIST_UNLOCK(&uris);
+- }
++ AST_RWLIST_UNLOCK(&uris);
+ }
+-
+- if (method == AST_HTTP_POST && !astman_is_authed(manid_from_vars(vars))) {
+- out = ast_http_error((*status = 403),
+- (*title = ast_strdup("Access Denied")),
+- NULL, "You do not have permission to access the requested URL.");
+- } else if (urih) {
+- *static_content = urih->static_content;
+- out = urih->callback(ser, urih, uri, method, vars, headers, status, title, contentlength);
+- AST_RWLIST_UNLOCK(&uris);
+- } else if (saw_method) {
+- out = ast_http_error((*status = 404),
+- (*title = ast_strdup("Not Found")), NULL,
+- "The requested URL was not found on this server.");
++ if (urih) {
++ res = urih->callback(ser, urih, uri, method, get_vars, headers);
+ } else {
+- out = ast_http_error((*status = 501),
+- (*title = ast_strdup("Not Implemented")), NULL,
+- "Attempt to use unimplemented / unsupported method");
++ ast_http_error(ser, 404, "Not Found", "The requested URL was not found on this server.");
+ }
+
+ cleanup:
+- ast_variables_destroy(vars);
+-
+- return out;
++ ast_variables_destroy(get_vars);
++ return res;
+ }
+
+ #ifdef DO_SSL
+@@ -624,12 +775,9 @@
+ char *cur;
+ struct ast_variable *vars = NULL, *var;
+
+- /* Skip Cookie: */
+- cookies += 8;
+-
+ while ((cur = strsep(&cookies, ";"))) {
+ char *name, *val;
+-
++
+ name = val = cur;
+ strsep(&val, "=");
+
+@@ -656,27 +804,55 @@
+ return vars;
+ }
+
++/* get cookie from Request headers */
++struct ast_variable *ast_http_get_cookies(struct ast_variable *headers)
++{
++ struct ast_variable *v, *cookies=NULL;
++
++ for (v = headers; v; v = v->next) {
++ if (!strncasecmp(v->name, "Cookie", 6)) {
++ if (cookies) {
++ ast_variables_destroy(cookies);
++ }
++
++ cookies = parse_cookies((char *)v->value);
++ }
++ }
++ return cookies;
++}
++
++
+ static void *httpd_helper_thread(void *data)
+ {
+ char buf[4096];
+- char cookie[4096];
++ char header_line[4096];
+ struct ast_tcptls_session_instance *ser = data;
+- struct ast_variable *vars=NULL, *headers = NULL;
+- char *uri, *title=NULL;
+- int status = 200, contentlength = 0;
+- struct ast_str *out = NULL;
+- unsigned int static_content = 0;
++ struct ast_variable *headers = NULL;
+ struct ast_variable *tail = headers;
++ char *uri, *method;
++ enum ast_http_method http_method = AST_HTTP_UNKNOWN;
+
+ if (!fgets(buf, sizeof(buf), ser->f)) {
+ goto done;
+ }
+
+- uri = ast_skip_nonblanks(buf); /* Skip method */
++ /* Get method */
++ method = ast_skip_blanks(buf);
++ uri = ast_skip_nonblanks(method);
+ if (*uri) {
+ *uri++ = '\0';
+ }
+
++ if (!strcasecmp(method,"GET")) {
++ http_method = AST_HTTP_GET;
++ } else if (!strcasecmp(method,"POST")) {
++ http_method = AST_HTTP_POST;
++ } else if (!strcasecmp(method,"HEAD")) {
++ http_method = AST_HTTP_HEAD;
++ } else if (!strcasecmp(method,"PUT")) {
++ http_method = AST_HTTP_PUT;
++ }
++
+ uri = ast_skip_blanks(uri); /* Skip white space */
+
+ if (*uri) { /* terminate at the first blank */
+@@ -687,101 +863,56 @@
+ }
+ }
+
+- /* process "Cookie: " lines */
+- while (fgets(cookie, sizeof(cookie), ser->f)) {
++ /* process "Request Headers" lines */
++ while (fgets(header_line, sizeof(header_line), ser->f)) {
++ char *name, *value;
++
+ /* Trim trailing characters */
+- ast_trim_blanks(cookie);
+- if (ast_strlen_zero(cookie)) {
++ ast_trim_blanks(header_line);
++ if (ast_strlen_zero(header_line)) {
+ break;
+ }
+- if (!strncasecmp(cookie, "Cookie: ", 8)) {
+- vars = parse_cookies(cookie);
+- } else {
+- char *name, *val;
+
+- val = cookie;
+- name = strsep(&val, ":");
+- if (ast_strlen_zero(name) || ast_strlen_zero(val)) {
+- continue;
+- }
+- ast_trim_blanks(name);
+- val = ast_skip_blanks(val);
++ value = header_line;
++ name = strsep(&value, ":");
++ if (!value) {
++ continue;
++ }
+
+- if (!headers) {
+- headers = ast_variable_new(name, val, __FILE__);
+- tail = headers;
+- } else {
+- tail->next = ast_variable_new(name, val, __FILE__);
+- tail = tail->next;
+- }
++ value = ast_skip_blanks(value);
++ if (ast_strlen_zero(value) || ast_strlen_zero(name)) {
++ continue;
+ }
++
++ ast_trim_blanks(name);
++
++ if (!headers) {
++ headers = ast_variable_new(name, value, __FILE__);
++ tail = headers;
++ } else {
++ tail->next = ast_variable_new(name, value, __FILE__);
++ tail = tail->next;
++ }
+ }
+
+ if (!*uri) {
+- out = ast_http_error(400, "Bad Request", NULL, "Invalid Request");
+- } else if (strcasecmp(buf, "post") && strcasecmp(buf, "get")) {
+- out = ast_http_error(501, "Not Implemented", NULL,
+- "Attempt to use unimplemented / unsupported method");
+- } else { /* try to serve it */
+- out = handle_uri(ser, uri, (!strcasecmp(buf, "get")) ? AST_HTTP_GET : AST_HTTP_POST,
+- &status, &title, &contentlength, &vars, headers, &static_content);
++ ast_http_error(ser, 400, "Bad Request", "Invalid Request");
++ return NULL;
+ }
+
+- /* If they aren't mopped up already, clean up the cookies */
+- if (vars) {
+- ast_variables_destroy(vars);
+- }
++ handle_uri(ser, uri, http_method, headers);
++
+ /* Clean up all the header information pulled as well */
+ if (headers) {
+ ast_variables_destroy(headers);
+ }
+
+- if (out) {
+- struct timeval now = ast_tvnow();
+- char timebuf[256];
+- struct ast_tm tm;
+-
+- ast_strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S %Z", ast_localtime(&now, &tm, "GMT"));
+- fprintf(ser->f,
+- "HTTP/1.1 %d %s\r\n"
+- "Server: Asterisk/%s\r\n"
+- "Date: %s\r\n"
+- "Connection: close\r\n"
+- "%s",
+- status, title ? title : "OK", ast_get_version(), timebuf,
+- static_content ? "" : "Cache-Control: no-cache, no-store\r\n");
+- /* We set the no-cache headers only for dynamic content.
+- * If you want to make sure the static file you requested is not from cache,
+- * append a random variable to your GET request. Ex: 'something.html?r=109987734'
+- */
+- if (!contentlength) { /* opaque body ? just dump it hoping it is properly formatted */
+- fprintf(ser->f, "%s", ast_str_buffer(out));
+- } else {
+- char *tmp = strstr(ast_str_buffer(out), "\r\n\r\n");
+-
+- if (tmp) {
+- fprintf(ser->f, "Content-length: %d\r\n", contentlength);
+- /* first write the header, then the body */
+- if (fwrite(ast_str_buffer(out), 1, (tmp + 4 - ast_str_buffer(out)), ser->f) != tmp + 4 - ast_str_buffer(out)) {
+- ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno));
+- }
+- if (fwrite(tmp + 4, 1, contentlength, ser->f) != contentlength ) {
+- ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno));
+- }
+- }
+- }
+- ast_free(out);
++done:
++ if (ser->f) {
++ fclose(ser->f);
+ }
+-
+- if (title) {
+- ast_free(title);
+- }
+-
+-done:
+- fclose(ser->f);
+ ao2_ref(ser, -1);
+ ser = NULL;
+-
+ return NULL;
+ }
+
+@@ -814,7 +945,6 @@
+ if (!(redirect = ast_calloc(1, total_len))) {
+ return;
+ }
+-
+ redirect->dest = redirect->target + target_len;
+ strcpy(redirect->target, target);
+ strcpy(redirect->dest, dest);
+@@ -822,8 +952,8 @@
+ AST_RWLIST_WRLOCK(&uri_redirects);
+
+ target_len--; /* So we can compare directly with strlen() */
+- if (AST_RWLIST_EMPTY(&uri_redirects)
+- || strlen(AST_RWLIST_FIRST(&uri_redirects)->target) <= target_len) {
++ if (AST_RWLIST_EMPTY(&uri_redirects)
++ || strlen(AST_RWLIST_FIRST(&uri_redirects)->target) <= target_len ) {
+ AST_RWLIST_INSERT_HEAD(&uri_redirects, redirect, entry);
+ AST_RWLIST_UNLOCK(&uri_redirects);
+
+@@ -831,11 +961,10 @@
+ }
+
+ AST_RWLIST_TRAVERSE(&uri_redirects, cur, entry) {
+- if (AST_RWLIST_NEXT(cur, entry)
+- && strlen(AST_RWLIST_NEXT(cur, entry)->target) <= target_len) {
++ if (AST_RWLIST_NEXT(cur, entry)
++ && strlen(AST_RWLIST_NEXT(cur, entry)->target) <= target_len ) {
+ AST_RWLIST_INSERT_AFTER(&uri_redirects, cur, redirect, entry);
+- AST_RWLIST_UNLOCK(&uri_redirects);
+-
++ AST_RWLIST_UNLOCK(&uri_redirects);
+ return;
+ }
+ }
+@@ -854,7 +983,6 @@
+ struct hostent *hp;
+ struct ast_hostent ahp;
+ char newprefix[MAX_PREFIX] = "";
+- int have_sslbindaddr = 0;
+ struct http_uri_redirect *redirect;
+ struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
+
+@@ -875,6 +1003,12 @@
+ ast_free(http_tls_cfg.certfile);
+ }
+ http_tls_cfg.certfile = ast_strdup(AST_CERTFILE);
++
++ if (http_tls_cfg.pvtfile) {
++ ast_free(http_tls_cfg.pvtfile);
++ }
++ http_tls_cfg.pvtfile = ast_strdup("");
++
+ if (http_tls_cfg.cipher) {
+ ast_free(http_tls_cfg.cipher);
+ }
+@@ -889,29 +1023,18 @@
+ if (cfg) {
+ v = ast_variable_browse(cfg, "general");
+ for (; v; v = v->next) {
++
++ /* handle tls conf */
++ if (!ast_tls_read_conf(&http_tls_cfg, &https_desc, v->name, v->value)) {
++ continue;
++ }
++
+ if (!strcasecmp(v->name, "enabled")) {
+ enabled = ast_true(v->value);
+- } else if (!strcasecmp(v->name, "sslenable")) {
+- http_tls_cfg.enabled = ast_true(v->value);
+- } else if (!strcasecmp(v->name, "sslbindport")) {
+- https_desc.local_address.sin_port = htons(atoi(v->value));
+- } else if (!strcasecmp(v->name, "sslcert")) {
+- ast_free(http_tls_cfg.certfile);
+- http_tls_cfg.certfile = ast_strdup(v->value);
+- } else if (!strcasecmp(v->name, "sslcipher")) {
+- ast_free(http_tls_cfg.cipher);
+- http_tls_cfg.cipher = ast_strdup(v->value);
+ } else if (!strcasecmp(v->name, "enablestatic")) {
+ newenablestatic = ast_true(v->value);
+ } else if (!strcasecmp(v->name, "bindport")) {
+ http_desc.local_address.sin_port = htons(atoi(v->value));
+- } else if (!strcasecmp(v->name, "sslbindaddr")) {
+- if ((hp = ast_gethostbyname(v->value, &ahp))) {
+- memcpy(&https_desc.local_address.sin_addr, hp->h_addr, sizeof(https_desc.local_address.sin_addr));
+- have_sslbindaddr = 1;
+- } else {
+- ast_log(LOG_WARNING, "Invalid bind address '%s'\n", v->value);
+- }
+ } else if (!strcasecmp(v->name, "bindaddr")) {
+ if ((hp = ast_gethostbyname(v->value, &ahp))) {
+ memcpy(&http_desc.local_address.sin_addr, hp->h_addr, sizeof(http_desc.local_address.sin_addr));
+@@ -934,8 +1057,8 @@
+
+ ast_config_destroy(cfg);
+ }
+-
+- if (!have_sslbindaddr) {
++ /* if the https addres has not been set, default is the same as non secure http */
++ if (!https_desc.local_address.sin_addr.s_addr) {
+ https_desc.local_address.sin_addr = http_desc.local_address.sin_addr;
+ }
+ if (enabled) {
+@@ -961,14 +1084,14 @@
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "http show status";
+- e->usage =
++ e->usage =
+ "Usage: http show status\n"
+ " Lists status of internal HTTP engine\n";
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+-
++
+ if (a->argc != 3) {
+ return CLI_SHOWUSAGE;
+ }
+@@ -992,17 +1115,15 @@
+ if (AST_RWLIST_EMPTY(&uris)) {
+ ast_cli(a->fd, "None.\n");
+ } else {
+- AST_RWLIST_TRAVERSE(&uris, urih, entry) {
+- ast_cli(a->fd, "%s/%s%s => %s\n", prefix, urih->uri, (urih->has_subtree ? "/..." : ""), urih->description);
+- }
++ AST_RWLIST_TRAVERSE(&uris, urih, entry)
++ ast_cli(a->fd, "%s/%s%s => %s\n", prefix, urih->uri, (urih->has_subtree ? "/..." : "" ), urih->description);
+ }
+ AST_RWLIST_UNLOCK(&uris);
+
+ ast_cli(a->fd, "\nEnabled Redirects:\n");
+ AST_RWLIST_RDLOCK(&uri_redirects);
+- AST_RWLIST_TRAVERSE(&uri_redirects, redirect, entry) {
++ AST_RWLIST_TRAVERSE(&uri_redirects, redirect, entry)
+ ast_cli(a->fd, " %s => %s\n", redirect->target, redirect->dest);
+- }
+ if (AST_RWLIST_EMPTY(&uri_redirects)) {
+ ast_cli(a->fd, " None.\n");
+ }
+Index: main/app.c
+===================================================================
+--- a/main/app.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/app.c (.../trunk) (revision 202568)
+@@ -180,7 +180,7 @@
+ /* The lock type used by ast_lock_path() / ast_unlock_path() */
+ static enum AST_LOCK_TYPE ast_lock_type = AST_LOCK_TYPE_LOCKFILE;
+
+-int ast_app_getdata_full(struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout, int audiofd, int ctrlfd)
++int ast_app_getdata_full(struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout, int audiofd, int ctrlfd)
+ {
+ int res, to = 2000, fto = 6000;
+
+@@ -203,6 +203,28 @@
+ return res;
+ }
+
++int ast_app_run_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const char * const macro_name, const char * const macro_args)
++{
++ struct ast_app *macro_app;
++ int res;
++ char buf[1024];
++
++ macro_app = pbx_findapp("Macro");
++ if (!macro_app) {
++ ast_log(LOG_WARNING, "Cannot run macro '%s' because the 'Macro' application in not available\n", macro_name);
++ return -1;
++ }
++ snprintf(buf, sizeof(buf), "%s%s%s", macro_name, ast_strlen_zero(macro_args) ? "" : ",", S_OR(macro_args, ""));
++ if (autoservice_chan) {
++ ast_autoservice_start(autoservice_chan);
++ }
++ res = pbx_exec(macro_chan, macro_app, buf);
++ if (autoservice_chan) {
++ ast_autoservice_stop(autoservice_chan);
++ }
++ return res;
++}
++
+ static int (*ast_has_voicemail_func)(const char *mailbox, const char *folder) = NULL;
+ static int (*ast_inboxcount_func)(const char *mailbox, int *newmsgs, int *oldmsgs) = NULL;
+ static int (*ast_inboxcount2_func)(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs) = NULL;
+@@ -949,8 +971,8 @@
+ return res;
+ }
+
+-static char default_acceptdtmf[] = "#";
+-static char default_canceldtmf[] = "";
++static const char default_acceptdtmf[] = "#";
++static const char default_canceldtmf[] = "";
+
+ int ast_play_and_record_full(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int silencethreshold, int maxsilence, const char *path, const char *acceptdtmf, const char *canceldtmf)
+ {
+Index: main/image.c
+===================================================================
+--- a/main/image.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/image.c (.../trunk) (revision 202568)
+@@ -81,7 +81,7 @@
+ return 0;
+ }
+
+-static void make_filename(char *buf, int len, char *filename, const char *preflang, char *ext)
++static void make_filename(char *buf, int len, const char *filename, const char *preflang, char *ext)
+ {
+ if (filename[0] == '/') {
+ if (!ast_strlen_zero(preflang))
+@@ -96,7 +96,7 @@
+ }
+ }
+
+-struct ast_frame *ast_read_image(char *filename, const char *preflang, int format)
++struct ast_frame *ast_read_image(const char *filename, const char *preflang, int format)
+ {
+ struct ast_imager *i;
+ char buf[256];
+@@ -152,7 +152,7 @@
+ return f;
+ }
+
+-int ast_send_image(struct ast_channel *chan, char *filename)
++int ast_send_image(struct ast_channel *chan, const char *filename)
+ {
+ struct ast_frame *f;
+ int res = -1;
+@@ -197,7 +197,7 @@
+ return CLI_SUCCESS;
+ }
+
+-struct ast_cli_entry cli_image[] = {
++static struct ast_cli_entry cli_image[] = {
+ AST_CLI_DEFINE(handle_core_show_image_formats, "Displays image formats")
+ };
+
+Index: main/db.c
+===================================================================
+--- a/main/db.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/db.c (.../trunk) (revision 202568)
+@@ -48,6 +48,58 @@
+ #include "asterisk/manager.h"
+ #include "db1-ast/include/db.h"
+
++/*** DOCUMENTATION
++ <manager name="DBGet" language="en_US">
++ <synopsis>
++ Get DB Entry.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Family" required="true" />
++ <parameter name="Key" required="true" />
++ </syntax>
++ <description>
++ </description>
++ </manager>
++ <manager name="DBPut" language="en_US">
++ <synopsis>
++ Put DB entry.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Family" required="true" />
++ <parameter name="Key" required="true" />
++ <parameter name="Val" />
++ </syntax>
++ <description>
++ </description>
++ </manager>
++ <manager name="DBDel" language="en_US">
++ <synopsis>
++ Delete DB entry.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Family" required="true" />
++ <parameter name="Key" required="true" />
++ </syntax>
++ <description>
++ </description>
++ </manager>
++ <manager name="DBDelTree" language="en_US">
++ <synopsis>
++ Delete DB Tree.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Family" required="true" />
++ <parameter name="Key" />
++ </syntax>
++ <description>
++ </description>
++ </manager>
++ ***/
++
+ static DB *astdb;
+ AST_MUTEX_DEFINE_STATIC(dblock);
+
+@@ -542,7 +594,7 @@
+ }
+ }
+
+-struct ast_cli_entry cli_database[] = {
++static struct ast_cli_entry cli_database[] = {
+ AST_CLI_DEFINE(handle_cli_database_show, "Shows database contents"),
+ AST_CLI_DEFINE(handle_cli_database_showkey, "Shows database contents"),
+ AST_CLI_DEFINE(handle_cli_database_get, "Gets database value"),
+@@ -666,9 +718,9 @@
+ {
+ dbinit();
+ ast_cli_register_multiple(cli_database, ARRAY_LEN(cli_database));
+- ast_manager_register("DBGet", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_dbget, "Get DB Entry");
+- ast_manager_register("DBPut", EVENT_FLAG_SYSTEM, manager_dbput, "Put DB Entry");
+- ast_manager_register("DBDel", EVENT_FLAG_SYSTEM, manager_dbdel, "Delete DB Entry");
+- ast_manager_register("DBDelTree", EVENT_FLAG_SYSTEM, manager_dbdeltree, "Delete DB Tree");
++ ast_manager_register_xml("DBGet", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_dbget);
++ ast_manager_register_xml("DBPut", EVENT_FLAG_SYSTEM, manager_dbput);
++ ast_manager_register_xml("DBDel", EVENT_FLAG_SYSTEM, manager_dbdel);
++ ast_manager_register_xml("DBDelTree", EVENT_FLAG_SYSTEM, manager_dbdeltree);
+ return 0;
+ }
+Index: main/ast_expr2.fl
+===================================================================
+--- a/main/ast_expr2.fl (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/ast_expr2.fl (.../trunk) (revision 202568)
+@@ -313,7 +313,7 @@
+ extra_error_message[0] = 0;
+ }
+
+-static char *expr2_token_equivs1[] =
++static const char * const expr2_token_equivs1[] =
+ {
+ "TOKEN",
+ "TOK_COND",
+@@ -339,7 +339,7 @@
+ "TOK_LP"
+ };
+
+-static char *expr2_token_equivs2[] =
++static const char * const expr2_token_equivs2[] =
+ {
+ "<token>",
+ "?",
+Index: main/Makefile
+===================================================================
+--- a/main/Makefile (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/Makefile (.../trunk) (revision 202568)
+@@ -17,29 +17,15 @@
+
+ include $(ASTTOPDIR)/Makefile.moddir_rules
+
+-OBJS= tcptls.o io.o sched.o logger.o frame.o loader.o config.o channel.o \
+- translate.o file.o pbx.o cli.o md5.o term.o heap.o \
+- ulaw.o alaw.o callerid.o fskmodem.o image.o app.o \
+- cdr.o tdd.o acl.o rtp.o udptl.o manager.o asterisk.o \
+- dsp.o chanvars.o indications.o autoservice.o db.o privacy.o \
+- astmm.o astfd.o enum.o srv.o dns.o aescrypt.o aestab.o aeskey.o \
+- utils.o plc.o jitterbuf.o dnsmgr.o devicestate.o \
+- netsock.o slinfactory.o ast_expr2.o ast_expr2f.o \
+- cryptostub.o sha1.o http.o fixedjitterbuf.o abstract_jb.o \
+- strcompat.o threadstorage.o dial.o event.o adsistub.o audiohook.o \
+- astobj2.o hashtab.o global_datastores.o version.o \
+- features.o taskprocessor.o timing.o datastore.o xml.o xmldoc.o \
+- strings.o bridging.o poll.o
++SRC=$(wildcard *.c)
++OBJSFILTER=fskmodem_int.o fskmodem_float.o cygload.o buildinfo.o
++OBJS=$(filter-out $(OBJSFILTER),$(SRC:.c=.o))
+
+ # we need to link in the objects statically, not as a library, because
+ # otherwise modules will not have them available if none of the static
+ # objects use it.
+ OBJS+=stdtime/localtime.o
+
+-# At the moment say.o is an optional component which can be overridden
+-# by a module.
+-OBJS+=say.o
+-
+ AST_LIBS += $(OPENSSL_LIB)
+ AST_LIBS += $(BKTR_LIB)
+ AST_LIBS += $(LIBXML2_LIB)
+@@ -58,9 +44,7 @@
+
+ ifneq ($(findstring darwin,$(OSARCH)),)
+ AST_LIBS+=-lresolv
+- ifneq ($(findstring LOADABLE_MODULES,$(MENUSELECT_CFLAGS)),)
+- ASTLINK=-Wl,-dynamic
+- endif
++ ASTLINK=-undefined suppress -force_flat_namespace
+ else
+ # These are used for all but Darwin
+ ifneq ($(findstring LOADABLE_MODULES,$(MENUSELECT_CFLAGS)),)
+@@ -103,6 +87,10 @@
+ endif
+ endif
+
++ifeq ($(GNU_LD),1)
++ASTLINK+=-Wl,--version-script,asterisk.exports
++endif
++
+ CHECK_SUBDIR: # do nothing, just make sure that we recurse in the subdir/
+
+ editline/libedit.a: CHECK_SUBDIR
+@@ -163,15 +151,14 @@
+ GMIMELDFLAGS+=$(GMIME_LIB)
+ endif
+
+-$(MAIN_TGT): $(OBJS) editline/libedit.a db1-ast/libdb1.a $(AST_EMBED_LDSCRIPTS)
++$(MAIN_TGT): $(OBJS) editline/libedit.a db1-ast/libdb1.a $(AST_EMBED_LDSCRIPTS) asterisk.exports
+ @$(CC) -c -o buildinfo.o $(ASTCFLAGS) buildinfo.c
+- $(ECHO_PREFIX) echo " [LD] $^ -> $@"
++ $(ECHO_PREFIX) echo " [LD] $(OBJS) editline/libedit.a db1-ast/libdb1.a $(AST_EMBED_LDSCRIPTS) -> $@"
+ ifneq ($(findstring chan_h323,$(MENUSELECT_CHANNELS)),)
+- $(CMD_PREFIX) $(CC) $(STATIC_BUILD) -o $@ $(ASTLINK) $(AST_EMBED_LDFLAGS) $(ASTLDFLAGS) $^ buildinfo.o $(AST_LIBS) $(AST_EMBED_LIBS) $(GMIMELDFLAGS)
++ $(CMD_PREFIX) $(CC) $(STATIC_BUILD) -o $@ $(ASTLINK) $(AST_EMBED_LDFLAGS) $(ASTLDFLAGS) $(OBJS) editline/libedit.a db1-ast/libdb1.a $(AST_EMBED_LDSCRIPTS) buildinfo.o $(AST_LIBS) $(AST_EMBED_LIBS) $(GMIMELDFLAGS)
+ else
+- $(CMD_PREFIX) $(CXX) $(STATIC_BUILD) -o $@ $(ASTLINK) $(AST_EMBED_LDFLAGS) $(ASTLDFLAGS) $(H323LDFLAGS) $^ buildinfo.o $(AST_LIBS) $(AST_EMBED_LIBS) $(H323LDLIBS) $(GMIMELDFLAGS)
++ $(CMD_PREFIX) $(CXX) $(STATIC_BUILD) -o $@ $(ASTLINK) $(AST_EMBED_LDFLAGS) $(ASTLDFLAGS) $(H323LDFLAGS) $(OBJS) editline/libedit.a db1-ast/libdb1.a $(AST_EMBED_LDSCRIPTS) buildinfo.o $(AST_LIBS) $(AST_EMBED_LIBS) $(H323LDLIBS) $(GMIMELDFLAGS)
+ endif
+- $(CMD_PREFIX) $(ASTTOPDIR)/build_tools/strip_nonapi $@ || rm $@
+
+ clean::
+ rm -f asterisk
+Index: main/slinfactory.c
+===================================================================
+--- a/main/slinfactory.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/slinfactory.c (.../trunk) (revision 202568)
+@@ -73,7 +73,7 @@
+ int ast_slinfactory_feed(struct ast_slinfactory *sf, struct ast_frame *f)
+ {
+ struct ast_frame *begin_frame = f, *duped_frame = NULL, *frame_ptr;
+- unsigned int x;
++ unsigned int x = 0;
+
+ /* In some cases, we can be passed a frame which has no data in it, but
+ * which has a positive number of samples defined. Once such situation is
+@@ -100,15 +100,17 @@
+ sf->format = f->subclass;
+ }
+
+- if (!(begin_frame = ast_translate(sf->trans, f, 0)))
++ if (!(begin_frame = ast_translate(sf->trans, f, 0))) {
+ return 0;
++ }
+
+- duped_frame = ast_frdup(begin_frame);
++ if (!(duped_frame = ast_frisolate(begin_frame))) {
++ return 0;
++ }
+
+- ast_frfree(begin_frame);
+-
+- if (!duped_frame)
+- return 0;
++ if (duped_frame != begin_frame) {
++ ast_frfree(begin_frame);
++ }
+ } else {
+ if (sf->trans) {
+ ast_translator_free_path(sf->trans);
+@@ -118,15 +120,18 @@
+ return 0;
+ }
+
+- x = 0;
+ AST_LIST_TRAVERSE(&sf->queue, frame_ptr, frame_list) {
+ x++;
+ }
+
+- AST_LIST_INSERT_TAIL(&sf->queue, duped_frame, frame_list);
++ /* if the frame was translated, the translator may have returned multiple
++ frames, so process each of them
++ */
++ for (begin_frame = duped_frame; begin_frame; begin_frame = AST_LIST_NEXT(begin_frame, frame_list)) {
++ AST_LIST_INSERT_TAIL(&sf->queue, begin_frame, frame_list);
++ sf->size += begin_frame->samples;
++ }
+
+- sf->size += duped_frame->samples;
+-
+ return x;
+ }
+
+Index: main/ast_expr2.c
+===================================================================
+--- a/main/ast_expr2.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/ast_expr2.c (.../trunk) (revision 202568)
+@@ -2415,6 +2415,7 @@
+ free_value (struct val *vp)
+ {
+ if (vp==NULL) {
++ free(vp);
+ return;
+ }
+ if (vp->type == AST_EXPR_string || vp->type == AST_EXPR_numeric_string)
+Index: main/db1-ast/recno/rec_open.c
+===================================================================
+--- a/main/db1-ast/recno/rec_open.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/db1-ast/recno/rec_open.c (.../trunk) (revision 202568)
+@@ -169,7 +169,7 @@
+ t->bt_msize = sb.st_size;
+ if ((t->bt_smap = mmap(NULL, t->bt_msize,
+ PROT_READ, MAP_PRIVATE, rfd,
+- (off_t)0)) == (caddr_t)-1)
++ (off_t)0)) == MAP_FAILED
+ goto slow;
+ t->bt_cmap = t->bt_smap;
+ t->bt_emap = t->bt_smap + sb.st_size;
+Index: main/abstract_jb.c
+===================================================================
+--- a/main/abstract_jb.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/abstract_jb.c (.../trunk) (revision 202568)
+@@ -110,8 +110,7 @@
+ static void jb_empty_and_reset_adaptive(void *jb);
+
+ /* Available jb implementations */
+-static struct ast_jb_impl avail_impl[] =
+-{
++static const struct ast_jb_impl avail_impl[] = {
+ {
+ .name = "fixed",
+ .create = jb_create_fixed,
+@@ -150,13 +149,13 @@
+ };
+
+ /* Translations between impl and abstract return codes */
+-static int fixed_to_abstract_code[] =
++static const int fixed_to_abstract_code[] =
+ {JB_IMPL_OK, JB_IMPL_DROP, JB_IMPL_INTERP, JB_IMPL_NOFRAME};
+-static int adaptive_to_abstract_code[] =
++static const int adaptive_to_abstract_code[] =
+ {JB_IMPL_OK, JB_IMPL_NOFRAME, JB_IMPL_NOFRAME, JB_IMPL_INTERP, JB_IMPL_DROP, JB_IMPL_OK};
+
+ /* JB_GET actions (used only for the frames log) */
+-static char *jb_get_actions[] = {"Delivered", "Dropped", "Interpolated", "No"};
++static const char * const jb_get_actions[] = {"Delivered", "Dropped", "Interpolated", "No"};
+
+ /*! \brief Macros for the frame log files */
+ #define jb_framelog(...) do { \
+@@ -181,7 +180,7 @@
+ {
+ struct ast_jb *jb = &chan->jb;
+ struct ast_jb_conf *jbconf = &jb->conf;
+- struct ast_jb_impl *test_impl;
++ const struct ast_jb_impl *test_impl;
+ int i, avail_impl_count = ARRAY_LEN(avail_impl);
+
+ jb->impl = &avail_impl[default_impl];
+@@ -303,7 +302,7 @@
+ int ast_jb_put(struct ast_channel *chan, struct ast_frame *f)
+ {
+ struct ast_jb *jb = &chan->jb;
+- struct ast_jb_impl *jbimpl = jb->impl;
++ const struct ast_jb_impl *jbimpl = jb->impl;
+ void *jbobj = jb->jbobj;
+ struct ast_frame *frr;
+ long now = 0;
+@@ -385,7 +384,7 @@
+ static void jb_get_and_deliver(struct ast_channel *chan)
+ {
+ struct ast_jb *jb = &chan->jb;
+- struct ast_jb_impl *jbimpl = jb->impl;
++ const struct ast_jb_impl *jbimpl = jb->impl;
+ void *jbobj = jb->jbobj;
+ struct ast_frame *f, finterp;
+ long now;
+@@ -450,7 +449,7 @@
+ {
+ struct ast_jb *jb = &chan->jb;
+ struct ast_jb_conf *jbconf = &jb->conf;
+- struct ast_jb_impl *jbimpl = jb->impl;
++ const struct ast_jb_impl *jbimpl = jb->impl;
+ void *jbobj;
+ struct ast_channel *bridged;
+ long now;
+@@ -534,7 +533,7 @@
+ void ast_jb_destroy(struct ast_channel *chan)
+ {
+ struct ast_jb *jb = &chan->jb;
+- struct ast_jb_impl *jbimpl = jb->impl;
++ const struct ast_jb_impl *jbimpl = jb->impl;
+ void *jbobj = jb->jbobj;
+ struct ast_frame *f;
+
+Index: main/event.c
+===================================================================
+--- a/main/event.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/event.c (.../trunk) (revision 202568)
+@@ -39,7 +39,7 @@
+ #include "asterisk/taskprocessor.h"
+ #include "asterisk/astobj2.h"
+
+-struct ast_taskprocessor *event_dispatcher;
++static struct ast_taskprocessor *event_dispatcher;
+
+ /*!
+ * \brief An event information element
+@@ -311,6 +311,7 @@
+ ast_free(ie_val->payload.raw);
+ break;
+ case AST_EVENT_IE_PLTYPE_UINT:
++ case AST_EVENT_IE_PLTYPE_BITFLAGS:
+ case AST_EVENT_IE_PLTYPE_EXISTS:
+ case AST_EVENT_IE_PLTYPE_UNKNOWN:
+ break;
+@@ -339,60 +340,104 @@
+ ie_type = va_arg(ap, enum ast_event_type))
+ {
+ struct ast_event_ie_val *ie_value = alloca(sizeof(*ie_value));
++ int insert = 1;
+ memset(ie_value, 0, sizeof(*ie_value));
+ ie_value->ie_type = ie_type;
+ ie_value->ie_pltype = va_arg(ap, enum ast_event_ie_pltype);
+- if (ie_value->ie_pltype == AST_EVENT_IE_PLTYPE_UINT)
++ switch (ie_value->ie_pltype) {
++ case AST_EVENT_IE_PLTYPE_UINT:
+ ie_value->payload.uint = va_arg(ap, uint32_t);
+- else if (ie_value->ie_pltype == AST_EVENT_IE_PLTYPE_STR)
+- ie_value->payload.str = ast_strdupa(va_arg(ap, const char *));
+- else if (ie_value->ie_pltype == AST_EVENT_IE_PLTYPE_RAW) {
++ break;
++ case AST_EVENT_IE_PLTYPE_BITFLAGS:
++ ie_value->payload.uint = va_arg(ap, uint32_t);
++ break;
++ case AST_EVENT_IE_PLTYPE_STR:
++ ie_value->payload.str = va_arg(ap, const char *);
++ break;
++ case AST_EVENT_IE_PLTYPE_RAW:
++ {
+ void *data = va_arg(ap, void *);
+ size_t datalen = va_arg(ap, size_t);
+ ie_value->payload.raw = alloca(datalen);
+ memcpy(ie_value->payload.raw, data, datalen);
+ ie_value->raw_datalen = datalen;
++ break;
+ }
+- AST_LIST_INSERT_TAIL(&ie_vals, ie_value, entry);
++ case AST_EVENT_IE_PLTYPE_UNKNOWN:
++ insert = 0;
++ case AST_EVENT_IE_PLTYPE_EXISTS:
++ break;
++ }
++
++ if (insert) {
++ AST_LIST_INSERT_TAIL(&ie_vals, ie_value, entry);
++ }
+ }
+ va_end(ap);
+
+ AST_RWDLLIST_RDLOCK(&ast_event_subs[type]);
+ AST_RWDLLIST_TRAVERSE(&ast_event_subs[type], sub, entry) {
+ AST_LIST_TRAVERSE(&ie_vals, ie_val, entry) {
++ int break_out = 0;
++
+ AST_LIST_TRAVERSE(&sub->ie_vals, sub_ie_val, entry) {
+- if (sub_ie_val->ie_type == ie_val->ie_type)
++ if (sub_ie_val->ie_type == ie_val->ie_type) {
+ break;
++ }
+ }
++
+ if (!sub_ie_val) {
+- if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_EXISTS)
+- break;
++ /* This subscriber doesn't care about this IE, so consider
++ * it matched. */
+ continue;
+ }
+- /* The subscriber doesn't actually care what the value is */
+- if (sub_ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_EXISTS)
+- continue;
+- if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_UINT &&
+- ie_val->payload.uint != sub_ie_val->payload.uint)
++
++ switch (ie_val->ie_pltype) {
++ case AST_EVENT_IE_PLTYPE_UINT:
++ break_out = (ie_val->payload.uint != sub_ie_val->payload.uint);
+ break;
+- if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_STR &&
+- strcmp(ie_val->payload.str, sub_ie_val->payload.str))
++ case AST_EVENT_IE_PLTYPE_BITFLAGS:
++ /* if the subscriber has requested *any* of the bitflags we are providing,
++ * then it's a match
++ */
++ break_out = (ie_val->payload.uint & sub_ie_val->payload.uint);
+ break;
+- if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_RAW &&
+- memcmp(ie_val->payload.raw, sub_ie_val->payload.raw, ie_val->raw_datalen))
++ case AST_EVENT_IE_PLTYPE_STR:
++ break_out = strcmp(ie_val->payload.str, sub_ie_val->payload.str);
+ break;
++ case AST_EVENT_IE_PLTYPE_RAW:
++ break_out = memcmp(ie_val->payload.raw,
++ sub_ie_val->payload.raw, ie_val->raw_datalen);
++ break;
++ case AST_EVENT_IE_PLTYPE_EXISTS:
++ /* The subscriber doesn't actually care what the value is */
++ break_out = 1;
++ break;
++ case AST_EVENT_IE_PLTYPE_UNKNOWN:
++ break;
++ }
++
++ if (break_out) {
++ break;
++ }
+ }
+- if (!ie_val)
++
++ if (!ie_val) {
++ /* Everything matched */
+ break;
++ }
+ }
+ AST_RWDLLIST_UNLOCK(&ast_event_subs[type]);
+
+- if (sub) /* All parameters were matched */
++ if (sub) {
++ /* All parameters were matched */
+ return AST_EVENT_SUB_EXISTS;
++ }
+
+ AST_RWDLLIST_RDLOCK(&ast_event_subs[AST_EVENT_ALL]);
+- if (!AST_DLLIST_EMPTY(&ast_event_subs[AST_EVENT_ALL]))
++ if (!AST_DLLIST_EMPTY(&ast_event_subs[AST_EVENT_ALL])) {
+ res = AST_EVENT_SUB_EXISTS;
++ }
+ AST_RWDLLIST_UNLOCK(&ast_event_subs[AST_EVENT_ALL]);
+
+ return res;
+@@ -401,14 +446,26 @@
+ static int match_ie_val(const struct ast_event *event,
+ const struct ast_event_ie_val *ie_val, const struct ast_event *event2)
+ {
+- if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_UINT) {
++ switch (ie_val->ie_pltype) {
++ case AST_EVENT_IE_PLTYPE_UINT:
++ {
+ uint32_t val = event2 ? ast_event_get_ie_uint(event2, ie_val->ie_type) : ie_val->payload.uint;
+- if (val == ast_event_get_ie_uint(event, ie_val->ie_type))
+- return 1;
+- return 0;
++
++ return (val == ast_event_get_ie_uint(event, ie_val->ie_type)) ? 1 : 0;
+ }
+
+- if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_STR) {
++ case AST_EVENT_IE_PLTYPE_BITFLAGS:
++ {
++ uint32_t flags = event2 ? ast_event_get_ie_uint(event2, ie_val->ie_type) : ie_val->payload.uint;
++
++ /* if the subscriber has requested *any* of the bitflags that this event provides,
++ * then it's a match
++ */
++ return (flags & ast_event_get_ie_bitflags(event, ie_val->ie_type)) ? 1 : 0;
++ }
++
++ case AST_EVENT_IE_PLTYPE_STR:
++ {
+ const char *str;
+ uint32_t hash;
+
+@@ -425,16 +482,19 @@
+ return 0;
+ }
+
+- if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_RAW) {
++ case AST_EVENT_IE_PLTYPE_RAW:
++ {
+ const void *buf = event2 ? ast_event_get_ie_raw(event2, ie_val->ie_type) : ie_val->payload.raw;
+- if (buf && !memcmp(buf, ast_event_get_ie_raw(event, ie_val->ie_type), ie_val->raw_datalen))
+- return 1;
+- return 0;
++
++ return (buf && !memcmp(buf, ast_event_get_ie_raw(event, ie_val->ie_type), ie_val->raw_datalen)) ? 1 : 0;
+ }
+
+- if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_EXISTS) {
+- if (ast_event_get_ie_raw(event, ie_val->ie_type))
+- return 1;
++ case AST_EVENT_IE_PLTYPE_EXISTS:
++ {
++ return ast_event_get_ie_raw(event, ie_val->ie_type) ? 1 : 0;
++ }
++
++ case AST_EVENT_IE_PLTYPE_UNKNOWN:
+ return 0;
+ }
+
+@@ -492,6 +552,9 @@
+ case AST_EVENT_IE_PLTYPE_UINT:
+ ast_event_append_ie_uint(&event, ie_val->ie_type, ie_val->payload.uint);
+ break;
++ case AST_EVENT_IE_PLTYPE_BITFLAGS:
++ ast_event_append_ie_bitflags(&event, ie_val->ie_type, ie_val->payload.uint);
++ break;
+ case AST_EVENT_IE_PLTYPE_STR:
+ ast_event_append_ie_str(&event, ie_val->ie_type, ie_val->payload.str);
+ break;
+@@ -529,13 +592,15 @@
+
+ AST_RWDLLIST_RDLOCK(&ast_event_subs[event_type]);
+ AST_RWDLLIST_TRAVERSE(&ast_event_subs[event_type], sub, entry) {
+- if (event_sub == sub)
++ if (event_sub == sub) {
+ continue;
++ }
+
+ event = gen_sub_event(sub);
+
+- if (!event)
++ if (!event) {
+ continue;
++ }
+
+ event_sub->cb(event, event_sub->userdata);
+
+@@ -544,7 +609,7 @@
+ AST_RWDLLIST_UNLOCK(&ast_event_subs[event_type]);
+ }
+
+-struct ast_event_sub *ast_event_subscribe_new(enum ast_event_type type,
++struct ast_event_sub *ast_event_subscribe_new(enum ast_event_type type,
+ ast_event_cb_t cb, void *userdata)
+ {
+ struct ast_event_sub *sub;
+@@ -554,8 +619,9 @@
+ return NULL;
+ }
+
+- if (!(sub = ast_calloc(1, sizeof(*sub))))
++ if (!(sub = ast_calloc(1, sizeof(*sub)))) {
+ return NULL;
++ }
+
+ sub->type = type;
+ sub->cb = cb;
+@@ -570,11 +636,13 @@
+ {
+ struct ast_event_ie_val *ie_val;
+
+- if (ie_type < 0 || ie_type > AST_EVENT_IE_MAX)
++ if (ie_type < 0 || ie_type > AST_EVENT_IE_MAX) {
+ return -1;
++ }
+
+- if (!(ie_val = ast_calloc(1, sizeof(*ie_val))))
++ if (!(ie_val = ast_calloc(1, sizeof(*ie_val)))) {
+ return -1;
++ }
+
+ ie_val->ie_type = ie_type;
+ ie_val->payload.uint = unsigned_int;
+@@ -585,8 +653,8 @@
+ return 0;
+ }
+
+-int ast_event_sub_append_ie_exists(struct ast_event_sub *sub,
+- enum ast_event_ie_type ie_type)
++int ast_event_sub_append_ie_bitflags(struct ast_event_sub *sub,
++ enum ast_event_ie_type ie_type, uint32_t flags)
+ {
+ struct ast_event_ie_val *ie_val;
+
+@@ -597,6 +665,28 @@
+ return -1;
+
+ ie_val->ie_type = ie_type;
++ ie_val->payload.uint = flags;
++ ie_val->ie_pltype = AST_EVENT_IE_PLTYPE_BITFLAGS;
++
++ AST_LIST_INSERT_TAIL(&sub->ie_vals, ie_val, entry);
++
++ return 0;
++}
++
++int ast_event_sub_append_ie_exists(struct ast_event_sub *sub,
++ enum ast_event_ie_type ie_type)
++{
++ struct ast_event_ie_val *ie_val;
++
++ if (ie_type < 0 || ie_type > AST_EVENT_IE_MAX) {
++ return -1;
++ }
++
++ if (!(ie_val = ast_calloc(1, sizeof(*ie_val)))) {
++ return -1;
++ }
++
++ ie_val->ie_type = ie_type;
+ ie_val->ie_pltype = AST_EVENT_IE_PLTYPE_EXISTS;
+
+ AST_LIST_INSERT_TAIL(&sub->ie_vals, ie_val, entry);
+@@ -604,16 +694,18 @@
+ return 0;
+ }
+
+-int ast_event_sub_append_ie_str(struct ast_event_sub *sub,
++int ast_event_sub_append_ie_str(struct ast_event_sub *sub,
+ enum ast_event_ie_type ie_type, const char *str)
+ {
+ struct ast_event_ie_val *ie_val;
+
+- if (ie_type < 0 || ie_type > AST_EVENT_IE_MAX)
++ if (ie_type < 0 || ie_type > AST_EVENT_IE_MAX) {
+ return -1;
++ }
+
+- if (!(ie_val = ast_calloc(1, sizeof(*ie_val))))
++ if (!(ie_val = ast_calloc(1, sizeof(*ie_val)))) {
+ return -1;
++ }
+
+ ie_val->ie_type = ie_type;
+ ie_val->ie_pltype = AST_EVENT_IE_PLTYPE_STR;
+@@ -630,16 +722,18 @@
+ return 0;
+ }
+
+-int ast_event_sub_append_ie_raw(struct ast_event_sub *sub,
++int ast_event_sub_append_ie_raw(struct ast_event_sub *sub,
+ enum ast_event_ie_type ie_type, void *data, size_t raw_datalen)
+ {
+ struct ast_event_ie_val *ie_val;
+
+- if (ie_type < 0 || ie_type > AST_EVENT_IE_MAX)
++ if (ie_type < 0 || ie_type > AST_EVENT_IE_MAX) {
+ return -1;
++ }
+
+- if (!(ie_val = ast_calloc(1, sizeof(*ie_val))))
++ if (!(ie_val = ast_calloc(1, sizeof(*ie_val)))) {
+ return -1;
++ }
+
+ ie_val->ie_type = ie_type;
+ ie_val->ie_pltype = AST_EVENT_IE_PLTYPE_RAW;
+@@ -666,8 +760,9 @@
+
+ event = gen_sub_event(sub);
+
+- if (event)
++ if (event) {
+ ast_event_queue(event);
++ }
+ }
+
+ AST_RWDLLIST_WRLOCK(&ast_event_subs[sub->type]);
+@@ -677,15 +772,16 @@
+ return 0;
+ }
+
+-struct ast_event_sub *ast_event_subscribe(enum ast_event_type type, ast_event_cb_t cb,
++struct ast_event_sub *ast_event_subscribe(enum ast_event_type type, ast_event_cb_t cb,
+ void *userdata, ...)
+ {
+ va_list ap;
+ enum ast_event_ie_type ie_type;
+ struct ast_event_sub *sub;
+
+- if (!(sub = ast_event_subscribe_new(type, cb, userdata)))
++ if (!(sub = ast_event_subscribe_new(type, cb, userdata))) {
+ return NULL;
++ }
+
+ va_start(ap, userdata);
+ for (ie_type = va_arg(ap, enum ast_event_type);
+@@ -705,6 +801,12 @@
+ ast_event_sub_append_ie_uint(sub, ie_type, unsigned_int);
+ break;
+ }
++ case AST_EVENT_IE_PLTYPE_BITFLAGS:
++ {
++ uint32_t unsigned_int = va_arg(ap, uint32_t);
++ ast_event_sub_append_ie_bitflags(sub, ie_type, unsigned_int);
++ break;
++ }
+ case AST_EVENT_IE_PLTYPE_STR:
+ {
+ const char *str = va_arg(ap, const char *);
+@@ -734,8 +836,9 @@
+ {
+ struct ast_event_ie_val *ie_val;
+
+- while ((ie_val = AST_LIST_REMOVE_HEAD(&sub->ie_vals, entry)))
++ while ((ie_val = AST_LIST_REMOVE_HEAD(&sub->ie_vals, entry))) {
+ ast_event_ie_val_destroy(ie_val);
++ }
+
+ ast_free(sub);
+ }
+@@ -751,14 +854,15 @@
+ if (ast_event_check_subscriber(AST_EVENT_UNSUB,
+ AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_PLTYPE_UINT, sub->type,
+ AST_EVENT_IE_END) != AST_EVENT_SUB_NONE) {
+-
++
+ event = ast_event_new(AST_EVENT_UNSUB,
+ AST_EVENT_IE_UNIQUEID, AST_EVENT_IE_PLTYPE_UINT, sub->uniqueid,
+ AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_PLTYPE_UINT, sub->type,
+ AST_EVENT_IE_END);
+
+- if (event)
++ if (event) {
+ ast_event_queue(event);
++ }
+ }
+
+ ast_event_sub_destroy(sub);
+@@ -771,7 +875,6 @@
+ iterator->event_len = ntohs(event->event_len);
+ iterator->event = event;
+ iterator->ie = (struct ast_event_ie *) ( ((char *) event) + sizeof(*event) );
+- return;
+ }
+
+ int ast_event_iterator_next(struct ast_event_iterator *iterator)
+@@ -790,6 +893,11 @@
+ return ntohl(get_unaligned_uint32(iterator->ie->ie_payload));
+ }
+
++uint32_t ast_event_iterator_get_ie_bitflags(struct ast_event_iterator *iterator)
++{
++ return ntohl(get_unaligned_uint32(iterator->ie->ie_payload));
++}
++
+ const char *ast_event_iterator_get_ie_str(struct ast_event_iterator *iterator)
+ {
+ const struct ast_event_ie_str_payload *str_payload;
+@@ -818,6 +926,15 @@
+ return ie_val ? ntohl(get_unaligned_uint32(ie_val)) : 0;
+ }
+
++uint32_t ast_event_get_ie_bitflags(const struct ast_event *event, enum ast_event_ie_type ie_type)
++{
++ const uint32_t *ie_val;
++
++ ie_val = ast_event_get_ie_raw(event, ie_type);
++
++ return ie_val ? ntohl(get_unaligned_uint32(ie_val)) : 0;
++}
++
+ uint32_t ast_event_get_ie_str_hash(const struct ast_event *event, enum ast_event_ie_type ie_type)
+ {
+ const struct ast_event_ie_str_payload *str_payload;
+@@ -842,8 +959,9 @@
+ int res = 0;
+
+ for (ast_event_iterator_init(&iterator, event); !res; res = ast_event_iterator_next(&iterator)) {
+- if (ast_event_iterator_get_ie_type(&iterator) == ie_type)
++ if (ast_event_iterator_get_ie_type(&iterator) == ie_type) {
+ return ast_event_iterator_get_ie_raw(&iterator);
++ }
+ }
+
+ return NULL;
+@@ -871,6 +989,13 @@
+ return ast_event_append_ie_raw(event, ie_type, &data, sizeof(data));
+ }
+
++int ast_event_append_ie_bitflags(struct ast_event **event, enum ast_event_ie_type ie_type,
++ uint32_t flags)
++{
++ flags = htonl(flags);
++ return ast_event_append_ie_raw(event, ie_type, &flags, sizeof(flags));
++}
++
+ int ast_event_append_ie_raw(struct ast_event **event, enum ast_event_ie_type ie_type,
+ const void *data, size_t data_len)
+ {
+@@ -881,8 +1006,9 @@
+ event_len = ntohs((*event)->event_len);
+ extra_len = sizeof(*ie) + data_len;
+
+- if (!(*event = ast_realloc(*event, event_len + extra_len)))
++ if (!(*event = ast_realloc(*event, event_len + extra_len))) {
+ return -1;
++ }
+
+ ie = (struct ast_event_ie *) ( ((char *) *event) + event_len );
+ ie->ie_type = htons(ie_type);
+@@ -915,40 +1041,76 @@
+ ie_type = va_arg(ap, enum ast_event_type))
+ {
+ struct ast_event_ie_val *ie_value = alloca(sizeof(*ie_value));
++ int insert = 1;
+ memset(ie_value, 0, sizeof(*ie_value));
+ ie_value->ie_type = ie_type;
+ ie_value->ie_pltype = va_arg(ap, enum ast_event_ie_pltype);
+- if (ie_value->ie_pltype == AST_EVENT_IE_PLTYPE_UINT)
++ switch (ie_value->ie_pltype) {
++ case AST_EVENT_IE_PLTYPE_UINT:
+ ie_value->payload.uint = va_arg(ap, uint32_t);
+- else if (ie_value->ie_pltype == AST_EVENT_IE_PLTYPE_STR)
+- ie_value->payload.str = ast_strdupa(va_arg(ap, const char *));
+- else if (ie_value->ie_pltype == AST_EVENT_IE_PLTYPE_RAW) {
++ break;
++ case AST_EVENT_IE_PLTYPE_BITFLAGS:
++ ie_value->payload.uint = va_arg(ap, uint32_t);
++ break;
++ case AST_EVENT_IE_PLTYPE_STR:
++ ie_value->payload.str = va_arg(ap, const char *);
++ break;
++ case AST_EVENT_IE_PLTYPE_RAW:
++ {
+ void *data = va_arg(ap, void *);
+ size_t datalen = va_arg(ap, size_t);
+ ie_value->payload.raw = alloca(datalen);
+ memcpy(ie_value->payload.raw, data, datalen);
+ ie_value->raw_datalen = datalen;
++ break;
+ }
+- AST_LIST_INSERT_TAIL(&ie_vals, ie_value, entry);
++ case AST_EVENT_IE_PLTYPE_UNKNOWN:
++ insert = 0;
++ break;
++ case AST_EVENT_IE_PLTYPE_EXISTS:
++ break;
++ }
++
++ if (insert) {
++ AST_LIST_INSERT_TAIL(&ie_vals, ie_value, entry);
++ }
+ }
+ va_end(ap);
+
+- if (!(event = ast_calloc(1, sizeof(*event))))
++ if (!(event = ast_calloc(1, sizeof(*event)))) {
+ return NULL;
++ }
+
+ event->type = htons(type);
+ event->event_len = htons(sizeof(*event));
+
+ AST_LIST_TRAVERSE(&ie_vals, ie_val, entry) {
+- if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_STR)
++ switch (ie_val->ie_pltype) {
++ case AST_EVENT_IE_PLTYPE_STR:
+ ast_event_append_ie_str(&event, ie_val->ie_type, ie_val->payload.str);
+- else if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_UINT)
++ break;
++ case AST_EVENT_IE_PLTYPE_UINT:
+ ast_event_append_ie_uint(&event, ie_val->ie_type, ie_val->payload.uint);
+- else if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_RAW)
+- ast_event_append_ie_raw(&event, ie_val->ie_type, ie_val->payload.raw, ie_val->raw_datalen);
++ break;
++ case AST_EVENT_IE_PLTYPE_BITFLAGS:
++ ast_event_append_ie_bitflags(&event, ie_val->ie_type, ie_val->payload.uint);
++ break;
++ case AST_EVENT_IE_PLTYPE_RAW:
++ ast_event_append_ie_raw(&event, ie_val->ie_type,
++ ie_val->payload.raw, ie_val->raw_datalen);
++ break;
++ case AST_EVENT_IE_PLTYPE_EXISTS:
++ ast_log(LOG_WARNING, "PLTYPE_EXISTS unsupported in event_new\n");
++ break;
++ case AST_EVENT_IE_PLTYPE_UNKNOWN:
++ ast_log(LOG_WARNING, "PLTYPE_UNKNOWN passed as an IE type "
++ "for a new event\n");
++ break;
++ }
+
+- if (!event)
++ if (!event) {
+ break;
++ }
+ }
+
+ if (!ast_event_get_ie_raw(event, AST_EVENT_IE_EID)) {
+@@ -1027,6 +1189,9 @@
+ case AST_EVENT_IE_PLTYPE_UINT:
+ ast_event_append_ie_uint(&cache_arg_event, ie_type, va_arg(ap, uint32_t));
+ break;
++ case AST_EVENT_IE_PLTYPE_BITFLAGS:
++ ast_event_append_ie_bitflags(&cache_arg_event, ie_type, va_arg(ap, uint32_t));
++ break;
+ case AST_EVENT_IE_PLTYPE_STR:
+ ast_event_append_ie_str(&cache_arg_event, ie_type, va_arg(ap, const char *));
+ break;
+Index: main/astmm.c
+===================================================================
+--- a/main/astmm.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/astmm.c (.../trunk) (revision 202568)
+@@ -324,7 +324,7 @@
+
+ static char *handle_memory_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+ {
+- char *fn = NULL;
++ const char *fn = NULL;
+ struct ast_region *reg;
+ unsigned int x;
+ unsigned int len = 0;
+@@ -386,7 +386,7 @@
+
+ static char *handle_memory_show_summary(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+ {
+- char *fn = NULL;
++ const char *fn = NULL;
+ int x;
+ struct ast_region *reg;
+ unsigned int len = 0;
+Index: main/asterisk.c
+===================================================================
+--- a/main/asterisk.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/asterisk.c (.../trunk) (revision 202568)
+@@ -120,7 +120,6 @@
+ #include "asterisk/cdr.h"
+ #include "asterisk/pbx.h"
+ #include "asterisk/enum.h"
+-#include "asterisk/rtp.h"
+ #include "asterisk/http.h"
+ #include "asterisk/udptl.h"
+ #include "asterisk/app.h"
+@@ -139,8 +138,6 @@
+ #include "asterisk/xmldoc.h"
+ #include "asterisk/poll-compat.h"
+
+-#include "asterisk/doxyref.h" /* Doxygen documentation */
+-
+ #include "../defaults.h"
+
+ #ifndef AF_LOCAL
+@@ -768,7 +765,7 @@
+ static char *handle_show_profile(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+ {
+ int i, min, max;
+- char *search = NULL;
++ const char *search = NULL;
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "core show profile";
+@@ -803,7 +800,7 @@
+ static char *handle_clear_profile(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+ {
+ int i, min, max;
+- char *search = NULL;
++ const char *search = NULL;
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "core clear profile";
+@@ -944,8 +941,7 @@
+ AST_RWLIST_TRAVERSE_SAFE_END;
+ AST_RWLIST_UNLOCK(&atexits);
+
+- if (ae)
+- free(ae);
++ free(ae);
+ }
+
+ /* Sending commands from consoles back to the daemon requires a terminating NULL */
+@@ -3608,7 +3604,6 @@
+ exit(1);
+ }
+
+- ast_rtp_init();
+ ast_dsp_init();
+ ast_udptl_init();
+
+@@ -3657,6 +3652,8 @@
+ /* loads the cli_permissoins.conf file needed to implement cli restrictions. */
+ ast_cli_perms_init(0);
+
++ ast_stun_init();
++
+ dnsmgr_start_refresh();
+
+ /* We might have the option of showing a console, but for now just
+Index: main/dsp.c
+===================================================================
+--- a/main/dsp.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/dsp.c (.../trunk) (revision 202568)
+@@ -283,24 +283,17 @@
+ } td;
+ } digit_detect_state_t;
+
+-static float dtmf_row[] =
+-{
++static const float dtmf_row[] = {
+ 697.0, 770.0, 852.0, 941.0
+ };
+-static float dtmf_col[] =
+-{
++static const float dtmf_col[] = {
+ 1209.0, 1336.0, 1477.0, 1633.0
+ };
+-
+-static float mf_tones[] =
+-{
++static const float mf_tones[] = {
+ 700.0, 900.0, 1100.0, 1300.0, 1500.0, 1700.0
+ };
+-
+-static char dtmf_positions[] = "123A" "456B" "789C" "*0#D";
+-
+-static char bell_mf_positions[] = "1247C-358A--69*---0B----#";
+-
++static const char dtmf_positions[] = "123A" "456B" "789C" "*0#D";
++static const char bell_mf_positions[] = "1247C-358A--69*---0B----#";
+ static int thresholds[THRESHOLD_MAX];
+
+ static inline void goertzel_sample(goertzel_state_t *s, short sample)
+Index: main/udptl.c
+===================================================================
+--- a/main/udptl.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/udptl.c (.../trunk) (revision 202568)
+@@ -1134,7 +1134,7 @@
+ if (strncasecmp(a->argv[3], "ip", 2))
+ return CLI_SHOWUSAGE;
+ port = 0;
+- arg = a->argv[4];
++ arg = ast_strdupa(a->argv[4]);
+ p = strstr(arg, ":");
+ if (p) {
+ *p = '\0';
+Index: main/autoservice.c
+===================================================================
+--- a/main/autoservice.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/autoservice.c (.../trunk) (revision 202568)
+@@ -163,15 +163,22 @@
+ continue;
+ }
+
+- if ((dup_f = ast_frdup(defer_frame))) {
+- AST_LIST_INSERT_HEAD(&ents[i]->deferred_frames, dup_f, frame_list);
++ if (defer_frame != f) {
++ if ((dup_f = ast_frdup(defer_frame))) {
++ AST_LIST_INSERT_HEAD(&ents[i]->deferred_frames, dup_f, frame_list);
++ }
++ } else {
++ if ((dup_f = ast_frisolate(defer_frame))) {
++ if (dup_f != defer_frame) {
++ ast_frfree(defer_frame);
++ }
++ AST_LIST_INSERT_HEAD(&ents[i]->deferred_frames, dup_f, frame_list);
++ }
+ }
+
+ break;
+ }
+- }
+-
+- if (f) {
++ } else if (f) {
+ ast_frfree(f);
+ }
+ }
+Index: main/frame.c
+===================================================================
+--- a/main/frame.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/frame.c (.../trunk) (revision 202568)
+@@ -40,11 +40,6 @@
+ #include "asterisk/dsp.h"
+ #include "asterisk/file.h"
+
+-#ifdef TRACE_FRAMES
+-static int headers;
+-static AST_LIST_HEAD_STATIC(headerlist, ast_frame);
+-#endif
+-
+ #if !defined(LOW_MEMORY)
+ static void frame_cache_cleanup(void *data);
+
+@@ -318,12 +313,6 @@
+ #endif
+
+ f->mallocd_hdr_len = sizeof(*f);
+-#ifdef TRACE_FRAMES
+- AST_LIST_LOCK(&headerlist);
+- headers++;
+- AST_LIST_INSERT_HEAD(&headerlist, f, frame_list);
+- AST_LIST_UNLOCK(&headerlist);
+-#endif
+
+ return f;
+ }
+@@ -341,7 +330,7 @@
+ }
+ #endif
+
+-void ast_frame_free(struct ast_frame *fr, int cache)
++static void __frame_free(struct ast_frame *fr, int cache)
+ {
+ if (ast_test_flag(fr, AST_FRFLAG_FROM_TRANSLATOR)) {
+ ast_translate_frame_freed(fr);
+@@ -360,8 +349,8 @@
+ * to keep things simple... */
+ struct ast_frame_cache *frames;
+
+- if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))
+- && frames->size < FRAME_CACHE_MAX_SIZE) {
++ if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames))) &&
++ (frames->size < FRAME_CACHE_MAX_SIZE)) {
+ AST_LIST_INSERT_HEAD(&frames->list, fr, frame_list);
+ frames->size++;
+ return;
+@@ -375,19 +364,25 @@
+ }
+ if (fr->mallocd & AST_MALLOCD_SRC) {
+ if (fr->src)
+- ast_free((char *)fr->src);
++ ast_free((void *) fr->src);
+ }
+ if (fr->mallocd & AST_MALLOCD_HDR) {
+-#ifdef TRACE_FRAMES
+- AST_LIST_LOCK(&headerlist);
+- headers--;
+- AST_LIST_REMOVE(&headerlist, fr, frame_list);
+- AST_LIST_UNLOCK(&headerlist);
+-#endif
+ ast_free(fr);
+ }
+ }
+
++
++void ast_frame_free(struct ast_frame *frame, int cache)
++{
++ struct ast_frame *next;
++
++ for (next = AST_LIST_NEXT(frame, frame_list);
++ frame;
++ frame = next, next = frame ? AST_LIST_NEXT(frame, frame_list) : NULL) {
++ __frame_free(frame, cache);
++ }
++}
++
+ /*!
+ * \brief 'isolates' a frame by duplicating non-malloc'ed components
+ * (header, src, data).
+@@ -398,19 +393,29 @@
+ struct ast_frame *out;
+ void *newdata;
+
+- ast_clear_flag(fr, AST_FRFLAG_FROM_TRANSLATOR);
+- ast_clear_flag(fr, AST_FRFLAG_FROM_DSP);
++ /* if none of the existing frame is malloc'd, let ast_frdup() do it
++ since it is more efficient
++ */
++ if (fr->mallocd == 0) {
++ return ast_frdup(fr);
++ }
+
++ /* if everything is already malloc'd, we are done */
++ if ((fr->mallocd & (AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA)) ==
++ (AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA)) {
++ return fr;
++ }
++
+ if (!(fr->mallocd & AST_MALLOCD_HDR)) {
+ /* Allocate a new header if needed */
+- if (!(out = ast_frame_header_new()))
++ if (!(out = ast_frame_header_new())) {
+ return NULL;
++ }
+ out->frametype = fr->frametype;
+ out->subclass = fr->subclass;
+ out->datalen = fr->datalen;
+ out->samples = fr->samples;
+ out->offset = fr->offset;
+- out->data = fr->data;
+ /* Copy the timing data */
+ ast_copy_flags(out, fr, AST_FRFLAG_HAS_TIMING_INFO);
+ if (ast_test_flag(fr, AST_FRFLAG_HAS_TIMING_INFO)) {
+@@ -418,26 +423,34 @@
+ out->len = fr->len;
+ out->seqno = fr->seqno;
+ }
+- } else
++ } else {
++ ast_clear_flag(fr, AST_FRFLAG_FROM_TRANSLATOR);
++ ast_clear_flag(fr, AST_FRFLAG_FROM_DSP);
++ ast_clear_flag(fr, AST_FRFLAG_FROM_FILESTREAM);
+ out = fr;
++ }
+
+- if (!(fr->mallocd & AST_MALLOCD_SRC)) {
+- if (fr->src) {
+- if (!(out->src = ast_strdup(fr->src))) {
+- if (out != fr)
+- ast_free(out);
+- return NULL;
++ if (!(fr->mallocd & AST_MALLOCD_SRC) && fr->src) {
++ if (!(out->src = ast_strdup(fr->src))) {
++ if (out != fr) {
++ ast_free(out);
+ }
++ return NULL;
+ }
+- } else
++ } else {
+ out->src = fr->src;
++ fr->src = NULL;
++ fr->mallocd &= ~AST_MALLOCD_SRC;
++ }
+
+ if (!(fr->mallocd & AST_MALLOCD_DATA)) {
+ if (!(newdata = ast_malloc(fr->datalen + AST_FRIENDLY_OFFSET))) {
+- if (out->src != fr->src)
++ if (out->src != fr->src) {
+ ast_free((void *) out->src);
+- if (out != fr)
++ }
++ if (out != fr) {
+ ast_free(out);
++ }
+ return NULL;
+ }
+ newdata += AST_FRIENDLY_OFFSET;
+@@ -445,6 +458,10 @@
+ out->datalen = fr->datalen;
+ memcpy(newdata, fr->data.ptr, fr->datalen);
+ out->data.ptr = newdata;
++ } else {
++ out->data = fr->data;
++ memset(&fr->data, 0, sizeof(fr->data));
++ fr->mallocd &= ~AST_MALLOCD_DATA;
+ }
+
+ out->mallocd = AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA;
+@@ -939,44 +956,10 @@
+ }
+
+
+-#ifdef TRACE_FRAMES
+-static char *show_frame_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+-{
+- struct ast_frame *f;
+- int x=1;
+-
+- switch (cmd) {
+- case CLI_INIT:
+- e->command = "core show frame stats";
+- e->usage =
+- "Usage: core show frame stats\n"
+- " Displays debugging statistics from framer\n";
+- return NULL;
+- case CLI_GENERATE:
+- return NULL;
+- }
+-
+- if (a->argc != 4)
+- return CLI_SHOWUSAGE;
+- AST_LIST_LOCK(&headerlist);
+- ast_cli(a->fd, " Framer Statistics \n");
+- ast_cli(a->fd, "---------------------------\n");
+- ast_cli(a->fd, "Total allocated headers: %d\n", headers);
+- ast_cli(a->fd, "Queue Dump:\n");
+- AST_LIST_TRAVERSE(&headerlist, f, frame_list)
+- ast_cli(a->fd, "%d. Type %d, subclass %d from %s\n", x++, f->frametype, f->subclass, f->src ? f->src : "<Unknown>");
+- AST_LIST_UNLOCK(&headerlist);
+- return CLI_SUCCESS;
+-}
+-#endif
+-
+ /* Builtin Asterisk CLI-commands for debugging */
+ static struct ast_cli_entry my_clis[] = {
+ AST_CLI_DEFINE(show_codecs, "Displays a list of codecs"),
+ AST_CLI_DEFINE(show_codec_n, "Shows a specific codec"),
+-#ifdef TRACE_FRAMES
+- AST_CLI_DEFINE(show_frame_stats, "Shows frame statistics"),
+-#endif
+ };
+
+ int init_framer(void)
+@@ -1354,7 +1337,7 @@
+
+ static int speex_get_wb_sz_at(unsigned char *data, int len, int bit)
+ {
+- static int SpeexWBSubModeSz[] = {
++ static const int SpeexWBSubModeSz[] = {
+ 0, 36, 112, 192,
+ 352, 0, 0, 0 };
+ int off = bit;
+@@ -1384,12 +1367,12 @@
+
+ static int speex_samples(unsigned char *data, int len)
+ {
+- static int SpeexSubModeSz[] = {
++ static const int SpeexSubModeSz[] = {
+ 5, 43, 119, 160,
+ 220, 300, 364, 492,
+ 79, 0, 0, 0,
+ 0, 0, 0, 0 };
+- static int SpeexInBandSz[] = {
++ static const int SpeexInBandSz[] = {
+ 1, 1, 4, 4,
+ 4, 4, 4, 4,
+ 8, 8, 16, 16,
+Index: main/say.c
+===================================================================
+--- a/main/say.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/say.c (.../trunk) (revision 202568)
+@@ -349,6 +349,7 @@
+ static int ast_say_number_full_ge(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
+ static int ast_say_number_full_hu(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
+ static int ast_say_number_full_th(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
++static int ast_say_number_full_ur(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
+
+ /* Forward declarations of language specific variants of ast_say_enumeration_full */
+ static int ast_say_enumeration_full_en(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
+@@ -467,6 +468,8 @@
+ return(ast_say_number_full_ru(chan, num, ints, language, options, audiofd, ctrlfd));
+ } else if (!strcasecmp(language, "th") ) { /* Thai syntax */
+ return(ast_say_number_full_th(chan, num, ints, language, audiofd, ctrlfd));
++ } else if (!strcasecmp(language, "ur") ) { /* Urdu syntax */
++ return(ast_say_number_full_ur(chan, num, ints, language, options, audiofd, ctrlfd));
+ } else if (!strcasecmp(language, "ge") ) { /* Georgian syntax */
+ return(ast_say_number_full_ge(chan, num, ints, language, options, audiofd, ctrlfd));
+ }
+@@ -2352,7 +2355,68 @@
+ return res;
+ }
+
++/*!\internal
++ * \brief Counting in Urdu, the national language of Pakistan
++ * \since 1.6.3
++ */
++static int ast_say_number_full_ur(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
++{
++ int res = 0;
++ int playh = 0;
++ char fn[256] = "";
+
++ if (!num) {
++ return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
++ }
++
++ while (!res && (num || playh)) {
++ if (playh) {
++ snprintf(fn, sizeof(fn), "digits/hundred");
++ playh = 0;
++ } else if (num < 100) {
++ snprintf(fn, sizeof(fn), "digits/%d", num);
++ num = 0;
++ } else if (num < 1000) {
++ snprintf(fn, sizeof(fn), "digits/%d", (num / 100));
++ playh++;
++ num -= ((num / 100) * 100);
++ } else if (num < 100000) { /* 1,00,000 */
++ if ((res = ast_say_number_full_ur(chan, num / 1000, ints, language, options, audiofd, ctrlfd))) {
++ return res;
++ }
++ num = num % 1000;
++ snprintf(fn, sizeof(fn), "digits/thousand");
++ } else if (num < 10000000) { /* 1,00,00,000 */
++ if ((res = ast_say_number_full_ur(chan, num / 100000, ints, language, options, audiofd, ctrlfd))) {
++ return res;
++ }
++ num = num % 100000;
++ snprintf(fn, sizeof(fn), "digits/lac");
++ } else if (num < 1000000000) { /* 1,00,00,00,000 */
++ if ((res = ast_say_number_full_ur(chan, num / 10000000, ints, language, options, audiofd, ctrlfd))) {
++ return res;
++ }
++ num = num % 10000000;
++ snprintf(fn, sizeof(fn), "digits/crore");
++ } else {
++ ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
++ res = -1;
++ }
++
++ if (!res) {
++ if (!ast_streamfile(chan, fn, language)) {
++ if ((audiofd > -1) && (ctrlfd > -1)) {
++ res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
++ } else {
++ res = ast_waitstream(chan, ints);
++ }
++ }
++ ast_stopstream(chan);
++ }
++ }
++ return res;
++}
++
+ /*! \brief determine last digits for thousands/millions (ru) */
+ static int get_lastdigits_ru(int num) {
+ if (num < 20) {
+Index: main/threadstorage.c
+===================================================================
+--- a/main/threadstorage.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/threadstorage.c (.../trunk) (revision 202568)
+@@ -125,7 +125,7 @@
+
+ static char *handle_cli_threadstorage_show_allocations(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+ {
+- char *fn = NULL;
++ const char *fn = NULL;
+ size_t len = 0;
+ unsigned int count = 0;
+ struct tls_object *to;
+@@ -169,7 +169,7 @@
+
+ static char *handle_cli_threadstorage_show_summary(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+ {
+- char *fn = NULL;
++ const char *fn = NULL;
+ size_t len = 0;
+ unsigned int count = 0;
+ struct tls_object *to;
+Index: main/devicestate.c
+===================================================================
+--- a/main/devicestate.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/devicestate.c (.../trunk) (revision 202568)
+@@ -128,7 +128,7 @@
+ #include "asterisk/event.h"
+
+ /*! \brief Device state strings for printing */
+-static const char *devstatestring[][2] = {
++static const char * const devstatestring[][2] = {
+ { /* 0 AST_DEVICE_UNKNOWN */ "Unknown", "UNKNOWN" }, /*!< Valid, but unknown state */
+ { /* 1 AST_DEVICE_NOT_INUSE */ "Not in use", "NOT_INUSE" }, /*!< Not used */
+ { /* 2 AST_DEVICE IN USE */ "In use", "INUSE" }, /*!< In use */
+@@ -190,7 +190,7 @@
+ char device[1];
+ };
+
+-struct {
++static struct {
+ pthread_t thread;
+ struct ast_event_sub *event_sub;
+ ast_cond_t cond;
+@@ -268,19 +268,15 @@
+ char match[AST_CHANNEL_NAME];
+ enum ast_device_state res;
+
+- ast_copy_string(match, device, sizeof(match)-1);
+- strcat(match, "-");
+- chan = ast_get_channel_by_name_prefix_locked(match, strlen(match));
++ snprintf(match, sizeof(match), "%s-", device);
+
+- if (!chan)
++ if (!(chan = ast_channel_get_by_name_prefix(match, strlen(match)))) {
+ return AST_DEVICE_UNKNOWN;
++ }
+
+- if (chan->_state == AST_STATE_RINGING)
+- res = AST_DEVICE_RINGING;
+- else
+- res = AST_DEVICE_INUSE;
++ res = (chan->_state == AST_STATE_RINGING) ? AST_DEVICE_RINGING : AST_DEVICE_INUSE;
+
+- ast_channel_unlock(chan);
++ chan = ast_channel_unref(chan);
+
+ return res;
+ }
+Index: main/autochan.c
+===================================================================
+--- a/main/autochan.c (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/main/autochan.c (.../trunk) (revision 202568)
+@@ -0,0 +1,94 @@
++/*
++ * Asterisk -- An open source telephony toolkit.
++ *
++ * Copyright (C) 2009, Digium, Inc.
++ *
++ * Mark Michelson <mmichelson@digium.com>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * 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.
++ */
++
++/*!
++ * \file
++ * \brief "smart" channels
++ *
++ * \author Mark Michelson <mmichelson@digium.com>
++ */
++
++#include "asterisk.h"
++
++ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
++
++#include "asterisk/autochan.h"
++#include "asterisk/utils.h"
++#include "asterisk/linkedlists.h"
++#include "asterisk/options.h"
++#include "asterisk/channel.h"
++
++struct ast_autochan *ast_autochan_setup(struct ast_channel *chan)
++{
++ struct ast_autochan *autochan;
++
++ if (!chan) {
++ return NULL;
++ }
++
++ if (!(autochan = ast_calloc(1, sizeof(*autochan)))) {
++ return NULL;
++ }
++
++ autochan->chan = ast_channel_ref(chan);
++
++ ast_channel_lock(autochan->chan);
++ AST_LIST_INSERT_TAIL(&autochan->chan->autochans, autochan, list);
++ ast_channel_unlock(autochan->chan);
++
++ ast_debug(1, "Created autochan %p to hold channel %s (%p)\n", autochan, chan->name, chan);
++
++ return autochan;
++}
++
++void ast_autochan_destroy(struct ast_autochan *autochan)
++{
++ struct ast_autochan *autochan_iter;
++
++ ast_channel_lock(autochan->chan);
++ AST_LIST_TRAVERSE_SAFE_BEGIN(&autochan->chan->autochans, autochan_iter, list) {
++ if (autochan_iter == autochan) {
++ AST_LIST_REMOVE_CURRENT(list);
++ ast_debug(1, "Removed autochan %p from the list, about to free it\n", autochan);
++ break;
++ }
++ }
++ AST_LIST_TRAVERSE_SAFE_END;
++ ast_channel_unlock(autochan->chan);
++
++ autochan->chan = ast_channel_unref(autochan->chan);
++
++ ast_free(autochan);
++}
++
++void ast_autochan_new_channel(struct ast_channel *old_chan, struct ast_channel *new_chan)
++{
++ struct ast_autochan *autochan;
++
++ AST_LIST_APPEND_LIST(&new_chan->autochans, &old_chan->autochans, list);
++
++ AST_LIST_TRAVERSE(&new_chan->autochans, autochan, list) {
++ if (autochan->chan == old_chan) {
++ autochan->chan = ast_channel_unref(old_chan);
++ autochan->chan = ast_channel_ref(new_chan);
++
++ ast_debug(1, "Autochan %p used to hold channel %s (%p) but now holds channel %s (%p)\n",
++ autochan, old_chan->name, old_chan, new_chan->name, new_chan);
++ }
++ }
++}
+
+Property changes on: main/autochan.c
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+
+Index: main/taskprocessor.c
+===================================================================
+--- a/main/taskprocessor.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/taskprocessor.c (.../trunk) (revision 202568)
+@@ -62,7 +62,7 @@
+ /*! \brief A ast_taskprocessor structure is a singleton by name */
+ struct ast_taskprocessor {
+ /*! \brief Friendly name of the taskprocessor */
+- char *name;
++ const char *name;
+ /*! \brief Thread poll condition */
+ ast_cond_t poll_cond;
+ /*! \brief Taskprocessor thread */
+@@ -189,7 +189,7 @@
+ static char *cli_tps_ping(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+ {
+ struct timeval begin, end, delta;
+- char *name;
++ const char *name;
+ struct timeval when;
+ struct timespec ts;
+ struct ast_taskprocessor *tps = NULL;
+@@ -366,7 +366,7 @@
+ ast_free(t->stats);
+ t->stats = NULL;
+ }
+- ast_free(t->name);
++ ast_free((char *) t->name);
+ }
+
+ /* pop the front task and return it */
+@@ -404,7 +404,7 @@
+ /* Provide a reference to a taskprocessor. Create the taskprocessor if necessary, but don't
+ * create the taskprocessor if we were told via ast_tps_options to return a reference only
+ * if it already exists */
+-struct ast_taskprocessor *ast_taskprocessor_get(char *name, enum ast_tps_options create)
++struct ast_taskprocessor *ast_taskprocessor_get(const char *name, enum ast_tps_options create)
+ {
+ struct ast_taskprocessor *p, tmp_tps = {
+ .name = name,
+Index: main/enum.c
+===================================================================
+--- a/main/enum.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/enum.c (.../trunk) (revision 202568)
+@@ -41,7 +41,7 @@
+ *
+ * \par Possible improvement
+ * \todo Implement a caching mechanism for multile enum lookups
+- * - See http://bugs.digium.com/view.php?id=6739
++ * - See https://issues.asterisk.org/view.php?id=6739
+ * \todo The service type selection needs to be redone.
+ */
+
+Index: main/astobj2.c
+===================================================================
+--- a/main/astobj2.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/astobj2.c (.../trunk) (revision 202568)
+@@ -134,19 +134,19 @@
+
+ /* the underlying functions common to debug and non-debug versions */
+
+-static int __ao2_ref(void *user_data, const int delta);
+-static struct ao2_container *__ao2_container_alloc(struct ao2_container *c, const uint n_buckets, ao2_hash_fn *hash_fn,
+- ao2_callback_fn *cmp_fn);
+-static struct bucket_list *__ao2_link(struct ao2_container *c, void *user_data, const char *file, int line, const char *func);
+-static void *__ao2_callback(struct ao2_container *c,
+- const enum search_flags flags, void *cb_fn, void *arg, void *data, enum ao2_callback_type type,
+- char *tag, char *file, int line, const char *funcname);
+-static void * __ao2_iterator_next(struct ao2_iterator *a, struct bucket_list **q);
++static int internal_ao2_ref(void *user_data, const int delta);
++static struct ao2_container *internal_ao2_container_alloc(struct ao2_container *c, const uint n_buckets, ao2_hash_fn *hash_fn,
++ ao2_callback_fn *cmp_fn);
++static struct bucket_list *internal_ao2_link(struct ao2_container *c, void *user_data, const char *file, int line, const char *func);
++static void *internal_ao2_callback(struct ao2_container *c,
++ const enum search_flags flags, void *cb_fn, void *arg, void *data, enum ao2_callback_type type,
++ char *tag, char *file, int line, const char *funcname);
++static void *internal_ao2_iterator_next(struct ao2_iterator *a, struct bucket_list **q);
+
+ #ifndef DEBUG_THREADS
+ int ao2_lock(void *user_data)
+ #else
+-int _ao2_lock(void *user_data, const char *file, const char *func, int line, const char *var)
++int __ao2_lock(void *user_data, const char *file, const char *func, int line, const char *var)
+ #endif
+ {
+ struct astobj2 *p = INTERNAL_OBJ(user_data);
+@@ -168,7 +168,7 @@
+ #ifndef DEBUG_THREADS
+ int ao2_unlock(void *user_data)
+ #else
+-int _ao2_unlock(void *user_data, const char *file, const char *func, int line, const char *var)
++int __ao2_unlock(void *user_data, const char *file, const char *func, int line, const char *var)
+ #endif
+ {
+ struct astobj2 *p = INTERNAL_OBJ(user_data);
+@@ -190,7 +190,7 @@
+ #ifndef DEBUG_THREADS
+ int ao2_trylock(void *user_data)
+ #else
+-int _ao2_trylock(void *user_data, const char *file, const char *func, int line, const char *var)
++int __ao2_trylock(void *user_data, const char *file, const char *func, int line, const char *var)
+ #endif
+ {
+ struct astobj2 *p = INTERNAL_OBJ(user_data);
+@@ -226,7 +226,7 @@
+ */
+
+
+-int _ao2_ref_debug(void *user_data, const int delta, char *tag, char *file, int line, const char *funcname)
++int __ao2_ref_debug(void *user_data, const int delta, char *tag, char *file, int line, const char *funcname)
+ {
+ struct astobj2 *obj = INTERNAL_OBJ(user_data);
+
+@@ -235,7 +235,7 @@
+
+ if (delta != 0) {
+ FILE *refo = fopen(REF_FILE,"a");
+- fprintf(refo, "%p %s%d %s:%d:%s (%s) [@%d]\n", user_data, (delta<0? "":"+"), delta, file, line, funcname, tag, obj->priv_data.ref_counter);
++ fprintf(refo, "%p %s%d %s:%d:%s (%s) [@%d]\n", user_data, (delta<0? "":"+"), delta, file, line, funcname, tag, obj ? obj->priv_data.ref_counter : -1);
+ fclose(refo);
+ }
+ if (obj->priv_data.ref_counter + delta == 0 && obj->priv_data.destructor_fn != NULL) { /* this isn't protected with lock; just for o/p */
+@@ -243,20 +243,20 @@
+ fprintf(refo, "%p **call destructor** %s:%d:%s (%s)\n", user_data, file, line, funcname, tag);
+ fclose(refo);
+ }
+- return __ao2_ref(user_data, delta);
++ return internal_ao2_ref(user_data, delta);
+ }
+
+-int _ao2_ref(void *user_data, const int delta)
++int __ao2_ref(void *user_data, const int delta)
+ {
+ struct astobj2 *obj = INTERNAL_OBJ(user_data);
+
+ if (obj == NULL)
+ return -1;
+
+- return __ao2_ref(user_data, delta);
++ return internal_ao2_ref(user_data, delta);
+ }
+
+-static int __ao2_ref(void *user_data, const int delta)
++static int internal_ao2_ref(void *user_data, const int delta)
+ {
+ struct astobj2 *obj = INTERNAL_OBJ(user_data);
+ int current_value;
+@@ -302,7 +302,7 @@
+ * We always alloc at least the size of a void *,
+ * for debugging purposes.
+ */
+-static void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, const char *file, int line, const char *funcname)
++static void *internal_ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, const char *file, int line, const char *funcname)
+ {
+ /* allocation */
+ struct astobj2 *obj;
+@@ -335,18 +335,18 @@
+ return EXTERNAL_OBJ(obj);
+ }
+
+-void *_ao2_alloc_debug(size_t data_size, ao2_destructor_fn destructor_fn, char *tag,
+- const char *file, int line, const char *funcname, int ref_debug)
++void *__ao2_alloc_debug(size_t data_size, ao2_destructor_fn destructor_fn, char *tag,
++ const char *file, int line, const char *funcname, int ref_debug)
+ {
+ /* allocation */
+ void *obj;
+ FILE *refo = ref_debug ? fopen(REF_FILE,"a") : NULL;
+
+- obj = __ao2_alloc(data_size, destructor_fn, file, line, funcname);
++ if ((obj = internal_ao2_alloc(data_size, destructor_fn, file, line, funcname)) == NULL) {
++ fclose(refo);
++ return NULL;
++ }
+
+- if (obj == NULL)
+- return NULL;
+-
+ if (refo) {
+ fprintf(refo, "%p =1 %s:%d:%s (%s)\n", obj, file, line, funcname, tag);
+ fclose(refo);
+@@ -356,9 +356,9 @@
+ return obj;
+ }
+
+-void *_ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn)
++void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn)
+ {
+- return __ao2_alloc(data_size, destructor_fn, __FILE__, __LINE__, __FUNCTION__);
++ return internal_ao2_alloc(data_size, destructor_fn, __FILE__, __LINE__, __FUNCTION__);
+ }
+
+
+@@ -422,8 +422,8 @@
+ /*
+ * A container is just an object, after all!
+ */
+-static struct ao2_container *__ao2_container_alloc(struct ao2_container *c, const unsigned int n_buckets, ao2_hash_fn *hash_fn,
+- ao2_callback_fn *cmp_fn)
++static struct ao2_container *internal_ao2_container_alloc(struct ao2_container *c, const unsigned int n_buckets, ao2_hash_fn *hash_fn,
++ ao2_callback_fn *cmp_fn)
+ {
+ /* XXX maybe consistency check on arguments ? */
+ /* compute the container size */
+@@ -432,7 +432,7 @@
+ return NULL;
+
+ c->version = 1; /* 0 is a reserved value here */
+- c->n_buckets = n_buckets;
++ c->n_buckets = hash_fn ? n_buckets : 1;
+ c->hash_fn = hash_fn ? hash_fn : hash_zero;
+ c->cmp_fn = cmp_fn;
+
+@@ -443,29 +443,30 @@
+ return c;
+ }
+
+-struct ao2_container *_ao2_container_alloc_debug(const unsigned int n_buckets, ao2_hash_fn *hash_fn,
++struct ao2_container *__ao2_container_alloc_debug(const unsigned int n_buckets, ao2_hash_fn *hash_fn,
+ ao2_callback_fn *cmp_fn, char *tag, char *file, int line,
+ const char *funcname, int ref_debug)
+ {
+ /* XXX maybe consistency check on arguments ? */
+ /* compute the container size */
+- size_t container_size = sizeof(struct ao2_container) + n_buckets * sizeof(struct bucket);
+- struct ao2_container *c = _ao2_alloc_debug(container_size, container_destruct_debug, tag, file, line, funcname, ref_debug);
++ const unsigned int num_buckets = hash_fn ? n_buckets : 1;
++ size_t container_size = sizeof(struct ao2_container) + num_buckets * sizeof(struct bucket);
++ struct ao2_container *c = __ao2_alloc_debug(container_size, container_destruct_debug, tag, file, line, funcname, ref_debug);
+
+- return __ao2_container_alloc(c, n_buckets, hash_fn, cmp_fn);
++ return internal_ao2_container_alloc(c, num_buckets, hash_fn, cmp_fn);
+ }
+
+-struct ao2_container *
+-_ao2_container_alloc(const unsigned int n_buckets, ao2_hash_fn *hash_fn,
+- ao2_callback_fn *cmp_fn)
++struct ao2_container *__ao2_container_alloc(const unsigned int n_buckets, ao2_hash_fn *hash_fn,
++ ao2_callback_fn *cmp_fn)
+ {
+ /* XXX maybe consistency check on arguments ? */
+ /* compute the container size */
+
+- size_t container_size = sizeof(struct ao2_container) + n_buckets * sizeof(struct bucket);
+- struct ao2_container *c = _ao2_alloc(container_size, container_destruct);
++ const unsigned int num_buckets = hash_fn ? n_buckets : 1;
++ size_t container_size = sizeof(struct ao2_container) + num_buckets * sizeof(struct bucket);
++ struct ao2_container *c = __ao2_alloc(container_size, container_destruct);
+
+- return __ao2_container_alloc(c, n_buckets, hash_fn, cmp_fn);
++ return internal_ao2_container_alloc(c, num_buckets, hash_fn, cmp_fn);
+ }
+
+ /*!
+@@ -491,7 +492,7 @@
+ * link an object to a container
+ */
+
+-static struct bucket_list *__ao2_link(struct ao2_container *c, void *user_data, const char *file, int line, const char *func)
++static struct bucket_list *internal_ao2_link(struct ao2_container *c, void *user_data, const char *file, int line, const char *func)
+ {
+ int i;
+ /* create a new list entry */
+@@ -521,23 +522,23 @@
+ return p;
+ }
+
+-void *_ao2_link_debug(struct ao2_container *c, void *user_data, char *tag, char *file, int line, const char *funcname)
++void *__ao2_link_debug(struct ao2_container *c, void *user_data, char *tag, char *file, int line, const char *funcname)
+ {
+- struct bucket_list *p = __ao2_link(c, user_data, file, line, funcname);
++ struct bucket_list *p = internal_ao2_link(c, user_data, file, line, funcname);
+
+ if (p) {
+- _ao2_ref_debug(user_data, +1, tag, file, line, funcname);
++ __ao2_ref_debug(user_data, +1, tag, file, line, funcname);
+ ao2_unlock(c);
+ }
+ return p;
+ }
+
+-void *_ao2_link(struct ao2_container *c, void *user_data)
++void *__ao2_link(struct ao2_container *c, void *user_data)
+ {
+- struct bucket_list *p = __ao2_link(c, user_data, __FILE__, __LINE__, __PRETTY_FUNCTION__);
++ struct bucket_list *p = internal_ao2_link(c, user_data, __FILE__, __LINE__, __PRETTY_FUNCTION__);
+
+ if (p) {
+- _ao2_ref(user_data, +1);
++ __ao2_ref(user_data, +1);
+ ao2_unlock(c);
+ }
+ return p;
+@@ -555,23 +556,23 @@
+ * Unlink an object from the container
+ * and destroy the associated * ao2_bucket_list structure.
+ */
+-void *_ao2_unlink_debug(struct ao2_container *c, void *user_data, char *tag,
+- char *file, int line, const char *funcname)
++void *__ao2_unlink_debug(struct ao2_container *c, void *user_data, char *tag,
++ char *file, int line, const char *funcname)
+ {
+ if (INTERNAL_OBJ(user_data) == NULL) /* safety check on the argument */
+ return NULL;
+
+- _ao2_callback_debug(c, OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA, ao2_match_by_addr, user_data, tag, file, line, funcname);
++ __ao2_callback_debug(c, OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA, ao2_match_by_addr, user_data, tag, file, line, funcname);
+
+ return NULL;
+ }
+
+-void *_ao2_unlink(struct ao2_container *c, void *user_data)
++void *__ao2_unlink(struct ao2_container *c, void *user_data)
+ {
+ if (INTERNAL_OBJ(user_data) == NULL) /* safety check on the argument */
+ return NULL;
+
+- _ao2_callback(c, OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA, ao2_match_by_addr, user_data);
++ __ao2_callback(c, OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA, ao2_match_by_addr, user_data);
+
+ return NULL;
+ }
+@@ -600,9 +601,9 @@
+ * aren't an excessive load to the system, as the callback should not be
+ * called as often as, say, the ao2_ref func is called.
+ */
+-static void *__ao2_callback(struct ao2_container *c,
+- const enum search_flags flags, void *cb_fn, void *arg, void *data, enum ao2_callback_type type,
+- char *tag, char *file, int line, const char *funcname)
++static void *internal_ao2_callback(struct ao2_container *c,
++ const enum search_flags flags, void *cb_fn, void *arg, void *data, enum ao2_callback_type type,
++ char *tag, char *file, int line, const char *funcname)
+ {
+ int i, last; /* search boundaries */
+ void *ret = NULL;
+@@ -680,9 +681,9 @@
+ /* it is important to handle this case before the unlink */
+ ret = EXTERNAL_OBJ(cur->astobj);
+ if (tag)
+- _ao2_ref_debug(ret, 1, tag, file, line, funcname);
++ __ao2_ref_debug(ret, 1, tag, file, line, funcname);
+ else
+- _ao2_ref(ret, 1);
++ __ao2_ref(ret, 1);
+ }
+
+ if (flags & OBJ_UNLINK) { /* must unlink */
+@@ -694,9 +695,9 @@
+ /* update number of elements and version */
+ ast_atomic_fetchadd_int(&c->elements, -1);
+ if (tag)
+- _ao2_ref_debug(EXTERNAL_OBJ(x->astobj), -1, tag, file, line, funcname);
++ __ao2_ref_debug(EXTERNAL_OBJ(x->astobj), -1, tag, file, line, funcname);
+ else
+- _ao2_ref(EXTERNAL_OBJ(x->astobj), -1);
++ __ao2_ref(EXTERNAL_OBJ(x->astobj), -1);
+ free(x); /* free the link record */
+ }
+
+@@ -720,45 +721,45 @@
+ return ret;
+ }
+
+-void *_ao2_callback_debug(struct ao2_container *c,
+- const enum search_flags flags,
+- ao2_callback_fn *cb_fn, void *arg,
+- char *tag, char *file, int line, const char *funcname)
++void *__ao2_callback_debug(struct ao2_container *c,
++ const enum search_flags flags,
++ ao2_callback_fn *cb_fn, void *arg,
++ char *tag, char *file, int line, const char *funcname)
+ {
+- return __ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, tag, file, line, funcname);
++ return internal_ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, tag, file, line, funcname);
+ }
+
+-void *_ao2_callback(struct ao2_container *c, const enum search_flags flags,
+- ao2_callback_fn *cb_fn, void *arg)
++void *__ao2_callback(struct ao2_container *c, const enum search_flags flags,
++ ao2_callback_fn *cb_fn, void *arg)
+ {
+- return __ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, NULL, NULL, 0, NULL);
++ return internal_ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, NULL, NULL, 0, NULL);
+ }
+
+-void *_ao2_callback_data_debug(struct ao2_container *c,
+- const enum search_flags flags,
+- ao2_callback_data_fn *cb_fn, void *arg, void *data,
+- char *tag, char *file, int line, const char *funcname)
++void *__ao2_callback_data_debug(struct ao2_container *c,
++ const enum search_flags flags,
++ ao2_callback_data_fn *cb_fn, void *arg, void *data,
++ char *tag, char *file, int line, const char *funcname)
+ {
+- return __ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, tag, file, line, funcname);
++ return internal_ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, tag, file, line, funcname);
+ }
+
+-void *_ao2_callback_data(struct ao2_container *c, const enum search_flags flags,
+- ao2_callback_data_fn *cb_fn, void *arg, void *data)
++void *__ao2_callback_data(struct ao2_container *c, const enum search_flags flags,
++ ao2_callback_data_fn *cb_fn, void *arg, void *data)
+ {
+- return __ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, NULL, NULL, 0, NULL);
++ return internal_ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, NULL, NULL, 0, NULL);
+ }
+
+ /*!
+ * the find function just invokes the default callback with some reasonable flags.
+ */
+-void *_ao2_find_debug(struct ao2_container *c, void *arg, enum search_flags flags, char *tag, char *file, int line, const char *funcname)
++void *__ao2_find_debug(struct ao2_container *c, void *arg, enum search_flags flags, char *tag, char *file, int line, const char *funcname)
+ {
+- return _ao2_callback_debug(c, flags, c->cmp_fn, arg, tag, file, line, funcname);
++ return __ao2_callback_debug(c, flags, c->cmp_fn, arg, tag, file, line, funcname);
+ }
+
+-void *_ao2_find(struct ao2_container *c, void *arg, enum search_flags flags)
++void *__ao2_find(struct ao2_container *c, void *arg, enum search_flags flags)
+ {
+- return _ao2_callback(c, flags, c->cmp_fn, arg);
++ return __ao2_callback(c, flags, c->cmp_fn, arg);
+ }
+
+ /*!
+@@ -777,7 +778,7 @@
+ /*
+ * move to the next element in the container.
+ */
+-static void * __ao2_iterator_next(struct ao2_iterator *a, struct bucket_list **q)
++static void *internal_ao2_iterator_next(struct ao2_iterator *a, struct bucket_list **q)
+ {
+ int lim;
+ struct bucket_list *p = NULL;
+@@ -832,16 +833,16 @@
+ return ret;
+ }
+
+-void * _ao2_iterator_next_debug(struct ao2_iterator *a, char *tag, char *file, int line, const char *funcname)
++void *__ao2_iterator_next_debug(struct ao2_iterator *a, char *tag, char *file, int line, const char *funcname)
+ {
+ struct bucket_list *p;
+ void *ret = NULL;
+
+- ret = __ao2_iterator_next(a, &p);
++ ret = internal_ao2_iterator_next(a, &p);
+
+ if (p) {
+ /* inc refcount of returned object */
+- _ao2_ref_debug(ret, 1, tag, file, line, funcname);
++ __ao2_ref_debug(ret, 1, tag, file, line, funcname);
+ }
+
+ if (!(a->flags & F_AO2I_DONTLOCK))
+@@ -850,16 +851,16 @@
+ return ret;
+ }
+
+-void * _ao2_iterator_next(struct ao2_iterator *a)
++void *__ao2_iterator_next(struct ao2_iterator *a)
+ {
+ struct bucket_list *p = NULL;
+ void *ret = NULL;
+
+- ret = __ao2_iterator_next(a, &p);
++ ret = internal_ao2_iterator_next(a, &p);
+
+ if (p) {
+ /* inc refcount of returned object */
+- _ao2_ref(ret, 1);
++ __ao2_ref(ret, 1);
+ }
+
+ if (!(a->flags & F_AO2I_DONTLOCK))
+@@ -873,13 +874,13 @@
+ */
+ static int cd_cb(void *obj, void *arg, int flag)
+ {
+- _ao2_ref(obj, -1);
++ __ao2_ref(obj, -1);
+ return 0;
+ }
+
+ static int cd_cb_debug(void *obj, void *arg, int flag)
+ {
+- _ao2_ref_debug(obj, -1, "deref object via container destroy", __FILE__, __LINE__, __PRETTY_FUNCTION__);
++ __ao2_ref_debug(obj, -1, "deref object via container destroy", __FILE__, __LINE__, __PRETTY_FUNCTION__);
+ return 0;
+ }
+
+@@ -888,7 +889,7 @@
+ struct ao2_container *c = _c;
+ int i;
+
+- _ao2_callback(c, OBJ_UNLINK, cd_cb, NULL);
++ __ao2_callback(c, OBJ_UNLINK, cd_cb, NULL);
+
+ for (i = 0; i < c->n_buckets; i++) {
+ struct bucket_list *current;
+@@ -908,7 +909,7 @@
+ struct ao2_container *c = _c;
+ int i;
+
+- _ao2_callback_debug(c, OBJ_UNLINK, cd_cb_debug, NULL, "container_destruct_debug called", __FILE__, __LINE__, __PRETTY_FUNCTION__);
++ __ao2_callback_debug(c, OBJ_UNLINK, cd_cb_debug, NULL, "container_destruct_debug called", __FILE__, __LINE__, __PRETTY_FUNCTION__);
+
+ for (i = 0; i < c->n_buckets; i++) {
+ struct bucket_list *current;
+@@ -926,10 +927,10 @@
+ #ifdef AO2_DEBUG
+ static int print_cb(void *obj, void *arg, int flag)
+ {
+- int *fd = arg;
++ struct ast_cli_args *a = (struct ast_cli_args *) arg;
+ char *s = (char *)obj;
+
+- ast_cli(*fd, "string <%s>\n", s);
++ ast_cli(a->fd, "string <%s>\n", s);
+ return 0;
+ }
+
+@@ -1016,7 +1017,7 @@
+ ao2_t_ref(obj, -1, "test");
+ }
+ ast_cli(a->fd, "testing callbacks\n");
+- ao2_t_callback(c1, 0, print_cb, &a->fd, "test callback");
++ ao2_t_callback(c1, 0, print_cb, a, "test callback");
+ ast_cli(a->fd, "testing iterators, remove every second object\n");
+ {
+ struct ao2_iterator ai;
+@@ -1037,7 +1038,7 @@
+ }
+ }
+ ast_cli(a->fd, "testing callbacks again\n");
+- ao2_t_callback(c1, 0, print_cb, &a->fd, "test callback");
++ ao2_t_callback(c1, 0, print_cb, a, "test callback");
+
+ ast_verbose("now you should see an error message:\n");
+ ao2_t_ref(&i, -1, ""); /* i is not a valid object so we print an error here */
+Index: main/asterisk.exports
+===================================================================
+--- a/main/asterisk.exports (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/main/asterisk.exports (.../trunk) (revision 202568)
+@@ -0,0 +1,33 @@
++{
++ global:
++ ast_*;
++ _ast_*;
++ __ast_*;
++ pbx_*;
++ astman_*;
++ ao2_*;
++ __ao2_*;
++ option_debug;
++ option_verbose;
++ dahdi_chan_name;
++ dahdi_chan_name_len;
++ dahdi_chan_mode;
++ callerid_*;
++ cid_di;
++ cid_dr;
++ clidsb;
++ MD5*;
++ sched_*;
++ io_*;
++ jb_*;
++ aes_*;
++ config_*;
++ tdd_*;
++ term_*;
++ channelreloadreason2txt;
++ devstate2str;
++ __manager_event;
++ dialed_interface_info;
++ local:
++ *;
++};
+
+Property changes on: main/asterisk.exports
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+
+Index: main/cli.c
+===================================================================
+--- a/main/cli.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/cli.c (.../trunk) (revision 202568)
+@@ -74,7 +74,7 @@
+ * it is already running. */
+ AST_MUTEX_DEFINE_STATIC(permsconfiglock);
+ /*! \brief List of users and permissions. */
+-AST_RWLIST_HEAD_STATIC(cli_perms, usergroup_cli_perm);
++static AST_RWLIST_HEAD_STATIC(cli_perms, usergroup_cli_perm);
+
+ /*!
+ * \brief map a debug or verbose value to a filename
+@@ -235,8 +235,7 @@
+ c += (strlen(ast_config_AST_MODULE_DIR) + 1);
+ if (c)
+ c = ast_strdup(c);
+- if (d)
+- free(d);
++ free(d);
+
+ return c;
+ }
+@@ -365,13 +364,13 @@
+ int atleast = 0;
+ int fd = a->fd;
+ int argc = a->argc;
+- char **argv = a->argv;
+- char *argv3 = a->argv ? S_OR(a->argv[3], "") : "";
++ const char * const *argv = a->argv;
++ const char *argv3 = a->argv ? S_OR(a->argv[3], "") : "";
+ int *dst;
+ char *what;
+ struct debug_file_list *dfl;
+ struct ast_debug_file *adf;
+- char *fn;
++ const char *fn;
+
+ switch (cmd) {
+ case CLI_INIT:
+@@ -387,7 +386,7 @@
+
+ case CLI_GENERATE:
+ if (a->pos == 3 || (a->pos == 4 && !strcasecmp(a->argv[3], "atleast"))) {
+- char *pos = a->pos == 3 ? argv3 : S_OR(a->argv[4], "");
++ const char *pos = a->pos == 3 ? argv3 : S_OR(a->argv[4], "");
+ int numbermatch = (ast_strlen_zero(pos) || strchr("123456789", pos[0])) ? 0 : 21;
+ if (a->n < 21 && numbermatch == 0) {
+ return complete_number(pos, 0, 0x7fffffff, a->n);
+@@ -534,7 +533,7 @@
+ /* "module unload mod_1 [mod_2 .. mod_N]" */
+ int x;
+ int force = AST_FORCE_SOFT;
+- char *s;
++ const char *s;
+
+ switch (cmd) {
+ case CLI_INIT:
+@@ -685,7 +684,7 @@
+
+ static char *handle_modlist(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+ {
+- char *like;
++ const char *like;
+
+ switch (cmd) {
+ case CLI_INIT:
+@@ -787,8 +786,7 @@
+
+ struct ast_channel *c = NULL;
+ int numchans = 0, concise = 0, verbose = 0, count = 0;
+- int fd, argc;
+- char **argv;
++ struct ast_channel_iterator *iter = NULL;
+
+ switch (cmd) {
+ case CLI_INIT:
+@@ -807,16 +805,13 @@
+ case CLI_GENERATE:
+ return NULL;
+ }
+- fd = a->fd;
+- argc = a->argc;
+- argv = a->argv;
+
+ if (a->argc == e->args) {
+- if (!strcasecmp(argv[e->args-1],"concise"))
++ if (!strcasecmp(a->argv[e->args-1],"concise"))
+ concise = 1;
+- else if (!strcasecmp(argv[e->args-1],"verbose"))
++ else if (!strcasecmp(a->argv[e->args-1],"verbose"))
+ verbose = 1;
+- else if (!strcasecmp(argv[e->args-1],"count"))
++ else if (!strcasecmp(a->argv[e->args-1],"count"))
+ count = 1;
+ else
+ return CLI_SHOWUSAGE;
+@@ -825,16 +820,24 @@
+
+ if (!count) {
+ if (!concise && !verbose)
+- ast_cli(fd, FORMAT_STRING2, "Channel", "Location", "State", "Application(Data)");
++ ast_cli(a->fd, FORMAT_STRING2, "Channel", "Location", "State", "Application(Data)");
+ else if (verbose)
+- ast_cli(fd, VERBOSE_FORMAT_STRING2, "Channel", "Context", "Extension", "Priority", "State", "Application", "Data",
++ ast_cli(a->fd, VERBOSE_FORMAT_STRING2, "Channel", "Context", "Extension", "Priority", "State", "Application", "Data",
+ "CallerID", "Duration", "Accountcode", "BridgedTo");
+ }
+
+- while ((c = ast_channel_walk_locked(c)) != NULL) {
+- struct ast_channel *bc = ast_bridged_channel(c);
++ if (!count && !(iter = ast_channel_iterator_all_new(0))) {
++ return CLI_FAILURE;
++ }
++
++ for (; iter && (c = ast_channel_iterator_next(iter)); ast_channel_unref(c)) {
++ struct ast_channel *bc;
+ char durbuf[10] = "-";
+
++ ast_channel_lock(c);
++
++ bc = ast_bridged_channel(c);
++
+ if (!count) {
+ if ((concise || verbose) && c->cdr && !ast_tvzero(c->cdr->start)) {
+ int duration = (int)(ast_tvdiff_ms(ast_tvnow(), c->cdr->start) / 1000);
+@@ -848,7 +851,7 @@
+ }
+ }
+ if (concise) {
+- ast_cli(fd, CONCISE_FORMAT_STRING, c->name, c->context, c->exten, c->priority, ast_state2str(c->_state),
++ ast_cli(a->fd, CONCISE_FORMAT_STRING, c->name, c->context, c->exten, c->priority, ast_state2str(c->_state),
+ c->appl ? c->appl : "(None)",
+ S_OR(c->data, ""), /* XXX different from verbose ? */
+ S_OR(c->cid.cid_num, ""),
+@@ -858,7 +861,7 @@
+ bc ? bc->name : "(None)",
+ c->uniqueid);
+ } else if (verbose) {
+- ast_cli(fd, VERBOSE_FORMAT_STRING, c->name, c->context, c->exten, c->priority, ast_state2str(c->_state),
++ ast_cli(a->fd, VERBOSE_FORMAT_STRING, c->name, c->context, c->exten, c->priority, ast_state2str(c->_state),
+ c->appl ? c->appl : "(None)",
+ c->data ? S_OR(c->data, "(Empty)" ): "(None)",
+ S_OR(c->cid.cid_num, ""),
+@@ -873,23 +876,29 @@
+ snprintf(locbuf, sizeof(locbuf), "%s@%s:%d", c->exten, c->context, c->priority);
+ if (c->appl)
+ snprintf(appdata, sizeof(appdata), "%s(%s)", c->appl, S_OR(c->data, ""));
+- ast_cli(fd, FORMAT_STRING, c->name, locbuf, ast_state2str(c->_state), appdata);
++ ast_cli(a->fd, FORMAT_STRING, c->name, locbuf, ast_state2str(c->_state), appdata);
+ }
+ }
+- numchans++;
+ ast_channel_unlock(c);
+ }
++
++ if (iter) {
++ ast_channel_iterator_destroy(iter);
++ }
++
+ if (!concise) {
+- ast_cli(fd, "%d active channel%s\n", numchans, ESS(numchans));
++ numchans = ast_active_channels();
++ ast_cli(a->fd, "%d active channel%s\n", numchans, ESS(numchans));
+ if (option_maxcalls)
+- ast_cli(fd, "%d of %d max active call%s (%5.2f%% of capacity)\n",
++ ast_cli(a->fd, "%d of %d max active call%s (%5.2f%% of capacity)\n",
+ ast_active_calls(), option_maxcalls, ESS(ast_active_calls()),
+ ((double)ast_active_calls() / (double)option_maxcalls) * 100.0);
+ else
+- ast_cli(fd, "%d active call%s\n", ast_active_calls(), ESS(ast_active_calls()));
++ ast_cli(a->fd, "%d active call%s\n", ast_active_calls(), ESS(ast_active_calls()));
+
+- ast_cli(fd, "%d call%s processed\n", ast_processed_calls(), ESS(ast_processed_calls()));
++ ast_cli(a->fd, "%d call%s processed\n", ast_processed_calls(), ESS(ast_processed_calls()));
+ }
++
+ return CLI_SUCCESS;
+
+ #undef FORMAT_STRING
+@@ -914,15 +923,21 @@
+ case CLI_GENERATE:
+ return ast_complete_channels(a->line, a->word, a->pos, a->n, e->args);
+ }
+- if (a->argc != 4)
++
++ if (a->argc != 4) {
+ return CLI_SHOWUSAGE;
+- c = ast_get_channel_by_name_locked(a->argv[3]);
+- if (c) {
++ }
++
++ if ((c = ast_channel_get_by_name(a->argv[3]))) {
++ ast_channel_lock(c);
+ ast_cli(a->fd, "Requested Hangup on channel '%s'\n", c->name);
+ ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
+ ast_channel_unlock(c);
+- } else
++ c = ast_channel_unref(c);
++ } else {
+ ast_cli(a->fd, "%s is not a known channel\n", a->argv[3]);
++ }
++
+ return CLI_SUCCESS;
+ }
+
+@@ -1174,10 +1189,41 @@
+ return CLI_SUCCESS;
+ }
+
++struct channel_set_debug_args {
++ int fd;
++ int is_off;
++};
++
++static int channel_set_debug(void *obj, void *arg, void *data, int flags)
++{
++ struct ast_channel *chan = obj;
++ struct channel_set_debug_args *args = data;
++
++ ast_channel_lock(chan);
++
++ if (!(chan->fin & DEBUGCHAN_FLAG) || !(chan->fout & DEBUGCHAN_FLAG)) {
++ if (args->is_off) {
++ chan->fin &= ~DEBUGCHAN_FLAG;
++ chan->fout &= ~DEBUGCHAN_FLAG;
++ } else {
++ chan->fin |= DEBUGCHAN_FLAG;
++ chan->fout |= DEBUGCHAN_FLAG;
++ }
++ ast_cli(args->fd, "Debugging %s on channel %s\n", args->is_off ? "disabled" : "enabled",
++ chan->name);
++ }
++
++ ast_channel_unlock(chan);
++
++ return 0;
++}
++
+ static char *handle_core_set_debug_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+ {
+ struct ast_channel *c = NULL;
+- int is_all, is_off = 0;
++ struct channel_set_debug_args args = {
++ .fd = a->fd,
++ };
+
+ switch (cmd) {
+ case CLI_INIT:
+@@ -1186,72 +1232,73 @@
+ "Usage: core set debug channel <all|channel> [off]\n"
+ " Enables/disables debugging on all or on a specific channel.\n";
+ return NULL;
+-
+ case CLI_GENERATE:
+ /* XXX remember to handle the optional "off" */
+ if (a->pos != e->args)
+ return NULL;
+ return a->n == 0 ? ast_strdup("all") : ast_complete_channels(a->line, a->word, a->pos, a->n - 1, e->args);
+ }
+- /* 'core set debug channel {all|chan_id}' */
+- if (a->argc == e->args + 2) {
++
++ if (cmd == (CLI_HANDLER + 1000)) {
++ /* called from handle_nodebugchan_deprecated */
++ args.is_off = 1;
++ } else if (a->argc == e->args + 2) {
++ /* 'core set debug channel {all|chan_id}' */
+ if (!strcasecmp(a->argv[e->args + 1], "off"))
+- is_off = 1;
++ args.is_off = 1;
+ else
+ return CLI_SHOWUSAGE;
+- } else if (a->argc != e->args + 1)
++ } else if (a->argc != e->args + 1) {
+ return CLI_SHOWUSAGE;
++ }
+
+- is_all = !strcasecmp("all", a->argv[e->args]);
+- if (is_all) {
+- if (is_off) {
++ if (!strcasecmp("all", a->argv[e->args])) {
++ if (args.is_off) {
+ global_fin &= ~DEBUGCHAN_FLAG;
+ global_fout &= ~DEBUGCHAN_FLAG;
+ } else {
+ global_fin |= DEBUGCHAN_FLAG;
+ global_fout |= DEBUGCHAN_FLAG;
+ }
+- c = ast_channel_walk_locked(NULL);
++ ast_channel_callback(channel_set_debug, NULL, &args, OBJ_NODATA | OBJ_MULTIPLE);
+ } else {
+- c = ast_get_channel_by_name_locked(a->argv[e->args]);
+- if (c == NULL)
++ if ((c = ast_channel_get_by_name(a->argv[e->args]))) {
++ channel_set_debug(c, NULL, &args, 0);
++ ast_channel_unref(c);
++ } else {
+ ast_cli(a->fd, "No such channel %s\n", a->argv[e->args]);
+- }
+- while (c) {
+- if (!(c->fin & DEBUGCHAN_FLAG) || !(c->fout & DEBUGCHAN_FLAG)) {
+- if (is_off) {
+- c->fin &= ~DEBUGCHAN_FLAG;
+- c->fout &= ~DEBUGCHAN_FLAG;
+- } else {
+- c->fin |= DEBUGCHAN_FLAG;
+- c->fout |= DEBUGCHAN_FLAG;
+- }
+- ast_cli(a->fd, "Debugging %s on channel %s\n", is_off ? "disabled" : "enabled", c->name);
+ }
+- ast_channel_unlock(c);
+- if (!is_all)
+- break;
+- c = ast_channel_walk_locked(c);
+ }
+- ast_cli(a->fd, "Debugging on new channels is %s\n", is_off ? "disabled" : "enabled");
++
++ ast_cli(a->fd, "Debugging on new channels is %s\n", args.is_off ? "disabled" : "enabled");
++
+ return CLI_SUCCESS;
+ }
+
+ static char *handle_nodebugchan_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+ {
+ char *res;
+- if (cmd == CLI_HANDLER) {
+- if (a->argc != e->args + 1)
+- return CLI_SHOWUSAGE;
+- /* pretend we have an extra "off" at the end. We can do this as the array
+- * is NULL terminated so we overwrite that entry.
+- */
+- a->argv[e->args+1] = "off";
+- a->argc++;
++
++ switch (cmd) {
++ case CLI_INIT:
++ e->command = "no debug channel";
++ return NULL;
++ case CLI_HANDLER:
++ /* exit out of switch statement */
++ break;
++ default:
++ return NULL;
+ }
+- res = handle_core_set_debug_channel(e, cmd, a);
+- if (cmd == CLI_INIT)
+- e->command = "no debug channel";
++
++ if (a->argc != e->args + 1)
++ return CLI_SHOWUSAGE;
++
++ /* add a 'magic' value to the CLI_HANDLER command so that
++ * handle_core_set_debug_channel() will act as if 'off'
++ * had been specified as part of the command
++ */
++ res = handle_core_set_debug_channel(e, CLI_HANDLER + 1000, a);
++
+ return res;
+ }
+
+@@ -1279,22 +1326,29 @@
+ return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
+ }
+
+- if (a->argc != 4)
++ if (a->argc != 4) {
+ return CLI_SHOWUSAGE;
++ }
++
+ now = ast_tvnow();
+- c = ast_get_channel_by_name_locked(a->argv[3]);
+- if (!c) {
++
++ if (!(c = ast_channel_get_by_name(a->argv[3]))) {
+ ast_cli(a->fd, "%s is not a known channel\n", a->argv[3]);
+ return CLI_SUCCESS;
+ }
++
++ ast_channel_lock(c);
++
+ if (c->cdr) {
+ elapsed_seconds = now.tv_sec - c->cdr->start.tv_sec;
+ hour = elapsed_seconds / 3600;
+ min = (elapsed_seconds % 3600) / 60;
+ sec = elapsed_seconds % 60;
+ snprintf(cdrtime, sizeof(cdrtime), "%dh%dm%ds", hour, min, sec);
+- } else
++ } else {
+ strcpy(cdrtime, "N/A");
++ }
++
+ ast_cli(a->fd,
+ " -- General --\n"
+ " Name: %s\n"
+@@ -1347,17 +1401,24 @@
+ ( c-> data ? S_OR(c->data, "(Empty)") : "(None)"),
+ (ast_test_flag(c, AST_FLAG_BLOCKING) ? c->blockproc : "(Not Blocking)"));
+
+- if (pbx_builtin_serialize_variables(c, &out))
++ if (pbx_builtin_serialize_variables(c, &out)) {
+ ast_cli(a->fd," Variables:\n%s\n", ast_str_buffer(out));
+- if (c->cdr && ast_cdr_serialize_variables(c->cdr, &out, '=', '\n', 1))
++ }
++
++ if (c->cdr && ast_cdr_serialize_variables(c->cdr, &out, '=', '\n', 1)) {
+ ast_cli(a->fd," CDR Variables:\n%s\n", ast_str_buffer(out));
++ }
++
+ #ifdef CHANNEL_TRACE
+ trace_enabled = ast_channel_trace_is_enabled(c);
+ ast_cli(a->fd, " Context Trace: %s\n", trace_enabled ? "Enabled" : "Disabled");
+ if (trace_enabled && ast_channel_trace_serialize(c, &out))
+ ast_cli(a->fd, " Trace:\n%s\n", ast_str_buffer(out));
+ #endif
++
+ ast_channel_unlock(c);
++ c = ast_channel_unref(c);
++
+ return CLI_SUCCESS;
+ }
+
+@@ -1365,7 +1426,7 @@
+ * helper function to generate CLI matches from a fixed set of values.
+ * A NULL word is acceptable.
+ */
+-char *ast_cli_complete(const char *word, char *const choices[], int state)
++char *ast_cli_complete(const char *word, const char * const choices[], int state)
+ {
+ int i, which = 0, len;
+ len = ast_strlen_zero(word) ? 0 : strlen(word);
+@@ -1381,20 +1442,27 @@
+ {
+ struct ast_channel *c = NULL;
+ int which = 0;
+- int wordlen;
+ char notfound = '\0';
+ char *ret = &notfound; /* so NULL can break the loop */
++ struct ast_channel_iterator *iter;
+
+- if (pos != rpos)
++ if (pos != rpos) {
+ return NULL;
++ }
+
+- wordlen = strlen(word);
++ if (!(iter = ast_channel_iterator_by_name_new(0, word, strlen(word)))) {
++ return NULL;
++ }
+
+- while (ret == &notfound && (c = ast_channel_walk_locked(c))) {
+- if (!strncasecmp(word, c->name, wordlen) && ++which > state)
++ while (ret == &notfound && (c = ast_channel_iterator_next(iter))) {
++ if (++which > state) {
++ ast_channel_lock(c);
+ ret = ast_strdup(c->name);
+- ast_channel_unlock(c);
++ ast_channel_unlock(c);
++ }
++ ast_channel_unref(c);
+ }
++
+ return ret == &notfound ? NULL : ret;
+ }
+
+@@ -1760,15 +1828,15 @@
+ * 1 true only on complete, exact match.
+ *
+ */
+-static struct ast_cli_entry *find_cli(char *const cmds[], int match_type)
++static struct ast_cli_entry *find_cli(const char * const cmds[], int match_type)
+ {
+ int matchlen = -1; /* length of longest match so far */
+ struct ast_cli_entry *cand = NULL, *e=NULL;
+
+ while ( (e = cli_next(e)) ) {
+ /* word-by word regexp comparison */
+- char * const *src = cmds;
+- char * const *dst = e->cmda;
++ const char * const *src = cmds;
++ const char * const *dst = e->cmda;
+ int n = 0;
+ for (;; dst++, src += n) {
+ n = word_match(*src, *dst);
+@@ -1804,16 +1872,15 @@
+ return e ? e : cand;
+ }
+
+-static char *find_best(char *argv[])
++static char *find_best(const char *argv[])
+ {
+ static char cmdline[80];
+ int x;
+ /* See how close we get, then print the candidate */
+- char *myargv[AST_MAX_CMD_LEN];
+- for (x=0;x<AST_MAX_CMD_LEN;x++)
+- myargv[x]=NULL;
++ const char *myargv[AST_MAX_CMD_LEN] = { NULL, };
++
+ AST_RWLIST_RDLOCK(&helpers);
+- for (x=0;argv[x];x++) {
++ for (x = 0; argv[x]; x++) {
+ myargv[x] = argv[x];
+ if (!find_cli(myargv, -1))
+ break;
+@@ -1939,7 +2006,7 @@
+ /*! \brief helper for final part of handle_help
+ * if locked = 1, assume the list is already locked
+ */
+-static char *help1(int fd, char *match[], int locked)
++static char *help1(int fd, const char * const match[], int locked)
+ {
+ char matchstr[80] = "";
+ struct ast_cli_entry *e = NULL;
+@@ -2014,7 +2081,7 @@
+ return res;
+ }
+
+-static char *parse_args(const char *s, int *argc, char *argv[], int max, int *trailingwhitespace)
++static char *parse_args(const char *s, int *argc, const char *argv[], int max, int *trailingwhitespace)
+ {
+ char *duplicate, *cur;
+ int x = 0;
+@@ -2145,7 +2212,7 @@
+ }
+
+ /*! \brief returns true if there are more words to match */
+-static int more_words (char * const *dst)
++static int more_words (const char * const *dst)
+ {
+ int i;
+ for (i = 0; dst[i]; i++) {
+@@ -2160,7 +2227,7 @@
+ */
+ static char *__ast_cli_generator(const char *text, const char *word, int state, int lock)
+ {
+- char *argv[AST_MAX_ARGS];
++ const char *argv[AST_MAX_ARGS];
+ struct ast_cli_entry *e = NULL;
+ int x = 0, argindex, matchlen;
+ int matchnum=0;
+@@ -2248,7 +2315,7 @@
+
+ int ast_cli_command_full(int uid, int gid, int fd, const char *s)
+ {
+- char *args[AST_MAX_ARGS + 1];
++ const char *args[AST_MAX_ARGS + 1];
+ struct ast_cli_entry *e;
+ int x;
+ char *duplicate = parse_args(s, &x, args + 1, AST_MAX_ARGS, NULL);
+Index: main/ulaw.c
+===================================================================
+--- a/main/ulaw.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/ulaw.c (.../trunk) (revision 202568)
+@@ -177,7 +177,7 @@
+ #ifndef G711_NEW_ALGORITHM
+ for (i = 0;i < 256;i++) {
+ short mu,e,f,y;
+- static short etab[]={0,132,396,924,1980,4092,8316,16764};
++ static const short etab[]={0,132,396,924,1980,4092,8316,16764};
+
+ mu = 255-i;
+ e = (mu & 0x70)/16;
+Index: main/dial.c
+===================================================================
+--- a/main/dial.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/dial.c (.../trunk) (revision 202568)
+@@ -37,6 +37,7 @@
+ #include "asterisk/dial.h"
+ #include "asterisk/pbx.h"
+ #include "asterisk/musiconhold.h"
++#include "asterisk/app.h"
+
+ /*! \brief Main dialing structure. Contains global options, channels being dialed, and more! */
+ struct ast_dial {
+@@ -274,20 +275,19 @@
+ ast_channel_datastore_inherit(chan, channel->owner);
+
+ /* Copy over callerid information */
+- S_REPLACE(channel->owner->cid.cid_num, ast_strdup(chan->cid.cid_num));
+- S_REPLACE(channel->owner->cid.cid_name, ast_strdup(chan->cid.cid_name));
+- S_REPLACE(channel->owner->cid.cid_ani, ast_strdup(chan->cid.cid_ani));
+ S_REPLACE(channel->owner->cid.cid_rdnis, ast_strdup(chan->cid.cid_rdnis));
++ ast_party_redirecting_copy(&channel->owner->redirecting, &chan->redirecting);
+
++ channel->owner->cid.cid_tns = chan->cid.cid_tns;
++
++ ast_connected_line_copy_from_caller(&channel->owner->connected, &chan->cid);
++
+ ast_string_field_set(channel->owner, language, chan->language);
+ ast_string_field_set(channel->owner, accountcode, chan->accountcode);
+ channel->owner->cdrflags = chan->cdrflags;
+ if (ast_strlen_zero(channel->owner->musicclass))
+ ast_string_field_set(channel->owner, musicclass, chan->musicclass);
+
+- channel->owner->cid.cid_pres = chan->cid.cid_pres;
+- channel->owner->cid.cid_ton = chan->cid.cid_ton;
+- channel->owner->cid.cid_tns = chan->cid.cid_tns;
+ channel->owner->adsicpe = chan->adsicpe;
+ channel->owner->transfercapability = chan->transfercapability;
+ }
+@@ -429,6 +429,16 @@
+ ast_verbose (VERBOSE_PREFIX_3 "%s requested a source update, passing it to %s\n", channel->owner->name, chan->name);
+ ast_indicate(chan, AST_CONTROL_SRCUPDATE);
+ break;
++ case AST_CONTROL_CONNECTED_LINE:
++ ast_verb(3, "%s connected line has changed, passing it to %s\n", channel->owner->name, chan->name);
++ if (ast_channel_connected_line_macro(channel->owner, chan, fr, 1, 1)) {
++ ast_indicate_data(chan, AST_CONTROL_CONNECTED_LINE, fr->data.ptr, fr->datalen);
++ }
++ break;
++ case AST_CONTROL_REDIRECTING:
++ ast_verb(3, "%s redirecting info has changed, passing it to %s\n", channel->owner->name, chan->name);
++ ast_indicate_data(chan, AST_CONTROL_REDIRECTING, fr->data.ptr, fr->datalen);
++ break;
+ case AST_CONTROL_PROCEEDING:
+ ast_verb(3, "%s is proceeding, passing it to %s\n", channel->owner->name, chan->name);
+ ast_indicate(chan, AST_CONTROL_PROCEEDING);
+Index: main/logger.c
+===================================================================
+--- a/main/logger.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/logger.c (.../trunk) (revision 202568)
+@@ -54,7 +54,7 @@
+ from <syslog.h> which is included by logger.h */
+ #include <syslog.h>
+
+-static int syslog_level_map[] = {
++static const int syslog_level_map[] = {
+ LOG_DEBUG,
+ LOG_INFO, /* arbitrary equivalent of LOG_EVENT */
+ LOG_NOTICE,
+@@ -89,16 +89,15 @@
+ #else
+ #define GETTID() getpid()
+ #endif
+-
+ static char dateformat[256] = "%b %e %T"; /* Original Asterisk Format */
+
+ static char queue_log_name[256] = QUEUELOG;
+ static char exec_after_rotate[256] = "";
+
+ static int filesize_reload_needed;
+-static int global_logmask = -1;
++static unsigned int global_logmask = 0xFFFF;
+
+-enum rotatestrategy {
++static enum rotatestrategy {
+ SEQUENTIAL = 1 << 0, /* Original method - create a new file, in order */
+ ROTATE = 1 << 1, /* Rotate all files, such that the oldest file has the highest suffix */
+ TIMESTAMP = 1 << 2, /* Append the epoch timestamp onto the end of the archived file */
+@@ -106,8 +105,7 @@
+
+ static struct {
+ unsigned int queue_log:1;
+- unsigned int event_log:1;
+-} logfiles = { 1, 1 };
++} logfiles = { 1 };
+
+ static char hostname[MAXHOSTNAMELEN];
+
+@@ -118,13 +116,24 @@
+ };
+
+ struct logchannel {
+- int logmask; /* What to log to this channel */
+- int disabled; /* If this channel is disabled or not */
+- int facility; /* syslog facility */
+- enum logtypes type; /* Type of log channel */
+- FILE *fileptr; /* logfile logging file pointer */
+- char filename[256]; /* Filename */
++ /*! What to log to this channel */
++ unsigned int logmask;
++ /*! If this channel is disabled or not */
++ int disabled;
++ /*! syslog facility */
++ int facility;
++ /*! Type of log channel */
++ enum logtypes type;
++ /*! logfile logging file pointer */
++ FILE *fileptr;
++ /*! Filename */
++ char filename[PATH_MAX];
++ /*! field for linking to list */
+ AST_LIST_ENTRY(logchannel) list;
++ /*! Line number from configuration file */
++ int lineno;
++ /*! Components (levels) from last config load */
++ char components[0];
+ };
+
+ static AST_RWLIST_HEAD_STATIC(logchannels, logchannel);
+@@ -136,14 +145,17 @@
+
+ struct logmsg {
+ enum logmsgtypes type;
+- char date[256];
+ int level;
+- char file[80];
+ int line;
+- char function[80];
+ long process_id;
++ AST_DECLARE_STRING_FIELDS(
++ AST_STRING_FIELD(date);
++ AST_STRING_FIELD(file);
++ AST_STRING_FIELD(function);
++ AST_STRING_FIELD(message);
++ AST_STRING_FIELD(level_name);
++ );
+ AST_LIST_ENTRY(logmsg) list;
+- char str[0];
+ };
+
+ static AST_LIST_HEAD_STATIC(logmsgs, logmsg);
+@@ -151,29 +163,63 @@
+ static ast_cond_t logcond;
+ static int close_logger_thread;
+
+-static FILE *eventlog;
+ static FILE *qlog;
+
+-/*! \brief Logging channels used in the Asterisk logging system */
+-static char *levels[] = {
++/*! \brief Logging channels used in the Asterisk logging system
++ *
++ * The first 16 levels are reserved for system usage, and the remaining
++ * levels are reserved for usage by dynamic levels registered via
++ * ast_logger_register_level.
++ */
++
++/* Modifications to this array are protected by the rwlock in the
++ * logchannels list.
++ */
++
++static char *levels[32] = {
+ "DEBUG",
+- "EVENT",
++ "---EVENT---", /* no longer used */
+ "NOTICE",
+ "WARNING",
+ "ERROR",
+ "VERBOSE",
+- "DTMF"
++ "DTMF",
+ };
+
+ /*! \brief Colors used in the console for logging */
+-static int colors[] = {
++static const int colors[32] = {
+ COLOR_BRGREEN,
+- COLOR_BRBLUE,
++ COLOR_BRBLUE, /* no longer used */
+ COLOR_YELLOW,
+ COLOR_BRRED,
+ COLOR_RED,
+ COLOR_GREEN,
+- COLOR_BRGREEN
++ COLOR_BRGREEN,
++ 0,
++ 0,
++ 0,
++ 0,
++ 0,
++ 0,
++ 0,
++ 0,
++ 0,
++ COLOR_BRBLUE,
++ COLOR_BRBLUE,
++ COLOR_BRBLUE,
++ COLOR_BRBLUE,
++ COLOR_BRBLUE,
++ COLOR_BRBLUE,
++ COLOR_BRBLUE,
++ COLOR_BRBLUE,
++ COLOR_BRBLUE,
++ COLOR_BRBLUE,
++ COLOR_BRBLUE,
++ COLOR_BRBLUE,
++ COLOR_BRBLUE,
++ COLOR_BRBLUE,
++ COLOR_BRBLUE,
++ COLOR_BRBLUE,
+ };
+
+ AST_THREADSTORAGE(verbose_buf);
+@@ -182,30 +228,24 @@
+ AST_THREADSTORAGE(log_buf);
+ #define LOG_BUF_INIT_SIZE 256
+
+-static int make_components(const char *s, int lineno)
++static unsigned int make_components(const char *s, int lineno)
+ {
+ char *w;
+- int res = 0;
++ unsigned int res = 0;
+ char *stringp = ast_strdupa(s);
++ unsigned int x;
+
+ while ((w = strsep(&stringp, ","))) {
++ int found = 0;
++
+ w = ast_skip_blanks(w);
+- if (!strcasecmp(w, "error"))
+- res |= (1 << __LOG_ERROR);
+- else if (!strcasecmp(w, "warning"))
+- res |= (1 << __LOG_WARNING);
+- else if (!strcasecmp(w, "notice"))
+- res |= (1 << __LOG_NOTICE);
+- else if (!strcasecmp(w, "event"))
+- res |= (1 << __LOG_EVENT);
+- else if (!strcasecmp(w, "debug"))
+- res |= (1 << __LOG_DEBUG);
+- else if (!strcasecmp(w, "verbose"))
+- res |= (1 << __LOG_VERBOSE);
+- else if (!strcasecmp(w, "dtmf"))
+- res |= (1 << __LOG_DTMF);
+- else {
+- fprintf(stderr, "Logfile Warning: Unknown keyword '%s' at line %d of logger.conf\n", w, lineno);
++
++ for (x = 0; x < ARRAY_LEN(levels); x++) {
++ if (levels[x] && !strcasecmp(w, levels[x])) {
++ res |= (1 << x);
++ found = 1;
++ break;
++ }
+ }
+ }
+
+@@ -220,9 +260,12 @@
+ CODE *cptr;
+ #endif
+
+- if (ast_strlen_zero(channel) || !(chan = ast_calloc(1, sizeof(*chan))))
++ if (ast_strlen_zero(channel) || !(chan = ast_calloc(1, sizeof(*chan) + strlen(components) + 1)))
+ return NULL;
+
++ strcpy(chan->components, components);
++ chan->lineno = lineno;
++
+ if (!strcasecmp(channel, "console")) {
+ chan->type = LOGTYPE_CONSOLE;
+ } else if (!strncasecmp(channel, "syslog", 6)) {
+@@ -296,7 +339,7 @@
+ }
+
+ chan->type = LOGTYPE_SYSLOG;
+- snprintf(chan->filename, sizeof(chan->filename), "%s", channel);
++ ast_copy_string(chan->filename, channel, sizeof(chan->filename));
+ openlog("asterisk", LOG_PID, chan->facility);
+ } else {
+ if (!ast_strlen_zero(hostname)) {
+@@ -306,14 +349,14 @@
+ snprintf(chan->filename, sizeof(chan->filename), "%s/%s",
+ channel[0] != '/' ? ast_config_AST_LOG_DIR : "", channel);
+ }
+- chan->fileptr = fopen(chan->filename, "a");
+- if (!chan->fileptr) {
++ if (!(chan->fileptr = fopen(chan->filename, "a"))) {
+ /* Can't log here, since we're called with a lock */
+ fprintf(stderr, "Logger Warning: Unable to open log file '%s': %s\n", chan->filename, strerror(errno));
+ }
+ chan->type = LOGTYPE_FILE;
+ }
+- chan->logmask = make_components(components, lineno);
++ chan->logmask = make_components(chan->components, lineno);
++
+ return chan;
+ }
+
+@@ -333,10 +376,10 @@
+ AST_RWLIST_WRLOCK(&logchannels);
+ while ((chan = AST_RWLIST_REMOVE_HEAD(&logchannels, list)))
+ ast_free(chan);
++ global_logmask = 0;
+ if (!locked)
+ AST_RWLIST_UNLOCK(&logchannels);
+
+- global_logmask = 0;
+ errno = 0;
+ /* close syslog */
+ closelog();
+@@ -350,13 +393,13 @@
+ if (!(chan = ast_calloc(1, sizeof(*chan))))
+ return;
+ chan->type = LOGTYPE_CONSOLE;
+- chan->logmask = 28; /*warning,notice,error */
++ chan->logmask = __LOG_WARNING | __LOG_NOTICE | __LOG_ERROR;
+ if (!locked)
+ AST_RWLIST_WRLOCK(&logchannels);
+ AST_RWLIST_INSERT_HEAD(&logchannels, chan, list);
++ global_logmask |= chan->logmask;
+ if (!locked)
+ AST_RWLIST_UNLOCK(&logchannels);
+- global_logmask |= chan->logmask;
+ return;
+ }
+
+@@ -376,8 +419,6 @@
+ ast_copy_string(dateformat, "%b %e %T", sizeof(dateformat));
+ if ((s = ast_variable_retrieve(cfg, "general", "queue_log")))
+ logfiles.queue_log = ast_true(s);
+- if ((s = ast_variable_retrieve(cfg, "general", "event_log")))
+- logfiles.event_log = ast_true(s);
+ if ((s = ast_variable_retrieve(cfg, "general", "queue_log_name")))
+ ast_copy_string(queue_log_name, s, sizeof(queue_log_name));
+ if ((s = ast_variable_retrieve(cfg, "general", "exec_after_rotate")))
+@@ -578,7 +619,7 @@
+ if (ast_safe_system(buf) != -1) {
+ ast_log(LOG_WARNING, "error executing '%s'\n", buf);
+ }
+- ast_channel_free(c);
++ c = ast_channel_release(c);
+ }
+ return res;
+ }
+@@ -586,29 +627,13 @@
+ static int reload_logger(int rotate)
+ {
+ char old[PATH_MAX] = "";
+- int event_rotate = rotate, queue_rotate = rotate;
++ int queue_rotate = rotate;
+ struct logchannel *f;
+ int res = 0;
+ struct stat st;
+
+ AST_RWLIST_WRLOCK(&logchannels);
+
+- if (eventlog) {
+- if (rotate < 0) {
+- /* Check filesize - this one typically doesn't need an auto-rotate */
+- snprintf(old, sizeof(old), "%s/%s", ast_config_AST_LOG_DIR, EVENTLOG);
+- if (stat(old, &st) != 0 || st.st_size > 0x40000000) { /* Arbitrarily, 1 GB */
+- fclose(eventlog);
+- eventlog = NULL;
+- } else
+- event_rotate = 0;
+- } else {
+- fclose(eventlog);
+- eventlog = NULL;
+- }
+- } else
+- event_rotate = 0;
+-
+ if (qlog) {
+ if (rotate < 0) {
+ /* Check filesize - this one typically doesn't need an auto-rotate */
+@@ -644,21 +669,6 @@
+
+ init_logger_chain(1 /* locked */);
+
+- if (logfiles.event_log) {
+- snprintf(old, sizeof(old), "%s/%s", ast_config_AST_LOG_DIR, EVENTLOG);
+- if (event_rotate)
+- rotate_file(old);
+-
+- eventlog = fopen(old, "a");
+- if (eventlog) {
+- ast_log(LOG_EVENT, "Restarted Asterisk Event Logger\n");
+- ast_verb(1, "Asterisk Event Logger restarted\n");
+- } else {
+- ast_log(LOG_ERROR, "Unable to create event log: %s\n", strerror(errno));
+- res = -1;
+- }
+- }
+-
+ if (logfiles.queue_log) {
+ snprintf(old, sizeof(old), "%s/%s", ast_config_AST_LOG_DIR, queue_log_name);
+ if (queue_rotate)
+@@ -669,7 +679,6 @@
+ AST_RWLIST_UNLOCK(&logchannels);
+ ast_queue_log("NONE", "NONE", "NONE", "CONFIGRELOAD", "%s", "");
+ AST_RWLIST_WRLOCK(&logchannels);
+- ast_log(LOG_EVENT, "Restarted Asterisk Queue Logger\n");
+ ast_verb(1, "Asterisk Queue Logger restarted\n");
+ } else {
+ ast_log(LOG_ERROR, "Unable to create queue log: %s\n", strerror(errno));
+@@ -749,13 +758,17 @@
+ if (a->argc < 5)
+ return CLI_SHOWUSAGE;
+
+- for (x = 0; x <= NUMLOGLEVELS; x++) {
+- if (!strcasecmp(a->argv[3], levels[x])) {
++ AST_RWLIST_WRLOCK(&logchannels);
++
++ for (x = 0; x < ARRAY_LEN(levels); x++) {
++ if (levels[x] && !strcasecmp(a->argv[3], levels[x])) {
+ level = x;
+ break;
+ }
+ }
+
++ AST_RWLIST_UNLOCK(&logchannels);
++
+ state = ast_true(a->argv[4]) ? 1 : 0;
+
+ if (level != -1) {
+@@ -788,23 +801,16 @@
+ ast_cli(a->fd, "-------------\n");
+ AST_RWLIST_RDLOCK(&logchannels);
+ AST_RWLIST_TRAVERSE(&logchannels, chan, list) {
++ unsigned int level;
++
+ ast_cli(a->fd, FORMATL, chan->filename, chan->type == LOGTYPE_CONSOLE ? "Console" : (chan->type == LOGTYPE_SYSLOG ? "Syslog" : "File"),
+ chan->disabled ? "Disabled" : "Enabled");
+ ast_cli(a->fd, " - ");
+- if (chan->logmask & (1 << __LOG_DEBUG))
+- ast_cli(a->fd, "Debug ");
+- if (chan->logmask & (1 << __LOG_DTMF))
+- ast_cli(a->fd, "DTMF ");
+- if (chan->logmask & (1 << __LOG_VERBOSE))
+- ast_cli(a->fd, "Verbose ");
+- if (chan->logmask & (1 << __LOG_WARNING))
+- ast_cli(a->fd, "Warning ");
+- if (chan->logmask & (1 << __LOG_NOTICE))
+- ast_cli(a->fd, "Notice ");
+- if (chan->logmask & (1 << __LOG_ERROR))
+- ast_cli(a->fd, "Error ");
+- if (chan->logmask & (1 << __LOG_EVENT))
+- ast_cli(a->fd, "Event ");
++ for (level = 0; level < ARRAY_LEN(levels); level++) {
++ if (chan->logmask & (1 << level)) {
++ ast_cli(a->fd, "%s ", levels[level]);
++ }
++ }
+ ast_cli(a->fd, "\n");
+ }
+ AST_RWLIST_UNLOCK(&logchannels);
+@@ -834,7 +840,7 @@
+ return 0;
+ }
+
+-static void ast_log_vsyslog(int level, const char *file, int line, const char *function, char *str, long pid)
++static void ast_log_vsyslog(int level, const char *file, int line, const char *function, const char *str, long pid)
+ {
+ char buf[BUFSIZ];
+
+@@ -867,13 +873,6 @@
+
+ AST_RWLIST_RDLOCK(&logchannels);
+
+- if (logfiles.event_log && logmsg->level == __LOG_EVENT) {
+- fprintf(eventlog, "%s asterisk[%ld]: %s", logmsg->date, (long)getpid(), logmsg->str);
+- fflush(eventlog);
+- AST_RWLIST_UNLOCK(&logchannels);
+- return;
+- }
+-
+ if (!AST_RWLIST_EMPTY(&logchannels)) {
+ AST_RWLIST_TRAVERSE(&logchannels, chan, list) {
+ /* If the channel is disabled, then move on to the next one */
+@@ -881,7 +880,7 @@
+ continue;
+ /* Check syslog channels */
+ if (chan->type == LOGTYPE_SYSLOG && (chan->logmask & (1 << logmsg->level))) {
+- ast_log_vsyslog(logmsg->level, logmsg->file, logmsg->line, logmsg->function, logmsg->str, logmsg->process_id);
++ ast_log_vsyslog(logmsg->level, logmsg->file, logmsg->line, logmsg->function, logmsg->message, logmsg->process_id);
+ /* Console channels */
+ } else if (chan->type == LOGTYPE_CONSOLE && (chan->logmask & (1 << logmsg->level))) {
+ char linestr[128];
+@@ -896,12 +895,12 @@
+ /* Build string to print out */
+ snprintf(buf, sizeof(buf), "[%s] %s[%ld]: %s:%s %s: %s",
+ logmsg->date,
+- term_color(tmp1, levels[logmsg->level], colors[logmsg->level], 0, sizeof(tmp1)),
++ term_color(tmp1, logmsg->level_name, colors[logmsg->level], 0, sizeof(tmp1)),
+ logmsg->process_id,
+ term_color(tmp2, logmsg->file, COLOR_BRWHITE, 0, sizeof(tmp2)),
+ term_color(tmp3, linestr, COLOR_BRWHITE, 0, sizeof(tmp3)),
+ term_color(tmp4, logmsg->function, COLOR_BRWHITE, 0, sizeof(tmp4)),
+- logmsg->str);
++ logmsg->message);
+ /* Print out */
+ ast_console_puts_mutable(buf, logmsg->level);
+ /* File channels */
+@@ -914,8 +913,8 @@
+
+ /* Print out to the file */
+ res = fprintf(chan->fileptr, "[%s] %s[%ld] %s: %s",
+- logmsg->date, levels[logmsg->level], logmsg->process_id, logmsg->file, logmsg->str);
+- if (res <= 0 && !ast_strlen_zero(logmsg->str)) {
++ logmsg->date, logmsg->level_name, logmsg->process_id, logmsg->file, logmsg->message);
++ if (res <= 0 && !ast_strlen_zero(logmsg->message)) {
+ fprintf(stderr, "**** Asterisk Logging Error: ***********\n");
+ if (errno == ENOMEM || errno == ENOSPC)
+ fprintf(stderr, "Asterisk logging error: Out of disk space, can't log to log file %s\n", chan->filename);
+@@ -929,7 +928,7 @@
+ }
+ }
+ } else if (logmsg->level != __LOG_VERBOSE) {
+- fputs(logmsg->str, stdout);
++ fputs(logmsg->message, stdout);
+ }
+
+ AST_RWLIST_UNLOCK(&logchannels);
+@@ -937,7 +936,6 @@
+ /* If we need to reload because of the file size, then do so */
+ if (filesize_reload_needed) {
+ reload_logger(-1);
+- ast_log(LOG_EVENT, "Rotated Logs Per SIGXFSZ (Exceeded file size limit)\n");
+ ast_verb(1, "Rotated Logs Per SIGXFSZ (Exceeded file size limit)\n");
+ }
+
+@@ -952,7 +950,7 @@
+ /* Iterate through the list of verbosers and pass them the log message string */
+ AST_RWLIST_RDLOCK(&verbosers);
+ AST_RWLIST_TRAVERSE(&verbosers, v, list)
+- v->verboser(logmsg->str);
++ v->verboser(logmsg->message);
+ AST_RWLIST_UNLOCK(&verbosers);
+
+ return;
+@@ -1023,19 +1021,6 @@
+ /* create log channels */
+ init_logger_chain(0 /* locked */);
+
+- /* create the eventlog */
+- if (logfiles.event_log) {
+- snprintf(tmp, sizeof(tmp), "%s/%s", ast_config_AST_LOG_DIR, EVENTLOG);
+- eventlog = fopen(tmp, "a");
+- if (eventlog) {
+- ast_log(LOG_EVENT, "Started Asterisk Event Logger\n");
+- ast_verb(1, "Asterisk Event Logger Started %s\n", tmp);
+- } else {
+- ast_log(LOG_ERROR, "Unable to create event log: %s\n", strerror(errno));
+- res = -1;
+- }
+- }
+-
+ if (logfiles.queue_log) {
+ snprintf(tmp, sizeof(tmp), "%s/%s", ast_config_AST_LOG_DIR, queue_log_name);
+ qlog = fopen(tmp, "a");
+@@ -1059,11 +1044,6 @@
+
+ AST_RWLIST_WRLOCK(&logchannels);
+
+- if (eventlog) {
+- fclose(eventlog);
+- eventlog = NULL;
+- }
+-
+ if (qlog) {
+ fclose(qlog);
+ qlog = NULL;
+@@ -1094,6 +1074,7 @@
+ struct timeval now = ast_tvnow();
+ int res = 0;
+ va_list ap;
++ char datestring[256];
+
+ if (!(buf = ast_str_thread_get(&log_buf, LOG_BUF_INIT_SIZE)))
+ return;
+@@ -1139,24 +1120,26 @@
+ return;
+
+ /* Create a new logging message */
+- if (!(logmsg = ast_calloc(1, sizeof(*logmsg) + res + 1)))
++ if (!(logmsg = ast_calloc_with_stringfields(1, struct logmsg, res + 128)))
+ return;
+
+ /* Copy string over */
+- strcpy(logmsg->str, ast_str_buffer(buf));
++ ast_string_field_set(logmsg, message, ast_str_buffer(buf));
+
+ /* Set type to be normal */
+ logmsg->type = LOGMSG_NORMAL;
+
+ /* Create our date/time */
+ ast_localtime(&now, &tm, NULL);
+- ast_strftime(logmsg->date, sizeof(logmsg->date), dateformat, &tm);
++ ast_strftime(datestring, sizeof(datestring), dateformat, &tm);
++ ast_string_field_set(logmsg, date, datestring);
+
+ /* Copy over data */
+ logmsg->level = level;
+ logmsg->line = line;
+- ast_copy_string(logmsg->file, file, sizeof(logmsg->file));
+- ast_copy_string(logmsg->function, function, sizeof(logmsg->function));
++ ast_string_field_set(logmsg, level_name, levels[level]);
++ ast_string_field_set(logmsg, file, file);
++ ast_string_field_set(logmsg, function, function);
+ logmsg->process_id = (long) GETTID();
+
+ /* If the logger thread is active, append it to the tail end of the list - otherwise skip that step */
+@@ -1225,6 +1208,9 @@
+ for (i = 0; i < bt->num_frames; i++) {
+ ast_log(LOG_DEBUG, "#%d: [%p] %s\n", i, bt->addresses[i], strings[i]);
+ }
++
++ /* MALLOC_DEBUG will erroneously report an error here, unless we undef the macro. */
++#undef free
+ free(strings);
+ } else {
+ ast_debug(1, "Could not allocate memory for backtrace\n");
+@@ -1269,12 +1255,12 @@
+ if (res == AST_DYNSTR_BUILD_FAILED)
+ return;
+
+- if (!(logmsg = ast_calloc(1, sizeof(*logmsg) + res + 1)))
++ if (!(logmsg = ast_calloc_with_stringfields(1, struct logmsg, res + 128)))
+ return;
+
+- strcpy(logmsg->str, ast_str_buffer(buf));
++ ast_string_field_set(logmsg, message, ast_str_buffer(buf));
+
+- ast_log(__LOG_VERBOSE, file, line, func, "%s", logmsg->str + 1);
++ ast_log(__LOG_VERBOSE, file, line, func, "%s", logmsg->message + 1);
+
+ /* Set type */
+ logmsg->type = LOGMSG_VERBOSE;
+@@ -1294,6 +1280,7 @@
+ void __ast_verbose(const char *file, int line, const char *func, const char *fmt, ...)
+ {
+ va_list ap;
++
+ va_start(ap, fmt);
+ __ast_verbose_ap(file, line, func, fmt, ap);
+ va_end(ap);
+@@ -1305,6 +1292,7 @@
+ void ast_verbose(const char *fmt, ...)
+ {
+ va_list ap;
++
+ va_start(ap, fmt);
+ __ast_verbose_ap("", 0, "", fmt, ap);
+ va_end(ap);
+@@ -1343,3 +1331,102 @@
+
+ return cur ? 0 : -1;
+ }
++
++static void update_logchannels(void)
++{
++ struct logchannel *cur;
++
++ AST_RWLIST_WRLOCK(&logchannels);
++
++ global_logmask = 0;
++
++ AST_RWLIST_TRAVERSE(&logchannels, cur, list) {
++ cur->logmask = make_components(cur->components, cur->lineno);
++ global_logmask |= cur->logmask;
++ }
++
++ AST_RWLIST_UNLOCK(&logchannels);
++}
++
++int ast_logger_register_level(const char *name)
++{
++ unsigned int level;
++ unsigned int available = 0;
++
++ AST_RWLIST_WRLOCK(&logchannels);
++
++ for (level = 0; level < ARRAY_LEN(levels); level++) {
++ if ((level >= 16) && !available && !levels[level]) {
++ available = level;
++ continue;
++ }
++
++ if (levels[level] && !strcasecmp(levels[level], name)) {
++ ast_log(LOG_WARNING,
++ "Unable to register dynamic logger level '%s': a standard logger level uses that name.\n",
++ name);
++ AST_RWLIST_UNLOCK(&logchannels);
++
++ return -1;
++ }
++ }
++
++ if (!available) {
++ ast_log(LOG_WARNING,
++ "Unable to register dynamic logger level '%s'; maximum number of levels registered.\n",
++ name);
++ AST_RWLIST_UNLOCK(&logchannels);
++
++ return -1;
++ }
++
++ levels[available] = ast_strdup(name);
++
++ AST_RWLIST_UNLOCK(&logchannels);
++
++ ast_debug(1, "Registered dynamic logger level '%s' with index %d.\n", name, available);
++
++ update_logchannels();
++
++ return available;
++}
++
++void ast_logger_unregister_level(const char *name)
++{
++ unsigned int found = 0;
++ unsigned int x;
++
++ AST_RWLIST_WRLOCK(&logchannels);
++
++ for (x = 16; x < ARRAY_LEN(levels); x++) {
++ if (!levels[x]) {
++ continue;
++ }
++
++ if (strcasecmp(levels[x], name)) {
++ continue;
++ }
++
++ found = 1;
++ break;
++ }
++
++ if (found) {
++ /* take this level out of the global_logmask, to ensure that no new log messages
++ * will be queued for it
++ */
++
++ global_logmask &= ~(1 << x);
++
++ free(levels[x]);
++ levels[x] = NULL;
++ AST_RWLIST_UNLOCK(&logchannels);
++
++ ast_debug(1, "Unregistered dynamic logger level '%s' with index %d.\n", name, x);
++
++ update_logchannels();
++ } else {
++ AST_RWLIST_UNLOCK(&logchannels);
++ }
++}
++
+Index: main/pbx.c
+===================================================================
+--- a/main/pbx.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/pbx.c (.../trunk) (revision 202568)
+@@ -717,6 +717,24 @@
+ <ref type="application">RaiseException</ref>
+ </see-also>
+ </function>
++ <manager name="ShowDialPlan" language="en_US">
++ <synopsis>
++ La merde se produit.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Extension">
++ <para>Show a specific extension.</para>
++ </parameter>
++ <parameter name="Context">
++ <para>Show a specific context.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Show dialplan contexts and extensions. Be aware that showing the full dialplan
++ may take a lot of capacity.</para>
++ </description>
++ </manager>
+ ***/
+
+ #ifdef LOW_MEMORY
+@@ -819,11 +837,11 @@
+ {
+ int is_pattern; /* the pattern started with '_' */
+ int deleted; /* if this is set, then... don't return it */
+- char *x; /* the pattern itself-- matches a single char */
+ int specificity; /* simply the strlen of x, or 10 for X, 9 for Z, and 8 for N; and '.' and '!' will add 11 ? */
+ struct match_char *alt_char;
+ struct match_char *next_char;
+ struct ast_exten *exten; /* attached to last char of a pattern for exten */
++ char x[1]; /* the pattern itself-- matches a single char */
+ };
+
+ struct scoreboard /* make sure all fields are 0 before calling new_find_extension */
+@@ -855,7 +873,7 @@
+
+ /*! \brief ast_app: A registered application */
+ struct ast_app {
+- int (*execute)(struct ast_channel *chan, void *data);
++ int (*execute)(struct ast_channel *chan, const char *data);
+ AST_DECLARE_STRING_FIELDS(
+ AST_STRING_FIELD(synopsis); /*!< Synopsis text for 'show applications' */
+ AST_STRING_FIELD(description); /*!< Description (help text) for 'show application &lt;name&gt;' */
+@@ -863,7 +881,9 @@
+ AST_STRING_FIELD(arguments); /*!< Arguments description */
+ AST_STRING_FIELD(seealso); /*!< See also */
+ );
+- enum ast_doc_src docsrc;/*!< Where the documentation come from. */
++#ifdef AST_XML_DOCS
++ enum ast_doc_src docsrc; /*!< Where the documentation come from. */
++#endif
+ AST_RWLIST_ENTRY(ast_app) list; /*!< Next app in list */
+ struct ast_module *module; /*!< Module this app belongs to */
+ char name[0]; /*!< Name of the application */
+@@ -919,38 +939,38 @@
+ int priority; /*!< Priority associated with this exception */
+ };
+
+-static int pbx_builtin_answer(struct ast_channel *, void *);
+-static int pbx_builtin_goto(struct ast_channel *, void *);
+-static int pbx_builtin_hangup(struct ast_channel *, void *);
+-static int pbx_builtin_background(struct ast_channel *, void *);
+-static int pbx_builtin_wait(struct ast_channel *, void *);
+-static int pbx_builtin_waitexten(struct ast_channel *, void *);
+-static int pbx_builtin_incomplete(struct ast_channel *, void *);
+-static int pbx_builtin_resetcdr(struct ast_channel *, void *);
+-static int pbx_builtin_setamaflags(struct ast_channel *, void *);
+-static int pbx_builtin_ringing(struct ast_channel *, void *);
+-static int pbx_builtin_proceeding(struct ast_channel *, void *);
+-static int pbx_builtin_progress(struct ast_channel *, void *);
+-static int pbx_builtin_congestion(struct ast_channel *, void *);
+-static int pbx_builtin_busy(struct ast_channel *, void *);
+-static int pbx_builtin_noop(struct ast_channel *, void *);
+-static int pbx_builtin_gotoif(struct ast_channel *, void *);
+-static int pbx_builtin_gotoiftime(struct ast_channel *, void *);
+-static int pbx_builtin_execiftime(struct ast_channel *, void *);
+-static int pbx_builtin_saynumber(struct ast_channel *, void *);
+-static int pbx_builtin_saydigits(struct ast_channel *, void *);
+-static int pbx_builtin_saycharacters(struct ast_channel *, void *);
+-static int pbx_builtin_sayphonetic(struct ast_channel *, void *);
++static int pbx_builtin_answer(struct ast_channel *, const char *);
++static int pbx_builtin_goto(struct ast_channel *, const char *);
++static int pbx_builtin_hangup(struct ast_channel *, const char *);
++static int pbx_builtin_background(struct ast_channel *, const char *);
++static int pbx_builtin_wait(struct ast_channel *, const char *);
++static int pbx_builtin_waitexten(struct ast_channel *, const char *);
++static int pbx_builtin_incomplete(struct ast_channel *, const char *);
++static int pbx_builtin_resetcdr(struct ast_channel *, const char *);
++static int pbx_builtin_setamaflags(struct ast_channel *, const char *);
++static int pbx_builtin_ringing(struct ast_channel *, const char *);
++static int pbx_builtin_proceeding(struct ast_channel *, const char *);
++static int pbx_builtin_progress(struct ast_channel *, const char *);
++static int pbx_builtin_congestion(struct ast_channel *, const char *);
++static int pbx_builtin_busy(struct ast_channel *, const char *);
++static int pbx_builtin_noop(struct ast_channel *, const char *);
++static int pbx_builtin_gotoif(struct ast_channel *, const char *);
++static int pbx_builtin_gotoiftime(struct ast_channel *, const char *);
++static int pbx_builtin_execiftime(struct ast_channel *, const char *);
++static int pbx_builtin_saynumber(struct ast_channel *, const char *);
++static int pbx_builtin_saydigits(struct ast_channel *, const char *);
++static int pbx_builtin_saycharacters(struct ast_channel *, const char *);
++static int pbx_builtin_sayphonetic(struct ast_channel *, const char *);
+ static int matchcid(const char *cidpattern, const char *callerid);
+-int pbx_builtin_setvar(struct ast_channel *, void *);
+-void log_match_char_tree(struct match_char *node, char *prefix); /* for use anywhere */
+-int pbx_builtin_setvar_multiple(struct ast_channel *, void *);
+-static int pbx_builtin_importvar(struct ast_channel *, void *);
++#ifdef NEED_DEBUG
++static void log_match_char_tree(struct match_char *node, char *prefix); /* for use anywhere */
++#endif
++static int pbx_builtin_importvar(struct ast_channel *, const char *);
+ static void set_ext_pri(struct ast_channel *c, const char *exten, int pri);
+ static void new_find_extension(const char *str, struct scoreboard *score,
+ struct match_char *tree, int length, int spec, const char *callerid,
+ const char *label, enum ext_match_t action);
+-static struct match_char *already_in_tree(struct match_char *current, char *pat);
++static struct match_char *already_in_tree(struct match_char *current, char *pat, int is_pattern);
+ static struct match_char *add_exten_to_pattern_tree(struct ast_context *con,
+ struct ast_exten *e1, int findonly);
+ static struct match_char *add_pattern_node(struct ast_context *con,
+@@ -959,11 +979,9 @@
+ static void create_match_char_tree(struct ast_context *con);
+ static struct ast_exten *get_canmatch_exten(struct match_char *node);
+ static void destroy_pattern_tree(struct match_char *pattern_tree);
+-int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b);
+ static int hashtab_compare_extens(const void *ha_a, const void *ah_b);
+ static int hashtab_compare_exten_numbers(const void *ah_a, const void *ah_b);
+ static int hashtab_compare_exten_labels(const void *ah_a, const void *ah_b);
+-unsigned int ast_hashtab_hash_contexts(const void *obj);
+ static unsigned int hashtab_hash_extens(const void *obj);
+ static unsigned int hashtab_hash_priority(const void *obj);
+ static unsigned int hashtab_hash_labels(const void *obj);
+@@ -1083,7 +1101,7 @@
+ /*! \brief Declaration of builtin applications */
+ static struct pbx_builtin {
+ char name[AST_MAX_APP];
+- int (*execute)(struct ast_channel *chan, void *data);
++ int (*execute)(struct ast_channel *chan, const char *data);
+ } builtins[] =
+ {
+ /* These applications are built into the PBX core and do not
+@@ -1320,9 +1338,9 @@
+ /*
+ \note This function is special. It saves the stack so that no matter
+ how many times it is called, it returns to the same place */
+-int pbx_exec(struct ast_channel *c, /*!< Channel */
+- struct ast_app *app, /*!< Application */
+- void *data) /*!< Data for execution */
++int pbx_exec(struct ast_channel *c, /*!< Channel */
++ struct ast_app *app, /*!< Application */
++ const char *data) /*!< Data for execution */
+ {
+ int res;
+ struct ast_module_user *u = NULL;
+@@ -1492,14 +1510,15 @@
+ #endif
+ }
+
+-void log_match_char_tree(struct match_char *node, char *prefix)
++#ifdef NEED_DEBUG
++static void log_match_char_tree(struct match_char *node, char *prefix)
+ {
+ char extenstr[40];
+ struct ast_str *my_prefix = ast_str_alloca(1024);
+
+ extenstr[0] = '\0';
+
+- if (node && node->exten && node->exten)
++ if (node && node->exten)
+ snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten);
+
+ if (strlen(node->x) > 1) {
+@@ -1520,6 +1539,7 @@
+ if (node->alt_char)
+ log_match_char_tree(node->alt_char, prefix);
+ }
++#endif
+
+ static void cli_match_char_tree(struct match_char *node, char *prefix, int fd)
+ {
+@@ -1528,7 +1548,7 @@
+
+ extenstr[0] = '\0';
+
+- if (node && node->exten && node->exten)
++ if (node && node->exten)
+ snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten);
+
+ if (strlen(node->x) > 1) {
+@@ -1603,6 +1623,7 @@
+ return e3;
+ }
+ }
++
+ return NULL;
+ }
+
+@@ -1638,117 +1659,123 @@
+ ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree NULL action=%s\n", str, action2str(action));
+ #endif
+ for (p = tree; p; p = p->alt_char) {
+- if (p->x[0] == 'N') {
+- if (p->x[1] == 0 && *str >= '2' && *str <= '9' ) {
+-#define NEW_MATCHER_CHK_MATCH \
+- if (p->exten && !(*(str + 1))) { /* if a shorter pattern matches along the way, might as well report it */ \
+- if (action == E_MATCH || action == E_SPAWN || action == E_FINDLABEL) { /* if in CANMATCH/MATCHMORE, don't let matches get in the way */ \
+- update_scoreboard(score, length + 1, spec + p->specificity, p->exten, 0, callerid, p->deleted, p); \
+- if (!p->deleted) { \
+- if (action == E_FINDLABEL) { \
+- if (ast_hashtab_lookup(score->exten->peer_label_table, &pattern)) { \
+- ast_debug(4, "Found label in preferred extension\n"); \
+- return; \
+- } \
+- } else { \
+- ast_debug(4,"returning an exact match-- first found-- %s\n", p->exten->exten); \
+- return; /* the first match, by definition, will be the best, because of the sorted tree */ \
+- } \
+- } \
+- } \
++ if (p->is_pattern) {
++ if (p->x[0] == 'N') {
++ if (p->x[1] == 0 && *str >= '2' && *str <= '9' ) {
++#define NEW_MATCHER_CHK_MATCH \
++ if (p->exten && !(*(str + 1))) { /* if a shorter pattern matches along the way, might as well report it */ \
++ if (action == E_MATCH || action == E_SPAWN || action == E_FINDLABEL) { /* if in CANMATCH/MATCHMORE, don't let matches get in the way */ \
++ update_scoreboard(score, length + 1, spec + p->specificity, p->exten, 0, callerid, p->deleted, p); \
++ if (!p->deleted) { \
++ if (action == E_FINDLABEL) { \
++ if (ast_hashtab_lookup(score->exten->peer_label_table, &pattern)) { \
++ ast_debug(4, "Found label in preferred extension\n"); \
++ return; \
++ } \
++ } else { \
++ ast_debug(4, "returning an exact match-- first found-- %s\n", p->exten->exten); \
++ return; /* the first match, by definition, will be the best, because of the sorted tree */ \
++ } \
++ } \
++ } \
++ }
++
++#define NEW_MATCHER_RECURSE \
++ if (p->next_char && (*(str + 1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0) \
++ || p->next_char->x[0] == '!')) { \
++ if (*(str + 1) || p->next_char->x[0] == '!') { \
++ new_find_extension(str + 1, score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \
++ if (score->exten) { \
++ ast_debug(4 ,"returning an exact match-- %s\n", score->exten->exten); \
++ return; /* the first match is all we need */ \
++ } \
++ } else { \
++ new_find_extension("/", score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \
++ if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { \
++ ast_debug(4,"returning a (can/more) match--- %s\n", score->exten ? score->exten->exten : \
++ "NULL"); \
++ return; /* the first match is all we need */ \
++ } \
++ } \
++ } else if (p->next_char && !*(str + 1)) { \
++ score->canmatch = 1; \
++ score->canmatch_exten = get_canmatch_exten(p); \
++ if (action == E_CANMATCH || action == E_MATCHMORE) { \
++ ast_debug(4, "returning a canmatch/matchmore--- str=%s\n", str); \
++ return; \
++ } \
++ }
++
++ NEW_MATCHER_CHK_MATCH;
++ NEW_MATCHER_RECURSE;
+ }
+-
+-#define NEW_MATCHER_RECURSE \
+- if (p->next_char && ( *(str + 1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0) \
+- || p->next_char->x[0] == '!')) { \
+- if (*(str + 1) || p->next_char->x[0] == '!') { \
+- new_find_extension(str + 1, score, p->next_char, length + 1, spec+p->specificity, callerid, label, action); \
+- if (score->exten) { \
+- ast_debug(4, "returning an exact match-- %s\n", score->exten->exten); \
+- return; /* the first match is all we need */ \
+- } \
+- } else { \
+- new_find_extension("/", score, p->next_char, length + 1, spec+p->specificity, callerid, label, action); \
+- if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { \
+- ast_debug(4,"returning a (can/more) match--- %s\n", score->exten ? score->exten->exten : \
+- "NULL"); \
+- return; /* the first match is all we need */ \
+- } \
+- } \
+- } else if (p->next_char && !*(str + 1)) { \
+- score->canmatch = 1; \
+- score->canmatch_exten = get_canmatch_exten(p); \
+- if (action == E_CANMATCH || action == E_MATCHMORE) { \
+- ast_debug(4, "returning a canmatch/matchmore--- str=%s\n", str); \
+- return; \
+- } \
++ } else if (p->x[0] == 'Z') {
++ if (p->x[1] == 0 && *str >= '1' && *str <= '9' ) {
++ NEW_MATCHER_CHK_MATCH;
++ NEW_MATCHER_RECURSE;
+ }
+-
+- NEW_MATCHER_CHK_MATCH;
+- NEW_MATCHER_RECURSE;
+- }
+- } else if (p->x[0] == 'Z') {
+- if (p->x[1] == 0 && *str >= '1' && *str <= '9' ) {
+- NEW_MATCHER_CHK_MATCH;
+- NEW_MATCHER_RECURSE;
+- }
+- } else if (p->x[0] == 'X') {
+- if (p->x[1] == 0 && *str >= '0' && *str <= '9' ) {
+- NEW_MATCHER_CHK_MATCH;
+- NEW_MATCHER_RECURSE;
+- }
+- } else if (p->x[0] == '.' && p->x[1] == 0) {
+- /* how many chars will the . match against? */
+- int i = 0;
+- const char *str2 = str;
+- while (*str2 && *str2 != '/') {
+- str2++;
+- i++;
+- }
+- if (p->exten && *str2 != '/') {
+- update_scoreboard(score, length+i, spec+(i*p->specificity), p->exten, '.', callerid, p->deleted, p);
+- if (score->exten) {
+- ast_debug(4,"return because scoreboard has a match with '/'--- %s\n", score->exten->exten);
+- return; /* the first match is all we need */
++ } else if (p->x[0] == 'X') {
++ if (p->x[1] == 0 && *str >= '0' && *str <= '9' ) {
++ NEW_MATCHER_CHK_MATCH;
++ NEW_MATCHER_RECURSE;
+ }
+- }
+- if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
+- new_find_extension("/", score, p->next_char, length+i, spec+(p->specificity*i), callerid, label, action);
+- if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
+- ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set--- %s\n", score->exten ? score->exten->exten : "NULL");
+- return; /* the first match is all we need */
++ } else if (p->x[0] == '.' && p->x[1] == 0) {
++ /* how many chars will the . match against? */
++ int i = 0;
++ const char *str2 = str;
++ while (*str2 && *str2 != '/') {
++ str2++;
++ i++;
+ }
+- }
+- } else if (p->x[0] == '!' && p->x[1] == 0) {
+- /* how many chars will the . match against? */
+- int i = 1;
+- const char *str2 = str;
+- while (*str2 && *str2 != '/') {
+- str2++;
+- i++;
+- }
+- if (p->exten && *str2 != '/') {
+- update_scoreboard(score, length + 1, spec+(p->specificity * i), p->exten, '!', callerid, p->deleted, p);
+- if (score->exten) {
+- ast_debug(4, "return because scoreboard has a '!' match--- %s\n", score->exten->exten);
+- return; /* the first match is all we need */
++ if (p->exten && *str2 != '/') {
++ update_scoreboard(score, length + i, spec + (i * p->specificity), p->exten, '.', callerid, p->deleted, p);
++ if (score->exten) {
++ ast_debug(4,"return because scoreboard has a match with '/'--- %s\n", score->exten->exten);
++ return; /* the first match is all we need */
++ }
+ }
+- }
+- if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
+- new_find_extension("/", score, p->next_char, length + i, spec + (p->specificity * i), callerid, label, action);
+- if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
+- ast_debug(4,"return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/' and '!'--- %s\n", score->exten ? score->exten->exten : "NULL");
+- return; /* the first match is all we need */
++ if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
++ new_find_extension("/", score, p->next_char, length + i, spec+(p->specificity*i), callerid, label, action);
++ if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
++ ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set--- %s\n", score->exten ? score->exten->exten : "NULL");
++ return; /* the first match is all we need */
++ }
+ }
+- }
+- } else if (p->x[0] == '/' && p->x[1] == 0) {
+- /* the pattern in the tree includes the cid match! */
+- if (p->next_char && callerid && *callerid) {
+- new_find_extension(callerid, score, p->next_char, length+1, spec, callerid, label, action);
+- if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
+- ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/'--- %s\n", score->exten ? score->exten->exten : "NULL");
+- return; /* the first match is all we need */
++ } else if (p->x[0] == '!' && p->x[1] == 0) {
++ /* how many chars will the . match against? */
++ int i = 1;
++ const char *str2 = str;
++ while (*str2 && *str2 != '/') {
++ str2++;
++ i++;
+ }
++ if (p->exten && *str2 != '/') {
++ update_scoreboard(score, length + 1, spec + (p->specificity * i), p->exten, '!', callerid, p->deleted, p);
++ if (score->exten) {
++ ast_debug(4, "return because scoreboard has a '!' match--- %s\n", score->exten->exten);
++ return; /* the first match is all we need */
++ }
++ }
++ if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
++ new_find_extension("/", score, p->next_char, length + i, spec + (p->specificity * i), callerid, label, action);
++ if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
++ ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/' and '!'--- %s\n", score->exten ? score->exten->exten : "NULL");
++ return; /* the first match is all we need */
++ }
++ }
++ } else if (p->x[0] == '/' && p->x[1] == 0) {
++ /* the pattern in the tree includes the cid match! */
++ if (p->next_char && callerid && *callerid) {
++ new_find_extension(callerid, score, p->next_char, length + 1, spec, callerid, label, action);
++ if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
++ ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/'--- %s\n", score->exten ? score->exten->exten : "NULL");
++ return; /* the first match is all we need */
++ }
++ }
++ } else if (strchr(p->x, *str)) {
++ ast_debug(4, "Nothing strange about this match\n");
++ NEW_MATCHER_CHK_MATCH;
++ NEW_MATCHER_RECURSE;
+ }
+ } else if (strchr(p->x, *str)) {
+ ast_debug(4, "Nothing strange about this match\n");
+@@ -1776,7 +1803,7 @@
+ * where the "|" (or) operator is allowed, I guess, in a way, sort of...
+ */
+
+-static struct match_char *already_in_tree(struct match_char *current, char *pat)
++static struct match_char *already_in_tree(struct match_char *current, char *pat, int is_pattern)
+ {
+ struct match_char *t;
+
+@@ -1785,7 +1812,7 @@
+ }
+
+ for (t = current; t; t = t->alt_char) {
+- if (!strcmp(pat, t->x)) { /* uh, we may want to sort exploded [] contents to make matching easy */
++ if (is_pattern == t->is_pattern && !strcmp(pat, t->x)) {/* uh, we may want to sort exploded [] contents to make matching easy */
+ return t;
+ }
+ }
+@@ -1805,42 +1832,44 @@
+ sorted in increasing value as you go to the leaves */
+ if (!(*parent_ptr)) {
+ *parent_ptr = node;
+- } else {
+- if ((*parent_ptr)->specificity > node->specificity) {
+- /* insert at head */
+- node->alt_char = (*parent_ptr);
+- *parent_ptr = node;
+- } else {
+- lcurr = *parent_ptr;
+- for (curr = (*parent_ptr)->alt_char; curr; curr = curr->alt_char) {
+- if (curr->specificity > node->specificity) {
+- node->alt_char = curr;
+- lcurr->alt_char = node;
+- break;
+- }
+- lcurr = curr;
+- }
+- if (!curr) {
+- lcurr->alt_char = node;
+- }
++ return;
++ }
++
++ if ((*parent_ptr)->specificity > node->specificity) {
++ /* insert at head */
++ node->alt_char = (*parent_ptr);
++ *parent_ptr = node;
++ return;
++ }
++
++ lcurr = *parent_ptr;
++ for (curr = (*parent_ptr)->alt_char; curr; curr = curr->alt_char) {
++ if (curr->specificity > node->specificity) {
++ node->alt_char = curr;
++ lcurr->alt_char = node;
++ break;
+ }
++ lcurr = curr;
+ }
+-}
+
++ if (!curr) {
++ lcurr->alt_char = node;
++ }
+
++}
+
+ static struct match_char *add_pattern_node(struct ast_context *con, struct match_char *current, char *pattern, int is_pattern, int already, int specificity, struct match_char **nextcharptr)
+ {
+ struct match_char *m;
+-
+- if (!(m = ast_calloc(1, sizeof(*m)))) {
++
++ if (!(m = ast_calloc(1, sizeof(*m) + strlen(pattern)))) {
+ return NULL;
+ }
+
+- if (!(m->x = ast_strdup(pattern))) {
+- ast_free(m);
+- return NULL;
+- }
++ /* strcpy is safe here since we know its size and have allocated
++ * just enough space for when we allocated m
++ */
++ strcpy(m->x, pattern);
+
+ /* the specificity scores are the same as used in the old
+ pattern matcher. */
+@@ -1903,25 +1932,25 @@
+ pattern = 1;
+ s1++;
+ }
+- while( *s1 ) {
+- if (pattern && *s1 == '[' && *(s1-1) != '\\') {
++ while (*s1) {
++ if (pattern && *s1 == '[' && *(s1 - 1) != '\\') {
+ char *s2 = buf;
+ buf[0] = 0;
+ s1++; /* get past the '[' */
+- while (*s1 != ']' && *(s1 - 1) != '\\' ) {
++ while (*s1 != ']' && *(s1 - 1) != '\\') {
+ if (*s1 == '\\') {
+ if (*(s1 + 1) == ']') {
+ *s2++ = ']';
+- s1++; s1++;
++ s1 += 2;
+ } else if (*(s1 + 1) == '\\') {
+ *s2++ = '\\';
+- s1++; s1++;
++ s1 += 2;
+ } else if (*(s1 + 1) == '-') {
+ *s2++ = '-';
+- s1++; s1++;
++ s1 += 2;
+ } else if (*(s1 + 1) == '[') {
+ *s2++ = '[';
+- s1++; s1++;
++ s1 += 2;
+ }
+ } else if (*s1 == '-') { /* remember to add some error checking to all this! */
+ char s3 = *(s1 - 1);
+@@ -1929,7 +1958,7 @@
+ for (s3++; s3 <= s4; s3++) {
+ *s2++ = s3;
+ }
+- s1++; s1++;
++ s1 += 2;
+ } else if (*s1 == '\0') {
+ ast_log(LOG_WARNING, "A matching ']' was not found for '[' in pattern string '%s'\n", extenbuf);
+ break;
+@@ -1945,18 +1974,18 @@
+ specif <<= 8;
+ specif += buf[0];
+ } else {
+-
+ if (*s1 == '\\') {
+ s1++;
+ buf[0] = *s1;
+ } else {
+ if (pattern) {
+- if (*s1 == 'n') /* make sure n,x,z patterns are canonicalized to N,X,Z */
++ if (*s1 == 'n') { /* make sure n,x,z patterns are canonicalized to N,X,Z */
+ *s1 = 'N';
+- else if (*s1 == 'x')
++ } else if (*s1 == 'x') {
+ *s1 = 'X';
+- else if (*s1 == 'z')
++ } else if (*s1 == 'z') {
+ *s1 = 'Z';
++ }
+ }
+ buf[0] = *s1;
+ }
+@@ -1964,9 +1993,12 @@
+ specif = 1;
+ }
+ m2 = 0;
+- if (already && (m2 = already_in_tree(m1,buf)) && m2->next_char) {
++ if (already && (m2 = already_in_tree(m1, buf, pattern)) && m2->next_char) {
+ if (!(*(s1 + 1))) { /* if this is the end of the pattern, but not the end of the tree, then mark this node with the exten...
+- * a shorter pattern might win if the longer one doesn't match */
++ a shorter pattern might win if the longer one doesn't match */
++ if (m2->exten) {
++ ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n", m2->exten->exten, e1->exten);
++ }
+ m2->exten = e1;
+ m2->deleted = 0;
+ }
+@@ -1982,15 +2014,22 @@
+ if (findonly) {
+ return m1;
+ }
+- m1 = add_pattern_node(con, m1, buf, pattern, already,specif, m0); /* m1 is the node just added */
++ if (!(m1 = add_pattern_node(con, m1, buf, pattern, already,specif, m0))) { /* m1 is the node just added */
++ return NULL;
++ }
+ m0 = &m1->next_char;
+ }
+-
+ if (!(*(s1 + 1))) {
++ if (m2 && m2->exten) {
++ ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n", m2->exten->exten, e1->exten);
++ }
+ m1->deleted = 0;
+ m1->exten = e1;
+ }
+
++ /* The 'already' variable is a mini-optimization designed to make it so that we
++ * don't have to call already_in_tree when we know it will return false.
++ */
+ already = 0;
+ }
+ s1++; /* advance to next char */
+@@ -2005,7 +2044,7 @@
+ #ifdef NEED_DEBUG
+ int biggest_bucket, resizes, numobjs, numbucks;
+
+- ast_log(LOG_DEBUG,"Creating Extension Trie for context %s\n", con->name);
++ ast_log(LOG_DEBUG,"Creating Extension Trie for context %s(%p)\n", con->name, con);
+ ast_hashtab_get_stats(con->root_table, &biggest_bucket, &resizes, &numobjs, &numbucks);
+ ast_log(LOG_DEBUG,"This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n",
+ numobjs, numbucks, biggest_bucket, resizes);
+@@ -2034,10 +2073,7 @@
+ pattern_tree->next_char = 0;
+ }
+ pattern_tree->exten = 0; /* never hurts to make sure there's no pointers laying around */
+- if (pattern_tree->x) {
+- free(pattern_tree->x);
+- }
+- free(pattern_tree);
++ ast_free(pattern_tree);
+ }
+
+ /*
+@@ -2496,14 +2532,6 @@
+ ast_copy_string(item.name, context, sizeof(item.name));
+
+ tmp = ast_hashtab_lookup(contexts_table, &item);
+-#ifdef NOTNOW
+- tmp = NULL;
+- while ((tmp = ast_walk_contexts(tmp)) ) {
+- if (!strcmp(tmp->name, context)) {
+- break;
+- }
+- }
+-#endif
+ if (!tmp) {
+ return NULL;
+ }
+@@ -2686,19 +2714,6 @@
+ } else {
+ e = ast_hashtab_lookup(eroot->peer_table, &pattern);
+ }
+-#ifdef NOTNOW
+- while ( (e = ast_walk_extension_priorities(eroot, e)) ) {
+- /* Match label or priority */
+- if (action == E_FINDLABEL) {
+- if (q->status < STATUS_NO_LABEL)
+- q->status = STATUS_NO_LABEL;
+- if (label && e->label && !strcmp(label, e->label))
+- break; /* found it */
+- } else if (e->priority == priority) {
+- break; /* found it */
+- } /* else keep searching */
+- }
+-#endif
+ if (e) { /* found a valid match */
+ q->status = STATUS_SUCCESS;
+ q->foundcontext = context;
+@@ -2843,6 +2858,54 @@
+ return ret;
+ }
+
++static const char *ast_str_substring(struct ast_str *value, int offset, int length)
++{
++ int lr; /* length of the input string after the copy */
++
++ lr = ast_str_strlen(value); /* compute length after copy, so we never go out of the workspace */
++
++ /* Quick check if no need to do anything */
++ if (offset == 0 && length >= lr) /* take the whole string */
++ return ast_str_buffer(value);
++
++ if (offset < 0) { /* translate negative offset into positive ones */
++ offset = lr + offset;
++ if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
++ offset = 0;
++ }
++
++ /* too large offset result in empty string so we know what to return */
++ if (offset >= lr) {
++ ast_str_reset(value);
++ return ast_str_buffer(value);
++ }
++
++ if (offset > 0) {
++ /* Go ahead and chop off the beginning */
++ memcpy(ast_str_buffer(value), ast_str_buffer(value) + offset, ast_str_strlen(value) - offset + 1);
++ lr -= offset;
++ }
++
++ if (length >= 0 && length < lr) { /* truncate if necessary */
++ char *tmp = ast_str_buffer(value);
++ tmp[length] = '\0';
++ ast_str_update(value);
++ } else if (length < 0) {
++ if (lr > -length) { /* After we remove from the front and from the rear, is there anything left? */
++ char *tmp = ast_str_buffer(value);
++ tmp[lr + length] = '\0';
++ ast_str_update(value);
++ } else {
++ ast_str_reset(value);
++ }
++ } else {
++ /* Nothing to do, but update the buffer length */
++ ast_str_update(value);
++ }
++
++ return ast_str_buffer(value);
++}
++
+ /*! \brief Support for Asterisk built-in variables in the dialplan
+
+ \note See also
+@@ -2851,8 +2914,20 @@
+ */
+ void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
+ {
++ struct ast_str *str = ast_str_create(16);
++ const char *cret;
++
++ cret = ast_str_retrieve_variable(&str, 0, c, headp, var);
++ ast_copy_string(workspace, ast_str_buffer(str), workspacelen);
++ *ret = cret ? workspace : NULL;
++ ast_free(str);
++}
++
++const char *ast_str_retrieve_variable(struct ast_str **str, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *var)
++{
+ const char not_found = '\0';
+ char *tmpvar;
++ const char *ret;
+ const char *s; /* the result */
+ int offset, length;
+ int i, need_substring;
+@@ -2891,47 +2966,48 @@
+ if (!strncmp(var, "CALL", 4)) {
+ if (!strncmp(var + 4, "ING", 3)) {
+ if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */
+- snprintf(workspace, workspacelen, "%d", c->cid.cid_pres);
+- s = workspace;
++ ast_str_set(str, maxlen, "%d", c->cid.cid_pres);
++ s = ast_str_buffer(*str);
+ } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */
+- snprintf(workspace, workspacelen, "%d", c->cid.cid_ani2);
+- s = workspace;
++ ast_str_set(str, maxlen, "%d", c->cid.cid_ani2);
++ s = ast_str_buffer(*str);
+ } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */
+- snprintf(workspace, workspacelen, "%d", c->cid.cid_ton);
+- s = workspace;
++ ast_str_set(str, maxlen, "%d", c->cid.cid_ton);
++ s = ast_str_buffer(*str);
+ } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */
+- snprintf(workspace, workspacelen, "%d", c->cid.cid_tns);
+- s = workspace;
++ ast_str_set(str, maxlen, "%d", c->cid.cid_tns);
++ s = ast_str_buffer(*str);
+ }
+ }
+ } else if (!strcmp(var, "HINT")) {
+- s = ast_get_hint(workspace, workspacelen, NULL, 0, c, c->context, c->exten) ? workspace : NULL;
++ s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL;
+ } else if (!strcmp(var, "HINTNAME")) {
+- s = ast_get_hint(NULL, 0, workspace, workspacelen, c, c->context, c->exten) ? workspace : NULL;
++ s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL;
+ } else if (!strcmp(var, "EXTEN")) {
+ s = c->exten;
+ } else if (!strcmp(var, "CONTEXT")) {
+ s = c->context;
+ } else if (!strcmp(var, "PRIORITY")) {
+- snprintf(workspace, workspacelen, "%d", c->priority);
+- s = workspace;
++ ast_str_set(str, maxlen, "%d", c->priority);
++ s = ast_str_buffer(*str);
+ } else if (!strcmp(var, "CHANNEL")) {
+ s = c->name;
+ } else if (!strcmp(var, "UNIQUEID")) {
+ s = c->uniqueid;
+ } else if (!strcmp(var, "HANGUPCAUSE")) {
+- snprintf(workspace, workspacelen, "%d", c->hangupcause);
+- s = workspace;
++ ast_str_set(str, maxlen, "%d", c->hangupcause);
++ s = ast_str_buffer(*str);
+ }
+ }
+ if (s == &not_found) { /* look for more */
+ if (!strcmp(var, "EPOCH")) {
+- snprintf(workspace, workspacelen, "%u",(int)time(NULL));
+- s = workspace;
++ ast_str_set(str, maxlen, "%u", (int) time(NULL));
++ s = ast_str_buffer(*str);
+ } else if (!strcmp(var, "SYSTEMNAME")) {
+ s = ast_config_AST_SYSTEM_NAME;
+ } else if (!strcmp(var, "ENTITYID")) {
+- ast_eid_to_str(workspace, workspacelen, &ast_eid_default);
++ char workspace[20];
++ ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default);
+ s = workspace;
+ }
+ }
+@@ -2951,18 +3027,25 @@
+ if (places[i] == &globals)
+ ast_rwlock_unlock(&globalslock);
+ }
+- if (s == &not_found || s == NULL)
+- *ret = NULL;
+- else {
+- if (s != workspace)
+- ast_copy_string(workspace, s, workspacelen);
+- *ret = workspace;
+- if (need_substring)
+- *ret = substring(*ret, offset, length, workspace, workspacelen);
++ if (s == &not_found || s == NULL) {
++ ast_debug(5, "Result of '%s' is NULL\n", var);
++ ret = NULL;
++ } else {
++ ast_debug(5, "Result of '%s' is '%s'\n", var, s);
++ if (s != ast_str_buffer(*str)) {
++ ast_str_set(str, maxlen, "%s", s);
++ }
++ ret = ast_str_buffer(*str);
++ if (need_substring) {
++ ret = ast_str_substring(*str, offset, length);
++ ast_debug(2, "Final result of '%s' is '%s'\n", var, ret);
++ }
+ }
+
+- if (c)
++ if (c) {
+ ast_channel_unlock(c);
++ }
++ return ret;
+ }
+
+ static void exception_store_free(void *data)
+@@ -2977,9 +3060,8 @@
+ .destroy = exception_store_free,
+ };
+
+-int pbx_builtin_raise_exception(struct ast_channel *chan, void *vreason)
++int pbx_builtin_raise_exception(struct ast_channel *chan, const char *reason)
+ {
+- const char *reason = vreason;
+ struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
+ struct pbx_exception *exception = NULL;
+
+@@ -3205,9 +3287,11 @@
+
+ AST_RWLIST_WRLOCK(&acf_root);
+ if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) {
++#ifdef AST_XML_DOCS
+ if (cur->docsrc == AST_XML_DOC) {
+ ast_string_field_free_memory(acf);
+ }
++#endif
+ ast_verb(2, "Unregistered custom function %s\n", cur->name);
+ }
+ AST_RWLIST_UNLOCK(&acf_root);
+@@ -3278,7 +3362,9 @@
+ }
+
+ acf->mod = mod;
++#ifdef AST_XML_DOCS
+ acf->docsrc = AST_STATIC_DOC;
++#endif
+
+ if (acf_retrieve_docs(acf)) {
+ return -1;
+@@ -3340,24 +3426,83 @@
+ char *copy = ast_strdupa(function);
+ char *args = func_args(copy);
+ struct ast_custom_function *acfptr = ast_custom_function_find(copy);
++ int res;
++ struct ast_module_user *u = NULL;
+
+- if (acfptr == NULL)
++ if (acfptr == NULL) {
+ ast_log(LOG_ERROR, "Function %s not registered\n", copy);
+- else if (!acfptr->read)
++ } else if (!acfptr->read && !acfptr->read2) {
+ ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
+- else {
+- int res;
+- struct ast_module_user *u = NULL;
+- if (acfptr->mod)
++ } else if (acfptr->read) {
++ if (acfptr->mod) {
+ u = __ast_module_user_add(acfptr->mod, chan);
++ }
+ res = acfptr->read(chan, copy, args, workspace, len);
+- if (acfptr->mod && u)
++ if (acfptr->mod && u) {
+ __ast_module_user_remove(acfptr->mod, u);
++ }
+ return res;
++ } else {
++ struct ast_str *str = ast_str_create(16);
++ if (acfptr->mod) {
++ u = __ast_module_user_add(acfptr->mod, chan);
++ }
++ res = acfptr->read2(chan, copy, args, &str, 0);
++ if (acfptr->mod && u) {
++ __ast_module_user_remove(acfptr->mod, u);
++ }
++ ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len);
++ ast_free(str);
++ return res;
+ }
+ return -1;
+ }
+
++int ast_func_read2(struct ast_channel *chan, const char *function, struct ast_str **str, ssize_t maxlen)
++{
++ char *copy = ast_strdupa(function);
++ char *args = func_args(copy);
++ struct ast_custom_function *acfptr = ast_custom_function_find(copy);
++ int res;
++ struct ast_module_user *u = NULL;
++
++ if (acfptr == NULL) {
++ ast_log(LOG_ERROR, "Function %s not registered\n", copy);
++ } else if (!acfptr->read && !acfptr->read2) {
++ ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
++ } else {
++ if (acfptr->mod) {
++ u = __ast_module_user_add(acfptr->mod, chan);
++ }
++ if (acfptr->read2) {
++ /* ast_str enabled */
++ ast_str_reset(*str);
++ res = acfptr->read2(chan, copy, args, str, maxlen);
++ } else {
++ /* Legacy function pointer, allocate buffer for result */
++ int maxsize = ast_str_size(*str);
++ if (maxlen > -1) {
++ if (maxlen == 0) {
++ if (acfptr->read_max) {
++ maxsize = acfptr->read_max;
++ } else {
++ maxsize = VAR_BUF_SIZE;
++ }
++ } else {
++ maxsize = maxlen;
++ }
++ ast_str_make_space(str, maxsize);
++ }
++ res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize);
++ }
++ if (acfptr->mod && u) {
++ __ast_module_user_remove(acfptr->mod, u);
++ }
++ return res;
++ }
++ return -1;
++}
++
+ int ast_func_write(struct ast_channel *chan, const char *function, const char *value)
+ {
+ char *copy = ast_strdupa(function);
+@@ -3382,10 +3527,198 @@
+ return -1;
+ }
+
++void ast_str_substitute_variables_full(struct ast_str **buf, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *templ, size_t *used)
++{
++ /* Substitutes variables into buf, based on string templ */
++ char *cp4 = NULL;
++ const char *tmp, *whereweare;
++ int orig_size = 0;
++ int offset, offset2, isfunction;
++ const char *nextvar, *nextexp, *nextthing;
++ const char *vars, *vare;
++ char *finalvars;
++ int pos, brackets, needsub, len;
++ struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16);
++
++ ast_str_reset(*buf);
++ whereweare = tmp = templ;
++ while (!ast_strlen_zero(whereweare)) {
++ /* Assume we're copying the whole remaining string */
++ pos = strlen(whereweare);
++ nextvar = NULL;
++ nextexp = NULL;
++ nextthing = strchr(whereweare, '$');
++ if (nextthing) {
++ switch (nextthing[1]) {
++ case '{':
++ nextvar = nextthing;
++ pos = nextvar - whereweare;
++ break;
++ case '[':
++ nextexp = nextthing;
++ pos = nextexp - whereweare;
++ break;
++ default:
++ pos = 1;
++ }
++ }
++
++ if (pos) {
++ /* Copy that many bytes */
++ ast_str_append_substr(buf, maxlen, whereweare, pos);
++
++ templ += pos;
++ whereweare += pos;
++ }
++
++ if (nextvar) {
++ /* We have a variable. Find the start and end, and determine
++ if we are going to have to recursively call ourselves on the
++ contents */
++ vars = vare = nextvar + 2;
++ brackets = 1;
++ needsub = 0;
++
++ /* Find the end of it */
++ while (brackets && *vare) {
++ if ((vare[0] == '$') && (vare[1] == '{')) {
++ needsub++;
++ } else if (vare[0] == '{') {
++ brackets++;
++ } else if (vare[0] == '}') {
++ brackets--;
++ } else if ((vare[0] == '$') && (vare[1] == '['))
++ needsub++;
++ vare++;
++ }
++ if (brackets)
++ ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
++ len = vare - vars - 1;
++
++ /* Skip totally over variable string */
++ whereweare += (len + 3);
++
++ /* Store variable name (and truncate) */
++ ast_str_set_substr(&substr1, 0, vars, len);
++ ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len);
++
++ /* Substitute if necessary */
++ if (needsub) {
++ size_t used;
++ if (!substr2) {
++ substr2 = ast_str_create(16);
++ }
++
++ ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
++ finalvars = ast_str_buffer(substr2);
++ } else {
++ finalvars = ast_str_buffer(substr1);
++ }
++
++ parse_variable_name(finalvars, &offset, &offset2, &isfunction);
++ if (isfunction) {
++ /* Evaluate function */
++ if (c || !headp) {
++ cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
++ } else {
++ struct varshead old;
++ struct ast_channel *bogus = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Bogus/%p", vars);
++ if (bogus) {
++ memcpy(&old, &bogus->varshead, sizeof(old));
++ memcpy(&bogus->varshead, headp, sizeof(bogus->varshead));
++ cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
++ /* Don't deallocate the varshead that was passed in */
++ memcpy(&bogus->varshead, &old, sizeof(bogus->varshead));
++ ast_channel_release(bogus);
++ } else {
++ ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n");
++ }
++ }
++ ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
++ } else {
++ /* Retrieve variable value */
++ ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars);
++ cp4 = ast_str_buffer(substr3);
++ }
++ if (cp4) {
++ ast_str_substring(substr3, offset, offset2);
++ ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
++ }
++ } else if (nextexp) {
++ /* We have an expression. Find the start and end, and determine
++ if we are going to have to recursively call ourselves on the
++ contents */
++ vars = vare = nextexp + 2;
++ brackets = 1;
++ needsub = 0;
++
++ /* Find the end of it */
++ while (brackets && *vare) {
++ if ((vare[0] == '$') && (vare[1] == '[')) {
++ needsub++;
++ brackets++;
++ vare++;
++ } else if (vare[0] == '[') {
++ brackets++;
++ } else if (vare[0] == ']') {
++ brackets--;
++ } else if ((vare[0] == '$') && (vare[1] == '{')) {
++ needsub++;
++ vare++;
++ }
++ vare++;
++ }
++ if (brackets)
++ ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
++ len = vare - vars - 1;
++
++ /* Skip totally over expression */
++ whereweare += (len + 3);
++
++ /* Store variable name (and truncate) */
++ ast_str_set_substr(&substr1, 0, vars, len);
++
++ /* Substitute if necessary */
++ if (needsub) {
++ size_t used;
++ if (!substr2) {
++ substr2 = ast_str_create(16);
++ }
++
++ ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
++ finalvars = ast_str_buffer(substr2);
++ } else {
++ finalvars = ast_str_buffer(substr1);
++ }
++
++ if (ast_str_expr(&substr3, 0, c, finalvars)) {
++ ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3));
++ }
++ ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
++ }
++ }
++ *used = ast_str_strlen(*buf) - orig_size;
++ ast_free(substr1);
++ ast_free(substr2);
++ ast_free(substr3);
++}
++
++void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
++{
++ size_t used;
++ ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used);
++}
++
++void ast_str_substitute_variables_varshead(struct ast_str **buf, ssize_t maxlen, struct varshead *headp, const char *templ)
++{
++ size_t used;
++ ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used);
++}
++
+ void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used)
+ {
+ /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */
+- char *cp4;
++ char *cp4 = NULL;
+ const char *tmp, *whereweare, *orig_cp2 = cp2;
+ int length, offset, offset2, isfunction;
+ char *workspace = NULL;
+@@ -3495,9 +3828,10 @@
+ cp4 = ast_func_read(bogus, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
+ /* Don't deallocate the varshead that was passed in */
+ memcpy(&bogus->varshead, &old, sizeof(bogus->varshead));
+- ast_channel_free(bogus);
+- } else
++ bogus = ast_channel_release(bogus);
++ } else {
+ ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n");
++ }
+ }
+ ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
+ } else {
+@@ -4114,6 +4448,27 @@
+ return 0;
+ }
+
++/*! \brief Get hint for channel */
++int ast_str_get_hint(struct ast_str **hint, ssize_t hintsize, struct ast_str **name, ssize_t namesize, struct ast_channel *c, const char *context, const char *exten)
++{
++ struct ast_exten *e = ast_hint_extension(c, context, exten);
++
++ if (!e) {
++ return 0;
++ }
++
++ if (hint) {
++ ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e));
++ }
++ if (name) {
++ const char *tmp = ast_get_extension_app_data(e);
++ if (tmp) {
++ ast_str_set(name, namesize, "%s", tmp);
++ }
++ }
++ return -1;
++}
++
+ int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
+ {
+ return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0);
+@@ -4635,13 +4990,6 @@
+ ast_rdlock_contexts();
+ c = ast_hashtab_lookup(contexts_table,&item);
+
+-#ifdef NOTNOW
+-
+- while ( (c = ast_walk_contexts(c)) ) {
+- if (!strcmp(ast_get_context_name(c), context))
+- return c;
+- }
+-#endif
+ if (!c)
+ ast_unlock_contexts();
+
+@@ -4968,18 +5316,6 @@
+ c = ast_hashtab_lookup(contexts_table,&item);
+ if (c)
+ ret = 0;
+-
+-
+-#ifdef NOTNOW
+-
+- while ((c = ast_walk_contexts(c))) {
+- if (!strcmp(ast_get_context_name(c), context)) {
+- ret = 0;
+- break;
+- }
+- }
+-
+-#endif
+ ast_unlock_contexts();
+
+ /* if we found context, lock macrolock */
+@@ -5008,16 +5344,6 @@
+ c = ast_hashtab_lookup(contexts_table,&item);
+ if (c)
+ ret = 0;
+-#ifdef NOTNOW
+-
+- while ((c = ast_walk_contexts(c))) {
+- if (!strcmp(ast_get_context_name(c), context)) {
+- ret = 0;
+- break;
+- }
+- }
+-
+-#endif
+ ast_unlock_contexts();
+
+ /* if we found context, unlock macrolock */
+@@ -5029,7 +5355,7 @@
+ }
+
+ /*! \brief Dynamically register a new dial plan application */
+-int ast_register_application2(const char *app, int (*execute)(struct ast_channel *, void *), const char *synopsis, const char *description, void *mod)
++int ast_register_application2(const char *app, int (*execute)(struct ast_channel *, const char *), const char *synopsis, const char *description, void *mod)
+ {
+ struct ast_app *tmp, *cur = NULL;
+ char tmps[80];
+@@ -5093,8 +5419,8 @@
+ #endif
+ ast_string_field_set(tmp, synopsis, synopsis);
+ ast_string_field_set(tmp, description, description);
++#ifdef AST_XML_DOCS
+ tmp->docsrc = AST_STATIC_DOC;
+-#ifdef AST_XML_DOCS
+ }
+ #endif
+
+@@ -5232,9 +5558,6 @@
+ {
+ struct ast_app *aa;
+ int app, no_registered_app = 1;
+- char *ret = NULL;
+- int which = 0;
+- int wordlen;
+
+ switch (cmd) {
+ case CLI_INIT:
+@@ -5249,18 +5572,7 @@
+ * application at one time. You can type 'show application Dial Echo' and
+ * you will see informations about these two applications ...
+ */
+- wordlen = strlen(a->word);
+- /* return the n-th [partial] matching entry */
+- AST_RWLIST_RDLOCK(&apps);
+- AST_RWLIST_TRAVERSE(&apps, aa, list) {
+- if (!strncasecmp(a->word, aa->name, wordlen) && ++which > a->n) {
+- ret = ast_strdup(aa->name);
+- break;
+- }
+- }
+- AST_RWLIST_UNLOCK(&apps);
+-
+- return ret;
++ return ast_complete_applications(a->line, a->word, a->n);
+ }
+
+ if (a->argc < 4) {
+@@ -5454,7 +5766,7 @@
+ int like = 0, describing = 0;
+ int total_match = 0; /* Number of matches in like clause */
+ int total_apps = 0; /* Number of apps registered */
+- static char* choices[] = { "like", "describing", NULL };
++ static const char * const choices[] = { "like", "describing", NULL };
+
+ switch (cmd) {
+ case CLI_INIT:
+@@ -5824,7 +6136,7 @@
+ if (ast_strlen_zero(exten))
+ exten = NULL;
+ } else { /* no '@' char, only context given */
+- context = a->argv[2];
++ context = ast_strdupa(a->argv[2]);
+ }
+ if (ast_strlen_zero(context))
+ context = NULL;
+@@ -5892,7 +6204,7 @@
+ if (ast_strlen_zero(exten))
+ exten = NULL;
+ } else { /* no '@' char, only context given */
+- context = a->argv[2];
++ context = ast_strdupa(a->argv[2]);
+ }
+ if (ast_strlen_zero(context))
+ context = NULL;
+@@ -6114,15 +6426,6 @@
+ return 0;
+ }
+
+-static char mandescr_show_dialplan[] =
+-"Description: Show dialplan contexts and extensions.\n"
+-"Be aware that showing the full dialplan may take a lot of capacity\n"
+-"Variables: \n"
+-" ActionID: <id> Action ID for this AMI transaction (optional)\n"
+-" Extension: <extension> Extension (Optional)\n"
+-" Context: <context> Context (Optional)\n"
+-"\n";
+-
+ /*! \brief CLI support for listing global variables in a parseable way */
+ static char *handle_show_globals(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+ {
+@@ -6171,16 +6474,19 @@
+ if (a->argc != e->args + 1)
+ return CLI_SHOWUSAGE;
+
+- if (!(chan = ast_get_channel_by_name_locked(a->argv[e->args]))) {
++ if (!(chan = ast_channel_get_by_name(a->argv[e->args]))) {
+ ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]);
+ return CLI_FAILURE;
+ }
+
+ pbx_builtin_serialize_variables(chan, &vars);
++
+ if (ast_str_strlen(vars)) {
+ ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], ast_str_buffer(vars));
+ }
+- ast_channel_unlock(chan);
++
++ chan = ast_channel_unref(chan);
++
+ return CLI_SUCCESS;
+ }
+
+@@ -6229,13 +6535,15 @@
+ var_name = a->argv[e->args + 1];
+ var_value = a->argv[e->args + 2];
+
+- if (!(chan = ast_get_channel_by_name_locked(chan_name))) {
++ if (!(chan = ast_channel_get_by_name(chan_name))) {
+ ast_cli(a->fd, "Channel '%s' not found\n", chan_name);
+ return CLI_FAILURE;
+ }
+
+ pbx_builtin_setvar_helper(chan, var_name, var_value);
+- ast_channel_unlock(chan);
++
++ chan = ast_channel_unref(chan);
++
+ ast_cli(a->fd, "\n -- Channel variable '%s' set to '%s' for '%s'\n", var_name, var_value, chan_name);
+
+ return CLI_SUCCESS;
+@@ -6717,7 +7025,7 @@
+ * return the index of the matching entry, starting from 1.
+ * If names is not supplied, try numeric values.
+ */
+-static int lookup_name(const char *s, char *const names[], int max)
++static int lookup_name(const char *s, const char * const names[], int max)
+ {
+ int i;
+
+@@ -6740,7 +7048,7 @@
+ /*! \brief helper function to return a range up to max (7, 12, 31 respectively).
+ * names, if supplied, is an array of names that should be mapped to numbers.
+ */
+-static unsigned get_range(char *src, int max, char *const names[], const char *msg)
++static unsigned get_range(char *src, int max, const char * const names[], const char *msg)
+ {
+ int start, end; /* start and ending position */
+ unsigned int mask = 0;
+@@ -6843,7 +7151,7 @@
+ return;
+ }
+
+-static char *days[] =
++static const char * const days[] =
+ {
+ "sun",
+ "mon",
+@@ -6855,7 +7163,7 @@
+ NULL,
+ };
+
+-static char *months[] =
++static const char * const months[] =
+ {
+ "jan",
+ "feb",
+@@ -7335,11 +7643,11 @@
+ struct ast_channel *chan;
+ int res = -1;
+
+- chan = ast_get_channel_by_name_locked(channame);
+- if (chan) {
++ if ((chan = ast_channel_get_by_name(channame))) {
+ res = ast_async_goto(chan, context, exten, priority);
+- ast_channel_unlock(chan);
++ chan = ast_channel_unref(chan);
+ }
++
+ return res;
+ }
+
+@@ -7597,12 +7905,10 @@
+
+ /* If we are adding a hint evalulate in variables and global variables */
+ if (priority == PRIORITY_HINT && strstr(application, "${") && !strstr(extension, "_")) {
+- struct ast_channel c = {0, };
+-
+- ast_copy_string(c.exten, extension, sizeof(c.exten));
+- ast_copy_string(c.context, con->name, sizeof(c.context));
+- pbx_substitute_variables_helper(&c, application, expand_buf, sizeof(expand_buf));
++ struct ast_channel *c = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", extension, con->name, 0, "Bogus/%s", __PRETTY_FUNCTION__);
++ pbx_substitute_variables_helper(c, application, expand_buf, sizeof(expand_buf));
+ application = expand_buf;
++ ast_channel_release(c);
+ }
+
+ length = sizeof(struct ast_exten);
+@@ -7855,7 +8161,7 @@
+
+ if (!chan->cdr) {
+ /* allocation of the cdr failed */
+- ast_channel_free(chan); /* free the channel */
++ chan = ast_channel_release(chan); /* free the channel */
+ return -1; /* return failure */
+ }
+
+@@ -7866,7 +8172,7 @@
+ ast_cdr_failed(chan->cdr); /* set the status to failed */
+ ast_cdr_detach(chan->cdr); /* post and free the record */
+ chan->cdr = NULL;
+- ast_channel_free(chan); /* free the channel */
++ chan = ast_channel_release(chan); /* free the channel */
+
+ return 0; /* success */
+ }
+@@ -8353,7 +8659,7 @@
+ ast_unlock_contexts();
+ }
+
+-static void wait_for_hangup(struct ast_channel *chan, void *data)
++static void wait_for_hangup(struct ast_channel *chan, const void *data)
+ {
+ int res;
+ struct ast_frame *f;
+@@ -8378,7 +8684,7 @@
+ /*!
+ * \ingroup applications
+ */
+-static int pbx_builtin_proceeding(struct ast_channel *chan, void *data)
++static int pbx_builtin_proceeding(struct ast_channel *chan, const char *data)
+ {
+ ast_indicate(chan, AST_CONTROL_PROCEEDING);
+ return 0;
+@@ -8387,7 +8693,7 @@
+ /*!
+ * \ingroup applications
+ */
+-static int pbx_builtin_progress(struct ast_channel *chan, void *data)
++static int pbx_builtin_progress(struct ast_channel *chan, const char *data)
+ {
+ ast_indicate(chan, AST_CONTROL_PROGRESS);
+ return 0;
+@@ -8396,7 +8702,7 @@
+ /*!
+ * \ingroup applications
+ */
+-static int pbx_builtin_ringing(struct ast_channel *chan, void *data)
++static int pbx_builtin_ringing(struct ast_channel *chan, const char *data)
+ {
+ ast_indicate(chan, AST_CONTROL_RINGING);
+ return 0;
+@@ -8405,7 +8711,7 @@
+ /*!
+ * \ingroup applications
+ */
+-static int pbx_builtin_busy(struct ast_channel *chan, void *data)
++static int pbx_builtin_busy(struct ast_channel *chan, const char *data)
+ {
+ ast_indicate(chan, AST_CONTROL_BUSY);
+ /* Don't change state of an UP channel, just indicate
+@@ -8421,7 +8727,7 @@
+ /*!
+ * \ingroup applications
+ */
+-static int pbx_builtin_congestion(struct ast_channel *chan, void *data)
++static int pbx_builtin_congestion(struct ast_channel *chan, const char *data)
+ {
+ ast_indicate(chan, AST_CONTROL_CONGESTION);
+ /* Don't change state of an UP channel, just indicate
+@@ -8435,7 +8741,7 @@
+ /*!
+ * \ingroup applications
+ */
+-static int pbx_builtin_answer(struct ast_channel *chan, void *data)
++static int pbx_builtin_answer(struct ast_channel *chan, const char *data)
+ {
+ int delay = 0;
+ int answer_cdr = 1;
+@@ -8467,9 +8773,9 @@
+ return __ast_answer(chan, delay, answer_cdr);
+ }
+
+-static int pbx_builtin_incomplete(struct ast_channel *chan, void *data)
++static int pbx_builtin_incomplete(struct ast_channel *chan, const char *data)
+ {
+- char *options = data;
++ const char *options = data;
+ int answer = 1;
+
+ /* Some channels can receive DTMF in unanswered state; some cannot */
+@@ -8497,7 +8803,7 @@
+ /*!
+ * \ingroup applications
+ */
+-static int pbx_builtin_resetcdr(struct ast_channel *chan, void *data)
++static int pbx_builtin_resetcdr(struct ast_channel *chan, const char *data)
+ {
+ char *args;
+ struct ast_flags flags = { 0 };
+@@ -8515,7 +8821,7 @@
+ /*!
+ * \ingroup applications
+ */
+-static int pbx_builtin_setamaflags(struct ast_channel *chan, void *data)
++static int pbx_builtin_setamaflags(struct ast_channel *chan, const char *data)
+ {
+ /* Copy the AMA Flags as specified */
+ ast_cdr_setamaflags(chan, data ? data : "");
+@@ -8525,7 +8831,7 @@
+ /*!
+ * \ingroup applications
+ */
+-static int pbx_builtin_hangup(struct ast_channel *chan, void *data)
++static int pbx_builtin_hangup(struct ast_channel *chan, const char *data)
+ {
+ if (!ast_strlen_zero(data)) {
+ int cause;
+@@ -8555,7 +8861,7 @@
+ /*!
+ * \ingroup applications
+ */
+-static int pbx_builtin_gotoiftime(struct ast_channel *chan, void *data)
++static int pbx_builtin_gotoiftime(struct ast_channel *chan, const char *data)
+ {
+ char *s, *ts, *branch1, *branch2, *branch;
+ struct ast_timing timing;
+@@ -8590,12 +8896,12 @@
+ /*!
+ * \ingroup applications
+ */
+-static int pbx_builtin_execiftime(struct ast_channel *chan, void *data)
++static int pbx_builtin_execiftime(struct ast_channel *chan, const char *data)
+ {
+ char *s, *appname;
+ struct ast_timing timing;
+ struct ast_app *app;
+- static const char *usage = "ExecIfTime requires an argument:\n <time range>,<days of week>,<days of month>,<months>[,<timezone>]?<appname>[(<appargs>)]";
++ static const char * const usage = "ExecIfTime requires an argument:\n <time range>,<days of week>,<days of month>,<months>[,<timezone>]?<appname>[(<appargs>)]";
+
+ if (ast_strlen_zero(data)) {
+ ast_log(LOG_WARNING, "%s\n", usage);
+@@ -8644,7 +8950,7 @@
+ /*!
+ * \ingroup applications
+ */
+-static int pbx_builtin_wait(struct ast_channel *chan, void *data)
++static int pbx_builtin_wait(struct ast_channel *chan, const char *data)
+ {
+ double s;
+ int ms;
+@@ -8660,7 +8966,7 @@
+ /*!
+ * \ingroup applications
+ */
+-static int pbx_builtin_waitexten(struct ast_channel *chan, void *data)
++static int pbx_builtin_waitexten(struct ast_channel *chan, const char *data)
+ {
+ int ms, res;
+ double s;
+@@ -8729,7 +9035,7 @@
+ /*!
+ * \ingroup applications
+ */
+-static int pbx_builtin_background(struct ast_channel *chan, void *data)
++static int pbx_builtin_background(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+ int mres = 0;
+@@ -8827,7 +9133,7 @@
+ /*! Goto
+ * \ingroup applications
+ */
+-static int pbx_builtin_goto(struct ast_channel *chan, void *data)
++static int pbx_builtin_goto(struct ast_channel *chan, const char *data)
+ {
+ int res = ast_parseable_goto(chan, data);
+ if (!res)
+@@ -8996,7 +9302,7 @@
+ ast_rwlock_unlock(&globalslock);
+ }
+
+-int pbx_builtin_setvar(struct ast_channel *chan, void *data)
++int pbx_builtin_setvar(struct ast_channel *chan, const char *data)
+ {
+ char *name, *value, *mydata;
+
+@@ -9019,7 +9325,7 @@
+ return(0);
+ }
+
+-int pbx_builtin_setvar_multiple(struct ast_channel *chan, void *vdata)
++int pbx_builtin_setvar_multiple(struct ast_channel *chan, const char *vdata)
+ {
+ char *data;
+ int x;
+@@ -9055,7 +9361,7 @@
+ return 0;
+ }
+
+-int pbx_builtin_importvar(struct ast_channel *chan, void *data)
++int pbx_builtin_importvar(struct ast_channel *chan, const char *data)
+ {
+ char *name;
+ char *value;
+@@ -9077,14 +9383,14 @@
+ name = strsep(&value,"=");
+ channel = strsep(&value,",");
+ if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */
+- struct ast_channel *chan2 = ast_get_channel_by_name_locked(channel);
++ struct ast_channel *chan2 = ast_channel_get_by_name(channel);
+ if (chan2) {
+ char *s = alloca(strlen(value) + 4);
+ if (s) {
+ sprintf(s, "${%s}", value);
+ pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1);
+ }
+- ast_channel_unlock(chan2);
++ chan2 = ast_channel_unref(chan2);
+ }
+ pbx_builtin_setvar_helper(chan, name, tmp);
+ }
+@@ -9092,7 +9398,7 @@
+ return(0);
+ }
+
+-static int pbx_builtin_noop(struct ast_channel *chan, void *data)
++static int pbx_builtin_noop(struct ast_channel *chan, const char *data)
+ {
+ return 0;
+ }
+@@ -9119,7 +9425,7 @@
+ }
+ }
+
+-static int pbx_builtin_gotoif(struct ast_channel *chan, void *data)
++static int pbx_builtin_gotoif(struct ast_channel *chan, const char *data)
+ {
+ char *condition, *branch1, *branch2, *branch;
+ char *stringp;
+@@ -9143,7 +9449,7 @@
+ return pbx_builtin_goto(chan, branch);
+ }
+
+-static int pbx_builtin_saynumber(struct ast_channel *chan, void *data)
++static int pbx_builtin_saynumber(struct ast_channel *chan, const char *data)
+ {
+ char tmp[256];
+ char *number = tmp;
+@@ -9171,7 +9477,7 @@
+ return 0;
+ }
+
+-static int pbx_builtin_saydigits(struct ast_channel *chan, void *data)
++static int pbx_builtin_saydigits(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+
+@@ -9180,7 +9486,7 @@
+ return res;
+ }
+
+-static int pbx_builtin_saycharacters(struct ast_channel *chan, void *data)
++static int pbx_builtin_saycharacters(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+
+@@ -9189,7 +9495,7 @@
+ return res;
+ }
+
+-static int pbx_builtin_sayphonetic(struct ast_channel *chan, void *data)
++static int pbx_builtin_sayphonetic(struct ast_channel *chan, const char *data)
+ {
+ int res = 0;
+
+@@ -9241,7 +9547,7 @@
+ }
+
+ /* Register manager application */
+- ast_manager_register2("ShowDialPlan", EVENT_FLAG_CONFIG | EVENT_FLAG_REPORTING, manager_show_dialplan, "List dialplan", mandescr_show_dialplan);
++ ast_manager_register_xml("ShowDialPlan", EVENT_FLAG_CONFIG | EVENT_FLAG_REPORTING, manager_show_dialplan);
+
+ if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, NULL,
+ AST_EVENT_IE_END))) {
+@@ -9481,8 +9787,9 @@
+ goto_func = (async) ? ast_async_goto : ast_explicit_goto;
+ if (ast_exists_extension(chan, context, exten, priority, chan->cid.cid_num))
+ return goto_func(chan, context, exten, priority);
+- else
+- return -3;
++ else {
++ return AST_PBX_GOTO_FAILED;
++ }
+ }
+
+ int ast_goto_if_exists(struct ast_channel *chan, const char* context, const char *exten, int priority)
+@@ -9557,3 +9864,22 @@
+ {
+ return pbx_parseable_goto(chan, goto_string, 1);
+ }
++
++char *ast_complete_applications(const char *line, const char *word, int state)
++{
++ struct ast_app *app = NULL;
++ int which = 0;
++ char *ret = NULL;
++ size_t wordlen = strlen(word);
++
++ AST_RWLIST_RDLOCK(&apps);
++ AST_RWLIST_TRAVERSE(&apps, app, list) {
++ if (!strncasecmp(word, app->name, wordlen) && ++which > state) {
++ ret = ast_strdup(app->name);
++ break;
++ }
++ }
++ AST_RWLIST_UNLOCK(&apps);
++
++ return ret;
++}
+Index: main/strings.c
+===================================================================
+--- a/main/strings.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/strings.c (.../trunk) (revision 202568)
+@@ -109,17 +109,6 @@
+ return res;
+ }
+
+-void ast_str_substitute_variables(struct ast_str **buf, size_t maxlen, struct ast_channel *chan, const char *template)
+-{
+- int first = 1;
+- do {
+- ast_str_make_space(buf, maxlen ? maxlen :
+- (first ? strlen(template) * 2 : (*buf)->__AST_STR_LEN * 2));
+- pbx_substitute_variables_helper_full(chan, NULL, template, (*buf)->__AST_STR_STR, (*buf)->__AST_STR_LEN - 1, &((*buf)->__AST_STR_USED));
+- first = 0;
+- } while (maxlen == 0 && (*buf)->__AST_STR_LEN - 5 < (*buf)->__AST_STR_USED);
+-}
+-
+ char *__ast_str_helper2(struct ast_str **buf, size_t maxlen, const char *src, size_t maxsrc, int append, int escapecommas)
+ {
+ int dynamic = 0;
+Index: main/stun.c
+===================================================================
+--- a/main/stun.c (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/main/stun.c (.../trunk) (revision 202568)
+@@ -0,0 +1,475 @@
++/*
++ * Asterisk -- An open source telephony toolkit.
++ *
++ * Copyright (C) 1999 - 2008, Digium, Inc.
++ *
++ * Mark Spencer <markster@digium.com>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * 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.
++ */
++
++/*!
++ * \file
++ *
++ * \brief STUN Support
++ *
++ * \author Mark Spencer <markster@digium.com>
++ *
++ * \note STUN is defined in RFC 3489.
++ */
++
++#include "asterisk.h"
++
++ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
++
++#include "asterisk/_private.h"
++#include "asterisk/stun.h"
++#include "asterisk/cli.h"
++#include "asterisk/utils.h"
++#include "asterisk/channel.h"
++
++static int stundebug; /*!< Are we debugging stun? */
++
++/*!
++ * \brief STUN support code
++ *
++ * This code provides some support for doing STUN transactions.
++ * Eventually it should be moved elsewhere as other protocols
++ * than RTP can benefit from it - e.g. SIP.
++ * STUN is described in RFC3489 and it is based on the exchange
++ * of UDP packets between a client and one or more servers to
++ * determine the externally visible address (and port) of the client
++ * once it has gone through the NAT boxes that connect it to the
++ * outside.
++ * The simplest request packet is just the header defined in
++ * struct stun_header, and from the response we may just look at
++ * one attribute, STUN_MAPPED_ADDRESS, that we find in the response.
++ * By doing more transactions with different server addresses we
++ * may determine more about the behaviour of the NAT boxes, of
++ * course - the details are in the RFC.
++ *
++ * All STUN packets start with a simple header made of a type,
++ * length (excluding the header) and a 16-byte random transaction id.
++ * Following the header we may have zero or more attributes, each
++ * structured as a type, length and a value (whose format depends
++ * on the type, but often contains addresses).
++ * Of course all fields are in network format.
++ */
++
++typedef struct { unsigned int id[4]; } __attribute__((packed)) stun_trans_id;
++
++struct stun_header {
++ unsigned short msgtype;
++ unsigned short msglen;
++ stun_trans_id id;
++ unsigned char ies[0];
++} __attribute__((packed));
++
++struct stun_attr {
++ unsigned short attr;
++ unsigned short len;
++ unsigned char value[0];
++} __attribute__((packed));
++
++/*
++ * The format normally used for addresses carried by STUN messages.
++ */
++struct stun_addr {
++ unsigned char unused;
++ unsigned char family;
++ unsigned short port;
++ unsigned int addr;
++} __attribute__((packed));
++
++/*! \brief STUN message types
++ * 'BIND' refers to transactions used to determine the externally
++ * visible addresses. 'SEC' refers to transactions used to establish
++ * a session key for subsequent requests.
++ * 'SEC' functionality is not supported here.
++ */
++
++#define STUN_BINDREQ 0x0001
++#define STUN_BINDRESP 0x0101
++#define STUN_BINDERR 0x0111
++#define STUN_SECREQ 0x0002
++#define STUN_SECRESP 0x0102
++#define STUN_SECERR 0x0112
++
++/*! \brief Basic attribute types in stun messages.
++ * Messages can also contain custom attributes (codes above 0x7fff)
++ */
++#define STUN_MAPPED_ADDRESS 0x0001
++#define STUN_RESPONSE_ADDRESS 0x0002
++#define STUN_CHANGE_REQUEST 0x0003
++#define STUN_SOURCE_ADDRESS 0x0004
++#define STUN_CHANGED_ADDRESS 0x0005
++#define STUN_USERNAME 0x0006
++#define STUN_PASSWORD 0x0007
++#define STUN_MESSAGE_INTEGRITY 0x0008
++#define STUN_ERROR_CODE 0x0009
++#define STUN_UNKNOWN_ATTRIBUTES 0x000a
++#define STUN_REFLECTED_FROM 0x000b
++
++/*! \brief helper function to print message names */
++static const char *stun_msg2str(int msg)
++{
++ switch (msg) {
++ case STUN_BINDREQ:
++ return "Binding Request";
++ case STUN_BINDRESP:
++ return "Binding Response";
++ case STUN_BINDERR:
++ return "Binding Error Response";
++ case STUN_SECREQ:
++ return "Shared Secret Request";
++ case STUN_SECRESP:
++ return "Shared Secret Response";
++ case STUN_SECERR:
++ return "Shared Secret Error Response";
++ }
++ return "Non-RFC3489 Message";
++}
++
++/*! \brief helper function to print attribute names */
++static const char *stun_attr2str(int msg)
++{
++ switch (msg) {
++ case STUN_MAPPED_ADDRESS:
++ return "Mapped Address";
++ case STUN_RESPONSE_ADDRESS:
++ return "Response Address";
++ case STUN_CHANGE_REQUEST:
++ return "Change Request";
++ case STUN_SOURCE_ADDRESS:
++ return "Source Address";
++ case STUN_CHANGED_ADDRESS:
++ return "Changed Address";
++ case STUN_USERNAME:
++ return "Username";
++ case STUN_PASSWORD:
++ return "Password";
++ case STUN_MESSAGE_INTEGRITY:
++ return "Message Integrity";
++ case STUN_ERROR_CODE:
++ return "Error Code";
++ case STUN_UNKNOWN_ATTRIBUTES:
++ return "Unknown Attributes";
++ case STUN_REFLECTED_FROM:
++ return "Reflected From";
++ }
++ return "Non-RFC3489 Attribute";
++}
++
++/*! \brief here we store credentials extracted from a message */
++struct stun_state {
++ const char *username;
++ const char *password;
++};
++
++static int stun_process_attr(struct stun_state *state, struct stun_attr *attr)
++{
++ if (stundebug)
++ ast_verbose("Found STUN Attribute %s (%04x), length %d\n",
++ stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len));
++ switch (ntohs(attr->attr)) {
++ case STUN_USERNAME:
++ state->username = (const char *) (attr->value);
++ break;
++ case STUN_PASSWORD:
++ state->password = (const char *) (attr->value);
++ break;
++ default:
++ if (stundebug)
++ ast_verbose("Ignoring STUN attribute %s (%04x), length %d\n",
++ stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len));
++ }
++ return 0;
++}
++
++/*! \brief append a string to an STUN message */
++static void append_attr_string(struct stun_attr **attr, int attrval, const char *s, int *len, int *left)
++{
++ int size = sizeof(**attr) + strlen(s);
++ if (*left > size) {
++ (*attr)->attr = htons(attrval);
++ (*attr)->len = htons(strlen(s));
++ memcpy((*attr)->value, s, strlen(s));
++ (*attr) = (struct stun_attr *)((*attr)->value + strlen(s));
++ *len += size;
++ *left -= size;
++ }
++}
++
++/*! \brief append an address to an STUN message */
++static void append_attr_address(struct stun_attr **attr, int attrval, struct sockaddr_in *sin, int *len, int *left)
++{
++ int size = sizeof(**attr) + 8;
++ struct stun_addr *addr;
++ if (*left > size) {
++ (*attr)->attr = htons(attrval);
++ (*attr)->len = htons(8);
++ addr = (struct stun_addr *)((*attr)->value);
++ addr->unused = 0;
++ addr->family = 0x01;
++ addr->port = sin->sin_port;
++ addr->addr = sin->sin_addr.s_addr;
++ (*attr) = (struct stun_attr *)((*attr)->value + 8);
++ *len += size;
++ *left -= size;
++ }
++}
++
++/*! \brief wrapper to send an STUN message */
++static int stun_send(int s, struct sockaddr_in *dst, struct stun_header *resp)
++{
++ return sendto(s, resp, ntohs(resp->msglen) + sizeof(*resp), 0,
++ (struct sockaddr *)dst, sizeof(*dst));
++}
++
++/*! \brief helper function to generate a random request id */
++static void stun_req_id(struct stun_header *req)
++{
++ int x;
++ for (x = 0; x < 4; x++)
++ req->id.id[x] = ast_random();
++}
++
++/*! \brief handle an incoming STUN message.
++ *
++ * Do some basic sanity checks on packet size and content,
++ * try to extract a bit of information, and possibly reply.
++ * At the moment this only processes BIND requests, and returns
++ * the externally visible address of the request.
++ * If a callback is specified, invoke it with the attribute.
++ */
++int ast_stun_handle_packet(int s, struct sockaddr_in *src, unsigned char *data, size_t len, stun_cb_f *stun_cb, void *arg)
++{
++ struct stun_header *hdr = (struct stun_header *)data;
++ struct stun_attr *attr;
++ struct stun_state st;
++ int ret = AST_STUN_IGNORE;
++ int x;
++
++ /* On entry, 'len' is the length of the udp payload. After the
++ * initial checks it becomes the size of unprocessed options,
++ * while 'data' is advanced accordingly.
++ */
++ if (len < sizeof(struct stun_header)) {
++ ast_debug(1, "Runt STUN packet (only %d, wanting at least %d)\n", (int) len, (int) sizeof(struct stun_header));
++ return -1;
++ }
++ len -= sizeof(struct stun_header);
++ data += sizeof(struct stun_header);
++ x = ntohs(hdr->msglen); /* len as advertised in the message */
++ if (stundebug)
++ ast_verbose("STUN Packet, msg %s (%04x), length: %d\n", stun_msg2str(ntohs(hdr->msgtype)), ntohs(hdr->msgtype), x);
++ if (x > len) {
++ ast_debug(1, "Scrambled STUN packet length (got %d, expecting %d)\n", x, (int)len);
++ } else
++ len = x;
++ memset(&st, 0, sizeof(st));
++ while (len) {
++ if (len < sizeof(struct stun_attr)) {
++ ast_debug(1, "Runt Attribute (got %d, expecting %d)\n", (int)len, (int) sizeof(struct stun_attr));
++ break;
++ }
++ attr = (struct stun_attr *)data;
++ /* compute total attribute length */
++ x = ntohs(attr->len) + sizeof(struct stun_attr);
++ if (x > len) {
++ ast_debug(1, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", x, (int)len);
++ break;
++ }
++ if (stun_cb)
++ stun_cb(attr, arg);
++ if (stun_process_attr(&st, attr)) {
++ ast_debug(1, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr));
++ break;
++ }
++ /* Clear attribute id: in case previous entry was a string,
++ * this will act as the terminator for the string.
++ */
++ attr->attr = 0;
++ data += x;
++ len -= x;
++ }
++ /* Null terminate any string.
++ * XXX NOTE, we write past the size of the buffer passed by the
++ * caller, so this is potentially dangerous. The only thing that
++ * saves us is that usually we read the incoming message in a
++ * much larger buffer in the struct ast_rtp
++ */
++ *data = '\0';
++
++ /* Now prepare to generate a reply, which at the moment is done
++ * only for properly formed (len == 0) STUN_BINDREQ messages.
++ */
++ if (len == 0) {
++ unsigned char respdata[1024];
++ struct stun_header *resp = (struct stun_header *)respdata;
++ int resplen = 0; /* len excluding header */
++ int respleft = sizeof(respdata) - sizeof(struct stun_header);
++
++ resp->id = hdr->id;
++ resp->msgtype = 0;
++ resp->msglen = 0;
++ attr = (struct stun_attr *)resp->ies;
++ switch (ntohs(hdr->msgtype)) {
++ case STUN_BINDREQ:
++ if (stundebug)
++ ast_verbose("STUN Bind Request, username: %s\n",
++ st.username ? st.username : "<none>");
++ if (st.username)
++ append_attr_string(&attr, STUN_USERNAME, st.username, &resplen, &respleft);
++ append_attr_address(&attr, STUN_MAPPED_ADDRESS, src, &resplen, &respleft);
++ resp->msglen = htons(resplen);
++ resp->msgtype = htons(STUN_BINDRESP);
++ stun_send(s, src, resp);
++ ret = AST_STUN_ACCEPT;
++ break;
++ default:
++ if (stundebug)
++ ast_verbose("Dunno what to do with STUN message %04x (%s)\n", ntohs(hdr->msgtype), stun_msg2str(ntohs(hdr->msgtype)));
++ }
++ }
++ return ret;
++}
++
++/*! \brief Extract the STUN_MAPPED_ADDRESS from the stun response.
++ * This is used as a callback for stun_handle_response
++ * when called from ast_stun_request.
++ */
++static int stun_get_mapped(struct stun_attr *attr, void *arg)
++{
++ struct stun_addr *addr = (struct stun_addr *)(attr + 1);
++ struct sockaddr_in *sa = (struct sockaddr_in *)arg;
++
++ if (ntohs(attr->attr) != STUN_MAPPED_ADDRESS || ntohs(attr->len) != 8)
++ return 1; /* not us. */
++ sa->sin_port = addr->port;
++ sa->sin_addr.s_addr = addr->addr;
++ return 0;
++}
++
++/*! \brief Generic STUN request
++ * Send a generic stun request to the server specified,
++ * possibly waiting for a reply and filling the 'reply' field with
++ * the externally visible address. Note that in this case the request
++ * will be blocking.
++ * (Note, the interface may change slightly in the future).
++ *
++ * \param s the socket used to send the request
++ * \param dst the address of the STUN server
++ * \param username if non null, add the username in the request
++ * \param answer if non null, the function waits for a response and
++ * puts here the externally visible address.
++ * \return 0 on success, other values on error.
++ */
++int ast_stun_request(int s, struct sockaddr_in *dst,
++ const char *username, struct sockaddr_in *answer)
++{
++ struct stun_header *req;
++ unsigned char reqdata[1024];
++ int reqlen, reqleft;
++ struct stun_attr *attr;
++ int res = 0;
++ int retry;
++
++ req = (struct stun_header *)reqdata;
++ stun_req_id(req);
++ reqlen = 0;
++ reqleft = sizeof(reqdata) - sizeof(struct stun_header);
++ req->msgtype = 0;
++ req->msglen = 0;
++ attr = (struct stun_attr *)req->ies;
++ if (username)
++ append_attr_string(&attr, STUN_USERNAME, username, &reqlen, &reqleft);
++ req->msglen = htons(reqlen);
++ req->msgtype = htons(STUN_BINDREQ);
++ for (retry = 0; retry < 3; retry++) { /* XXX make retries configurable */
++ /* send request, possibly wait for reply */
++ unsigned char reply_buf[1024];
++ fd_set rfds;
++ struct timeval to = { 3, 0 }; /* timeout, make it configurable */
++ struct sockaddr_in src;
++ socklen_t srclen;
++
++ res = stun_send(s, dst, req);
++ if (res < 0) {
++ ast_log(LOG_WARNING, "ast_stun_request send #%d failed error %d, retry\n",
++ retry, res);
++ continue;
++ }
++ if (answer == NULL)
++ break;
++ FD_ZERO(&rfds);
++ FD_SET(s, &rfds);
++ res = ast_select(s + 1, &rfds, NULL, NULL, &to);
++ if (res <= 0) /* timeout or error */
++ continue;
++ memset(&src, 0, sizeof(src));
++ srclen = sizeof(src);
++ /* XXX pass -1 in the size, because stun_handle_packet might
++ * write past the end of the buffer.
++ */
++ res = recvfrom(s, reply_buf, sizeof(reply_buf) - 1,
++ 0, (struct sockaddr *)&src, &srclen);
++ if (res < 0) {
++ ast_log(LOG_WARNING, "ast_stun_request recvfrom #%d failed error %d, retry\n",
++ retry, res);
++ continue;
++ }
++ memset(answer, 0, sizeof(struct sockaddr_in));
++ ast_stun_handle_packet(s, &src, reply_buf, res,
++ stun_get_mapped, answer);
++ res = 0; /* signal regular exit */
++ break;
++ }
++ return res;
++}
++
++static char *handle_cli_stun_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
++{
++ switch (cmd) {
++ case CLI_INIT:
++ e->command = "stun set debug {on|off}";
++ e->usage =
++ "Usage: stun set debug {on|off}\n"
++ " Enable/Disable STUN (Simple Traversal of UDP through NATs)\n"
++ " debugging\n";
++ return NULL;
++ case CLI_GENERATE:
++ return NULL;
++ }
++
++ if (a->argc != e->args)
++ return CLI_SHOWUSAGE;
++
++ if (!strncasecmp(a->argv[e->args-1], "on", 2))
++ stundebug = 1;
++ else if (!strncasecmp(a->argv[e->args-1], "off", 3))
++ stundebug = 0;
++ else
++ return CLI_SHOWUSAGE;
++
++ ast_cli(a->fd, "STUN Debugging %s\n", stundebug ? "Enabled" : "Disabled");
++ return CLI_SUCCESS;
++}
++
++static struct ast_cli_entry cli_stun[] = {
++ AST_CLI_DEFINE(handle_cli_stun_set_debug, "Enable/Disable STUN debugging"),
++};
++
++/*! \brief Initialize the STUN system in Asterisk */
++void ast_stun_init(void)
++{
++ ast_cli_register_multiple(cli_stun, sizeof(cli_stun) / sizeof(struct ast_cli_entry));
++}
+
+Property changes on: main/stun.c
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+
+Index: main/tcptls.c
+===================================================================
+--- a/main/tcptls.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/tcptls.c (.../trunk) (revision 202568)
+@@ -173,7 +173,7 @@
+ X509_NAME *name = X509_get_subject_name(peer);
+ int pos = -1;
+ int found = 0;
+-
++
+ for (;;) {
+ /* Walk the certificate to check all available "Common Name" */
+ /* XXX Probably should do a gethostbyname on the hostname and compare that as well */
+@@ -229,7 +229,7 @@
+ socklen_t sinlen;
+ struct ast_tcptls_session_instance *tcptls_session;
+ pthread_t launched;
+-
++
+ for (;;) {
+ int i, flags;
+
+@@ -261,7 +261,7 @@
+ memcpy(&tcptls_session->remote_address, &sin, sizeof(tcptls_session->remote_address));
+
+ tcptls_session->client = 0;
+-
++
+ if (ast_pthread_create_detached_background(&launched, NULL, handle_tls_connection, tcptls_session)) {
+ ast_log(LOG_WARNING, "Unable to launch helper thread: %s\n", strerror(errno));
+ close(tcptls_session->fd);
+@@ -283,23 +283,50 @@
+ SSL_load_error_strings();
+ SSLeay_add_ssl_algorithms();
+
+- if (!(cfg->ssl_ctx = SSL_CTX_new( client ? SSLv23_client_method() : SSLv23_server_method() ))) {
++ if (client) {
++ if (ast_test_flag(&cfg->flags, AST_SSL_SSLV2_CLIENT)) {
++ cfg->ssl_ctx = SSL_CTX_new(SSLv2_client_method());
++ } else if (ast_test_flag(&cfg->flags, AST_SSL_SSLV3_CLIENT)) {
++ cfg->ssl_ctx = SSL_CTX_new(SSLv3_client_method());
++ } else if (ast_test_flag(&cfg->flags, AST_SSL_TLSV1_CLIENT)) {
++ cfg->ssl_ctx = SSL_CTX_new(TLSv1_client_method());
++ } else {
++ /* SSLv23_client_method() sends SSLv2, this was the original
++ * default for ssl clients before the option was given to
++ * pick what protocol a client should use. In order not
++ * to break expected behavior it remains the default. */
++ cfg->ssl_ctx = SSL_CTX_new(SSLv23_client_method());
++ }
++ } else {
++ /* SSLv23_server_method() supports TLSv1, SSLv2, and SSLv3 inbound connections. */
++ cfg->ssl_ctx = SSL_CTX_new(SSLv23_server_method());
++ }
++
++ if (!cfg->ssl_ctx) {
+ ast_debug(1, "Sorry, SSL_CTX_new call returned null...\n");
+ cfg->enabled = 0;
+ return 0;
+ }
+ if (!ast_strlen_zero(cfg->certfile)) {
+- if (SSL_CTX_use_certificate_file(cfg->ssl_ctx, cfg->certfile, SSL_FILETYPE_PEM) == 0 ||
+- SSL_CTX_use_PrivateKey_file(cfg->ssl_ctx, cfg->certfile, SSL_FILETYPE_PEM) == 0 ||
+- SSL_CTX_check_private_key(cfg->ssl_ctx) == 0 ) {
++ char *tmpprivate = ast_strlen_zero(cfg->pvtfile) ? cfg->certfile : cfg->pvtfile;
++ if (SSL_CTX_use_certificate_file(cfg->ssl_ctx, cfg->certfile, SSL_FILETYPE_PEM) == 0) {
+ if (!client) {
+ /* Clients don't need a certificate, but if its setup we can use it */
+- ast_verb(0, "SSL cert error <%s>", cfg->certfile);
++ ast_verb(0, "SSL error loading cert file. <%s>", cfg->certfile);
+ sleep(2);
+ cfg->enabled = 0;
+ return 0;
+ }
+ }
++ if ((SSL_CTX_use_PrivateKey_file(cfg->ssl_ctx, tmpprivate, SSL_FILETYPE_PEM) == 0) || (SSL_CTX_check_private_key(cfg->ssl_ctx) == 0 )) {
++ if (!client) {
++ /* Clients don't need a private key, but if its setup we can use it */
++ ast_verb(0, "SSL error loading private key file. <%s>", tmpprivate);
++ sleep(2);
++ cfg->enabled = 0;
++ return 0;
++ }
++ }
+ }
+ if (!ast_strlen_zero(cfg->cipher)) {
+ if (SSL_CTX_set_cipher_list(cfg->ssl_ctx, cfg->cipher) == 0 ) {
+@@ -409,22 +436,22 @@
+ {
+ int flags;
+ int x = 1;
+-
++
+ /* Do nothing if nothing has changed */
+ if (!memcmp(&desc->old_address, &desc->local_address, sizeof(desc->old_address))) {
+ ast_debug(1, "Nothing changed in %s\n", desc->name);
+ return;
+ }
+-
++
+ desc->old_address = desc->local_address;
+-
++
+ /* Shutdown a running server if there is one */
+ if (desc->master != AST_PTHREADT_NULL) {
+ pthread_cancel(desc->master);
+ pthread_kill(desc->master, SIGURG);
+ pthread_join(desc->master, NULL);
+ }
+-
++
+ if (desc->accept_fd != -1)
+ close(desc->accept_fd);
+
+@@ -439,7 +466,7 @@
+ ast_log(LOG_ERROR, "Unable to allocate socket for %s: %s\n", desc->name, strerror(errno));
+ return;
+ }
+-
++
+ setsockopt(desc->accept_fd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
+ if (bind(desc->accept_fd, (struct sockaddr *) &desc->local_address, sizeof(desc->local_address))) {
+ ast_log(LOG_ERROR, "Unable to bind %s to %s:%d: %s\n",
+@@ -480,3 +507,53 @@
+ desc->accept_fd = -1;
+ ast_debug(2, "Stopped server :: %s\n", desc->name);
+ }
++
++int ast_tls_read_conf(struct ast_tls_config *tls_cfg, struct ast_tcptls_session_args *tls_desc, const char *varname, const char *value)
++{
++ if (!strcasecmp(varname, "tlsenable") || !strcasecmp(varname, "sslenable")) {
++ tls_cfg->enabled = ast_true(value) ? 1 : 0;
++ tls_desc->local_address.sin_family = AF_INET;
++ } else if (!strcasecmp(varname, "tlscertfile") || !strcasecmp(varname, "sslcert") || !strcasecmp(varname, "tlscert")) {
++ ast_free(tls_cfg->certfile);
++ tls_cfg->certfile = ast_strdup(value);
++ } else if (!strcasecmp(varname, "tlsprivatekey") || !strcasecmp(varname, "sslprivatekey")) {
++ ast_free(tls_cfg->pvtfile);
++ tls_cfg->pvtfile = ast_strdup(value);
++ } else if (!strcasecmp(varname, "tlscipher") || !strcasecmp(varname, "sslcipher")) {
++ ast_free(tls_cfg->cipher);
++ tls_cfg->cipher = ast_strdup(value);
++ } else if (!strcasecmp(varname, "tlscafile")) {
++ ast_free(tls_cfg->cafile);
++ tls_cfg->cafile = ast_strdup(value);
++ } else if (!strcasecmp(varname, "tlscapath")) {
++ ast_free(tls_cfg->capath);
++ tls_cfg->capath = ast_strdup(value);
++ } else if (!strcasecmp(varname, "tlsverifyclient")) {
++ ast_set2_flag(&tls_cfg->flags, ast_true(value), AST_SSL_VERIFY_CLIENT);
++ } else if (!strcasecmp(varname, "tlsdontverifyserver")) {
++ ast_set2_flag(&tls_cfg->flags, ast_true(value), AST_SSL_DONT_VERIFY_SERVER);
++ } else if (!strcasecmp(varname, "tlsbindaddr") || !strcasecmp(varname, "sslbindaddr")) {
++ if (ast_parse_arg(value, PARSE_INADDR, &tls_desc->local_address))
++ ast_log(LOG_WARNING, "Invalid %s '%s'\n", varname, value);
++ } else if (!strcasecmp(varname, "tlsbindport") || !strcasecmp(varname, "sslbindport")) {
++ tls_desc->local_address.sin_port = htons(atoi(value));
++ } else if (!strcasecmp(varname, "tlsclientmethod") || !strcasecmp(varname, "sslclientmethod")) {
++ if (!strcasecmp(value, "tlsv1")) {
++ ast_set_flag(&tls_cfg->flags, AST_SSL_TLSV1_CLIENT);
++ ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV3_CLIENT);
++ ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV2_CLIENT);
++ } else if (!strcasecmp(value, "sslv3")) {
++ ast_set_flag(&tls_cfg->flags, AST_SSL_SSLV3_CLIENT);
++ ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV2_CLIENT);
++ ast_clear_flag(&tls_cfg->flags, AST_SSL_TLSV1_CLIENT);
++ } else if (!strcasecmp(value, "sslv2")) {
++ ast_set_flag(&tls_cfg->flags, AST_SSL_SSLV2_CLIENT);
++ ast_clear_flag(&tls_cfg->flags, AST_SSL_TLSV1_CLIENT);
++ ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV3_CLIENT);
++ }
++ } else {
++ return -1;
++ }
++
++ return 0;
++}
+Index: main/file.c
+===================================================================
+--- a/main/file.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/file.c (.../trunk) (revision 202568)
+@@ -187,14 +187,20 @@
+ struct ast_frame *trf;
+ fs->lastwriteformat = f->subclass;
+ /* Get the translated frame but don't consume the original in case they're using it on another stream */
+- trf = ast_translate(fs->trans, f, 0);
+- if (trf) {
+- res = fs->fmt->write(fs, trf);
++ if ((trf = ast_translate(fs->trans, f, 0))) {
++ struct ast_frame *cur;
++
++ /* the translator may have returned multiple frames, so process them */
++ for (cur = trf; cur; cur = AST_LIST_NEXT(cur, frame_list)) {
++ if ((res = fs->fmt->write(fs, trf))) {
++ ast_log(LOG_WARNING, "Translated frame write failed\n");
++ break;
++ }
++ }
+ ast_frfree(trf);
+- if (res)
+- ast_log(LOG_WARNING, "Translated frame write failed\n");
+- } else
++ } else {
+ res = 0;
++ }
+ }
+ }
+ return res;
+@@ -1365,7 +1371,7 @@
+ #undef FORMAT2
+ }
+
+-struct ast_cli_entry cli_file[] = {
++static struct ast_cli_entry cli_file[] = {
+ AST_CLI_DEFINE(handle_cli_core_show_file_formats, "Displays file formats")
+ };
+
+Index: main/callerid.c
+===================================================================
+--- a/main/callerid.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/callerid.c (.../trunk) (revision 202568)
+@@ -791,8 +791,8 @@
+
+ }
+
+-int vmwi_generate(unsigned char *buf, int active, int type, int codec,
+- const char* name, const char* number, int flags)
++int ast_callerid_vmwi_generate(unsigned char *buf, int active, int type, int codec,
++ const char* name, const char* number, int flags)
+ {
+ char msg[256];
+ int len = 0;
+@@ -922,8 +922,10 @@
+ return bytes;
+ }
+
+-/*! \brief Clean up phone string
+- * remove '(', ' ', ')', non-trailing '.', and '-' not in square brackets.
++/*!
++ * \brief Clean up phone string
++ * \details
++ * Remove '(', ' ', ')', non-trailing '.', and '-' not in square brackets.
+ * Basically, remove anything that could be invalid in a pattern.
+ */
+ void ast_shrink_phone_number(char *n)
+@@ -958,11 +960,13 @@
+ n[y] = '\0';
+ }
+
+-/*! \brief Checks if phone number consists of valid characters
+- \param exten String that needs to be checked
+- \param valid Valid characters in string
+- \return 1 if valid string, 0 if string contains invalid characters
+-*/
++/*!
++ * \brief Checks if phone number consists of valid characters
++ * \param exten String that needs to be checked
++ * \param valid Valid characters in string
++ * \retval 1 if valid string
++ * \retval 0 if string contains invalid characters
++ */
+ static int ast_is_valid_string(const char *exten, const char *valid)
+ {
+ int x;
+@@ -975,34 +979,16 @@
+ return 1;
+ }
+
+-/*! \brief checks if string consists only of digits and * \# and +
+- \return 1 if string is valid AST phone number
+- \return 0 if not
+-*/
+ int ast_isphonenumber(const char *n)
+ {
+ return ast_is_valid_string(n, "0123456789*#+");
+ }
+
+-/*! \brief checks if string consists only of digits and ( ) - * \# and +
+- Pre-qualifies the string for ast_shrink_phone_number()
+- \return 1 if string is valid AST shrinkable phone number
+- \return 0 if not
+-*/
+ int ast_is_shrinkable_phonenumber(const char *exten)
+ {
+ return ast_is_valid_string(exten, "0123456789*#+()-.");
+ }
+
+-/*!
+- * \brief Destructively parse instr for caller id information
+- * \return always returns 0, as the code always returns something.
+- * \note XXX 'name' is not parsed consistently e.g. we have
+- * input location name
+- * " foo bar " <123> 123 ' foo bar ' (with spaces around)
+- * " foo bar " NULL 'foo bar' (without spaces around)
+- * The parsing of leading and trailing space/quotes should be more consistent.
+- */
+ int ast_callerid_parse(char *instr, char **name, char **location)
+ {
+ char *ns, *ne, *ls, *le;
+@@ -1103,68 +1089,191 @@
+ return 0;
+ }
+
+-/*! \brief Translation table for Caller ID Presentation settings */
+-static struct {
+- int val;
++struct ast_value_translation {
++ int value;
+ const char *name;
+ const char *description;
+-} pres_types[] = {
+- { AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, "allowed_not_screened", "Presentation Allowed, Not Screened"},
+- { AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, "allowed_passed_screen", "Presentation Allowed, Passed Screen"},
+- { AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN, "allowed_failed_screen", "Presentation Allowed, Failed Screen"},
+- { AST_PRES_ALLOWED_NETWORK_NUMBER, "allowed", "Presentation Allowed, Network Number"},
+- { AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED, "prohib_not_screened", "Presentation Prohibited, Not Screened"},
+- { AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN, "prohib_passed_screen", "Presentation Prohibited, Passed Screen"},
+- { AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN, "prohib_failed_screen", "Presentation Prohibited, Failed Screen"},
+- { AST_PRES_PROHIB_NETWORK_NUMBER, "prohib", "Presentation Prohibited, Network Number"},
+- { AST_PRES_NUMBER_NOT_AVAILABLE, "unavailable", "Number Unavailable"},
+ };
+
+-/*! \brief Convert caller ID text code to value
+- used in config file parsing
+- \param data text string
+- \return value AST_PRES_ from callerid.h
+-*/
++/*! \brief Translation table for Caller ID Presentation settings */
++static const struct ast_value_translation pres_types[] = {
++/* *INDENT-OFF* */
++ { AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_UNSCREENED, "allowed_not_screened", "Presentation Allowed, Not Screened" },
++ { AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_PASSED_SCREEN, "allowed_passed_screen", "Presentation Allowed, Passed Screen" },
++ { AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_FAILED_SCREEN, "allowed_failed_screen", "Presentation Allowed, Failed Screen" },
++ { AST_PRES_ALLOWED | AST_PRES_NETWORK_NUMBER, "allowed", "Presentation Allowed, Network Number" },
++
++ { AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_UNSCREENED, "prohib_not_screened", "Presentation Prohibited, Not Screened" },
++ { AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_PASSED_SCREEN, "prohib_passed_screen", "Presentation Prohibited, Passed Screen" },
++ { AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_FAILED_SCREEN, "prohib_failed_screen", "Presentation Prohibited, Failed Screen" },
++ { AST_PRES_RESTRICTED | AST_PRES_NETWORK_NUMBER, "prohib", "Presentation Prohibited, Network Number" },
++
++ { AST_PRES_UNAVAILABLE | AST_PRES_NETWORK_NUMBER, "unavailable", "Number Unavailable" }, /* Default name to value conversion. */
++ { AST_PRES_UNAVAILABLE | AST_PRES_USER_NUMBER_UNSCREENED, "unavailable", "Number Unavailable" },
++ { AST_PRES_UNAVAILABLE | AST_PRES_USER_NUMBER_FAILED_SCREEN, "unavailable", "Number Unavailable" },
++ { AST_PRES_UNAVAILABLE | AST_PRES_USER_NUMBER_PASSED_SCREEN, "unavailable", "Number Unavailable" },
++/* *INDENT-ON* */
++};
++
++/*!
++ * \brief Convert caller ID text code to value (used in config file parsing)
++ * \param data text string from config file
++ * \retval value AST_PRES_ from callerid.h
++ * \retval -1 if not in table
++ */
+ int ast_parse_caller_presentation(const char *data)
+ {
+- int i;
++ int index;
+
+- for (i = 0; i < ARRAY_LEN(pres_types); i++) {
+- if (!strcasecmp(pres_types[i].name, data))
+- return pres_types[i].val;
++ for (index = 0; index < ARRAY_LEN(pres_types); ++index) {
++ if (!strcasecmp(pres_types[index].name, data)) {
++ return pres_types[index].value;
++ }
+ }
+
+ return -1;
+ }
+
+-/*! \brief Convert caller ID pres value to explanatory string
+- \param data value (see callerid.h AST_PRES_ )
+- \return string for human presentation
+-*/
++/*!
++ * \brief Convert caller ID pres value to explanatory string
++ * \param data AST_PRES_ value from callerid.h
++ * \return string for human presentation
++ */
+ const char *ast_describe_caller_presentation(int data)
+ {
+- int i;
++ int index;
+
+- for (i = 0; i < ARRAY_LEN(pres_types); i++) {
+- if (pres_types[i].val == data)
+- return pres_types[i].description;
++ for (index = 0; index < ARRAY_LEN(pres_types); ++index) {
++ if (pres_types[index].value == data) {
++ return pres_types[index].description;
++ }
+ }
+
+ return "unknown";
+ }
+
+-/*! \brief Convert caller ID pres value to text code
+- \param data text string
+- \return string for config file
+-*/
++/*!
++ * \brief Convert caller ID pres value to text code
++ * \param data AST_PRES_ value from callerid.h
++ * \return string for config file
++ */
+ const char *ast_named_caller_presentation(int data)
+ {
+- int i;
++ int index;
+
+- for (i = 0; i < ARRAY_LEN(pres_types); i++) {
+- if (pres_types[i].val == data)
+- return pres_types[i].name;
++ for (index = 0; index < ARRAY_LEN(pres_types); ++index) {
++ if (pres_types[index].value == data) {
++ return pres_types[index].name;
++ }
+ }
+
+ return "unknown";
+ }
++
++/*! \brief Translation table for redirecting reason settings */
++static const struct ast_value_translation redirecting_reason_types[] = {
++/* *INDENT-OFF* */
++ { AST_REDIRECTING_REASON_UNKNOWN, "unknown", "Unknown" },
++ { AST_REDIRECTING_REASON_USER_BUSY, "cfb", "Call Forwarding Busy" },
++ { AST_REDIRECTING_REASON_NO_ANSWER, "cfnr", "Call Forwarding No Reply" },
++ { AST_REDIRECTING_REASON_UNAVAILABLE, "unavailable", "Callee is Unavailable" },
++ { AST_REDIRECTING_REASON_UNCONDITIONAL, "cfu", "Call Forwarding Unconditional" },
++ { AST_REDIRECTING_REASON_TIME_OF_DAY, "time_of_day", "Time of Day" },
++ { AST_REDIRECTING_REASON_DO_NOT_DISTURB, "dnd", "Do Not Disturb" },
++ { AST_REDIRECTING_REASON_DEFLECTION, "deflection", "Call Deflection" },
++ { AST_REDIRECTING_REASON_FOLLOW_ME, "follow_me", "Follow Me" },
++ { AST_REDIRECTING_REASON_OUT_OF_ORDER, "out_of_order", "Called DTE Out-Of-Order" },
++ { AST_REDIRECTING_REASON_AWAY, "away", "Callee is Away" },
++ { AST_REDIRECTING_REASON_CALL_FWD_DTE, "cf_dte", "Call Forwarding By The Called DTE" },
++/* *INDENT-ON* */
++};
++
++int ast_redirecting_reason_parse(const char *data)
++{
++ int index;
++
++ for (index = 0; index < ARRAY_LEN(redirecting_reason_types); ++index) {
++ if (!strcasecmp(redirecting_reason_types[index].name, data)) {
++ return redirecting_reason_types[index].value;
++ }
++ }
++
++ return -1;
++}
++
++const char *ast_redirecting_reason_describe(int data)
++{
++ int index;
++
++ for (index = 0; index < ARRAY_LEN(redirecting_reason_types); ++index) {
++ if (redirecting_reason_types[index].value == data) {
++ return redirecting_reason_types[index].description;
++ }
++ }
++
++ return "not-known";
++}
++
++const char *ast_redirecting_reason_name(int data)
++{
++ int index;
++
++ for (index = 0; index < ARRAY_LEN(redirecting_reason_types); ++index) {
++ if (redirecting_reason_types[index].value == data) {
++ return redirecting_reason_types[index].name;
++ }
++ }
++
++ return "not-known";
++}
++
++/*! \brief Translation table for connected line update source settings */
++static const struct ast_value_translation connected_line_source_types[] = {
++/* *INDENT-OFF* */
++ { AST_CONNECTED_LINE_UPDATE_SOURCE_UNKNOWN, "unknown", "Unknown" },
++ { AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER, "answer", "Normal Call Answering" },
++ { AST_CONNECTED_LINE_UPDATE_SOURCE_DIVERSION, "diversion", "Call Diversion (Deprecated, use REDIRECTING)" },
++ { AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER, "transfer_active", "Call Transfer(Active)" },
++ { AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER, "transfer", "Call Transfer(Active)" },/* Old name must come after new name. */
++ { AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING, "transfer_alerting", "Call Transfer(Alerting)" }
++/* *INDENT-ON* */
++};
++
++int ast_connected_line_source_parse(const char *data)
++{
++ int index;
++
++ for (index = 0; index < ARRAY_LEN(connected_line_source_types); ++index) {
++ if (!strcasecmp(connected_line_source_types[index].name, data)) {
++ return connected_line_source_types[index].value;
++ }
++ }
++
++ return -1;
++}
++
++const char *ast_connected_line_source_describe(int data)
++{
++ int index;
++
++ for (index = 0; index < ARRAY_LEN(connected_line_source_types); ++index) {
++ if (connected_line_source_types[index].value == data) {
++ return connected_line_source_types[index].description;
++ }
++ }
++
++ return "not-known";
++}
++
++const char *ast_connected_line_source_name(int data)
++{
++ int index;
++
++ for (index = 0; index < ARRAY_LEN(connected_line_source_types); ++index) {
++ if (connected_line_source_types[index].value == data) {
++ return connected_line_source_types[index].name;
++ }
++ }
++
++ return "not-known";
++}
+Index: main/audiohook.c
+===================================================================
+--- a/main/audiohook.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/audiohook.c (.../trunk) (revision 202568)
+@@ -20,7 +20,7 @@
+ *
+ * \brief Audiohooks Architecture
+ *
+- * \author Joshua 'file' Colp <jcolp@digium.com>
++ * \author Joshua Colp <jcolp@digium.com>
+ */
+
+ #include "asterisk.h"
+Index: main/xmldoc.c
+===================================================================
+--- a/main/xmldoc.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/main/xmldoc.c (.../trunk) (revision 202568)
+@@ -19,6 +19,8 @@
+ * \brief XML Documentation API
+ *
+ * \author Eliel C. Sardanons (LU1ALY) <eliels@gmail.com>
++ *
++ * \extref libxml2 http://www.xmlsoft.org/
+ */
+
+ #include "asterisk.h"
+@@ -984,19 +986,77 @@
+ return ret;
+ }
+
++/*! \internal
++ * \brief Generate an AMI action syntax.
++ * \param fixnode The manager action node pointer.
++ * \param name The name of the manager action.
++ * \retval The generated syntax.
++ * \retval NULL on error.
++ */
++static char *xmldoc_get_syntax_manager(struct ast_xml_node *fixnode, const char *name)
++{
++ struct ast_str *syntax;
++ struct ast_xml_node *node = fixnode;
++ const char *paramtype, *attrname;
++ int required;
++ char *ret;
++
++ syntax = ast_str_create(128);
++ if (!syntax) {
++ return ast_strdup(name);
++ }
++
++ ast_str_append(&syntax, 0, "Action: %s", name);
++
++ for (node = ast_xml_node_get_children(node); node; node = ast_xml_node_get_next(node)) {
++ if (strcasecmp(ast_xml_node_get_name(node), "parameter")) {
++ continue;
++ }
++
++ /* Is this parameter required? */
++ required = 0;
++ paramtype = ast_xml_get_attribute(node, "required");
++ if (paramtype) {
++ required = ast_true(paramtype);
++ ast_xml_free_attr(paramtype);
++ }
++
++ attrname = ast_xml_get_attribute(node, "name");
++ if (!attrname) {
++ /* ignore this bogus parameter and continue. */
++ continue;
++ }
++
++ ast_str_append(&syntax, 0, "\n%s%s:%s <value>",
++ (required ? "" : "["),
++ attrname,
++ (required ? "" : "]"));
++
++ ast_xml_free_attr(attrname);
++ }
++
++ /* return a common string. */
++ ret = ast_strdup(ast_str_buffer(syntax));
++ ast_free(syntax);
++
++ return ret;
++}
++
+ /*! \brief Types of syntax that we are able to generate. */
+ enum syntaxtype {
+ FUNCTION_SYNTAX,
++ MANAGER_SYNTAX,
+ COMMAND_SYNTAX
+ };
+
+ /*! \brief Mapping between type of node and type of syntax to generate. */
+-struct strsyntaxtype {
++static struct strsyntaxtype {
+ const char *type;
+ enum syntaxtype stxtype;
+ } stxtype[] = {
+ { "function", FUNCTION_SYNTAX },
+ { "application", FUNCTION_SYNTAX },
++ { "manager", MANAGER_SYNTAX },
+ { "agi", COMMAND_SYNTAX }
+ };
+
+@@ -1034,10 +1094,18 @@
+ }
+
+ if (node) {
+- if (xmldoc_get_syntax_type(type) == FUNCTION_SYNTAX) {
++ switch (xmldoc_get_syntax_type(type)) {
++ case FUNCTION_SYNTAX:
+ syntax = xmldoc_get_syntax_fun(node, name, "parameter", 1, 1);
+- } else {
++ break;
++ case COMMAND_SYNTAX:
+ syntax = xmldoc_get_syntax_cmd(node, name, 1);
++ break;
++ case MANAGER_SYNTAX:
++ syntax = xmldoc_get_syntax_manager(node, name);
++ break;
++ default:
++ syntax = xmldoc_get_syntax_fun(node, name, "parameter", 1, 1);
+ }
+ }
+ return syntax;
+Index: main/rtp_engine.c
+===================================================================
+--- a/main/rtp_engine.c (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/main/rtp_engine.c (.../trunk) (revision 202568)
+@@ -0,0 +1,1617 @@
++/*
++ * Asterisk -- An open source telephony toolkit.
++ *
++ * Copyright (C) 1999 - 2008, Digium, Inc.
++ *
++ * Joshua Colp <jcolp@digium.com>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * 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.
++ */
++
++/*! \file
++ *
++ * \brief Pluggable RTP Architecture
++ *
++ * \author Joshua Colp <jcolp@digium.com>
++ */
++
++#include "asterisk.h"
++
++ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
++
++#include <math.h>
++
++#include "asterisk/channel.h"
++#include "asterisk/frame.h"
++#include "asterisk/module.h"
++#include "asterisk/rtp_engine.h"
++#include "asterisk/manager.h"
++#include "asterisk/options.h"
++#include "asterisk/astobj2.h"
++#include "asterisk/pbx.h"
++#include "asterisk/translate.h"
++
++/*! Structure that represents an RTP session (instance) */
++struct ast_rtp_instance {
++ /*! Engine that is handling this RTP instance */
++ struct ast_rtp_engine *engine;
++ /*! Data unique to the RTP engine */
++ void *data;
++ /*! RTP properties that have been set and their value */
++ int properties[AST_RTP_PROPERTY_MAX];
++ /*! Address that we are expecting RTP to come in to */
++ struct sockaddr_in local_address;
++ /*! Address that we are sending RTP to */
++ struct sockaddr_in remote_address;
++ /*! Alternate address that we are receiving RTP from */
++ struct sockaddr_in alt_remote_address;
++ /*! Instance that we are bridged to if doing remote or local bridging */
++ struct ast_rtp_instance *bridged;
++ /*! Payload and packetization information */
++ struct ast_rtp_codecs codecs;
++ /*! RTP timeout time (negative or zero means disabled, negative value means temporarily disabled) */
++ int timeout;
++ /*! RTP timeout when on hold (negative or zero means disabled, negative value means temporarily disabled). */
++ int holdtimeout;
++ /*! DTMF mode in use */
++ enum ast_rtp_dtmf_mode dtmf_mode;
++};
++
++/*! List of RTP engines that are currently registered */
++static AST_RWLIST_HEAD_STATIC(engines, ast_rtp_engine);
++
++/*! List of RTP glues */
++static AST_RWLIST_HEAD_STATIC(glues, ast_rtp_glue);
++
++/*! The following array defines the MIME Media type (and subtype) for each
++ of our codecs, or RTP-specific data type. */
++static const struct ast_rtp_mime_type {
++ struct ast_rtp_payload_type payload_type;
++ char *type;
++ char *subtype;
++ unsigned int sample_rate;
++} ast_rtp_mime_types[] = {
++ {{1, AST_FORMAT_G723_1}, "audio", "G723", 8000},
++ {{1, AST_FORMAT_GSM}, "audio", "GSM", 8000},
++ {{1, AST_FORMAT_ULAW}, "audio", "PCMU", 8000},
++ {{1, AST_FORMAT_ULAW}, "audio", "G711U", 8000},
++ {{1, AST_FORMAT_ALAW}, "audio", "PCMA", 8000},
++ {{1, AST_FORMAT_ALAW}, "audio", "G711A", 8000},
++ {{1, AST_FORMAT_G726}, "audio", "G726-32", 8000},
++ {{1, AST_FORMAT_ADPCM}, "audio", "DVI4", 8000},
++ {{1, AST_FORMAT_SLINEAR}, "audio", "L16", 8000},
++ {{1, AST_FORMAT_LPC10}, "audio", "LPC", 8000},
++ {{1, AST_FORMAT_G729A}, "audio", "G729", 8000},
++ {{1, AST_FORMAT_G729A}, "audio", "G729A", 8000},
++ {{1, AST_FORMAT_G729A}, "audio", "G.729", 8000},
++ {{1, AST_FORMAT_SPEEX}, "audio", "speex", 8000},
++ {{1, AST_FORMAT_ILBC}, "audio", "iLBC", 8000},
++ /* this is the sample rate listed in the RTP profile for the G.722
++ codec, *NOT* the actual sample rate of the media stream
++ */
++ {{1, AST_FORMAT_G722}, "audio", "G722", 8000},
++ {{1, AST_FORMAT_G726_AAL2}, "audio", "AAL2-G726-32", 8000},
++ {{0, AST_RTP_DTMF}, "audio", "telephone-event", 8000},
++ {{0, AST_RTP_CISCO_DTMF}, "audio", "cisco-telephone-event", 8000},
++ {{0, AST_RTP_CN}, "audio", "CN", 8000},
++ {{1, AST_FORMAT_JPEG}, "video", "JPEG", 90000},
++ {{1, AST_FORMAT_PNG}, "video", "PNG", 90000},
++ {{1, AST_FORMAT_H261}, "video", "H261", 90000},
++ {{1, AST_FORMAT_H263}, "video", "H263", 90000},
++ {{1, AST_FORMAT_H263_PLUS}, "video", "h263-1998", 90000},
++ {{1, AST_FORMAT_H264}, "video", "H264", 90000},
++ {{1, AST_FORMAT_MP4_VIDEO}, "video", "MP4V-ES", 90000},
++ {{1, AST_FORMAT_T140RED}, "text", "RED", 1000},
++ {{1, AST_FORMAT_T140}, "text", "T140", 1000},
++ {{1, AST_FORMAT_SIREN7}, "audio", "G7221", 16000},
++ {{1, AST_FORMAT_SIREN14}, "audio", "G7221", 32000},
++};
++
++/*!
++ * \brief Mapping between Asterisk codecs and rtp payload types
++ *
++ * Static (i.e., well-known) RTP payload types for our "AST_FORMAT..."s:
++ * also, our own choices for dynamic payload types. This is our master
++ * table for transmission
++ *
++ * See http://www.iana.org/assignments/rtp-parameters for a list of
++ * assigned values
++ */
++static const struct ast_rtp_payload_type static_RTP_PT[AST_RTP_MAX_PT] = {
++ [0] = {1, AST_FORMAT_ULAW},
++ #ifdef USE_DEPRECATED_G726
++ [2] = {1, AST_FORMAT_G726}, /* Technically this is G.721, but if Cisco can do it, so can we... */
++ #endif
++ [3] = {1, AST_FORMAT_GSM},
++ [4] = {1, AST_FORMAT_G723_1},
++ [5] = {1, AST_FORMAT_ADPCM}, /* 8 kHz */
++ [6] = {1, AST_FORMAT_ADPCM}, /* 16 kHz */
++ [7] = {1, AST_FORMAT_LPC10},
++ [8] = {1, AST_FORMAT_ALAW},
++ [9] = {1, AST_FORMAT_G722},
++ [10] = {1, AST_FORMAT_SLINEAR}, /* 2 channels */
++ [11] = {1, AST_FORMAT_SLINEAR}, /* 1 channel */
++ [13] = {0, AST_RTP_CN},
++ [16] = {1, AST_FORMAT_ADPCM}, /* 11.025 kHz */
++ [17] = {1, AST_FORMAT_ADPCM}, /* 22.050 kHz */
++ [18] = {1, AST_FORMAT_G729A},
++ [19] = {0, AST_RTP_CN}, /* Also used for CN */
++ [26] = {1, AST_FORMAT_JPEG},
++ [31] = {1, AST_FORMAT_H261},
++ [34] = {1, AST_FORMAT_H263},
++ [97] = {1, AST_FORMAT_ILBC},
++ [98] = {1, AST_FORMAT_H263_PLUS},
++ [99] = {1, AST_FORMAT_H264},
++ [101] = {0, AST_RTP_DTMF},
++ [102] = {1, AST_FORMAT_SIREN7},
++ [103] = {1, AST_FORMAT_H263_PLUS},
++ [104] = {1, AST_FORMAT_MP4_VIDEO},
++ [105] = {1, AST_FORMAT_T140RED}, /* Real time text chat (with redundancy encoding) */
++ [106] = {1, AST_FORMAT_T140}, /* Real time text chat */
++ [110] = {1, AST_FORMAT_SPEEX},
++ [111] = {1, AST_FORMAT_G726},
++ [112] = {1, AST_FORMAT_G726_AAL2},
++ [115] = {1, AST_FORMAT_SIREN14},
++ [121] = {0, AST_RTP_CISCO_DTMF}, /* Must be type 121 */
++};
++
++int ast_rtp_engine_register2(struct ast_rtp_engine *engine, struct ast_module *module)
++{
++ struct ast_rtp_engine *current_engine;
++
++ /* Perform a sanity check on the engine structure to make sure it has the basics */
++ if (ast_strlen_zero(engine->name) || !engine->new || !engine->destroy || !engine->write || !engine->read) {
++ ast_log(LOG_WARNING, "RTP Engine '%s' failed sanity check so it was not registered.\n", !ast_strlen_zero(engine->name) ? engine->name : "Unknown");
++ return -1;
++ }
++
++ /* Link owner module to the RTP engine for reference counting purposes */
++ engine->mod = module;
++
++ AST_RWLIST_WRLOCK(&engines);
++
++ /* Ensure that no two modules with the same name are registered at the same time */
++ AST_RWLIST_TRAVERSE(&engines, current_engine, entry) {
++ if (!strcmp(current_engine->name, engine->name)) {
++ ast_log(LOG_WARNING, "An RTP engine with the name '%s' has already been registered.\n", engine->name);
++ AST_RWLIST_UNLOCK(&engines);
++ return -1;
++ }
++ }
++
++ /* The engine survived our critique. Off to the list it goes to be used */
++ AST_RWLIST_INSERT_TAIL(&engines, engine, entry);
++
++ AST_RWLIST_UNLOCK(&engines);
++
++ ast_verb(2, "Registered RTP engine '%s'\n", engine->name);
++
++ return 0;
++}
++
++int ast_rtp_engine_unregister(struct ast_rtp_engine *engine)
++{
++ struct ast_rtp_engine *current_engine = NULL;
++
++ AST_RWLIST_WRLOCK(&engines);
++
++ if ((current_engine = AST_RWLIST_REMOVE(&engines, engine, entry))) {
++ ast_verb(2, "Unregistered RTP engine '%s'\n", engine->name);
++ }
++
++ AST_RWLIST_UNLOCK(&engines);
++
++ return current_engine ? 0 : -1;
++}
++
++int ast_rtp_glue_register2(struct ast_rtp_glue *glue, struct ast_module *module)
++{
++ struct ast_rtp_glue *current_glue = NULL;
++
++ if (ast_strlen_zero(glue->type)) {
++ return -1;
++ }
++
++ glue->mod = module;
++
++ AST_RWLIST_WRLOCK(&glues);
++
++ AST_RWLIST_TRAVERSE(&glues, current_glue, entry) {
++ if (!strcasecmp(current_glue->type, glue->type)) {
++ ast_log(LOG_WARNING, "RTP glue with the name '%s' has already been registered.\n", glue->type);
++ AST_RWLIST_UNLOCK(&glues);
++ return -1;
++ }
++ }
++
++ AST_RWLIST_INSERT_TAIL(&glues, glue, entry);
++
++ AST_RWLIST_UNLOCK(&glues);
++
++ ast_verb(2, "Registered RTP glue '%s'\n", glue->type);
++
++ return 0;
++}
++
++int ast_rtp_glue_unregister(struct ast_rtp_glue *glue)
++{
++ struct ast_rtp_glue *current_glue = NULL;
++
++ AST_RWLIST_WRLOCK(&glues);
++
++ if ((current_glue = AST_RWLIST_REMOVE(&glues, glue, entry))) {
++ ast_verb(2, "Unregistered RTP glue '%s'\n", glue->type);
++ }
++
++ AST_RWLIST_UNLOCK(&glues);
++
++ return current_glue ? 0 : -1;
++}
++
++static void instance_destructor(void *obj)
++{
++ struct ast_rtp_instance *instance = obj;
++
++ /* Pass us off to the engine to destroy */
++ if (instance->data && instance->engine->destroy(instance)) {
++ ast_debug(1, "Engine '%s' failed to destroy RTP instance '%p'\n", instance->engine->name, instance);
++ return;
++ }
++
++ /* Drop our engine reference */
++ ast_module_unref(instance->engine->mod);
++
++ ast_debug(1, "Destroyed RTP instance '%p'\n", instance);
++}
++
++int ast_rtp_instance_destroy(struct ast_rtp_instance *instance)
++{
++ ao2_ref(instance, -1);
++
++ return 0;
++}
++
++struct ast_rtp_instance *ast_rtp_instance_new(const char *engine_name, struct sched_context *sched, struct sockaddr_in *sin, void *data)
++{
++ struct sockaddr_in address = { 0, };
++ struct ast_rtp_instance *instance = NULL;
++ struct ast_rtp_engine *engine = NULL;
++
++ AST_RWLIST_RDLOCK(&engines);
++
++ /* If an engine name was specified try to use it or otherwise use the first one registered */
++ if (!ast_strlen_zero(engine_name)) {
++ AST_RWLIST_TRAVERSE(&engines, engine, entry) {
++ if (!strcmp(engine->name, engine_name)) {
++ break;
++ }
++ }
++ } else {
++ engine = AST_RWLIST_FIRST(&engines);
++ }
++
++ /* If no engine was actually found bail out now */
++ if (!engine) {
++ ast_log(LOG_ERROR, "No RTP engine was found. Do you have one loaded?\n");
++ AST_RWLIST_UNLOCK(&engines);
++ return NULL;
++ }
++
++ /* Bump up the reference count before we return so the module can not be unloaded */
++ ast_module_ref(engine->mod);
++
++ AST_RWLIST_UNLOCK(&engines);
++
++ /* Allocate a new RTP instance */
++ if (!(instance = ao2_alloc(sizeof(*instance), instance_destructor))) {
++ ast_module_unref(engine->mod);
++ return NULL;
++ }
++ instance->engine = engine;
++ instance->local_address.sin_family = AF_INET;
++ instance->local_address.sin_addr = sin->sin_addr;
++ instance->remote_address.sin_family = AF_INET;
++ address.sin_addr = sin->sin_addr;
++
++ ast_debug(1, "Using engine '%s' for RTP instance '%p'\n", engine->name, instance);
++
++ /* And pass it off to the engine to setup */
++ if (instance->engine->new(instance, sched, &address, data)) {
++ ast_debug(1, "Engine '%s' failed to setup RTP instance '%p'\n", engine->name, instance);
++ ao2_ref(instance, -1);
++ return NULL;
++ }
++
++ ast_debug(1, "RTP instance '%p' is setup and ready to go\n", instance);
++
++ return instance;
++}
++
++void ast_rtp_instance_set_data(struct ast_rtp_instance *instance, void *data)
++{
++ instance->data = data;
++}
++
++void *ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
++{
++ return instance->data;
++}
++
++int ast_rtp_instance_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
++{
++ return instance->engine->write(instance, frame);
++}
++
++struct ast_frame *ast_rtp_instance_read(struct ast_rtp_instance *instance, int rtcp)
++{
++ return instance->engine->read(instance, rtcp);
++}
++
++int ast_rtp_instance_set_local_address(struct ast_rtp_instance *instance, struct sockaddr_in *address)
++{
++ instance->local_address.sin_addr = address->sin_addr;
++ instance->local_address.sin_port = address->sin_port;
++ return 0;
++}
++
++int ast_rtp_instance_set_remote_address(struct ast_rtp_instance *instance, struct sockaddr_in *address)
++{
++ instance->remote_address.sin_addr = address->sin_addr;
++ instance->remote_address.sin_port = address->sin_port;
++
++ /* moo */
++
++ if (instance->engine->remote_address_set) {
++ instance->engine->remote_address_set(instance, &instance->remote_address);
++ }
++
++ return 0;
++}
++
++int ast_rtp_instance_set_alt_remote_address(struct ast_rtp_instance *instance, struct sockaddr_in *address)
++{
++ instance->alt_remote_address.sin_addr = address->sin_addr;
++ instance->alt_remote_address.sin_port = address->sin_port;
++
++ /* oink */
++
++ if (instance->engine->alt_remote_address_set) {
++ instance->engine->alt_remote_address_set(instance, &instance->alt_remote_address);
++ }
++
++ return 0;
++}
++
++int ast_rtp_instance_get_local_address(struct ast_rtp_instance *instance, struct sockaddr_in *address)
++{
++ if ((address->sin_family != AF_INET) ||
++ (address->sin_port != instance->local_address.sin_port) ||
++ (address->sin_addr.s_addr != instance->local_address.sin_addr.s_addr)) {
++ memcpy(address, &instance->local_address, sizeof(*address));
++ return 1;
++ }
++
++ return 0;
++}
++
++int ast_rtp_instance_get_remote_address(struct ast_rtp_instance *instance, struct sockaddr_in *address)
++{
++ if ((address->sin_family != AF_INET) ||
++ (address->sin_port != instance->remote_address.sin_port) ||
++ (address->sin_addr.s_addr != instance->remote_address.sin_addr.s_addr)) {
++ memcpy(address, &instance->remote_address, sizeof(*address));
++ return 1;
++ }
++
++ return 0;
++}
++
++void ast_rtp_instance_set_extended_prop(struct ast_rtp_instance *instance, int property, void *value)
++{
++ if (instance->engine->extended_prop_set) {
++ instance->engine->extended_prop_set(instance, property, value);
++ }
++}
++
++void *ast_rtp_instance_get_extended_prop(struct ast_rtp_instance *instance, int property)
++{
++ if (instance->engine->extended_prop_get) {
++ return instance->engine->extended_prop_get(instance, property);
++ }
++
++ return NULL;
++}
++
++void ast_rtp_instance_set_prop(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value)
++{
++ instance->properties[property] = value;
++
++ if (instance->engine->prop_set) {
++ instance->engine->prop_set(instance, property, value);
++ }
++}
++
++int ast_rtp_instance_get_prop(struct ast_rtp_instance *instance, enum ast_rtp_property property)
++{
++ return instance->properties[property];
++}
++
++struct ast_rtp_codecs *ast_rtp_instance_get_codecs(struct ast_rtp_instance *instance)
++{
++ return &instance->codecs;
++}
++
++void ast_rtp_codecs_payloads_clear(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance)
++{
++ int i;
++
++ for (i = 0; i < AST_RTP_MAX_PT; i++) {
++ ast_debug(2, "Clearing payload %d on %p\n", i, codecs);
++ codecs->payloads[i].asterisk_format = 0;
++ codecs->payloads[i].code = 0;
++ if (instance && instance->engine && instance->engine->payload_set) {
++ instance->engine->payload_set(instance, i, 0, 0);
++ }
++ }
++}
++
++void ast_rtp_codecs_payloads_default(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance)
++{
++ int i;
++
++ for (i = 0; i < AST_RTP_MAX_PT; i++) {
++ if (static_RTP_PT[i].code) {
++ ast_debug(2, "Set default payload %d on %p\n", i, codecs);
++ codecs->payloads[i].asterisk_format = static_RTP_PT[i].asterisk_format;
++ codecs->payloads[i].code = static_RTP_PT[i].code;
++ if (instance && instance->engine && instance->engine->payload_set) {
++ instance->engine->payload_set(instance, i, codecs->payloads[i].asterisk_format, codecs->payloads[i].code);
++ }
++ }
++ }
++}
++
++void ast_rtp_codecs_payloads_copy(struct ast_rtp_codecs *src, struct ast_rtp_codecs *dest, struct ast_rtp_instance *instance)
++{
++ int i;
++
++ for (i = 0; i < AST_RTP_MAX_PT; i++) {
++ if (src->payloads[i].code) {
++ ast_debug(2, "Copying payload %d from %p to %p\n", i, src, dest);
++ dest->payloads[i].asterisk_format = src->payloads[i].asterisk_format;
++ dest->payloads[i].code = src->payloads[i].code;
++ if (instance && instance->engine && instance->engine->payload_set) {
++ instance->engine->payload_set(instance, i, dest->payloads[i].asterisk_format, dest->payloads[i].code);
++ }
++ }
++ }
++}
++
++void ast_rtp_codecs_payloads_set_m_type(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload)
++{
++ if (payload < 0 || payload > AST_RTP_MAX_PT || !static_RTP_PT[payload].code) {
++ return;
++ }
++
++ codecs->payloads[payload].asterisk_format = static_RTP_PT[payload].asterisk_format;
++ codecs->payloads[payload].code = static_RTP_PT[payload].code;
++
++ ast_debug(1, "Setting payload %d based on m type on %p\n", payload, codecs);
++
++ if (instance && instance->engine && instance->engine->payload_set) {
++ instance->engine->payload_set(instance, payload, codecs->payloads[payload].asterisk_format, codecs->payloads[payload].code);
++ }
++}
++
++int ast_rtp_codecs_payloads_set_rtpmap_type_rate(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int pt,
++ char *mimetype, char *mimesubtype,
++ enum ast_rtp_options options,
++ unsigned int sample_rate)
++{
++ unsigned int i;
++ int found = 0;
++
++ if (pt < 0 || pt > AST_RTP_MAX_PT)
++ return -1; /* bogus payload type */
++
++ for (i = 0; i < ARRAY_LEN(ast_rtp_mime_types); ++i) {
++ const struct ast_rtp_mime_type *t = &ast_rtp_mime_types[i];
++
++ if (strcasecmp(mimesubtype, t->subtype)) {
++ continue;
++ }
++
++ if (strcasecmp(mimetype, t->type)) {
++ continue;
++ }
++
++ /* if both sample rates have been supplied, and they don't match,
++ then this not a match; if one has not been supplied, then the
++ rates are not compared */
++ if (sample_rate && t->sample_rate &&
++ (sample_rate != t->sample_rate)) {
++ continue;
++ }
++
++ found = 1;
++ codecs->payloads[pt] = t->payload_type;
++
++ if ((t->payload_type.code == AST_FORMAT_G726) &&
++ t->payload_type.asterisk_format &&
++ (options & AST_RTP_OPT_G726_NONSTANDARD)) {
++ codecs->payloads[pt].code = AST_FORMAT_G726_AAL2;
++ }
++
++ if (instance && instance->engine && instance->engine->payload_set) {
++ instance->engine->payload_set(instance, pt, codecs->payloads[i].asterisk_format, codecs->payloads[i].code);
++ }
++
++ break;
++ }
++
++ return (found ? 0 : -2);
++}
++
++int ast_rtp_codecs_payloads_set_rtpmap_type(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload, char *mimetype, char *mimesubtype, enum ast_rtp_options options)
++{
++ return ast_rtp_codecs_payloads_set_rtpmap_type_rate(codecs, instance, payload, mimetype, mimesubtype, options, 0);
++}
++
++void ast_rtp_codecs_payloads_unset(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload)
++{
++ if (payload < 0 || payload > AST_RTP_MAX_PT) {
++ return;
++ }
++
++ ast_debug(2, "Unsetting payload %d on %p\n", payload, codecs);
++
++ codecs->payloads[payload].asterisk_format = 0;
++ codecs->payloads[payload].code = 0;
++
++ if (instance && instance->engine && instance->engine->payload_set) {
++ instance->engine->payload_set(instance, payload, 0, 0);
++ }
++}
++
++struct ast_rtp_payload_type ast_rtp_codecs_payload_lookup(struct ast_rtp_codecs *codecs, int payload)
++{
++ struct ast_rtp_payload_type result = { .asterisk_format = 0, };
++
++ if (payload < 0 || payload > AST_RTP_MAX_PT) {
++ return result;
++ }
++
++ result.asterisk_format = codecs->payloads[payload].asterisk_format;
++ result.code = codecs->payloads[payload].code;
++
++ if (!result.code) {
++ result = static_RTP_PT[payload];
++ }
++
++ return result;
++}
++
++void ast_rtp_codecs_payload_formats(struct ast_rtp_codecs *codecs, int *astformats, int *nonastformats)
++{
++ int i;
++
++ *astformats = *nonastformats = 0;
++
++ for (i = 0; i < AST_RTP_MAX_PT; i++) {
++ if (codecs->payloads[i].code) {
++ ast_debug(1, "Incorporating payload %d on %p\n", i, codecs);
++ }
++ if (codecs->payloads[i].asterisk_format) {
++ *astformats |= codecs->payloads[i].code;
++ } else {
++ *nonastformats |= codecs->payloads[i].code;
++ }
++ }
++}
++
++int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, const int asterisk_format, const int code)
++{
++ int i;
++
++ for (i = 0; i < AST_RTP_MAX_PT; i++) {
++ if (codecs->payloads[i].asterisk_format == asterisk_format && codecs->payloads[i].code == code) {
++ ast_debug(2, "Found code %d at payload %d on %p\n", code, i, codecs);
++ return i;
++ }
++ }
++
++ for (i = 0; i < AST_RTP_MAX_PT; i++) {
++ if (static_RTP_PT[i].asterisk_format == asterisk_format && static_RTP_PT[i].code == code) {
++ return i;
++ }
++ }
++
++ return -1;
++}
++
++const char *ast_rtp_lookup_mime_subtype2(const int asterisk_format, const int code, enum ast_rtp_options options)
++{
++ int i;
++
++ for (i = 0; i < ARRAY_LEN(ast_rtp_mime_types); i++) {
++ if (ast_rtp_mime_types[i].payload_type.code == code && ast_rtp_mime_types[i].payload_type.asterisk_format == asterisk_format) {
++ if (asterisk_format && (code == AST_FORMAT_G726_AAL2) && (options & AST_RTP_OPT_G726_NONSTANDARD)) {
++ return "G726-32";
++ } else {
++ return ast_rtp_mime_types[i].subtype;
++ }
++ }
++ }
++
++ return "";
++}
++
++unsigned int ast_rtp_lookup_sample_rate2(int asterisk_format, int code)
++{
++ unsigned int i;
++
++ for (i = 0; i < ARRAY_LEN(ast_rtp_mime_types); ++i) {
++ if ((ast_rtp_mime_types[i].payload_type.code == code) && (ast_rtp_mime_types[i].payload_type.asterisk_format == asterisk_format)) {
++ return ast_rtp_mime_types[i].sample_rate;
++ }
++ }
++
++ return 0;
++}
++
++char *ast_rtp_lookup_mime_multiple2(struct ast_str *buf, const int capability, const int asterisk_format, enum ast_rtp_options options)
++{
++ int format, found = 0;
++
++ if (!buf) {
++ return NULL;
++ }
++
++ ast_str_append(&buf, 0, "0x%x (", capability);
++
++ for (format = 1; format < AST_RTP_MAX; format <<= 1) {
++ if (capability & format) {
++ const char *name = ast_rtp_lookup_mime_subtype2(asterisk_format, format, options);
++ ast_str_append(&buf, 0, "%s|", name);
++ found = 1;
++ }
++ }
++
++ ast_str_append(&buf, 0, "%s", found ? ")" : "nothing)");
++
++ return ast_str_buffer(buf);
++}
++
++void ast_rtp_codecs_packetization_set(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, struct ast_codec_pref *prefs)
++{
++ codecs->pref = *prefs;
++
++ if (instance && instance->engine->packetization_set) {
++ instance->engine->packetization_set(instance, &instance->codecs.pref);
++ }
++}
++
++int ast_rtp_instance_dtmf_begin(struct ast_rtp_instance *instance, char digit)
++{
++ return instance->engine->dtmf_begin ? instance->engine->dtmf_begin(instance, digit) : -1;
++}
++
++int ast_rtp_instance_dtmf_end(struct ast_rtp_instance *instance, char digit)
++{
++ return instance->engine->dtmf_end ? instance->engine->dtmf_end(instance, digit) : -1;
++}
++
++int ast_rtp_instance_dtmf_mode_set(struct ast_rtp_instance *instance, enum ast_rtp_dtmf_mode dtmf_mode)
++{
++ if (!instance->engine->dtmf_mode_set || instance->engine->dtmf_mode_set(instance, dtmf_mode)) {
++ return -1;
++ }
++
++ instance->dtmf_mode = dtmf_mode;
++
++ return 0;
++}
++
++enum ast_rtp_dtmf_mode ast_rtp_instance_dtmf_mode_get(struct ast_rtp_instance *instance)
++{
++ return instance->dtmf_mode;
++}
++
++void ast_rtp_instance_new_source(struct ast_rtp_instance *instance)
++{
++ if (instance->engine->new_source) {
++ instance->engine->new_source(instance);
++ }
++}
++
++int ast_rtp_instance_set_qos(struct ast_rtp_instance *instance, int tos, int cos, const char *desc)
++{
++ return instance->engine->qos ? instance->engine->qos(instance, tos, cos, desc) : -1;
++}
++
++void ast_rtp_instance_stop(struct ast_rtp_instance *instance)
++{
++ if (instance->engine->stop) {
++ instance->engine->stop(instance);
++ }
++}
++
++int ast_rtp_instance_fd(struct ast_rtp_instance *instance, int rtcp)
++{
++ return instance->engine->fd ? instance->engine->fd(instance, rtcp) : -1;
++}
++
++struct ast_rtp_glue *ast_rtp_instance_get_glue(const char *type)
++{
++ struct ast_rtp_glue *glue = NULL;
++
++ AST_RWLIST_RDLOCK(&glues);
++
++ AST_RWLIST_TRAVERSE(&glues, glue, entry) {
++ if (!strcasecmp(glue->type, type)) {
++ break;
++ }
++ }
++
++ AST_RWLIST_UNLOCK(&glues);
++
++ return glue;
++}
++
++static enum ast_bridge_result local_bridge_loop(struct ast_channel *c0, struct ast_channel *c1, struct ast_rtp_instance *instance0, struct ast_rtp_instance *instance1, int timeoutms, int flags, struct ast_frame **fo, struct ast_channel **rc, void *pvt0, void *pvt1)
++{
++ enum ast_bridge_result res = AST_BRIDGE_FAILED;
++ struct ast_channel *who = NULL, *other = NULL, *cs[3] = { NULL, };
++ struct ast_frame *fr = NULL;
++
++ /* Start locally bridging both instances */
++ if (instance0->engine->local_bridge && instance0->engine->local_bridge(instance0, instance1)) {
++ ast_debug(1, "Failed to locally bridge %s to %s, backing out.\n", c0->name, c1->name);
++ ast_channel_unlock(c0);
++ ast_channel_unlock(c1);
++ return AST_BRIDGE_FAILED_NOWARN;
++ }
++ if (instance1->engine->local_bridge && instance1->engine->local_bridge(instance1, instance0)) {
++ ast_debug(1, "Failed to locally bridge %s to %s, backing out.\n", c1->name, c0->name);
++ if (instance0->engine->local_bridge) {
++ instance0->engine->local_bridge(instance0, NULL);
++ }
++ ast_channel_unlock(c0);
++ ast_channel_unlock(c1);
++ return AST_BRIDGE_FAILED_NOWARN;
++ }
++
++ ast_channel_unlock(c0);
++ ast_channel_unlock(c1);
++
++ instance0->bridged = instance1;
++ instance1->bridged = instance0;
++
++ ast_poll_channel_add(c0, c1);
++
++ /* Hop into a loop waiting for a frame from either channel */
++ cs[0] = c0;
++ cs[1] = c1;
++ cs[2] = NULL;
++ for (;;) {
++ /* If the underlying formats have changed force this bridge to break */
++ if ((c0->rawreadformat != c1->rawwriteformat) || (c1->rawreadformat != c0->rawwriteformat)) {
++ ast_debug(1, "rtp-engine-local-bridge: Oooh, formats changed, backing out\n");
++ res = AST_BRIDGE_FAILED_NOWARN;
++ break;
++ }
++ /* Check if anything changed */
++ if ((c0->tech_pvt != pvt0) ||
++ (c1->tech_pvt != pvt1) ||
++ (c0->masq || c0->masqr || c1->masq || c1->masqr) ||
++ (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) {
++ ast_debug(1, "rtp-engine-local-bridge: Oooh, something is weird, backing out\n");
++ /* If a masquerade needs to happen we have to try to read in a frame so that it actually happens. Without this we risk being called again and going into a loop */
++ if ((c0->masq || c0->masqr) && (fr = ast_read(c0))) {
++ ast_frfree(fr);
++ }
++ if ((c1->masq || c1->masqr) && (fr = ast_read(c1))) {
++ ast_frfree(fr);
++ }
++ res = AST_BRIDGE_RETRY;
++ break;
++ }
++ /* Wait on a channel to feed us a frame */
++ if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
++ if (!timeoutms) {
++ res = AST_BRIDGE_RETRY;
++ break;
++ }
++ ast_debug(2, "rtp-engine-local-bridge: Ooh, empty read...\n");
++ if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
++ break;
++ }
++ continue;
++ }
++ /* Read in frame from channel */
++ fr = ast_read(who);
++ other = (who == c0) ? c1 : c0;
++ /* Depending on the frame we may need to break out of our bridge */
++ if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) &&
++ ((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) |
++ ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)))) {
++ /* Record received frame and who */
++ *fo = fr;
++ *rc = who;
++ ast_debug(1, "rtp-engine-local-bridge: Ooh, got a %s\n", fr ? "digit" : "hangup");
++ res = AST_BRIDGE_COMPLETE;
++ break;
++ } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
++ if ((fr->subclass == AST_CONTROL_HOLD) ||
++ (fr->subclass == AST_CONTROL_UNHOLD) ||
++ (fr->subclass == AST_CONTROL_VIDUPDATE) ||
++ (fr->subclass == AST_CONTROL_T38) ||
++ (fr->subclass == AST_CONTROL_SRCUPDATE)) {
++ /* If we are going on hold, then break callback mode and P2P bridging */
++ if (fr->subclass == AST_CONTROL_HOLD) {
++ if (instance0->engine->local_bridge) {
++ instance0->engine->local_bridge(instance0, NULL);
++ }
++ if (instance1->engine->local_bridge) {
++ instance1->engine->local_bridge(instance1, NULL);
++ }
++ instance0->bridged = NULL;
++ instance1->bridged = NULL;
++ } else if (fr->subclass == AST_CONTROL_UNHOLD) {
++ if (instance0->engine->local_bridge) {
++ instance0->engine->local_bridge(instance0, instance1);
++ }
++ if (instance1->engine->local_bridge) {
++ instance1->engine->local_bridge(instance1, instance0);
++ }
++ instance0->bridged = instance1;
++ instance1->bridged = instance0;
++ }
++ ast_indicate_data(other, fr->subclass, fr->data.ptr, fr->datalen);
++ ast_frfree(fr);
++ } else {
++ *fo = fr;
++ *rc = who;
++ ast_debug(1, "rtp-engine-local-bridge: Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name);
++ res = AST_BRIDGE_COMPLETE;
++ break;
++ }
++ } else {
++ if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
++ (fr->frametype == AST_FRAME_DTMF_END) ||
++ (fr->frametype == AST_FRAME_VOICE) ||
++ (fr->frametype == AST_FRAME_VIDEO) ||
++ (fr->frametype == AST_FRAME_IMAGE) ||
++ (fr->frametype == AST_FRAME_HTML) ||
++ (fr->frametype == AST_FRAME_MODEM) ||
++ (fr->frametype == AST_FRAME_TEXT)) {
++ ast_write(other, fr);
++ }
++
++ ast_frfree(fr);
++ }
++ /* Swap priority */
++ cs[2] = cs[0];
++ cs[0] = cs[1];
++ cs[1] = cs[2];
++ }
++
++ /* Stop locally bridging both instances */
++ if (instance0->engine->local_bridge) {
++ instance0->engine->local_bridge(instance0, NULL);
++ }
++ if (instance1->engine->local_bridge) {
++ instance1->engine->local_bridge(instance1, NULL);
++ }
++
++ instance0->bridged = NULL;
++ instance1->bridged = NULL;
++
++ ast_poll_channel_del(c0, c1);
++
++ return res;
++}
++
++static enum ast_bridge_result remote_bridge_loop(struct ast_channel *c0, struct ast_channel *c1, struct ast_rtp_instance *instance0, struct ast_rtp_instance *instance1,
++ struct ast_rtp_instance *vinstance0, struct ast_rtp_instance *vinstance1, struct ast_rtp_instance *tinstance0,
++ struct ast_rtp_instance *tinstance1, struct ast_rtp_glue *glue0, struct ast_rtp_glue *glue1, int codec0, int codec1, int timeoutms,
++ int flags, struct ast_frame **fo, struct ast_channel **rc, void *pvt0, void *pvt1)
++{
++ enum ast_bridge_result res = AST_BRIDGE_FAILED;
++ struct ast_channel *who = NULL, *other = NULL, *cs[3] = { NULL, };
++ int oldcodec0 = codec0, oldcodec1 = codec1;
++ struct sockaddr_in ac1 = {0,}, vac1 = {0,}, tac1 = {0,}, ac0 = {0,}, vac0 = {0,}, tac0 = {0,};
++ struct sockaddr_in t1 = {0,}, vt1 = {0,}, tt1 = {0,}, t0 = {0,}, vt0 = {0,}, tt0 = {0,};
++ struct ast_frame *fr = NULL;
++
++ /* Test the first channel */
++ if (!(glue0->update_peer(c0, instance1, vinstance1, tinstance1, codec1, 0))) {
++ ast_rtp_instance_get_remote_address(instance1, &ac1);
++ if (vinstance1) {
++ ast_rtp_instance_get_remote_address(vinstance1, &vac1);
++ }
++ if (tinstance1) {
++ ast_rtp_instance_get_remote_address(tinstance1, &tac1);
++ }
++ } else {
++ ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name);
++ }
++
++ /* Test the second channel */
++ if (!(glue1->update_peer(c1, instance0, vinstance0, tinstance0, codec0, 0))) {
++ ast_rtp_instance_get_remote_address(instance0, &ac0);
++ if (vinstance0) {
++ ast_rtp_instance_get_remote_address(instance0, &vac0);
++ }
++ if (tinstance0) {
++ ast_rtp_instance_get_remote_address(instance0, &tac0);
++ }
++ } else {
++ ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c1->name, c0->name);
++ }
++
++ ast_channel_unlock(c0);
++ ast_channel_unlock(c1);
++
++ instance0->bridged = instance1;
++ instance1->bridged = instance0;
++
++ ast_poll_channel_add(c0, c1);
++
++ /* Go into a loop handling any stray frames that may come in */
++ cs[0] = c0;
++ cs[1] = c1;
++ cs[2] = NULL;
++ for (;;) {
++ /* Check if anything changed */
++ if ((c0->tech_pvt != pvt0) ||
++ (c1->tech_pvt != pvt1) ||
++ (c0->masq || c0->masqr || c1->masq || c1->masqr) ||
++ (c0->monitor || c0->audiohooks || c1->monitor || c1->audiohooks)) {
++ ast_debug(1, "Oooh, something is weird, backing out\n");
++ res = AST_BRIDGE_RETRY;
++ break;
++ }
++
++ /* Check if they have changed their address */
++ ast_rtp_instance_get_remote_address(instance1, &t1);
++ if (vinstance1) {
++ ast_rtp_instance_get_remote_address(vinstance1, &vt1);
++ }
++ if (tinstance1) {
++ ast_rtp_instance_get_remote_address(tinstance1, &tt1);
++ }
++ if (glue1->get_codec) {
++ codec1 = glue1->get_codec(c1);
++ }
++
++ ast_rtp_instance_get_remote_address(instance0, &t0);
++ if (vinstance0) {
++ ast_rtp_instance_get_remote_address(vinstance0, &vt0);
++ }
++ if (tinstance0) {
++ ast_rtp_instance_get_remote_address(tinstance0, &tt0);
++ }
++ if (glue0->get_codec) {
++ codec0 = glue0->get_codec(c0);
++ }
++
++ if ((inaddrcmp(&t1, &ac1)) ||
++ (vinstance1 && inaddrcmp(&vt1, &vac1)) ||
++ (tinstance1 && inaddrcmp(&tt1, &tac1)) ||
++ (codec1 != oldcodec1)) {
++ ast_debug(1, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
++ c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port), codec1);
++ ast_debug(1, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n",
++ c1->name, ast_inet_ntoa(vt1.sin_addr), ntohs(vt1.sin_port), codec1);
++ ast_debug(1, "Oooh, '%s' changed end taddress to %s:%d (format %d)\n",
++ c1->name, ast_inet_ntoa(tt1.sin_addr), ntohs(tt1.sin_port), codec1);
++ ast_debug(1, "Oooh, '%s' was %s:%d/(format %d)\n",
++ c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1);
++ ast_debug(1, "Oooh, '%s' was %s:%d/(format %d)\n",
++ c1->name, ast_inet_ntoa(vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1);
++ ast_debug(1, "Oooh, '%s' was %s:%d/(format %d)\n",
++ c1->name, ast_inet_ntoa(tac1.sin_addr), ntohs(tac1.sin_port), oldcodec1);
++ if (glue0->update_peer(c0, t1.sin_addr.s_addr ? instance1 : NULL, vt1.sin_addr.s_addr ? vinstance1 : NULL, tt1.sin_addr.s_addr ? tinstance1 : NULL, codec1, 0)) {
++ ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name);
++ }
++ memcpy(&ac1, &t1, sizeof(ac1));
++ memcpy(&vac1, &vt1, sizeof(vac1));
++ memcpy(&tac1, &tt1, sizeof(tac1));
++ oldcodec1 = codec1;
++ }
++ if ((inaddrcmp(&t0, &ac0)) ||
++ (vinstance0 && inaddrcmp(&vt0, &vac0)) ||
++ (tinstance0 && inaddrcmp(&tt0, &tac0)) ||
++ (codec0 != oldcodec0)) {
++ ast_debug(1, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
++ c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port), codec0);
++ ast_debug(1, "Oooh, '%s' was %s:%d/(format %d)\n",
++ c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0);
++ if (glue1->update_peer(c1, t0.sin_addr.s_addr ? instance0 : NULL, vt0.sin_addr.s_addr ? vinstance0 : NULL, tt0.sin_addr.s_addr ? tinstance0 : NULL, codec0, 0)) {
++ ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name);
++ }
++ memcpy(&ac0, &t0, sizeof(ac0));
++ memcpy(&vac0, &vt0, sizeof(vac0));
++ memcpy(&tac0, &tt0, sizeof(tac0));
++ oldcodec0 = codec0;
++ }
++
++ /* Wait for frame to come in on the channels */
++ if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
++ if (!timeoutms) {
++ res = AST_BRIDGE_RETRY;
++ break;
++ }
++ ast_debug(1, "Ooh, empty read...\n");
++ if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
++ break;
++ }
++ continue;
++ }
++ fr = ast_read(who);
++ other = (who == c0) ? c1 : c0;
++ if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) &&
++ (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) ||
++ ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) {
++ /* Break out of bridge */
++ *fo = fr;
++ *rc = who;
++ ast_debug(1, "Oooh, got a %s\n", fr ? "digit" : "hangup");
++ res = AST_BRIDGE_COMPLETE;
++ break;
++ } else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
++ if ((fr->subclass == AST_CONTROL_HOLD) ||
++ (fr->subclass == AST_CONTROL_UNHOLD) ||
++ (fr->subclass == AST_CONTROL_VIDUPDATE) ||
++ (fr->subclass == AST_CONTROL_T38) ||
++ (fr->subclass == AST_CONTROL_SRCUPDATE)) {
++ if (fr->subclass == AST_CONTROL_HOLD) {
++ /* If we someone went on hold we want the other side to reinvite back to us */
++ if (who == c0) {
++ glue1->update_peer(c1, NULL, NULL, NULL, 0, 0);
++ } else {
++ glue0->update_peer(c0, NULL, NULL, NULL, 0, 0);
++ }
++ } else if (fr->subclass == AST_CONTROL_UNHOLD) {
++ /* If they went off hold they should go back to being direct */
++ if (who == c0) {
++ glue1->update_peer(c1, instance0, vinstance0, tinstance0, codec0, 0);
++ } else {
++ glue0->update_peer(c0, instance1, vinstance1, tinstance1, codec1, 0);
++ }
++ }
++ /* Update local address information */
++ ast_rtp_instance_get_remote_address(instance0, &t0);
++ memcpy(&ac0, &t0, sizeof(ac0));
++ ast_rtp_instance_get_remote_address(instance1, &t1);
++ memcpy(&ac1, &t1, sizeof(ac1));
++ /* Update codec information */
++ if (glue0->get_codec && c0->tech_pvt) {
++ oldcodec0 = codec0 = glue0->get_codec(c0);
++ }
++ if (glue1->get_codec && c1->tech_pvt) {
++ oldcodec1 = codec1 = glue1->get_codec(c1);
++ }
++ ast_indicate_data(other, fr->subclass, fr->data.ptr, fr->datalen);
++ ast_frfree(fr);
++ } else {
++ *fo = fr;
++ *rc = who;
++ ast_debug(1, "Got a FRAME_CONTROL (%d) frame on channel %s\n", fr->subclass, who->name);
++ return AST_BRIDGE_COMPLETE;
++ }
++ } else {
++ if ((fr->frametype == AST_FRAME_DTMF_BEGIN) ||
++ (fr->frametype == AST_FRAME_DTMF_END) ||
++ (fr->frametype == AST_FRAME_VOICE) ||
++ (fr->frametype == AST_FRAME_VIDEO) ||
++ (fr->frametype == AST_FRAME_IMAGE) ||
++ (fr->frametype == AST_FRAME_HTML) ||
++ (fr->frametype == AST_FRAME_MODEM) ||
++ (fr->frametype == AST_FRAME_TEXT)) {
++ ast_write(other, fr);
++ }
++ ast_frfree(fr);
++ }
++ /* Swap priority */
++ cs[2] = cs[0];
++ cs[0] = cs[1];
++ cs[1] = cs[2];
++ }
++
++ if (glue0->update_peer(c0, NULL, NULL, NULL, 0, 0)) {
++ ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
++ }
++ if (glue1->update_peer(c1, NULL, NULL, NULL, 0, 0)) {
++ ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
++ }
++
++ instance0->bridged = NULL;
++ instance1->bridged = NULL;
++
++ ast_poll_channel_del(c0, c1);
++
++ return res;
++}
++
++/*!
++ * \brief Conditionally unref an rtp instance
++ */
++static void unref_instance_cond(struct ast_rtp_instance **instance)
++{
++ if (*instance) {
++ ao2_ref(*instance, -1);
++ *instance = NULL;
++ }
++}
++
++enum ast_bridge_result ast_rtp_instance_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
++{
++ struct ast_rtp_instance *instance0 = NULL, *instance1 = NULL,
++ *vinstance0 = NULL, *vinstance1 = NULL,
++ *tinstance0 = NULL, *tinstance1 = NULL;
++ struct ast_rtp_glue *glue0, *glue1;
++ enum ast_rtp_glue_result audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID, video_glue0_res = AST_RTP_GLUE_RESULT_FORBID, text_glue0_res = AST_RTP_GLUE_RESULT_FORBID;
++ enum ast_rtp_glue_result audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID, video_glue1_res = AST_RTP_GLUE_RESULT_FORBID, text_glue1_res = AST_RTP_GLUE_RESULT_FORBID;
++ enum ast_bridge_result res = AST_BRIDGE_FAILED;
++ int codec0 = 0, codec1 = 0;
++ int unlock_chans = 1;
++
++ /* Lock both channels so we can look for the glue that binds them together */
++ ast_channel_lock(c0);
++ while (ast_channel_trylock(c1)) {
++ ast_channel_unlock(c0);
++ usleep(1);
++ ast_channel_lock(c0);
++ }
++
++ /* Ensure neither channel got hungup during lock avoidance */
++ if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
++ ast_log(LOG_WARNING, "Got hangup while attempting to bridge '%s' and '%s'\n", c0->name, c1->name);
++ goto done;
++ }
++
++ /* Grab glue that binds each channel to something using the RTP engine */
++ if (!(glue0 = ast_rtp_instance_get_glue(c0->tech->type)) || !(glue1 = ast_rtp_instance_get_glue(c1->tech->type))) {
++ ast_debug(1, "Can't find native functions for channel '%s'\n", glue0 ? c1->name : c0->name);
++ goto done;
++ }
++
++ audio_glue0_res = glue0->get_rtp_info(c0, &instance0);
++ video_glue0_res = glue0->get_vrtp_info ? glue0->get_vrtp_info(c0, &vinstance0) : AST_RTP_GLUE_RESULT_FORBID;
++ text_glue0_res = glue0->get_trtp_info ? glue0->get_trtp_info(c0, &tinstance0) : AST_RTP_GLUE_RESULT_FORBID;
++
++ audio_glue1_res = glue1->get_rtp_info(c1, &instance1);
++ video_glue1_res = glue1->get_vrtp_info ? glue1->get_vrtp_info(c1, &vinstance1) : AST_RTP_GLUE_RESULT_FORBID;
++ text_glue1_res = glue1->get_trtp_info ? glue1->get_trtp_info(c1, &tinstance1) : AST_RTP_GLUE_RESULT_FORBID;
++
++ /* If we are carrying video, and both sides are not going to remotely bridge... fail the native bridge */
++ if (video_glue0_res != AST_RTP_GLUE_RESULT_FORBID && (audio_glue0_res != AST_RTP_GLUE_RESULT_REMOTE || video_glue0_res != AST_RTP_GLUE_RESULT_REMOTE)) {
++ audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID;
++ }
++ if (video_glue1_res != AST_RTP_GLUE_RESULT_FORBID && (audio_glue1_res != AST_RTP_GLUE_RESULT_REMOTE || video_glue1_res != AST_RTP_GLUE_RESULT_REMOTE)) {
++ audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID;
++ }
++
++ /* If any sort of bridge is forbidden just completely bail out and go back to generic bridging */
++ if (audio_glue0_res == AST_RTP_GLUE_RESULT_FORBID || audio_glue1_res == AST_RTP_GLUE_RESULT_FORBID) {
++ res = AST_BRIDGE_FAILED_NOWARN;
++ goto done;
++ }
++
++ /* If we need to get DTMF see if we can do it outside of the RTP stream itself */
++ if ((flags & AST_BRIDGE_DTMF_CHANNEL_0) && instance0->properties[AST_RTP_PROPERTY_DTMF]) {
++ res = AST_BRIDGE_FAILED_NOWARN;
++ goto done;
++ }
++ if ((flags & AST_BRIDGE_DTMF_CHANNEL_1) && instance1->properties[AST_RTP_PROPERTY_DTMF]) {
++ res = AST_BRIDGE_FAILED_NOWARN;
++ goto done;
++ }
++
++ /* If we have gotten to a local bridge make sure that both sides have the same local bridge callback and that they are DTMF compatible */
++ if ((audio_glue0_res == AST_RTP_GLUE_RESULT_LOCAL || audio_glue1_res == AST_RTP_GLUE_RESULT_LOCAL) && ((instance0->engine->local_bridge != instance1->engine->local_bridge) || (instance0->engine->dtmf_compatible && !instance0->engine->dtmf_compatible(c0, instance0, c1, instance1)))) {
++ res = AST_BRIDGE_FAILED_NOWARN;
++ goto done;
++ }
++
++ /* Make sure that codecs match */
++ codec0 = glue0->get_codec ? glue0->get_codec(c0) : 0;
++ codec1 = glue1->get_codec ? glue1->get_codec(c1) : 0;
++ if (codec0 && codec1 && !(codec0 & codec1)) {
++ ast_debug(1, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1);
++ res = AST_BRIDGE_FAILED_NOWARN;
++ goto done;
++ }
++
++ /* Depending on the end result for bridging either do a local bridge or remote bridge */
++ if (audio_glue0_res == AST_RTP_GLUE_RESULT_LOCAL || audio_glue1_res == AST_RTP_GLUE_RESULT_LOCAL) {
++ ast_verbose(VERBOSE_PREFIX_3 "Locally bridging %s and %s\n", c0->name, c1->name);
++ res = local_bridge_loop(c0, c1, instance0, instance1, timeoutms, flags, fo, rc, c0->tech_pvt, c1->tech_pvt);
++ } else {
++ ast_verbose(VERBOSE_PREFIX_3 "Remotely bridging %s and %s\n", c0->name, c1->name);
++ res = remote_bridge_loop(c0, c1, instance0, instance1, vinstance0, vinstance1,
++ tinstance0, tinstance1, glue0, glue1, codec0, codec1, timeoutms, flags,
++ fo, rc, c0->tech_pvt, c1->tech_pvt);
++ }
++
++ unlock_chans = 0;
++
++done:
++ if (unlock_chans) {
++ ast_channel_unlock(c0);
++ ast_channel_unlock(c1);
++ }
++
++ unref_instance_cond(&instance0);
++ unref_instance_cond(&instance1);
++ unref_instance_cond(&vinstance0);
++ unref_instance_cond(&vinstance1);
++ unref_instance_cond(&tinstance0);
++ unref_instance_cond(&tinstance1);
++
++ return res;
++}
++
++struct ast_rtp_instance *ast_rtp_instance_get_bridged(struct ast_rtp_instance *instance)
++{
++ return instance->bridged;
++}
++
++void ast_rtp_instance_early_bridge_make_compatible(struct ast_channel *c0, struct ast_channel *c1)
++{
++ struct ast_rtp_instance *instance0 = NULL, *instance1 = NULL,
++ *vinstance0 = NULL, *vinstance1 = NULL,
++ *tinstance0 = NULL, *tinstance1 = NULL;
++ struct ast_rtp_glue *glue0, *glue1;
++ enum ast_rtp_glue_result audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID, video_glue0_res = AST_RTP_GLUE_RESULT_FORBID, text_glue0_res = AST_RTP_GLUE_RESULT_FORBID;
++ enum ast_rtp_glue_result audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID, video_glue1_res = AST_RTP_GLUE_RESULT_FORBID, text_glue1_res = AST_RTP_GLUE_RESULT_FORBID;
++ int codec0 = 0, codec1 = 0;
++ int res = 0;
++
++ /* Lock both channels so we can look for the glue that binds them together */
++ ast_channel_lock(c0);
++ while (ast_channel_trylock(c1)) {
++ ast_channel_unlock(c0);
++ usleep(1);
++ ast_channel_lock(c0);
++ }
++
++ /* Grab glue that binds each channel to something using the RTP engine */
++ if (!(glue0 = ast_rtp_instance_get_glue(c0->tech->type)) || !(glue1 = ast_rtp_instance_get_glue(c1->tech->type))) {
++ ast_debug(1, "Can't find native functions for channel '%s'\n", glue0 ? c1->name : c0->name);
++ goto done;
++ }
++
++ audio_glue0_res = glue0->get_rtp_info(c0, &instance0);
++ video_glue0_res = glue0->get_vrtp_info ? glue0->get_vrtp_info(c0, &vinstance0) : AST_RTP_GLUE_RESULT_FORBID;
++ text_glue0_res = glue0->get_trtp_info ? glue0->get_trtp_info(c0, &tinstance0) : AST_RTP_GLUE_RESULT_FORBID;
++
++ audio_glue1_res = glue1->get_rtp_info(c1, &instance1);
++ video_glue1_res = glue1->get_vrtp_info ? glue1->get_vrtp_info(c1, &vinstance1) : AST_RTP_GLUE_RESULT_FORBID;
++ text_glue1_res = glue1->get_trtp_info ? glue1->get_trtp_info(c1, &tinstance1) : AST_RTP_GLUE_RESULT_FORBID;
++
++ /* If we are carrying video, and both sides are not going to remotely bridge... fail the native bridge */
++ if (video_glue0_res != AST_RTP_GLUE_RESULT_FORBID && (audio_glue0_res != AST_RTP_GLUE_RESULT_REMOTE || video_glue0_res != AST_RTP_GLUE_RESULT_REMOTE)) {
++ audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID;
++ }
++ if (video_glue1_res != AST_RTP_GLUE_RESULT_FORBID && (audio_glue1_res != AST_RTP_GLUE_RESULT_REMOTE || video_glue1_res != AST_RTP_GLUE_RESULT_REMOTE)) {
++ audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID;
++ }
++ if (audio_glue0_res == AST_RTP_GLUE_RESULT_REMOTE && (video_glue0_res == AST_RTP_GLUE_RESULT_FORBID || video_glue0_res == AST_RTP_GLUE_RESULT_REMOTE) && glue0->get_codec(c0)) {
++ codec0 = glue0->get_codec(c0);
++ }
++ if (audio_glue1_res == AST_RTP_GLUE_RESULT_REMOTE && (video_glue1_res == AST_RTP_GLUE_RESULT_FORBID || video_glue1_res == AST_RTP_GLUE_RESULT_REMOTE) && glue1->get_codec(c1)) {
++ codec1 = glue1->get_codec(c1);
++ }
++
++ /* If any sort of bridge is forbidden just completely bail out and go back to generic bridging */
++ if (audio_glue0_res != AST_RTP_GLUE_RESULT_REMOTE || audio_glue1_res != AST_RTP_GLUE_RESULT_REMOTE) {
++ goto done;
++ }
++
++ /* Make sure we have matching codecs */
++ if (!(codec0 & codec1)) {
++ goto done;
++ }
++
++ ast_rtp_codecs_payloads_copy(&instance0->codecs, &instance1->codecs, instance1);
++
++ if (vinstance0 && vinstance1) {
++ ast_rtp_codecs_payloads_copy(&vinstance0->codecs, &vinstance1->codecs, vinstance1);
++ }
++ if (tinstance0 && tinstance1) {
++ ast_rtp_codecs_payloads_copy(&tinstance0->codecs, &tinstance1->codecs, tinstance1);
++ }
++
++ res = 0;
++
++done:
++ ast_channel_unlock(c0);
++ ast_channel_unlock(c1);
++
++ unref_instance_cond(&instance0);
++ unref_instance_cond(&instance1);
++ unref_instance_cond(&vinstance0);
++ unref_instance_cond(&vinstance1);
++ unref_instance_cond(&tinstance0);
++ unref_instance_cond(&tinstance1);
++
++ if (!res) {
++ ast_debug(1, "Seeded SDP of '%s' with that of '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
++ }
++}
++
++int ast_rtp_instance_early_bridge(struct ast_channel *c0, struct ast_channel *c1)
++{
++ struct ast_rtp_instance *instance0 = NULL, *instance1 = NULL,
++ *vinstance0 = NULL, *vinstance1 = NULL,
++ *tinstance0 = NULL, *tinstance1 = NULL;
++ struct ast_rtp_glue *glue0, *glue1;
++ enum ast_rtp_glue_result audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID, video_glue0_res = AST_RTP_GLUE_RESULT_FORBID, text_glue0_res = AST_RTP_GLUE_RESULT_FORBID;
++ enum ast_rtp_glue_result audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID, video_glue1_res = AST_RTP_GLUE_RESULT_FORBID, text_glue1_res = AST_RTP_GLUE_RESULT_FORBID;
++ int codec0 = 0, codec1 = 0;
++ int res = 0;
++
++ /* If there is no second channel just immediately bail out, we are of no use in that scenario */
++ if (!c1) {
++ return -1;
++ }
++
++ /* Lock both channels so we can look for the glue that binds them together */
++ ast_channel_lock(c0);
++ while (ast_channel_trylock(c1)) {
++ ast_channel_unlock(c0);
++ usleep(1);
++ ast_channel_lock(c0);
++ }
++
++ /* Grab glue that binds each channel to something using the RTP engine */
++ if (!(glue0 = ast_rtp_instance_get_glue(c0->tech->type)) || !(glue1 = ast_rtp_instance_get_glue(c1->tech->type))) {
++ ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", glue0 ? c1->name : c0->name);
++ goto done;
++ }
++
++ audio_glue0_res = glue0->get_rtp_info(c0, &instance0);
++ video_glue0_res = glue0->get_vrtp_info ? glue0->get_vrtp_info(c0, &vinstance0) : AST_RTP_GLUE_RESULT_FORBID;
++ text_glue0_res = glue0->get_trtp_info ? glue0->get_trtp_info(c0, &tinstance0) : AST_RTP_GLUE_RESULT_FORBID;
++
++ audio_glue1_res = glue1->get_rtp_info(c1, &instance1);
++ video_glue1_res = glue1->get_vrtp_info ? glue1->get_vrtp_info(c1, &vinstance1) : AST_RTP_GLUE_RESULT_FORBID;
++ text_glue1_res = glue1->get_trtp_info ? glue1->get_trtp_info(c1, &tinstance1) : AST_RTP_GLUE_RESULT_FORBID;
++
++ /* If we are carrying video, and both sides are not going to remotely bridge... fail the native bridge */
++ if (video_glue0_res != AST_RTP_GLUE_RESULT_FORBID && (audio_glue0_res != AST_RTP_GLUE_RESULT_REMOTE || video_glue0_res != AST_RTP_GLUE_RESULT_REMOTE)) {
++ audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID;
++ }
++ if (video_glue1_res != AST_RTP_GLUE_RESULT_FORBID && (audio_glue1_res != AST_RTP_GLUE_RESULT_REMOTE || video_glue1_res != AST_RTP_GLUE_RESULT_REMOTE)) {
++ audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID;
++ }
++ if (audio_glue0_res == AST_RTP_GLUE_RESULT_REMOTE && (video_glue0_res == AST_RTP_GLUE_RESULT_FORBID || video_glue0_res == AST_RTP_GLUE_RESULT_REMOTE) && glue0->get_codec(c0)) {
++ codec0 = glue0->get_codec(c0);
++ }
++ if (audio_glue1_res == AST_RTP_GLUE_RESULT_REMOTE && (video_glue1_res == AST_RTP_GLUE_RESULT_FORBID || video_glue1_res == AST_RTP_GLUE_RESULT_REMOTE) && glue1->get_codec(c1)) {
++ codec1 = glue1->get_codec(c1);
++ }
++
++ /* If any sort of bridge is forbidden just completely bail out and go back to generic bridging */
++ if (audio_glue0_res != AST_RTP_GLUE_RESULT_REMOTE || audio_glue1_res != AST_RTP_GLUE_RESULT_REMOTE) {
++ goto done;
++ }
++
++ /* Make sure we have matching codecs */
++ if (!(codec0 & codec1)) {
++ goto done;
++ }
++
++ /* Bridge media early */
++ if (glue0->update_peer(c0, instance1, vinstance1, tinstance1, codec1, 0)) {
++ ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
++ }
++
++ res = 0;
++
++done:
++ ast_channel_unlock(c0);
++ ast_channel_unlock(c1);
++
++ unref_instance_cond(&instance0);
++ unref_instance_cond(&instance1);
++ unref_instance_cond(&vinstance0);
++ unref_instance_cond(&vinstance1);
++ unref_instance_cond(&tinstance0);
++ unref_instance_cond(&tinstance1);
++
++ if (!res) {
++ ast_debug(1, "Setting early bridge SDP of '%s' with that of '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
++ }
++
++ return res;
++}
++
++int ast_rtp_red_init(struct ast_rtp_instance *instance, int buffer_time, int *payloads, int generations)
++{
++ return instance->engine->red_init ? instance->engine->red_init(instance, buffer_time, payloads, generations) : -1;
++}
++
++int ast_rtp_red_buffer(struct ast_rtp_instance *instance, struct ast_frame *frame)
++{
++ return instance->engine->red_buffer ? instance->engine->red_buffer(instance, frame) : -1;
++}
++
++int ast_rtp_instance_get_stats(struct ast_rtp_instance *instance, struct ast_rtp_instance_stats *stats, enum ast_rtp_instance_stat stat)
++{
++ return instance->engine->get_stat ? instance->engine->get_stat(instance, stats, stat) : -1;
++}
++
++char *ast_rtp_instance_get_quality(struct ast_rtp_instance *instance, enum ast_rtp_instance_stat_field field, char *buf, size_t size)
++{
++ struct ast_rtp_instance_stats stats = { 0, };
++ enum ast_rtp_instance_stat stat;
++
++ /* Determine what statistics we will need to retrieve based on field passed in */
++ if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY) {
++ stat = AST_RTP_INSTANCE_STAT_ALL;
++ } else if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY_JITTER) {
++ stat = AST_RTP_INSTANCE_STAT_COMBINED_JITTER;
++ } else if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY_LOSS) {
++ stat = AST_RTP_INSTANCE_STAT_COMBINED_LOSS;
++ } else if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY_RTT) {
++ stat = AST_RTP_INSTANCE_STAT_COMBINED_RTT;
++ } else {
++ return NULL;
++ }
++
++ /* Attempt to actually retrieve the statistics we need to generate the quality string */
++ if (ast_rtp_instance_get_stats(instance, &stats, stat)) {
++ return NULL;
++ }
++
++ /* Now actually fill the buffer with the good information */
++ if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY) {
++ snprintf(buf, size, "ssrc=%i;themssrc=%u;lp=%u;rxjitter=%u;rxcount=%u;txjitter=%u;txcount=%u;rlp=%u;rtt=%u",
++ stats.local_ssrc, stats.remote_ssrc, stats.rxploss, stats.txjitter, stats.rxcount, stats.rxjitter, stats.txcount, stats.txploss, stats.rtt);
++ } else if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY_JITTER) {
++ snprintf(buf, size, "minrxjitter=%f;maxrxjitter=%f;avgrxjitter=%f;stdevrxjitter=%f;reported_minjitter=%f;reported_maxjitter=%f;reported_avgjitter=%f;reported_stdevjitter=%f;",
++ stats.local_minjitter, stats.local_maxjitter, stats.local_normdevjitter, sqrt(stats.local_stdevjitter), stats.remote_minjitter, stats.remote_maxjitter, stats.remote_normdevjitter, sqrt(stats.remote_stdevjitter));
++ } else if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY_LOSS) {
++ snprintf(buf, size, "minrxlost=%f;maxrxlost=%f;avgrxlost=%f;stdevrxlost=%f;reported_minlost=%f;reported_maxlost=%f;reported_avglost=%f;reported_stdevlost=%f;",
++ stats.local_minrxploss, stats.local_maxrxploss, stats.local_normdevrxploss, sqrt(stats.local_stdevrxploss), stats.remote_minrxploss, stats.remote_maxrxploss, stats.remote_normdevrxploss, sqrt(stats.remote_stdevrxploss));
++ } else if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY_RTT) {
++ snprintf(buf, size, "minrtt=%f;maxrtt=%f;avgrtt=%f;stdevrtt=%f;", stats.minrtt, stats.maxrtt, stats.normdevrtt, stats.stdevrtt);
++ }
++
++ return buf;
++}
++
++void ast_rtp_instance_set_stats_vars(struct ast_channel *chan, struct ast_rtp_instance *instance)
++{
++ char quality_buf[AST_MAX_USER_FIELD], *quality;
++ struct ast_channel *bridge = ast_bridged_channel(chan);
++
++ if ((quality = ast_rtp_instance_get_quality(instance, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, quality_buf, sizeof(quality_buf)))) {
++ pbx_builtin_setvar_helper(chan, "RTPAUDIOQOS", quality);
++ if (bridge) {
++ pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSBRIDGED", quality);
++ }
++ }
++
++ if ((quality = ast_rtp_instance_get_quality(instance, AST_RTP_INSTANCE_STAT_FIELD_QUALITY_JITTER, quality_buf, sizeof(quality_buf)))) {
++ pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSJITTER", quality);
++ if (bridge) {
++ pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSJITTERBRIDGED", quality);
++ }
++ }
++
++ if ((quality = ast_rtp_instance_get_quality(instance, AST_RTP_INSTANCE_STAT_FIELD_QUALITY_LOSS, quality_buf, sizeof(quality_buf)))) {
++ pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSLOSS", quality);
++ if (bridge) {
++ pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSLOSSBRIDGED", quality);
++ }
++ }
++
++ if ((quality = ast_rtp_instance_get_quality(instance, AST_RTP_INSTANCE_STAT_FIELD_QUALITY_RTT, quality_buf, sizeof(quality_buf)))) {
++ pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSRTT", quality);
++ if (bridge) {
++ pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSRTTBRIDGED", quality);
++ }
++ }
++}
++
++int ast_rtp_instance_set_read_format(struct ast_rtp_instance *instance, int format)
++{
++ return instance->engine->set_read_format ? instance->engine->set_read_format(instance, format) : -1;
++}
++
++int ast_rtp_instance_set_write_format(struct ast_rtp_instance *instance, int format)
++{
++ return instance->engine->set_write_format ? instance->engine->set_write_format(instance, format) : -1;
++}
++
++int ast_rtp_instance_make_compatible(struct ast_channel *chan, struct ast_rtp_instance *instance, struct ast_channel *peer)
++{
++ struct ast_rtp_glue *glue;
++ struct ast_rtp_instance *peer_instance = NULL;
++ int res = -1;
++
++ if (!instance->engine->make_compatible) {
++ return -1;
++ }
++
++ ast_channel_lock(peer);
++
++ if (!(glue = ast_rtp_instance_get_glue(peer->tech->type))) {
++ ast_channel_unlock(peer);
++ return -1;
++ }
++
++ glue->get_rtp_info(peer, &peer_instance);
++
++ if (!peer_instance || peer_instance->engine != instance->engine) {
++ ast_channel_unlock(peer);
++ ao2_ref(peer_instance, -1);
++ peer_instance = NULL;
++ return -1;
++ }
++
++ res = instance->engine->make_compatible(chan, instance, peer, peer_instance);
++
++ ast_channel_unlock(peer);
++
++ ao2_ref(peer_instance, -1);
++ peer_instance = NULL;
++
++ return res;
++}
++
++int ast_rtp_instance_available_formats(struct ast_rtp_instance *instance, int to_endpoint, int to_asterisk)
++{
++ int formats;
++
++ if (instance->engine->available_formats && (formats = instance->engine->available_formats(instance, to_endpoint, to_asterisk))) {
++ return formats;
++ }
++
++ return ast_translate_available_formats(to_endpoint, to_asterisk);
++}
++
++int ast_rtp_instance_activate(struct ast_rtp_instance *instance)
++{
++ return instance->engine->activate ? instance->engine->activate(instance) : 0;
++}
++
++void ast_rtp_instance_stun_request(struct ast_rtp_instance *instance, struct sockaddr_in *suggestion, const char *username)
++{
++ if (instance->engine->stun_request) {
++ instance->engine->stun_request(instance, suggestion, username);
++ }
++}
++
++void ast_rtp_instance_set_timeout(struct ast_rtp_instance *instance, int timeout)
++{
++ instance->timeout = timeout;
++}
++
++void ast_rtp_instance_set_hold_timeout(struct ast_rtp_instance *instance, int timeout)
++{
++ instance->holdtimeout = timeout;
++}
++
++int ast_rtp_instance_get_timeout(struct ast_rtp_instance *instance)
++{
++ return instance->timeout;
++}
++
++int ast_rtp_instance_get_hold_timeout(struct ast_rtp_instance *instance)
++{
++ return instance->holdtimeout;
++}
+
+Property changes on: main/rtp_engine.c
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+
+Index: configs/adtranvofr.conf.sample
+===================================================================
+--- a/configs/adtranvofr.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/adtranvofr.conf.sample (.../trunk) (revision 202568)
+@@ -1,39 +0,0 @@
+-;
+-; Voice over Frame Relay (Adtran style)
+-;
+-; Configuration file
+-
+-[interfaces]
+-;
+-; Default language
+-;
+-;language=en
+-;
+-; Lines for which we are the user termination. They accept incoming
+-; and outgoing calls. We use the default context on the first 8 lines
+-; used by internal phones.
+-;
+-context=default
+-;user => voice00
+-;user => voice01
+-;user => voice02
+-;user => voice03
+-;user => voice04
+-;user => voice05
+-;user => voice06
+-;user => voice07
+-; Calls on 16 and 17 come from the outside world, so they get
+-; a little bit special treatment
+-context=remote
+-;user => voice16
+-;user => voice17
+-;
+-; Next we have lines which we only accept calls on, and typically
+-; do not send outgoing calls on (i.e. these are where we are the
+-; network termination)
+-;
+-;network => voice08
+-;network => voice09
+-;network => voice10
+-;network => voice11
+-;network => voice12
+Index: configs/skinny.conf.sample
+===================================================================
+--- a/configs/skinny.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/skinny.conf.sample (.../trunk) (revision 202568)
+@@ -15,12 +15,12 @@
+
+ ; If regcontext is specified, Asterisk will dynamically create and destroy a
+ ; NoOp priority 1 extension for a given line which registers or unregisters with
+-; us and have a "regexten=" configuration item.
+-; Multiple contexts may be specified by separating them with '&'. The
++; us and have a "regexten=" configuration item.
++; Multiple contexts may be specified by separating them with '&'. The
+ ; actual extension is the 'regexten' parameter of the registering line or its
+ ; name if 'regexten' is not provided. If more than one context is provided,
+ ; the context must be specified within regexten by appending the desired
+-; context after '@'. More than one regexten may be supplied if they are
++; context after '@'. More than one regexten may be supplied if they are
+ ; separated by '&'. Patterns may be used in regexten.
+ ;
+ ;regcontext=skinnyregistrations
+@@ -93,7 +93,7 @@
+ ;vmexten=8500 ; Device level voicemailmain pilot number
+ ;regexten=100
+ ;context=inbound
+-;linelabel="Support Line" ; Displays next to the line
++;linelabel="Support Line" ; Displays next to the line
+ ; button on 7940's and 7960s
+ ;[110]
+ ;callerid="John Chambers" <408-526-4000>
+Index: configs/meetme.conf.sample
+===================================================================
+--- a/configs/meetme.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/meetme.conf.sample (.../trunk) (revision 202568)
+@@ -34,12 +34,12 @@
+ ;
+ [rooms]
+ ;
+-; Usage is conf => confno[,pin][,adminpin]
++; Usage is conf => confno[,pin][,adminpin]
+ ;
+ ; Note that once a participant has called the conference, a change to the pin
+ ; number done in this file will not take effect until there are no more users
+ ; in the conference and it goes away. When it is created again, it will have
+ ; the new pin number.
+ ;
+-;conf => 1234
++;conf => 1234
+ ;conf => 2345,9938
+Index: configs/ais.conf.sample
+===================================================================
+--- a/configs/ais.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/ais.conf.sample (.../trunk) (revision 202568)
+@@ -1,5 +1,5 @@
+ ;
+-; Sample configuration file for res_ais
++; Sample configuration file for res_ais
+ ; * SAForum AIS (Application Interface Specification)
+ ;
+ ; More information on the AIS specification is available from the SAForum.
+@@ -76,7 +76,7 @@
+ ;
+ ; This example would be used for a node that has phones directly registered
+ ; to it, but does not have direct access to voicemail. So, this node wants
+-; to be informed about MWI state changes on other voicemail server nodes, but
++; to be informed about MWI state changes on other voicemail server nodes, but
+ ; is not capable of publishing any state changes.
+ ;
+ ; [mwi]
+Index: configs/iax.conf.sample
+===================================================================
+--- a/configs/iax.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/iax.conf.sample (.../trunk) (revision 202568)
+@@ -16,7 +16,7 @@
+ ; bindaddr if followed by colon and port
+ ; (e.g. bindaddr=192.168.0.1:4569)
+ ;bindaddr=192.168.0.1 ; more than once to bind to multiple
+-; ; addresses, but the first will be the
++; ; addresses, but the first will be the
+ ; ; default
+ ;
+ ; Set iaxcompat to yes if you plan to use layered switches or
+@@ -36,7 +36,7 @@
+ ;
+ ; For increased security against brute force password attacks
+ ; enable "delayreject" which will delay the sending of authentication
+-; reject for REGREQ or AUTHREP if there is a password.
++; reject for REGREQ or AUTHREP if there is a password.
+ ;
+ ;delayreject=yes
+ ;
+@@ -60,7 +60,7 @@
+ ;
+ ;accountcode=lss0101
+ ;
+-; You may specify a global default language for users.
++; You may specify a global default language for users.
+ ; Can be specified also on a per-user basis
+ ; If omitted, will fallback to english
+ ;
+@@ -111,7 +111,7 @@
+ ;
+ ; forcejitterbuffer=yes|no: in the ideal world, when we bridge VoIP channels
+ ; we don't want to do jitterbuffering on the switch, since the endpoints
+-; can each handle this. However, some endpoints may have poor jitterbuffers
++; can each handle this. However, some endpoints may have poor jitterbuffers
+ ; themselves, so this option will force * to always jitterbuffer, even in this
+ ; case.
+ ;
+@@ -166,7 +166,7 @@
+ ;
+ ; With a large amount of traffic on IAX2 trunks, there is a risk of bad voice quality due to
+ ; the fact that the IAX2 trunking scheme depends on the Linux system to handle fragmentation of
+-; UDP packets. This may not be very efficient.
++; UDP packets. This may not be very efficient.
+ ; This setting sets the maximum transmission unit for IAX2 UDP trunking.
+ ; default is 1240 bytes. Zero disables this functionality and let's the O/S handle fragmentation.
+ ;
+@@ -177,7 +177,7 @@
+ ; encryption = yes
+ ;
+ ; Force encryption insures no connection is established unless both sides support
+-; encryption. By turning this option on, encryption is automatically turned on as well.
++; encryption. By turning this option on, encryption is automatically turned on as well.
+ ;
+ ; forceencryption = yes
+
+@@ -211,7 +211,7 @@
+ ; Sample Registration for iaxtel
+ ;
+ ; Visit http://www.iaxtel.com to register with iaxtel. Replace "user"
+-; and "pass" with your username and password for iaxtel. Incoming
++; and "pass" with your username and password for iaxtel. Incoming
+ ; calls arrive at the "s" extension of "default" context.
+ ;
+ ;register => user:pass@iaxtel.com
+@@ -228,7 +228,7 @@
+ ;register => FWDNumber:passwd@iax.fwdnet.net
+ ;
+ ;
+-; You can disable authentication debugging to reduce the amount of
++; You can disable authentication debugging to reduce the amount of
+ ; debugging traffic.
+ ;
+ ;authdebug=no
+@@ -256,7 +256,7 @@
+ autokill=yes
+ ;
+ ; codecpriority controls the codec negotiation of an inbound IAX call.
+-; This option is inherited to all user entities. It can also be defined
++; This option is inherited to all user entities. It can also be defined
+ ; in each user entity separately which will override the setting in general.
+ ;
+ ; The valid values are:
+@@ -287,6 +287,9 @@
+ ; just like friends added from the config file only on a
+ ; as-needed basis? (yes|no)
+
++;rtsavesysname=yes ; Save systemname in realtime database at registration
++ ; Default = no
++
+ ;rtupdate=yes ; Send registry updates to database using realtime? (yes|no)
+ ; If set to yes, when a IAX2 peer registers successfully,
+ ; the ip address, the origination port, the registration period,
+@@ -357,7 +360,7 @@
+ ; across the net. "md5" uses a challenge/response md5 sum arrangement, but
+ ; still requires both ends have plain text access to the secret. "rsa" allows
+ ; unidirectional secret knowledge through public/private keys. If "rsa"
+-; authentication is used, "inkeys" is a list of acceptable public keys on the
++; authentication is used, "inkeys" is a list of acceptable public keys on the
+ ; local system that can be used to authenticate the remote peer, separated by
+ ; the ":" character. "outkey" is a single, private key to use to authenticate
+ ; to the other side. Public keys are named /var/lib/asterisk/keys/<name>.pub
+@@ -382,7 +385,7 @@
+ ; an attended transfer.
+ ;dbsecret=mysecrets/place ; Secrets can be stored in astdb, too
+ ;transfer=no ; Disable IAX native transfer
+-;transfer=mediaonly ; When doing IAX native transfers, transfer
++;transfer=mediaonly ; When doing IAX native transfers, transfer
+ ; only media stream
+ ;jitterbuffer=yes ; Override global setting an enable jitter buffer
+ ; ; for this user
+@@ -395,10 +398,10 @@
+ ;language=en ; Use english as default language
+ ;encryption=yes ; Enable IAX2 encryption. The default is no.
+ ;keyrotate=off ; This is a compatibility option for older versions of
+-; ; IAX2 that do not support key rotation with encryption.
+-; ; This option will disable the IAX_COMMAND_RTENC message.
++; ; IAX2 that do not support key rotation with encryption.
++; ; This option will disable the IAX_COMMAND_RTENC message.
+ ; ; default is on.
+-; ;
++; ;
+ ;
+ ; Peers may also be specified, with a secret and
+ ; a remote hostname.
+@@ -424,10 +427,10 @@
+ ;
+ ;encryption=yes ; Enable IAX2 encryption. The default is no.
+ ;keyrotate=off ; This is a compatibility option for older versions of
+-; ; IAX2 that do not support key rotation with encryption.
+-; ; This option will disable the IAX_COMMAND_RTENC message.
++; ; IAX2 that do not support key rotation with encryption.
++; ; This option will disable the IAX_COMMAND_RTENC message.
+ ; ; default is on.
+-; ;
++; ;
+ ; Peers can remotely register as well, so that they can be mobile. Default
+ ; IP's can also optionally be given but are not required. Caller*ID can be
+ ; suggested to the other side as well if it is for example a phone instead of
+Index: configs/mgcp.conf.sample
+===================================================================
+--- a/configs/mgcp.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/mgcp.conf.sample (.../trunk) (revision 202568)
+@@ -47,27 +47,27 @@
+
+ ;; The MGCP channel supports the following service codes:
+ ;; # - Transfer
+-;; *67 - Calling Number Delivery Blocking
+-;; *70 - Cancel Call Waiting
+-;; *72 - Call Forwarding Activation
+-;; *73 - Call Forwarding Deactivation
+-;; *78 - Do Not Disturb Activation
+-;; *79 - Do Not Disturb Deactivation
++;; *67 - Calling Number Delivery Blocking
++;; *70 - Cancel Call Waiting
++;; *72 - Call Forwarding Activation
++;; *73 - Call Forwarding Deactivation
++;; *78 - Do Not Disturb Activation
++;; *79 - Do Not Disturb Deactivation
+ ;; *8 - Call pick-up
+ ;
+-; known to work with Swissvoice IP10s
+-;[192.168.1.20]
+-;context=local
+-;host=192.168.1.20
+-;callerid = "John Doe" <123>
++; known to work with Swissvoice IP10s
++;[192.168.1.20]
++;context=local
++;host=192.168.1.20
++;callerid = "John Doe" <123>
+ ;callgroup=0 ; in the range from 0 to 63
+ ;pickupgroup=0 ; in the range from 0 to 63
+-;nat=no
+-;threewaycalling=yes
++;nat=no
++;threewaycalling=yes
+ ;transfer=yes ; transfer requires threewaycalling=yes. Use FLASH to transfer
+ ;callwaiting=yes ; this might be a cause of trouble for ip10s
+-;cancallforward=yes
+-;line => aaln/1
++;cancallforward=yes
++;line => aaln/1
+ ;
+
+ ;[dph100]
+@@ -90,7 +90,7 @@
+ ; 'documentation', or 'omit'
+ ;context = local
+ ;host = 192.168.1.20
+-;wcardep = aaln/* ; enables wildcard endpoint and sets it to 'aaln/*'
++;wcardep = aaln/* ; enables wildcard endpoint and sets it to 'aaln/*'
+ ; another common format is '*'
+ ;callerid = "Duane Cox" <123> ; now lets setup line 1 using per endpoint configuration...
+ ;callwaiting = no
+Index: configs/extensions.lua.sample
+===================================================================
+--- a/configs/extensions.lua.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/extensions.lua.sample (.../trunk) (revision 202568)
+@@ -22,20 +22,20 @@
+ -- an extension name is prefixed by a '_' character, it is interpreted as
+ -- a pattern rather than a literal. In patterns, some characters have
+ -- special meanings:
+---
++--
+ -- X - any digit from 0-9
+ -- Z - any digit from 1-9
+ -- N - any digit from 2-9
+ -- [1235-9] - any digit in the brackets (in this example, 1,2,3,5,6,7,8,9)
+--- . - wildcard, matches anything remaining (e.g. _9011. matches
++-- . - wildcard, matches anything remaining (e.g. _9011. matches
+ -- anything starting with 9011 excluding 9011 itself)
+ -- ! - wildcard, causes the matching process to complete as soon as
+ -- it can unambiguously determine that no other matches are possible
+---
++--
+ -- For example the extension _NXXXXXX would match normal 7 digit
+ -- dialings, while _1NXXNXXXXXX would represent an area code plus phone
+ -- number preceded by a one.
+---
++--
+ -- If your extension has special characters in it such as '.' and '!' you must
+ -- explicitly make it a string in the tabale definition:
+ --
+@@ -44,7 +44,7 @@
+ --
+ -- There are no priorities. All extensions to asterisk appear to have a single
+ -- priority as if they consist of a single priority.
+---
++--
+ -- Each context is defined as a table in the extensions table. The
+ -- context names should be strings.
+ --
+@@ -52,7 +52,7 @@
+ -- extension. This extension should be set to a table containing a list
+ -- of context names. Do not put references to tables in the includes
+ -- table.
+---
++--
+ -- include = {"a", "b", "c"};
+ --
+ -- Channel variables can be accessed thorugh the global 'channel' table.
+@@ -79,8 +79,8 @@
+ -- Also notice the absence of the following constructs from the examples above:
+ -- channel.func_name(1,2,3) = "value" -- this will NOT work
+ -- value = channel.func_name(1,2,3) -- this will NOT work as expected
+---
+ --
++--
+ -- Dialplan applications can be accessed through the global 'app' table.
+ --
+ -- app.Dial("DAHDI/1")
+Index: configs/sip.conf.sample
+===================================================================
+--- a/configs/sip.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/sip.conf.sample (.../trunk) (revision 202568)
+@@ -3,7 +3,7 @@
+ ;
+ ; SIP dial strings
+ ;-----------------------------------------------------------
+-; In the dialplan (extensions.conf) you can use several
++; In the dialplan (extensions.conf) you can use several
+ ; syntaxes for dialing SIP devices.
+ ; SIP/devicename
+ ; SIP/username@domain (SIP uri)
+@@ -17,11 +17,11 @@
+ ; username@domain
+ ; Call any SIP user on the Internet
+ ; (Don't forget to enable DNS SRV records if you want to use this)
+-;
++;
+ ; devicename/extension
+ ; If you define a SIP proxy as a peer below, you may call
+-; SIP/proxyhostname/user or SIP/user@proxyhostname
+-; where the proxyhostname is defined in a section below
++; SIP/proxyhostname/user or SIP/user@proxyhostname
++; where the proxyhostname is defined in a section below
+ ; This syntax also works with ATA's with FXO ports
+ ;
+ ; SIP/username[:password[:md5secret[:authname]]]@host[:port]
+@@ -54,7 +54,7 @@
+ ; When naming devices, make sure you understand how Asterisk matches calls
+ ; that come in.
+ ; 1. Asterisk checks the SIP From: address username and matches against
+-; names of devices with type=user
++; names of devices with type=user
+ ; The name is the text between square brackets [name]
+ ; 2. Asterisk checks the From: addres and matches the list of devices
+ ; with a type=peer
+@@ -64,14 +64,14 @@
+ ; Don't mix extensions with the names of the devices. Devices need a unique
+ ; name. The device name is *not* used as phone numbers. Phone numbers are
+ ; anything you declare as an extension in the dialplan (extensions.conf).
+-;
++;
+ ; When setting up trunks, make sure there's no risk that any From: username
+-; (caller ID) will match any of your device names, because then Asterisk
++; (caller ID) will match any of your device names, because then Asterisk
+ ; might match the wrong device.
+ ;
+ ; Note: The parameter "username" is not the username and in most cases is
+ ; not needed at all. Check below. In later releases, it's renamed
+-; to "defaultuser" which is a better name, since it is used in
++; to "defaultuser" which is a better name, since it is used in
+ ; combination with the "defaultip" setting.
+ ;-----------------------------------------------------------------------------
+
+@@ -81,7 +81,7 @@
+ ; You are encouraged to use the dialplan groupcount functionality
+ ; to enforce call limits instead of using this channel-specific method.
+ ;
+-; You can still set limits per device in sip.conf or in a database by using
++; You can still set limits per device in sip.conf or in a database by using
+ ; "setvar" to set variables that can be used in the dialplan for various limits.
+
+ [general]
+@@ -117,38 +117,46 @@
+ ; Remember that the IP address must match the common name (hostname) in the
+ ; certificate, so you don't want to bind a TLS socket to multiple IP addresses.
+
+-;tlscertfile=asterisk.pem ; Certificate file (*.pem only) to use for TLS connections
+- ; default is to look for "asterisk.pem" in current directory
++;tlscertfile=</path/to/certificate.pem> ; Certificate file (*.pem only) to use for TLS connections
++ ; default is to look for "asterisk.pem" in current directory
+
++;tlsprivatekey=</path/to/private.pem> ; Private key file (*.pem only) for TLS connections.
++ ; If no tlsprivatekey is specified, tlscertfile is searched for
++ ; for both public and private key.
++
+ ;tlscafile=</path/to/certificate>
+ ; If the server your connecting to uses a self signed certificate
+-; you should have their certificate installed here so the code can
++; you should have their certificate installed here so the code can
+ ; verify the authenticity of their certificate.
+
+ ;tlscadir=</path/to/ca/dir>
+-; A directory full of CA certificates. The files must be named with
+-; the CA subject name hash value.
+-; (see man SSL_CTX_load_verify_locations for more info)
++; A directory full of CA certificates. The files must be named with
++; the CA subject name hash value.
++; (see man SSL_CTX_load_verify_locations for more info)
+
+ ;tlsdontverifyserver=[yes|no]
+-; If set to yes, don't verify the servers certificate when acting as
++; If set to yes, don't verify the servers certificate when acting as
+ ; a client. If you don't have the server's CA certificate you can
+ ; set this and it will connect without requiring tlscafile to be set.
+ ; Default is no.
+
+ ;tlscipher=<SSL cipher string>
+ ; A string specifying which SSL ciphers to use or not use
+-; A list of valid SSL cipher strings can be found at:
++; A list of valid SSL cipher strings can be found at:
+ ; http://www.openssl.org/docs/apps/ciphers.html#CIPHER_STRINGS
++;
++;tlsclientmethod=tlsv1 ; values include tlsv1, sslv3, sslv2.
++ ; Specify protocol for outbound client connections.
++ ; If left unspecified, the default is sslv2.
+
+ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
+- ; Note: Asterisk only uses the first host
++ ; Note: Asterisk only uses the first host
+ ; in SRV records
+- ; Disabling DNS SRV lookups disables the
+- ; ability to place SIP calls based on domain
++ ; Disabling DNS SRV lookups disables the
++ ; ability to place SIP calls based on domain
+ ; names to some other SIP users on the Internet
+
+-;pedantic=yes ; Enable checking of tags in headers,
++;pedantic=yes ; Enable checking of tags in headers,
+ ; international character conversions in URIs
+ ; and multiline formatted headers for strict
+ ; SIP compatibility (defaults to "no")
+@@ -169,7 +177,7 @@
+ ;minexpiry=60 ; Minimum length of registrations/subscriptions (default 60)
+ ;defaultexpiry=120 ; Default length of incoming/outgoing registration
+ ;mwiexpiry=3600 ; Expiry time for outgoing MWI subscriptions
+-;qualifyfreq=60 ; Qualification: How often to check for the
++;qualifyfreq=60 ; Qualification: How often to check for the
+ ; host to be up in seconds
+ ; Set to low value if you use low timeout for
+ ; NAT of UDP sessions
+@@ -179,9 +187,19 @@
+ ;buggymwi=no ; Cisco SIP firmware doesn't support the MWI RFC
+ ; fully. Enable this option to not get error messages
+ ; when sending MWI to phones with this bug.
+-;vmexten=voicemail ; dialplan extension to reach mailbox sets the
+- ; Message-Account in the MWI notify message
++;mwi_from=asterisk ; When sending MWI NOTIFY requests, use this setting in
++ ; the From: header as the "name" portion. Also fill the
++ ; "user" portion of the URI in the From: header with this
++ ; value if no fromuser is set
++ ; Default: empty
++;vmexten=voicemail ; dialplan extension to reach mailbox sets the
++ ; Message-Account in the MWI notify message
+ ; defaults to "asterisk"
++
++;preferred_codec_only=yes ; Respond to a SIP invite with the single most preferred codec
++ ; rather than advertising all joint codec capabilities. This
++ ; limits the other side's codec choice to exactly what we prefer.
++
+ ;disallow=all ; First disallow all codecs
+ ;allow=ulaw ; Allow codecs in order of preference
+ ;allow=ilbc ; see doc/rtp-packetization for framing options
+@@ -209,6 +227,18 @@
+ ;relaxdtmf=yes ; Relax dtmf handling
+ ;trustrpid = no ; If Remote-Party-ID should be trusted
+ ;sendrpid = yes ; If Remote-Party-ID should be sent
++;sendrpid = rpid ; Use the "Remote-Party-ID" header
++ ; to send the identity of the remote party
++ ; This is identical to sendrpid=yes
++;sendrpid = pai ; Use the "P-Asserted-Identity" header
++ ; to send the identity of the remote party
++;rpid_update = no ; In certain cases, the only method by which a connected line
++ ; change may be immediately transmitted is with a SIP UPDATE request.
++ ; If communicating with another Asterisk server, and you wish to be able
++ ; transmit such UPDATE messages to it, then you must enable this option.
++ ; Otherwise, we will have to wait until we can send a reinvite to
++ ; transmit the information.
++
+ ;progressinband=never ; If we should generate in-band ringing always
+ ; use 'never' to never use in-band signalling, even in cases
+ ; where some buggy devices might not render it
+@@ -229,7 +259,7 @@
+ ;usereqphone = no ; If yes, ";user=phone" is added to uri that contains
+ ; a valid phone number
+ ;dtmfmode = rfc2833 ; Set default dtmfmode for sending DTMF. Default: rfc2833
+- ; Other options:
++ ; Other options:
+ ; info : SIP INFO messages (application/dtmf-relay)
+ ; shortinfo : SIP INFO messages (application/dtmf)
+ ; inband : Inband audio (requires 64 kbit codec -alaw, ulaw)
+@@ -251,7 +281,7 @@
+ ;maxcallbitrate=384 ; Maximum bitrate for video calls (default 384 kb/s)
+ ; Videosupport and maxcallbitrate is settable
+ ; for peers and users as well
+-;callevents=no ; generate manager events when sip ua
++;callevents=no ; generate manager events when sip ua
+ ; performs events (e.g. hold)
+ ;authfailureevents=no ; generate manager "peerstatus" events when peer can't
+ ; authenticate with Asterisk. Peerstatus will be "rejected".
+@@ -270,7 +300,7 @@
+ ;outboundproxy=proxy.provider.domain ; send outbound signaling to this proxy, not directly to the devices
+ ;outboundproxy=proxy.provider.domain:8080 ; send outbound signaling to this proxy, not directly to the devices
+ ;outboundproxy=proxy.provider.domain,force ; Send ALL outbound signalling to proxy, ignoring route: headers
+-;outboundproxy=tls://proxy.provider.domain ; same as '=proxy.provider.domain' except we try to connect with tls
++;outboundproxy=tls://proxy.provider.domain ; same as '=proxy.provider.domain' except we try to connect with tls
+ ; ; (could also be tcp,udp) - defining transports on the proxy line only
+ ; ; applies for the global proxy, otherwise use the transport= option
+ ;matchexterniplocally = yes ; Only substitute the externip or externhost setting if it matches
+@@ -287,15 +317,17 @@
+ ;contactpermit=172.16.0.0/255.255.0.0 ; restrict at what IPs your users may
+ ; register their phones.
+
++;engine=asterisk ; RTP engine to use when communicating with the device
++
+ ;
+ ; If regcontext is specified, Asterisk will dynamically create and destroy a
+ ; NoOp priority 1 extension for a given peer who registers or unregisters with
+-; us and have a "regexten=" configuration item.
+-; Multiple contexts may be specified by separating them with '&'. The
++; us and have a "regexten=" configuration item.
++; Multiple contexts may be specified by separating them with '&'. The
+ ; actual extension is the 'regexten' parameter of the registering peer or its
+ ; name if 'regexten' is not provided. If more than one context is provided,
+ ; the context must be specified within regexten by appending the desired
+-; context after '@'. More than one regexten may be supplied if they are
++; context after '@'. More than one regexten may be supplied if they are
+ ; separated by '&'. Patterns may be used in regexten.
+ ;
+ ;regcontext=sipregistrations
+@@ -305,7 +337,7 @@
+ ; extension for the peer
+ ;
+ ;--------------------------- SIP timers ----------------------------------------------------
+-; These timers are used primarily in INVITE transactions.
++; These timers are used primarily in INVITE transactions.
+ ; The default for Timer T1 is 500 ms or the measured run-trip time between
+ ; Asterisk and the device if you have qualify=yes for the device.
+ ;
+@@ -372,7 +404,7 @@
+ ;--------------------------- SIP DEBUGGING ---------------------------------------------------
+ ;sipdebug = yes ; Turn on SIP debugging by default, from
+ ; the moment the channel loads this configuration
+-;recordhistory=yes ; Record SIP history by default
++;recordhistory=yes ; Record SIP history by default
+ ; (see sip history / sip no history)
+ ;dumphistory=yes ; Dump SIP history at end of SIP dialogue
+ ; SIP history is output to the DEBUG logging channel
+@@ -381,12 +413,12 @@
+ ;--------------------------- STATUS NOTIFICATIONS (SUBSCRIPTIONS) ----------------------------
+ ; You can subscribe to the status of extensions with a "hint" priority
+ ; (See extensions.conf.sample for examples)
+-; chan_sip support two major formats for notifications: dialog-info and SIMPLE
++; chan_sip support two major formats for notifications: dialog-info and SIMPLE
+ ;
+ ; You will get more detailed reports (busy etc) if you have a call counter enabled
+-; for a device.
++; for a device.
+ ;
+-; If you set the busylevel, we will indicate busy when we have a number of calls that
++; If you set the busylevel, we will indicate busy when we have a number of calls that
+ ; matches the busylevel treshold.
+ ;
+ ; For queues, you will need this level of detail in status reporting, regardless
+@@ -427,9 +459,9 @@
+ ;
+ ; This setting is available in the [general] section as well as in device configurations.
+ ; Setting this to yes, enables T.38 fax (UDPTL) passthrough on SIP to SIP calls, provided
+-; both parties have T38 support enabled in their Asterisk configuration
++; both parties have T38 support enabled in their Asterisk configuration
+ ; This has to be enabled in the general section for all devices to work. You can then
+-; disable it on a per device basis.
++; disable it on a per device basis.
+ ;
+ ; T.38 faxing only works in SIP to SIP calls, with no local or agent channel being used.
+ ;
+@@ -437,21 +469,21 @@
+ ;
+ ; Fax Detect will cause the SIP channel to jump to the 'fax' extension (if it exists)
+ ; after T.38 is successfully negotiated.
+-;
+-; faxdetect = yes ; Default false
+ ;
++; faxdetect = yes ; Default false
++;
+ ;----------------------------------------- OUTBOUND SIP REGISTRATIONS ------------------------
+ ; Asterisk can register as a SIP user agent to a SIP proxy (provider)
+ ; Format for the register statement is:
+ ; register => [transport://]user[@domain][:secret[:authuser]]@host[:port][/extension][~expiry]
+ ;
+-;
+ ;
+-; domain is either
++;
++; domain is either
+ ; - domain in DNS
+ ; - host name in DNS
+ ; - the name of a peer defined below or in realtime
+-; The domain is where you register your username, so your SIP uri you are registering to
++; The domain is where you register your username, so your SIP uri you are registering to
+ ; is username@domain
+ ;
+ ; If no extension is given, the 's' extension is used. The extension needs to
+@@ -482,7 +514,7 @@
+ ;
+ ; Examples:
+ ;
+-;register => 1234:password@mysipprovider.com
++;register => 1234:password@mysipprovider.com
+ ;
+ ; This will pass incoming calls to the 's' extension
+ ;
+@@ -501,7 +533,7 @@
+ ;
+ ; Note that in this example, the optional authuser and secret portions have
+ ; been left blank because we have specified a port in the user section
+-
++
+ ;registertimeout=20 ; retry registration calls every 20 seconds (default)
+ ;registerattempts=10 ; Number of registration attempts before we give up
+ ; 0 = continue forever, hammering the other server
+@@ -603,7 +635,7 @@
+ ; nat = no ; default. Use NAT mode only according to RFC3581 (;rport)
+ ; nat = yes ; Always ignore info and assume NAT
+ ; nat = never ; Never attempt NAT mode or RFC3581 support
+-; nat = route ; route = Assume NAT, don't send rport
++; nat = route ; route = Assume NAT, don't send rport
+ ; ; (work around more UNIDEN bugs)
+
+ ;----------------------------------- MEDIA HANDLING --------------------------------
+@@ -627,7 +659,7 @@
+
+ ;directrtpsetup=yes ; Enable the new experimental direct RTP setup. This sets up
+ ; the call directly with media peer-2-peer without re-invites.
+- ; Will not work for video and cases where the callee sends
++ ; Will not work for video and cases where the callee sends
+ ; RTP payloads and fmtp headers in the 200 OK that does not match the
+ ; callers INVITE. This will also fail if canreinvite is enabled when
+ ; the device is actually behind NAT.
+@@ -666,7 +698,7 @@
+ ;rtupdate=yes ; Send registry updates to database using realtime? (yes|no)
+ ; If set to yes, when a SIP UA registers successfully, the ip address,
+ ; the origination port, the registration period, and the username of
+- ; the UA will be set to database via realtime.
++ ; the UA will be set to database via realtime.
+ ; If not present, defaults to 'yes'. Note: realtime peers will
+ ; probably not function across reloads in the way that you expect, if
+ ; you turn this option off.
+@@ -686,8 +718,8 @@
+ ;
+ ; For realtime peers, when the peer is retrieved from realtime storage,
+ ; the registration information will be used regardless of whether
+- ; it has expired or not; if it expires while the realtime peer
+- ; is still in memory (due to caching or other reasons), the
++ ; it has expired or not; if it expires while the realtime peer
++ ; is still in memory (due to caching or other reasons), the
+ ; information will not be removed from realtime storage
+
+ ;----------------------------------------- SIP DOMAIN SUPPORT ------------------------
+@@ -727,7 +759,7 @@
+ ; address. This is to be polite and
+ ; it may be a mandatory requirement for some
+ ; destinations which do not have a prior
+- ; account relationship with your server.
++ ; account relationship with your server.
+
+ ;------------------------------ JITTER BUFFER CONFIGURATION --------------------------
+ ; jbenable = yes ; Enables the use of a jitterbuffer on the receiving side of a
+@@ -761,20 +793,20 @@
+ ; any credentials in peer/register definition if realm is matched.
+ ;
+ ; This way, Asterisk can authenticate for outbound calls to other
+-; realms. We match realm on the proxy challenge and pick an set of
++; realms. We match realm on the proxy challenge and pick an set of
+ ; credentials from this list
+ ; Syntax:
+ ; auth = <user>:<secret>@<realm>
+ ; auth = <user>#<md5secret>@<realm>
+ ; Example:
+ ;auth=mark:topsecret@digium.com
+-;
+-; You may also add auth= statements to [peer] definitions
++;
++; You may also add auth= statements to [peer] definitions
+ ; Peer auth= override all other authentication settings if we match on realm
+
+ ;------------------------------------------------------------------------------
+ ; DEVICE CONFIGURATION
+-;
++;
+ ; The SIP channel has two types of devices, the friend and the peer.
+ ; * The type=friend is a device type that accepts both incoming and outbound calls,
+ ; where Asterisk match on the From: username on incoming calls.
+@@ -785,16 +817,16 @@
+ ; trunks.
+ ;
+ ; For device names, we recommend using only a-z, numerics (0-9) and underscore
+-;
++;
+ ; For local phones, type=friend works most of the time
+ ;
+-; If you have one-way audio, you probably have NAT problems.
++; If you have one-way audio, you probably have NAT problems.
+ ; If Asterisk is on a public IP, and the phone is inside of a NAT device
+ ; you will need to configure nat option for those phones.
+ ; Also, turn on qualify=yes to keep the nat session open
+-;
+-; Configuration options available
+-; --------------------
++;
++; Configuration options available
++; --------------------
+ ; context
+ ; callingpres
+ ; permit
+@@ -863,7 +895,7 @@
+
+ ;[sip_proxy]
+ ; For incoming calls only. Example: FWD (Free World Dialup)
+-; We match on IP address of the proxy for incoming calls
++; We match on IP address of the proxy for incoming calls
+ ; since we can not match on username (caller id)
+ ;type=peer
+ ;context=from-fwd
+@@ -874,7 +906,7 @@
+ ;remotesecret=guessit ; Our password to their service
+ ;defaultuser=yourusername ; Authentication user for outbound proxies
+ ;fromuser=yourusername ; Many SIP providers require this!
+-;fromdomain=provider.sip.domain
++;fromdomain=provider.sip.domain
+ ;host=box.provider.com
+ ;transport=udp,tcp ; This sets the default transport type to udp for outgoing, and will
+ ; ; accept both tcp and udp. The default transport type is only used for
+@@ -947,7 +979,7 @@
+ ; Standard configurations not using templates look like this:
+ ;
+ ;[grandstream1]
+-;type=friend
++;type=friend
+ ;context=from-sip ; Where to start in the dialplan when this phone calls
+ ;callerid=John Doe <1234> ; Full caller ID, to override the phones config
+ ; on incoming calls to Asterisk
+@@ -997,14 +1029,14 @@
+ ;context=from-sip ; Context for incoming calls from this user
+ ;secret=blah
+ ;subscribecontext=localextensions ; Only allow SUBSCRIBE for local extensions
+-;language=de ; Use German prompts for this user
++;language=de ; Use German prompts for this user
+ ;host=dynamic ; This peer register with us
+ ;dtmfmode=inband ; Choices are inband, rfc2833, or info
+ ;defaultip=192.168.0.59 ; IP used until peer registers
+ ;mailbox=1234@context,2345 ; Mailbox(-es) for message waiting indicator
+-;subscribemwi=yes ; Only send notifications if this phone
++;subscribemwi=yes ; Only send notifications if this phone
+ ; subscribes for mailbox notification
+-;vmexten=voicemail ; dialplan extension to reach mailbox
++;vmexten=voicemail ; dialplan extension to reach mailbox
+ ; sets the Message-Account in the MWI notify message
+ ; defaults to global vmexten which defaults to "asterisk"
+ ;disallow=all
+@@ -1029,14 +1061,14 @@
+ ;type=friend
+ ;secret=blah
+ ;host=dynamic
+-;insecure=port ; Allow matching of peer by IP address without
++;insecure=port ; Allow matching of peer by IP address without
+ ; matching port number
+ ;insecure=invite ; Do not require authentication of incoming INVITEs
+ ;insecure=port,invite ; (both)
+ ;qualify=1000 ; Consider it down if it's 1 second to reply
+ ; Helps with NAT session
+ ; qualify=yes uses default value
+-;qualifyfreq=60 ; Qualification: How often to check for the
++;qualifyfreq=60 ; Qualification: How often to check for the
+ ; host to be up in seconds
+ ; Set to low value if you use low timeout for
+ ; NAT of UDP sessions
+@@ -1054,13 +1086,13 @@
+ ;secret=blah
+ ;qualify=200 ; Qualify peer is no more than 200ms away
+ ;nat=yes ; This phone may be natted
+- ; Send SIP and RTP to the IP address that packet is
+- ; received from instead of trusting SIP headers
++ ; Send SIP and RTP to the IP address that packet is
++ ; received from instead of trusting SIP headers
+ ;host=dynamic ; This device registers with us
+ ;canreinvite=no ; Asterisk by default tries to redirect the
+ ; RTP media stream (audio) to go directly from
+ ; the caller to the callee. Some devices do not
+- ; support this (especially if one of them is
++ ; support this (especially if one of them is
+ ; behind a NAT).
+ ;defaultip=192.168.0.4 ; IP address to use until registration
+ ;defaultuser=goran ; Username to use when calling this device before registration
+Index: configs/say.conf.sample
+===================================================================
+--- a/configs/say.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/say.conf.sample (.../trunk) (revision 202568)
+@@ -1,4 +1,4 @@
+-;
++;
+ ; language configuration
+ ;
+
+@@ -66,7 +66,7 @@
+ ; date:M:200604172030.00-4-102
+ ; date:p:200604172030.00-4-102
+ ;
+-;
++;
+ ; Remember, normally X Z N are special, and the search is
+ ; case insensitive, so you must use [X] [N] [Z] .. if you
+ ; want exact match.
+Index: configs/queuerules.conf.sample
+===================================================================
+--- a/configs/queuerules.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/queuerules.conf.sample (.../trunk) (revision 202568)
+@@ -1,12 +1,12 @@
+-; It is possible to change the value of the QUEUE_MAX_PENALTY and QUEUE_MIN_PENALTY
++; It is possible to change the value of the QUEUE_MAX_PENALTY and QUEUE_MIN_PENALTY
+ ; channel variables in mid-call by defining rules in the queue for when to do so. This can allow for
+-; a call to be opened to more members or potentially a different set of members.
+-; The advantage to changing members this way as opposed to inserting the caller into a
+-; different queue with more members or reinserting the caller into the same queue with a different
+-; QUEUE_MAX_PENALTY or QUEUE_MIN_PENALTY set is that the caller does not lose his place in the queue.
++; a call to be opened to more members or potentially a different set of members.
++; The advantage to changing members this way as opposed to inserting the caller into a
++; different queue with more members or reinserting the caller into the same queue with a different
++; QUEUE_MAX_PENALTY or QUEUE_MIN_PENALTY set is that the caller does not lose his place in the queue.
+ ;
+-; Note: There is a limitation to these rules; a caller will follow the penaltychange rules for
+-; the queue that were defined at the time the caller entered the queue. If an update to the rules is
++; Note: There is a limitation to these rules; a caller will follow the penaltychange rules for
++; the queue that were defined at the time the caller entered the queue. If an update to the rules is
+ ; made during the the caller's stay in the queue, these will not be reflected for that caller.
+ ;
+ ; The syntax for these rules is
+Index: configs/indications.conf.sample
+===================================================================
+--- a/configs/indications.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/indications.conf.sample (.../trunk) (revision 202568)
+@@ -516,7 +516,7 @@
+ dialrecall = 425/500,0/50
+ ; RECORDTONE - not specified
+ record = 1400/500,0/15000
+-; 950/1400/1800 3x0.33 on 1.0 off repeated 3 times
++; 950/1400/1800 3x0.33 on 1.0 off repeated 3 times
+ info = !950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000
+ ; STUTTER - not specified
+ stutter = !425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,!425/100,!0/100,425
+@@ -567,7 +567,7 @@
+ [sg]
+ description = Singapore
+ ; Singapore
+-; Reference: http://www.ida.gov.sg/idaweb/doc/download/I397/ida_ts_pstn1_i4r2.pdf
++; Reference: http://www.ida.gov.sg/idaweb/doc/download/I397/ida_ts_pstn1_i4r2.pdf
+ ; Frequency specs are: 425 Hz +/- 20Hz; 24 Hz +/- 2Hz; modulation depth 100%; SIT +/- 50Hz
+ ringcadence = 400,200,400,2000
+ dial = 425
+@@ -691,7 +691,7 @@
+ stutter = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440
+
+ [ve]
+-; Tone definition source for ve found on
++; Tone definition source for ve found on
+ ; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf
+ description = Venezuela / South America
+ ringcadence = 1000,4000
+Index: configs/jingle.conf.sample
+===================================================================
+--- a/configs/jingle.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/jingle.conf.sample (.../trunk) (revision 202568)
+@@ -5,16 +5,16 @@
+ ;;list of peers
+ ;
+ ;[guest] ;;special account for options on guest account
+-;disallow=all
++;disallow=all
+ ;allow=ulaw
+ ;context=guest
+ ;
+ ;[ogorman]
+-;username=ogorman@gmail.com ;;username of the peer your
++;username=ogorman@gmail.com ;;username of the peer your
+ ;;calling or accepting calls from
+ ;disallow=all
+ ;allow=ulaw
+-;context=default
++;context=default
+ ;connection=asterisk ;;client or component in jabber.conf
+ ;;for the call to leave on.
+ ;
+Index: configs/voicemail.conf.sample
+===================================================================
+--- a/configs/voicemail.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/voicemail.conf.sample (.../trunk) (revision 202568)
+@@ -65,7 +65,7 @@
+ ;userscontext=default
+ ;
+ ; If you need to have an external program, i.e. /usr/bin/myapp
+-; called when a voicemail is left, delivered, or your voicemailbox
++; called when a voicemail is left, delivered, or your voicemailbox
+ ; is checked, uncomment this.
+ ;externnotify=/usr/bin/myapp
+
+@@ -93,7 +93,7 @@
+ ;directoryintro=dir-intro
+ ; The character set for voicemail messages can be specified here
+ ;charset=ISO-8859-1
+-; The ADSI feature descriptor number to download to
++; The ADSI feature descriptor number to download to
+ ;adsifdn=0000000F
+ ; The ADSI security lock code
+ ;adsisec=9BDBF7AC
+@@ -156,59 +156,59 @@
+ ; ; enables polling mailboxes for changes. Normally, it will
+ ; ; expect that changes are only made when someone called in
+ ; ; to one of the voicemail applications.
+-; ; Examples of situations that would require this option are
+-; ; web interfaces to voicemail or an email client in the case
++; ; Examples of situations that would require this option are
++; ; web interfaces to voicemail or an email client in the case
+ ; ; of using IMAP storage.
+ ;
+ ;pollfreq=30 ; If the "pollmailboxes" option is enabled, this option
+ ; ; sets the polling frequency. The default is once every
+ ; ; 30 seconds.
+-; If using IMAP storage, specify whether voicemail greetings should be stored
++; If using IMAP storage, specify whether voicemail greetings should be stored
+ ; via IMAP. If no, then greetings are stored as if IMAP storage were not enabled
+ ;imapgreetings=no
+ ; If imapgreetings=yes, then specify which folder to store your greetings in. If
+ ; you do not specify a folder, then INBOX will be used
+ ;greetingsfolder=INBOX
+-; Some IMAP server implementations store folders under INBOX instead of
++; Some IMAP server implementations store folders under INBOX instead of
+ ; using a top level folder (ex. INBOX/Friends). In this case, user
+ ; imapparentfolder to set the parent folder. For example, Cyrus IMAP does
+ ; NOT use INBOX as the parent. Default is to have no parent folder set.
+ ;imapparentfolder=INBOX
+-;
+-; Users may be located in different timezones, or may have different
+-; message announcements for their introductory message when they enter
+-; the voicemail system. Set the message and the timezone each user
+-; hears here. Set the user into one of these zones with the tz= attribute
+-; in the options field of the mailbox. Of course, language substitution
+-; still applies here so you may have several directory trees that have
+-; alternate language choices.
+-;
+-; Look in /usr/share/zoneinfo/ for names of timezones.
+-; Look at the manual page for strftime for a quick tutorial on how the
+-; variable substitution is done on the values below.
+-;
+-; Supported values:
++;
++; Users may be located in different timezones, or may have different
++; message announcements for their introductory message when they enter
++; the voicemail system. Set the message and the timezone each user
++; hears here. Set the user into one of these zones with the tz= attribute
++; in the options field of the mailbox. Of course, language substitution
++; still applies here so you may have several directory trees that have
++; alternate language choices.
++;
++; Look in /usr/share/zoneinfo/ for names of timezones.
++; Look at the manual page for strftime for a quick tutorial on how the
++; variable substitution is done on the values below.
++;
++; Supported values:
+ ; 'filename' filename of a soundfile (single ticks around the filename
+ ; required)
+-; ${VAR} variable substitution
+-; A or a Day of week (Saturday, Sunday, ...)
+-; B or b or h Month name (January, February, ...)
+-; d or e numeric day of month (first, second, ..., thirty-first)
+-; Y Year
+-; I or l Hour, 12 hour clock
+-; H Hour, 24 hour clock (single digit hours preceded by "oh")
+-; k Hour, 24 hour clock (single digit hours NOT preceded by "oh")
+-; M Minute, with 00 pronounced as "o'clock"
++; ${VAR} variable substitution
++; A or a Day of week (Saturday, Sunday, ...)
++; B or b or h Month name (January, February, ...)
++; d or e numeric day of month (first, second, ..., thirty-first)
++; Y Year
++; I or l Hour, 12 hour clock
++; H Hour, 24 hour clock (single digit hours preceded by "oh")
++; k Hour, 24 hour clock (single digit hours NOT preceded by "oh")
++; M Minute, with 00 pronounced as "o'clock"
+ ; N Minute, with 00 pronounced as "hundred" (US military time)
+-; P or p AM or PM
++; P or p AM or PM
+ ; Q "today", "yesterday" or ABdY
+-; (*note: not standard strftime value)
++; (*note: not standard strftime value)
+ ; q "" (for today), "yesterday", weekday, or ABdY
+-; (*note: not standard strftime value)
+-; R 24 hour time, including minute
+-;
+-;
++; (*note: not standard strftime value)
++; R 24 hour time, including minute
+ ;
++;
++;
+ ; Each mailbox is listed in the form <mailbox>=<password>,<name>,<email>,<pager_email>,<options>
+ ; if the e-mail is specified, a message will be sent when a message is
+ ; received, to the given mailbox. If pager is specified, a message will be
+@@ -218,7 +218,7 @@
+ ; Advanced options example is extension 4069
+ ; NOTE: All options can be expressed globally in the general section, and
+ ; overridden in the per-mailbox settings, unless listed otherwise.
+-;
++;
+ ; tz=central ; Timezone from zonemessages below. Irrelevant if envelope=no.
+ ; attach=yes ; Attach the voicemail to the notification email *NOT* the pager email
+ ; attachfmt=wav49 ; Which format to attach to the email. Normally this is the
+@@ -226,16 +226,16 @@
+ ; option lets you customize the format sent to particular mailboxes.
+ ; Useful if Windows users want wav49, but Linux users want gsm.
+ ; [per-mailbox only]
+-; saycid=yes ; Say the caller id information before the message. If not described,
++; saycid=yes ; Say the caller id information before the message. If not described,
+ ; or set to no, it will be in the envelope
+-; cidinternalcontexts=intern ; Internal Context for Name Playback instead of
++; cidinternalcontexts=intern ; Internal Context for Name Playback instead of
+ ; extension digits when saying caller id.
+ ; sayduration=no ; Turn on/off the duration information before the message. [ON by default]
+ ; saydurationm=2 ; Specify the minimum duration to say. Default is 2 minutes
+-; dialout=fromvm ; Context to dial out from [option 4 from mailbox's advanced menu].
+- ; If not specified, option 4 will not be listed and dialing out
++; dialout=fromvm ; Context to dial out from [option 4 from mailbox's advanced menu].
++ ; If not specified, option 4 will not be listed and dialing out
+ ; from within VoiceMailMain() will not be permitted.
+-sendvoicemail=yes ; Allow the user to compose and send a voicemail while inside
++sendvoicemail=yes ; Allow the user to compose and send a voicemail while inside
+ ; VoiceMailMain() [option 5 from mailbox's advanced menu].
+ ; If set to 'no', option 5 will not be listed.
+ ; searchcontexts=yes ; Current default behavior is to search only the default context
+@@ -244,7 +244,7 @@
+ ; Note: If you have this option enabled, then you will be required to have
+ ; unique mailbox names across all contexts. Otherwise, an ambiguity is created
+ ; since it is impossible to know which mailbox to retrieve when one is requested.
+-; callback=fromvm ; Context to call back from
++; callback=fromvm ; Context to call back from
+ ; if not listed, calling the sender back will not be permitted
+ ; exitcontext=fromvm ; Context to go to on user exit such as * or 0
+ ; The default is the current context.
+@@ -253,10 +253,10 @@
+ ; reach an operator. This option REQUIRES an 'o' extension in the
+ ; same context (or in exitcontext, if set), as that is where the
+ ; 0 key will send you. [OFF by default]
+-; envelope=no ; Turn on/off envelope playback before message playback. [ON by default]
++; envelope=no ; Turn on/off envelope playback before message playback. [ON by default]
+ ; This does NOT affect option 3,3 from the advanced options menu
+ ; delete=yes ; After notification, the voicemail is deleted from the server. [per-mailbox only]
+- ; This is intended for use with users who wish to receive their
++ ; This is intended for use with users who wish to receive their
+ ; voicemail ONLY by email. Note: "deletevoicemail" is provided as an
+ ; equivalent option for Realtime configuration.
+ ; volgain=0.0 ; Emails bearing the voicemail may arrive in a volume too
+@@ -264,7 +264,7 @@
+ ; much gain to add to the message when sending a voicemail.
+ ; NOTE: sox must be installed for this option to work.
+ ; nextaftercmd=yes ; Skips to the next message after hitting 7 or 9 to delete/save current message.
+- ; [global option only at this time]
++ ; [global option only at this time]
+ ; forcename=yes ; Forces a new user to record their name. A new user is
+ ; determined by the password being the same as
+ ; the mailbox number. The default is "no".
+Index: configs/misdn.conf.sample
+===================================================================
+--- a/configs/misdn.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/misdn.conf.sample (.../trunk) (revision 202568)
+@@ -7,13 +7,13 @@
+ ; for debugging and general setup, things that are not bound to port groups
+ ;
+
+-[general]
++[general]
+ ;
+ ; Sets the Path to the misdn-init.conf (for nt_ptp mode checking)
+ ;
+ misdn_init=/etc/misdn-init.conf
+
+-; set debugging flag:
++; set debugging flag:
+ ; 0 - No Debug
+ ; 1 - mISDN Messages and * - Messages, and * - State changes
+ ; 2 - Messages + Message specific Informations (e.g. bearer capability)
+@@ -26,8 +26,8 @@
+
+
+
+-; set debugging file and flags for mISDNuser (NT-Stack)
+-;
++; set debugging file and flags for mISDNuser (NT-Stack)
++;
+ ; flags can be or'ed with the following values:
+ ;
+ ; DBGM_NET 0x00000001
+@@ -57,7 +57,7 @@
+ ntdebugfile=/var/log/misdn-nt.log
+
+
+-; some pbx systems do cut the L1 for some milliseconds, to avoid
++; some pbx systems do cut the L1 for some milliseconds, to avoid
+ ; dropping running calls, we can set this flag to yes and tell
+ ; mISDNuser not to drop the calls on L2_RELEASE
+ ntkeepcalls=no
+@@ -76,26 +76,13 @@
+ bridging=no
+
+
+-;
+-; watches the L1s of every port. If one l1 is down it tries to
+-; get it up. The timeout is given in seconds. with 0 as value it
+-; does not watch the l1 at all
+-;
+-; default value: 0
+-;
+-; this option is only read at loading time of chan_misdn,
+-; which means you need to unload and load chan_misdn to change the
+-; value, an asterisk restart should do the trick
+-;
+-l1watcher_timeout=0
+-
+ ; stops dialtone after getting first digit on nt Port
+ ;
+ ; default value: yes
+ ;
+ stop_tone_after_first_digit=yes
+
+-; whether to append overlapdialed Digits to Extension or not
++; whether to append overlapdialed Digits to Extension or not
+ ;
+ ; default value: yes
+ ;
+@@ -122,19 +109,6 @@
+ ;
+ crypt_keys=test,muh
+
+-; users sections:
+-;
+-; name your sections as you which but not "general" !
+-; the sections are Groups, you can dial out in extensions.conf
+-; with Dial(mISDN/g:extern/101) where extern is a section name,
+-; chan_misdn tries every port in this section to find a
+-; new free channel
+-;
+-
+-; The default section is not a group section, it just contains config elements
+-; which are inherited by group sections.
+-;
+-
+ ;------------------------------ JITTER BUFFER CONFIGURATION --------------------------
+ ; jbenable = yes ; Enables the use of a jitterbuffer on the receiving side of a
+ ; SIP channel. Defaults to "no". An enabled jitterbuffer will
+@@ -161,6 +135,17 @@
+ ; jblog = no ; Enables jitterbuffer frame logging. Defaults to "no".
+ ;-----------------------------------------------------------------------------------
+
++; users sections:
++;
++; name your sections as you wish but not "general" or "default" !
++; the sections are Groups, you can dial out in extensions.conf
++; with Dial(mISDN/g:extern/101) where extern is a section name,
++; chan_misdn tries every port in this section to find a
++; new free channel
++;
++; The default section is not a group section, it just contains config elements
++; which are inherited by group sections.
++;
+ [default]
+
+ ; define your default context here
+@@ -176,13 +161,16 @@
+ language=en
+
+ ;
+-; sets the musiconhold class
++; This option specifies a default music on hold class to
++; use when put on hold if the channel's moh class was not
++; explicitly set with Set(CHANNEL(musicclass)=whatever) and
++; the peer channel did not suggest a class to use.
+ ;
+ musicclass=default
+
+ ;
+ ; Either if we should produce DTMF Tones ourselves
+-;
++;
+ senddtmf=yes
+
+ ;
+@@ -205,14 +193,26 @@
+ ;
+ allowed_bearers=all
+
+-; Prefixes for national and international, those are put before the
+-; oad if an according dialplan is set by the other end.
++; Incoming number prefixes for the indicated Type-Of-Number. These are
++; inserted before any number (caller, dialed, connected, redirecting,
++; redirection) received from the ISDN link if that number has the
++; corresponding Type-Of-Number.
++; See the dialplan options.
+ ;
+-; default values: nationalprefix : 0
+-; internationalprefix : 00
++; default values:
++; unknownprefix=
++; internationalprefix=00
++; nationalprefix=0
++; netspecificprefix=
++; subscriberprefix=
++; abbreviatedprefix=
+ ;
++;unknownprefix=
++internationalprefix=00
+ nationalprefix=0
+-internationalprefix=00
++;netspecificprefix=
++;subscriberprefix=
++;abbreviatedprefix=
+
+ ; set rx/tx gains between -8 and 8 to change the RX/TX Gain
+ ;
+@@ -222,7 +222,7 @@
+ rxgain=0
+ txgain=0
+
+-; some telcos especially in NL seem to need this set to yes, also in
++; some telcos especially in NL seem to need this set to yes, also in
+ ; switzerland this seems to be important
+ ;
+ ; default value: no
+@@ -232,7 +232,20 @@
+
+
+ ;
+-; This option defines, if chan_misdn should check the L1 on a PMP
++; Monitors L1 of the port. If L1 is down it tries
++; to bring it up. The polling timeout is given in seconds.
++; Setting the value to 0 disables monitoring L1 of the port.
++;
++; default value: 0
++;
++; This option is only read at chan_misdn loading time.
++; You need to unload and load chan_misdn to change the
++; value. An asterisk restart will also do the trick.
++;
++l1watcher_timeout=0
++
++;
++; This option defines, if chan_misdn should check the L1 on a PMP
+ ; before making a group call on it. The L1 may go down for PMP Ports
+ ; so we might need this.
+ ; But be aware! a broken or plugged off cable might be used for a group call
+@@ -245,19 +258,19 @@
+
+
+ ;
+-; in PMP this option defines which cause should be sent out to
++; in PMP this option defines which cause should be sent out to
+ ; the 3. caller. chan_misdn does not support callwaiting on TE
+-; PMP side. This allows to modify the RELEASE_COMPLETE cause
++; PMP side. This allows to modify the RELEASE_COMPLETE cause
+ ; at least.
+ ;
+ reject_cause=16
+
+
+ ;
+-; Send Setup_Acknowledge on incoming calls anyway (instead of PROCEEDING),
+-; this requests additional Infos, so we can waitfordigits
++; Send Setup_Acknowledge on incoming calls anyway (instead of PROCEEDING),
++; this requests additional Infos, so we can waitfordigits
+ ; without much issues. This works only for PTP Ports
+-;
++;
+ ; default value: no
+ ;
+ need_more_infos=no
+@@ -280,30 +293,31 @@
+ method=standard
+
+
+-; specify if chan_misdn should collect digits before going into the
++; specify if chan_misdn should collect digits before going into the
+ ; dialplan, you can choose yes=4 Seconds, no, or specify the amount
+ ; of seconds you need;
+-;
++;
+ overlapdial=yes
+
+ ;
+-; dialplan means Type Of Number in ISDN Terms (for outgoing calls)
++; dialplan means Type Of Number in ISDN Terms
++; There are different types of the dialplan:
+ ;
+-; there are different types of the dialplan:
++; dialplan -> for outgoing call's dialed number
++; localdialplan -> for outgoing call's callerid
++; (if -1 is set use the value from the asterisk channel)
++; cpndialplan -> for incoming call's connected party number sent to caller
++; (if -1 is set use the value from the asterisk channel)
+ ;
+-; dialplan -> outgoing Number
+-; localdialplan -> callerid
+-; cpndialplan -> connected party number
++; dialplan options:
+ ;
+-; dialplan options:
+-;
+ ; 0 - unknown
+ ; 1 - International
+ ; 2 - National
++; 3 - Network-Specific
+ ; 4 - Subscriber
++; 5 - Abbreviated
+ ;
+-; This setting is used for outgoing calls
+-;
+ ; default value: 0
+ ;
+ dialplan=0
+@@ -313,7 +327,7 @@
+
+
+ ;
+-; turn this to no if you don't mind correct handling of Progress Indicators
++; turn this to no if you don't mind correct handling of Progress Indicators
+ ;
+ early_bconnect=yes
+
+@@ -321,16 +335,16 @@
+ ;
+ ; turn this on if you like to send Tone Indications to a Incoming
+ ; isdn channel on a TE Port. Rarely used, only if the Telco allows
+-; you to send indications by yourself, normally the Telco sends the
++; you to send indications by yourself, normally the Telco sends the
+ ; indications to the remote party.
+-;
++;
+ ; default: no
+ ;
+ incoming_early_audio=no
+
+ ; uncomment the following to get into s extension at extension conf
+ ; there you can use DigitTimeout if you can't or don't want to use
+-; isdn overlap dial.
++; isdn overlap dial.
+ ; note: This will jump into the s exten for every exten!
+ ;
+ ; default value: no
+@@ -338,7 +352,7 @@
+ ;always_immediate=no
+
+ ;
+-; set this to yes if you want to generate your own dialtone
++; set this to yes if you want to generate your own dialtone
+ ; with always_immediate=yes, else chan_misdn generates the dialtone
+ ;
+ ; default value: no
+@@ -346,9 +360,9 @@
+ nodialtone=no
+
+
+-; uncomment the following if you want callers which called exactly the
++; uncomment the following if you want callers which called exactly the
+ ; base number (so no extension is set) jump to the s extension.
+-; if the user dials something more it jumps to the correct extension
++; if the user dials something more it jumps to the correct extension
+ ; instead
+ ;
+ ; default value: no
+@@ -369,6 +383,8 @@
+ ;callgroup=1
+ ;pickupgroup=1
+
++; Set the outgoing caller id to the value.
++;callerid="name" <number>
+
+ ;
+ ; these are the exact isdn screening and presentation indicators
+@@ -376,11 +392,38 @@
+ ; from asterisks CALLERPRES function.
+ ; s=0, p=0 -> callerid presented
+ ; s=1, p=1 -> callerid restricted (the remote end does not see it!)
+-;
++;
+ ; default values s=-1, p=-1
+ presentation=-1
+ screen=-1
+
++; Select what to do with outgoing COLP information on this port.
++;
++; 0 - Send out COLP information unaltered. (default)
++; 1 - Force COLP to restricted on all outgoing COLP information.
++; 2 - Do not send COLP information.
++outgoing_colp=0
++
++; Put a display ie in the CONNECT message containing the following
++; information if it is available (nt port only):
++;
++; 0 - Do not put the connected line information in the display ie.
++; 1 - Put the available connected line name in the display ie.
++; 2 - Put the available connected line number in the display ie.
++; 3 - Put the available connected line name and number in the display ie.
++;
++display_connected=0
++
++; Put a display ie in the SETUP message containing the following
++; information if it is available (nt port only):
++;
++; 0 - Do not put the caller information in the display ie.
++; 1 - Put the available caller name in the display ie.
++; 2 - Put the available caller number in the display ie.
++; 3 - Put the available caller name and number in the display ie.
++;
++display_setup=0
++
+ ; This enables echo cancellation with the given number of taps.
+ ; Be aware: Move this setting only to outgoing portgroups!
+ ; A value of zero turns echo cancellation off.
+@@ -391,18 +434,9 @@
+ ;
+ ;echocancel=no
+
+-; Set this to no to disable echotraining. You can enter a number > 10
+-; the value is a multiple of 0.125 ms.
+ ;
+-; default value: no
+-; yes = 2000
+-; no = 0
++; chan_misdns jitterbuffer, default 4000
+ ;
+-echotraining=no
+-
+-;
+-; chan_misdns jitterbuffer, default 4000
+-;
+ jitterbuffer=4000
+
+ ;
+@@ -412,7 +446,7 @@
+
+
+ ;
+-; change this to yes, if you want to bridge a mISDN data channel to
++; change this to yes, if you want to bridge a mISDN data channel to
+ ; another channel type or to an application.
+ ;
+ hdlc=no
+@@ -420,8 +454,8 @@
+
+ ;
+ ; defines the maximum amount of incoming calls per port for
+-; this group. Calls which exceed the maximum will be marked with
+-; the channel variable MAX_OVERFLOW. It will contain the amount of
++; this group. Calls which exceed the maximum will be marked with
++; the channel variable MAX_OVERFLOW. It will contain the amount of
+ ; overflowed calls
+ ;
+ max_incoming=-1
+@@ -432,8 +466,19 @@
+ ;
+ max_outgoing=-1
+
++;
++; Enable/disable the call-completion retention option support (ptp only).
++;
++; Note: To use the CCBS/CCNR supplementary service feature and other
++; supplementary services using FACILITY messages requires a
++; modified version of mISDN from:
++; http://svn.digium.com/svn/thirdparty/mISDN/trunk
++; http://svn.digium.com/svn/thirdparty/mISDNuser/trunk
++;
++cc_request_retention=yes
++
+ [intern]
+-; define your ports, e.g. 1,2 (depends on mISDN-driver loading order)
++; define your ports, e.g. 1,2 (depends on mISDN-driver loading order)
+ ports=1,2
+ ; context where to go to when incoming Call on one of the above ports
+ context=Intern
+@@ -445,21 +490,21 @@
+ ; configs. For backwards compatibility you can still set ptp here.
+ ;
+ ports=3
+-
++
+ [first_extern]
+ ; again port defs
+ ports=4
+ ; again a context for incoming calls
+ context=Extern1
+-; msns for te ports, listen on those numbers on the above ports, and
++; msns for te ports, listen on those numbers on the above ports, and
+ ; indicate the incoming calls to asterisk
+-; here you can give a comma separated list or simply an '*' for
+-; any msn.
++; here you can give a comma separated list or simply an '*' for
++; any msn.
+ msns=*
+
+ ; here an example with given msns
+ [second_extern]
+ ports=5
+ context=Extern2
+-callerid=15
++callerid="Asterisk" <1234>
+ msns=102,144,101,104
+Index: configs/festival.conf.sample
+===================================================================
+--- a/configs/festival.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/festival.conf.sample (.../trunk) (revision 202568)
+@@ -15,9 +15,9 @@
+ ;
+ ;usecache=yes
+ ;
+-; If usecache=yes, a directory to store waveform cache files.
++; If usecache=yes, a directory to store waveform cache files.
+ ; The cache is never cleared (yet), so you must take care of cleaning it
+-; yourself (just delete any or all files from the cache).
++; yourself (just delete any or all files from the cache).
+ ; THIS DIRECTORY *MUST* EXIST and must be writable from the asterisk process.
+ ; Defaults to /tmp/
+ ;
+@@ -25,10 +25,10 @@
+ ;
+ ; Festival command to send to the server.
+ ; Defaults to: (tts_textasterisk "%s" 'file)(quit)\n
+-; %s is replaced by the desired text to say. The command MUST end with a
+-; (quit) directive, or the cache handling mechanism will hang. Do not
+-; forget the \n at the end.
+-;
++; %s is replaced by the desired text to say. The command MUST end with a
++; (quit) directive, or the cache handling mechanism will hang. Do not
++; forget the \n at the end.
++;
+ ;festivalcommand=(tts_textasterisk "%s" 'file)(quit)\n
+ ;
+ ;
+Index: configs/http.conf.sample
+===================================================================
+--- a/configs/http.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/http.conf.sample (.../trunk) (revision 202568)
+@@ -38,7 +38,7 @@
+ ;enablestatic=yes
+ ;
+ ; Redirect one URI to another. This is how you would set a
+-; default page.
++; default page.
+ ; Syntax: redirect=<from here> <to there>
+ ; For example, if you are using the Asterisk-gui,
+ ; it is convenient to enable the following redirect:
+@@ -46,18 +46,21 @@
+ ;redirect = / /static/config/cfgbasic.html
+ ;
+ ; HTTPS support. In addition to enabled=yes, you need to
+-; explicitly enable ssl, define the port to use,
++; explicitly enable tls, define the port to use,
+ ; and have a certificate somewhere.
+-; sslenable=yes ; enable ssl - default no.
+-; sslbindport=4433 ; port to use - default is 8089
+-; sslbindaddr=0.0.0.0 ; address to bind to - default is bindaddr.
++;tlsenable=yes ; enable tls - default no.
++;tlsbindport=4433 ; port to use - default is 8089
++;tlsbindaddr=0.0.0.0 ; address to bind to - default is bindaddr.
+ ;
+-; sslcert=/tmp/foo.pem ; path to the certificate
++;tlscertfile=</path/to/certificate.pem> ; path to the certificate file (*.pem) only.
++;tlsprivatekey=</path/to/private.pem> ; path to private key file (*.pem) only.
++; If no path is given for tlscertfile or tlsprivatekey, default is to look in current
++; directory. If no tlsprivatekey is given, default is to search tlscertfile for private key.
+ ;
+-; To produce a certificate you can e.g. use openssl
+-; openssl req -new -x509 -days 365 -nodes -out /tmp/foo.pem -keyout /tmp/foo.pem
++; To produce a certificate you can e.g. use openssl. This places both the cert and
++; private in same .pem file.
++; openssl req -new -x509 -days 365 -nodes -out /tmp/foo.pem -keyout /tmp/foo.pem
+ ;
+-
+ ; The post_mappings section maps URLs to real paths on the filesystem. If a
+ ; POST is done from within an authenticated manager session to one of the
+ ; configured POST mappings, then any files in the POST will be placed in the
+Index: configs/phoneprov.conf.sample
+===================================================================
+--- a/configs/phoneprov.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/phoneprov.conf.sample (.../trunk) (revision 202568)
+@@ -14,7 +14,7 @@
+ ; You can define profiles for different phones specifying what files to register
+ ; with the provisioning server. You can define either static files, or dynamically
+ ; generated files that can have dynamic names and point to templates that variables
+-; can be substituted into. You can also set arbitrary variables for the profiles
++; can be substituted into. You can also set arbitrary variables for the profiles
+ ; templates to have access to. Example:
+
+ ;[example]
+@@ -44,7 +44,7 @@
+ [polycom]
+ staticdir => configs/ ; Sub directory of AST_DATA_DIR/phoneprov that static files reside
+ ; in. This allows a request to /phoneprov/sip.cfg to pull the file
+- ; from /phoneprov/configs/sip.cfg
++ ; from /phoneprov/configs/sip.cfg
+ mime_type => text/xml ; Default mime type to use if one isn't specified or the
+ ; extension isn't recognized
+ static_file => bootrom.ld,application/octet-stream ; Static files the phone will download
+@@ -53,38 +53,38 @@
+ static_file => sip.ver,plain/text
+ static_file => sip.cfg
+ static_file => custom.cfg
+-static_file => 2201-06642-001.bootrom.ld,application/octet-stream
+-static_file => 2201-06642-001.sip.ld,application/octet-stream
+-static_file => 2345-11000-001.bootrom.ld,application/octet-stream
++static_file => 2201-06642-001.bootrom.ld,application/octet-stream
++static_file => 2201-06642-001.sip.ld,application/octet-stream
++static_file => 2345-11000-001.bootrom.ld,application/octet-stream
+ static_file => 2345-11300-001.bootrom.ld,application/octet-stream
+ static_file => 2345-11300-010.bootrom.ld,application/octet-stream
+ static_file => 2345-11300-010.sip.ld,application/octet-stream
+-static_file => 2345-11402-001.bootrom.ld,application/octet-stream
+-static_file => 2345-11402-001.sip.ld,application/octet-stream
+-static_file => 2345-11500-001.bootrom.ld,application/octet-stream
+-static_file => 2345-11500-010.bootrom.ld,application/octet-stream
+-static_file => 2345-11500-020.bootrom.ld,application/octet-stream
+-static_file => 2345-11500-030.bootrom.ld,application/octet-stream
+-static_file => 2345-11500-030.sip.ld,application/octet-stream
+-static_file => 2345-11500-040.bootrom.ld,application/octet-stream
+-static_file => 2345-11500-040.sip.ld,application/octet-stream
+-static_file => 2345-11600-001.bootrom.ld,application/octet-stream
+-static_file => 2345-11600-001.sip.ld,application/octet-stream
+-static_file => 2345-11605-001.bootrom.ld,application/octet-stream
+-static_file => 2345-11605-001.sip.ld,application/octet-stream
+-static_file => 2345-12200-001.bootrom.ld,application/octet-stream
+-static_file => 2345-12200-001.sip.ld,application/octet-stream
+-static_file => 2345-12200-002.bootrom.ld,application/octet-stream
+-static_file => 2345-12200-002.sip.ld,application/octet-stream
++static_file => 2345-11402-001.bootrom.ld,application/octet-stream
++static_file => 2345-11402-001.sip.ld,application/octet-stream
++static_file => 2345-11500-001.bootrom.ld,application/octet-stream
++static_file => 2345-11500-010.bootrom.ld,application/octet-stream
++static_file => 2345-11500-020.bootrom.ld,application/octet-stream
++static_file => 2345-11500-030.bootrom.ld,application/octet-stream
++static_file => 2345-11500-030.sip.ld,application/octet-stream
++static_file => 2345-11500-040.bootrom.ld,application/octet-stream
++static_file => 2345-11500-040.sip.ld,application/octet-stream
++static_file => 2345-11600-001.bootrom.ld,application/octet-stream
++static_file => 2345-11600-001.sip.ld,application/octet-stream
++static_file => 2345-11605-001.bootrom.ld,application/octet-stream
++static_file => 2345-11605-001.sip.ld,application/octet-stream
++static_file => 2345-12200-001.bootrom.ld,application/octet-stream
++static_file => 2345-12200-001.sip.ld,application/octet-stream
++static_file => 2345-12200-002.bootrom.ld,application/octet-stream
++static_file => 2345-12200-002.sip.ld,application/octet-stream
+ static_file => 2345-12200-004.bootrom.ld,application/octet-stream
+ static_file => 2345-12200-004.sip.ld,application/octet-stream
+ static_file => 2345-12200-005.bootrom.ld,application/octet-stream
+ static_file => 2345-12200-005.sip.ld,application/octet-stream
+ static_file => 2345-12500-001.bootrom.ld,application/octet-stream
+-static_file => 2345-12500-001.sip.ld,application/octet-stream
+-static_file => 2345-12560-001.bootrom.ld,application/octet-stream
+-static_file => 2345-12560-001.sip.ld,application/octet-stream
+-static_file => 2345-12600-001.bootrom.ld,application/octet-stream
++static_file => 2345-12500-001.sip.ld,application/octet-stream
++static_file => 2345-12560-001.bootrom.ld,application/octet-stream
++static_file => 2345-12560-001.sip.ld,application/octet-stream
++static_file => 2345-12600-001.bootrom.ld,application/octet-stream
+ static_file => 2345-12600-001.sip.ld,application/octet-stream
+ static_file => 2345-12670-001.bootrom.ld,application/octet-stream
+ static_file => 2345-12670-001.sip.ld,application/octet-stream
+@@ -112,6 +112,6 @@
+
+ ${MAC}.cfg => 000000000000.cfg ; Dynamically generated files.
+ ${MAC}-phone.cfg => 000000000000-phone.cfg ; (relative to AST_DATA_DIR/phoneprov)
+-config/${MAC} => polycom.xml ; Dynamic Filename => template file
++config/${MAC} => polycom.xml ; Dynamic Filename => template file
+ ${MAC}-directory.xml => 000000000000-directory.xml
+ setvar => CUSTOM_CONFIG=/var/lib/asterisk/phoneprov/configs/custom.cfg ; Custom variable
+Index: configs/alarmreceiver.conf.sample
+===================================================================
+--- a/configs/alarmreceiver.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/alarmreceiver.conf.sample (.../trunk) (revision 202568)
+@@ -7,10 +7,10 @@
+
+ [general]
+
+-;
++;
+ ; Specify a timestamp format for the metadata section of the event files
+ ; Default is %a %b %d, %Y @ %H:%M:%S %Z
+-
++
+ timestampformat = %a %b %d, %Y @ %H:%M:%S %Z
+
+ ;
+@@ -32,7 +32,7 @@
+
+ eventspooldir = /tmp
+
+-;
++;
+ ; The alarmreceiver app can either log the events one-at-a-time to individual
+ ; files in the spool directory, or it can store them until the caller
+ ; disconnects and write them all to one file.
+@@ -46,7 +46,7 @@
+ ; The timeout for receiving the first DTMF digit is adjustable from 1000 msec.
+ ; to 10000 msec. The default is 2000 msec. Note: if you wish to test the
+ ; receiver by entering digits manually, set this to a reasonable time out
+-; like 10000 milliseconds.
++; like 10000 milliseconds.
+
+ fdtimeout = 2000
+
+@@ -54,7 +54,7 @@
+ ; The timeout for receiving subsequent DTMF digits is adjustable from
+ ; 110 msec. to 4000 msec. The default is 200 msec. Note: if you wish to test
+ ; the receiver by entering digits manually, set this to a reasonable time out
+-; like 4000 milliseconds.
++; like 4000 milliseconds.
+ ;
+
+ sdtimeout = 200
+Index: configs/musiconhold.conf.sample
+===================================================================
+--- a/configs/musiconhold.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/musiconhold.conf.sample (.../trunk) (revision 202568)
+@@ -8,9 +8,9 @@
+
+
+ ; valid mode options:
+-; files -- read files from a directory in any Asterisk supported
++; files -- read files from a directory in any Asterisk supported
+ ; media format
+-; quietmp3 -- default
++; quietmp3 -- default
+ ; mp3 -- loud
+ ; mp3nb -- unbuffered
+ ; quietmp3nb -- quiet unbuffered
+Index: configs/iaxprov.conf.sample
+===================================================================
+--- a/configs/iaxprov.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/iaxprov.conf.sample (.../trunk) (revision 202568)
+@@ -7,7 +7,7 @@
+ ; Templates provide a group of settings from which provisioning takes place.
+ ; A template may be based upon any template that has been specified before
+ ; it. If the template that an entry is based on is not specified then it is
+-; presumed to be 'default' (unless it is the first of course).
++; presumed to be 'default' (unless it is the first of course).
+ ;
+ ; Templates which begin with 'si-' are used for provisioning units with
+ ; specific service identifiers. For example the entry "si-000364000126"
+Index: configs/unistim.conf.sample
+===================================================================
+--- a/configs/unistim.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/unistim.conf.sample (.../trunk) (revision 202568)
+@@ -69,7 +69,7 @@
+ ;bookmark=Hans C.@123 ; Use a softkey to dial 123. Name : 9 char max
+ ;bookmark=Mailbox@011@54 ; 54 shows a mailbox icon. See #define FAV_ICON_ for other values (32 to 63)
+ ;bookmark=Test@*@USTM/violet ; Display an icon if violet is connected (dynamic), only for unistim device
+-;bookmark=4@Pager@54321@51 ; Display a pager icon and dial 54321 when softkey 4 is pressed
++;bookmark=4@Pager@54321@51 ; Display a pager icon and dial 54321 when softkey 4 is pressed
+
+ ;[violet]
+ ;device=006038abcdef
+Index: configs/extensions.conf.sample
+===================================================================
+--- a/configs/extensions.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/extensions.conf.sample (.../trunk) (revision 202568)
+@@ -1,21 +1,21 @@
+ ; extensions.conf - the Asterisk dial plan
+ ;
+ ; Static extension configuration file, used by
+-; the pbx_config module. This is where you configure all your
+-; inbound and outbound calls in Asterisk.
+-;
+-; This configuration file is reloaded
++; the pbx_config module. This is where you configure all your
++; inbound and outbound calls in Asterisk.
++;
++; This configuration file is reloaded
+ ; - With the "dialplan reload" command in the CLI
+ ; - With the "reload" command (that reloads everything) in the CLI
+
+ ;
+-; The "General" category is for certain variables.
++; The "General" category is for certain variables.
+ ;
+ [general]
+ ;
+ ; If static is set to no, or omitted, then the pbx_config will rewrite
+ ; this file when extensions are modified. Remember that all comments
+-; made in the file will be lost when that happens.
++; made in the file will be lost when that happens.
+ ;
+ ; XXX Not yet implemented XXX
+ ;
+@@ -30,8 +30,8 @@
+ ; things to do, it will terminate the call with BUSY, CONGESTION
+ ; or HANGUP depending on Asterisk's best guess. This is the default.
+ ;
+-; If autofallthrough is not set, then if an extension runs out of
+-; things to do, Asterisk will wait for a new extension to be dialed
++; If autofallthrough is not set, then if an extension runs out of
++; things to do, Asterisk will wait for a new extension to be dialed
+ ; (this is the original behavior of Asterisk 1.0 and earlier).
+ ;
+ ;autofallthrough=no
+@@ -41,7 +41,7 @@
+ ; If extenpatternmatchnew is set (true, yes, etc), then a new algorithm that uses
+ ; a Trie to find the best matching pattern is used. In dialplans
+ ; with more than about 20-40 extensions in a single context, this
+-; new algorithm can provide a noticeable speedup.
++; new algorithm can provide a noticeable speedup.
+ ; With 50 extensions, the speedup is 1.32x
+ ; with 88 extensions, the speedup is 2.23x
+ ; with 138 extensions, the speedup is 3.44x
+@@ -49,27 +49,27 @@
+ ; with 438 extensions, the speedup is 10.4x
+ ; With 1000 extensions, the speedup is ~25x
+ ; with 10,000 extensions, the speedup is 374x
+-; Basically, the new algorithm provides a flat response
++; Basically, the new algorithm provides a flat response
+ ; time, no matter the number of extensions.
+ ;
+-; By default, the old pattern matcher is used.
++; By default, the old pattern matcher is used.
+ ;
+ ; ****This is a new feature! *********************
+-; The new pattern matcher is for the brave, the bold, and
++; The new pattern matcher is for the brave, the bold, and
+ ; the desperate. If you have large dialplans (more than about 50 extensions
+-; in a context), and/or high call volume, you might consider setting
++; in a context), and/or high call volume, you might consider setting
+ ; this value to "yes" !!
+ ; Please, if you try this out, and are forced to return to the
+ ; old pattern matcher, please report your reasons in a bug report
+-; on bugs.digium.com. We have made good progress in providing something
+-; compatible with the old matcher; help us finish the job!
++; on https://issues.asterisk.org. We have made good progress in providing
++; something compatible with the old matcher; help us finish the job!
+ ;
+ ; This value can be switched at runtime using the cli command "dialplan set extenpatternmatchnew true"
+ ; or "dialplan set extenpatternmatchnew false", so you can experiment to your hearts content.
+ ;
+ ;extenpatternmatchnew=no
+ ;
+-; If clearglobalvars is set, global variables will be cleared
++; If clearglobalvars is set, global variables will be cleared
+ ; and reparsed on a dialplan reload, or Asterisk reload.
+ ;
+ ; If clearglobalvars is not set, then global variables will persist
+@@ -108,7 +108,7 @@
+ ;#include "filename.conf"
+ ;
+ ; You can execute a program or script that produces config files, and they
+-; will be inserted where you insert the #exec command. The #exec command
++; will be inserted where you insert the #exec command. The #exec command
+ ; works on all asterisk configuration files. However, you will need to
+ ; activate them within asterisk.conf with the "execincludes" option. They
+ ; are otherwise considered a security risk.
+@@ -153,8 +153,8 @@
+ ; yourself a ton of grief.
+ ; WARNING WARNING WARNING WARNING
+ ;
+-; Any category other than "General" and "Globals" represent
+-; extension contexts, which are collections of extensions.
++; Any category other than "General" and "Globals" represent
++; extension contexts, which are collections of extensions.
+ ;
+ ; Extension names may be numbers, letters, or combinations
+ ; thereof. If an extension name is prefixed by a '_'
+@@ -165,12 +165,12 @@
+ ; Z - any digit from 1-9
+ ; N - any digit from 2-9
+ ; [1235-9] - any digit in the brackets (in this example, 1,2,3,5,6,7,8,9)
+-; . - wildcard, matches anything remaining (e.g. _9011. matches
++; . - wildcard, matches anything remaining (e.g. _9011. matches
+ ; anything starting with 9011 excluding 9011 itself)
+ ; ! - wildcard, causes the matching process to complete as soon as
+ ; it can unambiguously determine that no other matches are possible
+ ;
+-; For example, the extension _NXXXXXX would match normal 7 digit dialings,
++; For example, the extension _NXXXXXX would match normal 7 digit dialings,
+ ; while _1NXXNXXXXXX would represent an area code plus phone number
+ ; preceded by a one.
+ ;
+@@ -197,7 +197,7 @@
+ ;[context]
+ ;exten => someexten,{priority|label{+|-}offset}[(alias)],application(arg1,arg2,...)
+ ;
+-; Timing list for includes is
++; Timing list for includes is
+ ;
+ ; <time range>,<days of week>,<days of month>,<months>[,<timezone>]
+ ;
+@@ -246,7 +246,7 @@
+ ;
+ ; If you are freely delivering calls to the PSTN, list them here
+ ;
+-;exten => _1256428XXXX,1,Dial(DAHDI/G2/${EXTEN:7}) ; Expose all of 256-428
++;exten => _1256428XXXX,1,Dial(DAHDI/G2/${EXTEN:7}) ; Expose all of 256-428
+ ;exten => _1256325XXXX,1,Dial(DAHDI/G2/${EXTEN:7}) ; Ditto for 256-325
+
+ [dundi-e164-local]
+@@ -272,15 +272,15 @@
+ include => dundi-e164-local
+ include => dundi-e164-switch
+ ;
+-; DUNDi can also be implemented as a Macro instead of using
+-; the Local channel driver.
++; DUNDi can also be implemented as a Macro instead of using
++; the Local channel driver.
+ ;
+ [macro-dundi-e164]
+ ;
+ ; ARG1 is the extension to Dial
+ ;
+ ; Extension "s" is not a wildcard extension that matches "anything".
+-; In macros, it is the start extension. In most other cases,
++; In macros, it is the start extension. In most other cases,
+ ; you have to goto "s" to execute that extension.
+ ;
+ ; For wildcard matches, see above - all pattern matches start with
+@@ -367,10 +367,10 @@
+ include => parkedcalls
+ ;
+ ; You can use an alternative switch type as well, to resolve
+-; extensions that are not known here, for example with remote
++; extensions that are not known here, for example with remote
+ ; IAX switching you transparently get access to the remote
+ ; Asterisk PBX
+-;
++;
+ ; switch => IAX2/user:password@bigserver/local
+ ;
+ ; An "lswitch" is like a switch but is literal, in that
+@@ -388,7 +388,7 @@
+
+ [macro-trunkdial]
+ ;
+-; Standard trunk dial macro (hangs up on a dialstatus that should
++; Standard trunk dial macro (hangs up on a dialstatus that should
+ ; terminate call)
+ ; ${ARG1} - What to dial
+ ;
+@@ -458,7 +458,7 @@
+ exten => _X.,n,Set(LOCAL(cntx)=${ARG5})
+
+ exten => _X.,n,Set(LOCAL(mbx)="${ext}"$["${cntx}" ? "@${cntx}" :: ""])
+-exten => _X.,n,Dial(${dev},20,p) ; Ring the interface, 20 seconds maximum, call screening
++exten => _X.,n,Dial(${dev},20,p) ; Ring the interface, 20 seconds maximum, call screening
+ ; option (or use P for databased call _X.creening)
+ exten => _X.,n,Goto(s-${DIALSTATUS},1) ; Jump based on status (NOANSWER,BUSY,CHANUNAVAIL,CONGESTION,ANSWER)
+
+@@ -520,7 +520,7 @@
+ ; We also create an example user, 1234, who is on the console and has
+ ; voicemail, etc.
+ ;
+-exten => 1234,1,Playback(transfer,skip) ; "Please hold while..."
++exten => 1234,1,Playback(transfer,skip) ; "Please hold while..."
+ ; (but skip if channel is not up)
+ exten => 1234,n,Gosub(stdexten(1234,${GLOBAL(CONSOLE)}))
+ exten => 1234,n,Goto(default,s,1) ; exited Voicemail
+@@ -583,7 +583,7 @@
+
+ ;
+ ; The page context calls up the page macro that sets variables needed for auto-answer
+-; It is in is own context to make calling it from the Page() application as simple as
++; It is in is own context to make calling it from the Page() application as simple as
+ ; Local/{peername}@page
+ ;
+ [page]
+@@ -610,7 +610,7 @@
+
+ [default]
+ ;
+-; By default we include the demo. In a production system, you
++; By default we include the demo. In a production system, you
+ ; probably don't want to have the demo there.
+ ;
+ include => demo
+@@ -723,7 +723,7 @@
+ ; friendly Asterisk CLI prompt.
+ ;
+ ; "core show application <command>" will show details of how you
+-; use that particular application in this file, the dial plan.
++; use that particular application in this file, the dial plan.
+ ; "core show functions" will list all dialplan functions
+ ; "core show function <COMMAND>" will show you more information about
+ ; one function. Remember that function names are UPPER CASE.
+Index: configs/asterisk.adsi
+===================================================================
+--- a/configs/asterisk.adsi (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/asterisk.adsi (.../trunk) (revision 202568)
+@@ -86,10 +86,10 @@
+ IFEVENT OFFHOOK THEN
+ CLEAR
+ CLEARFLAG "nocallwaiting"
+- CLEARDISPLAY
++ CLEARDISPLAY
+ SHOWDISPLAY "titles" AT 1
+- SHOWKEYS "vmail"
+- SHOWKEYS "cidblock"
++ SHOWKEYS "vmail"
++ SHOWKEYS "cidblock"
+ SHOWKEYS "cwdisable" UNLESS "nocallwaiting"
+ GOTO "offHook"
+ ENDIF
+@@ -117,9 +117,9 @@
+ SHOWKEYS "vmail_OH"
+ ENDIF
+ IFEVENT TIMER THEN
+- CLEAR
++ CLEAR
+ SHOWDISPLAY "empty" AT 4
+- ENDIF
++ ENDIF
+ ENDSUB
+
+ SUB "offHook" IS
+Index: configs/users.conf.sample
+===================================================================
+--- a/configs/users.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/users.conf.sample (.../trunk) (revision 202568)
+@@ -2,11 +2,11 @@
+ ; User configuration
+ ;
+ ; Creating entries in users.conf is a "shorthand" for creating individual
+-; entries in each configuration file. Using users.conf is not intended to
++; entries in each configuration file. Using users.conf is not intended to
+ ; provide you with as much flexibility as using the separate configuration
+ ; files (e.g. sip.conf, iax.conf, etc) but is intended to accelerate the
+ ; simple task of adding users. Note that creating individual items (e.g.
+-; custom SIP peers, IAX friends, etc.) will allow you to override specific
++; custom SIP peers, IAX friends, etc.) will allow you to override specific
+ ; parameters within this file. Parameter names here are the same as they
+ ; appear in the other configuration files. There is no way to change the
+ ; value of a parameter here for just one subsystem.
+Index: configs/gtalk.conf.sample
+===================================================================
+--- a/configs/gtalk.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/gtalk.conf.sample (.../trunk) (revision 202568)
+@@ -5,16 +5,16 @@
+ ;;list of peers
+ ;
+ ;[guest] ;;special account for options on guest account
+-;disallow=all
++;disallow=all
+ ;allow=ulaw
+ ;context=guest
+ ;
+ ;[ogorman]
+-;username=ogorman@gmail.com ;;username of the peer your
++;username=ogorman@gmail.com ;;username of the peer your
+ ;;calling or accepting calls from
+ ;disallow=all
+ ;allow=ulaw
+-;context=default
++;context=default
+ ;connection=asterisk ;;client or component in jabber.conf
+ ;;for the call to leave on.
+ ;
+Index: configs/rpt.conf.sample
+===================================================================
+--- a/configs/rpt.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/rpt.conf.sample (.../trunk) (revision 202568)
+@@ -86,7 +86,7 @@
+ ; specify the rxchannel and the txchannel will be assumed from the rxchannel
+ ;txchannel = DAHDI/6 ; Tx audio/signalling channel
+ ;functions = functions-remote
+-;remote = ft897 ; Set remote=y for dumb remote or
++;remote = ft897 ; Set remote=y for dumb remote or
+ ; remote=ft897 for Yaesu FT-897 or
+ ; remote=rbi for Doug Hall RBI1
+ ;iobase = 0x378 ; Specify IO port for parallel port (optional)
+@@ -106,7 +106,7 @@
+ ;6=autopatchup ; Autopatch up
+ ;0=autopatchdn ; Autopatch down
+
+-;90=cop,1 ; System warm boot
++;90=cop,1 ; System warm boot
+ ;91=cop,2 ; System enable
+ ;92=cop,3 ; System disable
+
+@@ -135,7 +135,7 @@
+ ; Single frequencies are created by setting freq1 or freq2 to zero.
+ ;
+ ; |m - Morse escape sequence
+-;
++;
+ ; Sends Morse code at the telemetry amplitude and telemetry frequency as defined in the
+ ; [morse] section.
+ ;
+@@ -150,15 +150,15 @@
+
+
+ ;ct1=|t(350,0,100,2048)(500,0,100,2048)(660,0,100,2048)
+-;ct2=|t(660,880,150,2048)
+-;ct3=|t(440,0,150,2048)
++;ct2=|t(660,880,150,2048)
++;ct3=|t(440,0,150,2048)
+ ;ct4=|t(550,0,150,2048)
+ ;ct5=|t(660,0,150,2048)
+ ;ct6=|t(880,0,150,2048)
+ ;ct7=|t(660,440,150,2048)
+ ;ct8=|t(700,1100,150,2048)
+-;remotetx=|t(2000,0,75,2048)(0,0,75,0)(1600,0,75,2048);
+-;remotemon=|t(1600,0,75,2048)
++;remotetx=|t(2000,0,75,2048)(0,0,75,0)(1600,0,75,2048);
++;remotemon=|t(1600,0,75,2048)
+ ;cmdmode=|t(900,903,200,2048)
+ ;functcomplete=|t(1000,0,100,2048)(0,0,100,0)(1000,0,100,2048)
+
+@@ -168,7 +168,7 @@
+ ;speed=20 ; Approximate speed in WPM
+ ;frequency=800 ; Morse Telemetry Frequency
+ ;amplitude=4096 ; Morse Telemetry Amplitude
+-;idfrequency=330 ; Morse ID Frequency
++;idfrequency=330 ; Morse ID Frequency
+ ;idamplitude=2048 ; Morse ID Amplitude
+
+ ;[nodes]
+Index: configs/rtp.conf.sample
+===================================================================
+--- a/configs/rtp.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/rtp.conf.sample (.../trunk) (revision 202568)
+@@ -18,7 +18,7 @@
+ ; allowed to continue (in 'samples', 1/8000 of a second)
+ ;
+ ;dtmftimeout=3000
+-; rtcpinterval = 5000 ; Milliseconds between rtcp reports
++; rtcpinterval = 5000 ; Milliseconds between rtcp reports
+ ;(min 500, max 60000, default 5000)
+ ;
+ ; Enable strict RTP protection. This will drop RTP packets that
+Index: configs/cli_aliases.conf.sample
+===================================================================
+--- a/configs/cli_aliases.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/cli_aliases.conf.sample (.../trunk) (revision 202568)
+@@ -13,7 +13,7 @@
+ ;template = asterisk12 ; Asterisk 1.2 style syntax
+ ;template = asterisk14 ; Asterisk 1.4 style syntax
+ ;template = individual_custom ; see [individual_custom] example below which
+- ; includes a list of aliases from an external
++ ; includes a list of aliases from an external
+ ; file
+
+
+@@ -70,7 +70,7 @@
+ ; by Asterisk. If you wish to use the provided templates, simply define the
+ ; context name which does not utilize the '_tpl' at the end. For example,
+ ; if you would like to use the Asterisk 1.2 style syntax, define in the
+-; [general] section
++; [general] section
+
+ [asterisk12_tpl](!)
+ show channeltypes=core show channeltypes
+@@ -92,7 +92,7 @@
+ show applications=core show applications
+ show functions=core show functions
+ show switches=core show switches
+-show hints=core show hints
++show hints=core show hints
+ show globals=core show globals
+ show function=core show function
+ show application=core show application
+@@ -102,7 +102,7 @@
+ show audio codecs=core show audio codecs
+ show video codecs=core show video codecs
+ show image codecs=core show image codecs
+-show codec=core show codec
++show codec=core show codec
+ moh classes show=moh show classes
+ moh files show=moh show files
+ agi no debug=agi debug off
+Index: configs/extensions.ael.sample
+===================================================================
+--- a/configs/extensions.ael.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/extensions.ael.sample (.../trunk) (revision 202568)
+@@ -3,16 +3,16 @@
+ //
+ //
+ // Static extension configuration file, used by
+-// the pbx_ael module. This is where you configure all your
+-// inbound and outbound calls in Asterisk.
+-//
+-// This configuration file is reloaded
++// the pbx_ael module. This is where you configure all your
++// inbound and outbound calls in Asterisk.
++//
++// This configuration file is reloaded
+ // - With the "ael reload" command in the CLI
+ // - With the "reload" command (that reloads everything) in the CLI
+
+ // The "Globals" category contains global variables that can be referenced
+ // in the dialplan by using the GLOBAL dialplan function:
+-// ${GLOBAL(VARIABLE)}
++// ${GLOBAL(VARIABLE)}
+ // ${${GLOBAL(VARIABLE)}} or ${text${GLOBAL(VARIABLE)}} or any hybrid
+ // Unix/Linux environmental variables are reached with the ENV dialplan
+ // function: ${ENV(VARIABLE)}
+@@ -44,8 +44,8 @@
+ };
+
+ //
+-// Any category other than "General" and "Globals" represent
+-// extension contexts, which are collections of extensions.
++// Any category other than "General" and "Globals" represent
++// extension contexts, which are collections of extensions.
+ //
+ // Extension names may be numbers, letters, or combinations
+ // thereof. If an extension name is prefixed by a '_'
+@@ -56,12 +56,12 @@
+ // Z - any digit from 1-9
+ // N - any digit from 2-9
+ // [1235-9] - any digit in the brackets (in this example, 1,2,3,5,6,7,8,9)
+-// . - wildcard, matches anything remaining (e.g. _9011. matches
++// . - wildcard, matches anything remaining (e.g. _9011. matches
+ // anything starting with 9011 excluding 9011 itself)
+ // ! - wildcard, causes the matching process to complete as soon as
+ // it can unambiguously determine that no other matches are possible
+ //
+-// For example the extension _NXXXXXX would match normal 7 digit dialings,
++// For example the extension _NXXXXXX would match normal 7 digit dialings,
+ // while _1NXXNXXXXXX would represent an area code plus phone number
+ // preceded by a one.
+ //
+@@ -72,8 +72,8 @@
+ // The priority "same" or "s" means the same as the previously specified
+ // priority, again regardless of whether the previous entry was for the
+ // same extension. Priorities may be immediately followed by a plus sign
+-// and another integer to add that amount (most useful with 's' or 'n').
+-// Priorities may then also have an alias, or label, in
++// and another integer to add that amount (most useful with 's' or 'n').
++// Priorities may then also have an alias, or label, in
+ // parenthesis after their name which can be used in goto situations
+ //
+ // Contexts contain several lines, one for each step of each
+@@ -87,11 +87,11 @@
+ // exten-name => {
+ // application(arg1,arg2,...);
+ //
+-// Timing list for includes is
++// Timing list for includes is
+ //
+ // <time range>|<days of week>|<days of month>|<months>
+ //
+-// includes {
++// includes {
+ // daytime|9:00-17:00|mon-fri|*|*;
+ // };
+ //
+@@ -129,7 +129,7 @@
+ //
+ // If you are freely delivering calls to the PSTN, list them here
+ //
+- //_1256428XXXX => Dial(DAHDI/G2/${EXTEN:7}); // Expose all of 256-428
++ //_1256428XXXX => Dial(DAHDI/G2/${EXTEN:7}); // Expose all of 256-428
+ //_1256325XXXX => Dial(DAHDI/G2/${EXTEN:7}); // Ditto for 256-325
+ };
+
+@@ -149,8 +149,8 @@
+ //
+ // Just a wrapper for the switch
+ //
+-
+- switches {
++
++ switches {
+ DUNDi/e164;
+ };
+ };
+@@ -168,8 +168,8 @@
+ };
+
+ //
+-// DUNDi can also be implemented as a Macro instead of using
+-// the Local channel driver.
++// DUNDi can also be implemented as a Macro instead of using
++// the Local channel driver.
+ //
+ macro ael-dundi-e164(exten) {
+ //
+@@ -240,7 +240,7 @@
+ //
+ // Long distance context accessed through trunk interface
+ //
+-
++
+ _91800NXXXXXX => Dial(${TRUNK}/${EXTEN:${TRUNKMSD}});
+ _91888NXXXXXX => Dial(${TRUNK}/${EXTEN:${TRUNKMSD}});
+ _91877NXXXXXX => Dial(${TRUNK}/${EXTEN:${TRUNKMSD}});
+@@ -285,10 +285,10 @@
+
+ //
+ // You can use an alternative switch type as well, to resolve
+-// extensions that are not known here, for example with remote
++// extensions that are not known here, for example with remote
+ // IAX switching you transparently get access to the remote
+ // Asterisk PBX
+-//
++//
+ // switch => IAX2/user:password@bigserver/local
+ //
+ // An "lswitch" is like a switch but is literal, in that
+@@ -380,7 +380,7 @@
+
+ context ael-default {
+
+-// By default we include the demo. In a production system, you
++// By default we include the demo. In a production system, you
+ // probably don't want to have the demo there.
+
+ includes {
+@@ -443,6 +443,6 @@
+ // friendly Asterisk CLI prompt.
+ //
+ // 'show application <command>' will show details of how you
+-// use that particular application in this file, the dial plan.
++// use that particular application in this file, the dial plan.
+ //
+ }
+Index: configs/extensions_minivm.conf.sample
+===================================================================
+--- a/configs/extensions_minivm.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/extensions_minivm.conf.sample (.../trunk) (revision 202568)
+@@ -1,4 +1,4 @@
+-; MINI-VOICEMAIL dialplan example
++; MINI-VOICEMAIL dialplan example
+ ; ---------------------------------------------------------------------------------------
+ ; ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+ ;
+@@ -10,8 +10,8 @@
+ ; A macro to test the MINIVMACCOUNT dialplan function
+ ; Currently, accountcode and pincode is not used in the application
+ ; They where added to be used in dialplan scripting
+-;
+ ;
++;
+ [macro-minivmfunctest]
+ exten => s,1,set(account=${ARGV1})
+ exten => minivm,n,verbose(1,-------------------- Minivm Function test - Accoutn ${account} -------------)
+Index: configs/followme.conf.sample
+===================================================================
+--- a/configs/followme.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/followme.conf.sample (.../trunk) (revision 202568)
+@@ -29,7 +29,7 @@
+ status_prompt=>followme/status
+ ; The global default for 'The party you're calling isn't at their desk' message.
+ ;
+-sorry_prompt=>followme/sorry
++sorry_prompt=>followme/sorry
+ ; The global default for 'I'm sorry, but we were unable to locate your party' message.
+ ;
+ ;
+@@ -41,9 +41,9 @@
+ number=>01233456,25
+ ; The a follow-me number to call. The format is:
+ ; number=> <number to call[&2nd #[&3rd #]]> [, <timeout value in seconds> [, <order in follow-me>] ]
+-; You can specify as many of these numbers as you like. They will be dialed in the
++; You can specify as many of these numbers as you like. They will be dialed in the
+ ; order that you specify them in the config file OR as specified with the order field
+-; on the number prompt. As you can see from the example, forked dialing of multiple
++; on the number prompt. As you can see from the example, forked dialing of multiple
+ ; numbers in the same step is supported with this application if you'd like to dial
+ ; multiple numbers in the same followme step.
+ ; It's also important to note that the timeout value is not the same
+@@ -79,7 +79,7 @@
+ ; The 'The party you're calling isn't at their desk' message prompt.
+ ; Default is the global default.
+ ;
+-sorry_prompt=>followme/sorry
++sorry_prompt=>followme/sorry
+ ; The 'I'm sorry, but we were unable to locate your party' message prompt. Default
+ ; is the global default.
+
+Index: configs/minivm.conf.sample
+===================================================================
+--- a/configs/minivm.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/minivm.conf.sample (.../trunk) (revision 202568)
+@@ -16,7 +16,7 @@
+ ; Change the from, body and/or subject, variables:
+ ; MVM_NAME, MVM_DUR, MVM_MSGNUM, VM_MAILBOX, MVM_CALLERID, MVM_CIDNUM,
+ ; MVM_CIDNAME, MVM_DATE
+-;
++;
+ ; In addition to these, you can set the MVM_COUNTER channel variable in the
+ ; dial plan and use that as a counter. It will also be used in the file name
+ ; of the media file attached to the message
+@@ -89,43 +89,43 @@
+ ;pagersubject=New VM ${MVM_COUNTER}
+ ;pagerbody=New ${MVM_DUR} long msg in box ${MVM_MAILBOX}\nfrom ${MVM_CALLERID}, on ${MVM_DATE}
+ ;
+-;
++;
+ ;--------------Timezone definitions (used in voicemail accounts) -------------------
+ ;
+-; Users may be located in different timezones, or may have different
+-; message announcements for their introductory message when they enter
+-; the voicemail system. Set the message and the timezone each user
+-; hears here. Set the user into one of these zones with the tz= attribute
+-; in the options field of the mailbox. Of course, language substitution
+-; still applies here so you may have several directory trees that have
+-; alternate language choices.
+-;
+-; Look in /usr/share/zoneinfo/ for names of timezones.
+-; Look at the manual page for strftime for a quick tutorial on how the
+-; variable substitution is done on the values below.
+-;
+-; Supported values:
++; Users may be located in different timezones, or may have different
++; message announcements for their introductory message when they enter
++; the voicemail system. Set the message and the timezone each user
++; hears here. Set the user into one of these zones with the tz= attribute
++; in the options field of the mailbox. Of course, language substitution
++; still applies here so you may have several directory trees that have
++; alternate language choices.
++;
++; Look in /usr/share/zoneinfo/ for names of timezones.
++; Look at the manual page for strftime for a quick tutorial on how the
++; variable substitution is done on the values below.
++;
++; Supported values:
+ ; 'filename' filename of a soundfile (single ticks around the filename
+ ; required)
+-; ${VAR} variable substitution
+-; A or a Day of week (Saturday, Sunday, ...)
+-; B or b or h Month name (January, February, ...)
+-; d or e numeric day of month (first, second, ..., thirty-first)
+-; Y Year
+-; I or l Hour, 12 hour clock
+-; H Hour, 24 hour clock (single digit hours preceded by "oh")
+-; k Hour, 24 hour clock (single digit hours NOT preceded by "oh")
+-; M Minute, with 00 pronounced as "o'clock"
++; ${VAR} variable substitution
++; A or a Day of week (Saturday, Sunday, ...)
++; B or b or h Month name (January, February, ...)
++; d or e numeric day of month (first, second, ..., thirty-first)
++; Y Year
++; I or l Hour, 12 hour clock
++; H Hour, 24 hour clock (single digit hours preceded by "oh")
++; k Hour, 24 hour clock (single digit hours NOT preceded by "oh")
++; M Minute, with 00 pronounced as "o'clock"
+ ; N Minute, with 00 pronounced as "hundred" (US military time)
+-; P or p AM or PM
++; P or p AM or PM
+ ; Q "today", "yesterday" or ABdY
+-; (*note: not standard strftime value)
++; (*note: not standard strftime value)
+ ; q "" (for today), "yesterday", weekday, or ABdY
+-; (*note: not standard strftime value)
+-; R 24 hour time, including minute
+-;
++; (*note: not standard strftime value)
++; R 24 hour time, including minute
++;
+ ; The message here is not used in mini-voicemail, but stays for
+-; backwards compatibility
++; backwards compatibility
+
+ [zonemessages]
+ eastern=America/New_York|'vm-received' Q 'digits/at' IMp
+@@ -141,27 +141,27 @@
+ ; attachmedia = yes | no ; Add media file as attachment?
+ ; dateformat = <formatstring> ; See above
+ ; charset = <charset> ; Mime charset definition for e-mail messages
+-; locale = <locale> ; Locale for LC_TIME - to get weekdays in local language
++; locale = <locale> ; Locale for LC_TIME - to get weekdays in local language
+ ; ; See your O/S documentation for proper settings for setlocale()
+ ; templatefile = <filename> ; File name (relative to Asterisk configuration directory,
+ ; or absolute
+ ; messagebody = Format ; Message body definition with variables
+ ;
+-[template-sv_SE_email]
++[template-sv_SE_email]
+ messagebody=Hej ${MVM_NAME}:\n\n\tDu har fått ett röstbrevlåde-meddelande från ${MVM_CALLERID}.\nLängd: ${MVM_DUR}\nMailbox ${MVM_MAILBOX}\nDatum: ${MVM_DATE}. \nMeddelandet bifogas det här brevet. Om du inte kan läsa det, kontakta intern support. \nHälsningar\n\n\t\t\t\t--Asterisk\n
+ subject = Du har fått röstmeddelande (se bilaga)
+ fromemail = swedish-voicemail-service@stockholm.example.com
+ fromaddress = Asterisk Röstbrevlåda
+ charset=iso-8859-1
+-attachmedia=yes
++attachmedia=yes
+ dateformat=%A, %d %B %Y at %H:%M:%S
+ locale=sv_SE
+
+-[template-en_US_email]
++[template-en_US_email]
+ messagebody=Dear ${MVM_NAME}:\n\n\tjust wanted to let you know you were just left a ${MVM_DUR} long message \nin mailbox ${MVM_MAILBOX} from ${MVM_CALLERID}, on ${MVM_DATE}, so you might\nwant to check it when you get a chance. Thanks!\n\n\t\t\t\t--Asterisk\n
+ subject = New voicemail
+ charset=ascii
+-attachmedia=yes
++attachmedia=yes
+ dateformat=%A, %B %d, %Y at %r
+
+ ;[template-sv_SE_pager]
+@@ -180,12 +180,12 @@
+ ;[template-en_US_email_southern]
+ ;templatefile = templates/email_en_US.txt
+ ;subject = Y'all got voicemail, honey!
+-;charset=ascii
++;charset=ascii
+
+ ;[template-en_UK_email]
+ ;templatefile = templates/email_en_us.txt
+ ;subject = Dear old chap, you've got an electronic communique
+-;charset=ascii
++;charset=ascii
+
+ ;----------------------- Mailbox accounts --------------------------
+ ;Template for mailbox definition - all options
+Index: configs/osp.conf.sample
+===================================================================
+--- a/configs/osp.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/osp.conf.sample (.../trunk) (revision 202568)
+@@ -1,25 +1,34 @@
+ ;
+ ; Open Settlement Protocol Sample Configuration File
+ ;
+-; This file contains configuration of OSP server providers that are used by the
+-; Asterisk OSP module. The section "general" is reserved for global options.
+-; All other sections describe specific OSP Providers. The provider "default"
+-; is used when no provider is otherwise specified.
++; This file contains configuration of OSP server providers that are used by the
++; Asterisk OSP module. The section "general" is reserved for global options.
++; All other sections describe specific OSP Providers. The provider "default"
++; is used when no provider is otherwise specified.
+ ;
+-; The "servicepoint" and "source" parameters must be configured. For most
++; The "servicepoint" and "source" parameters must be configured. For most
+ ; implementations the other parameters in this file can be left unchanged.
+ ;
+ [general]
+ ;
+-; Enable cryptographic acceleration hardware.
++; Enable cryptographic acceleration hardware.
++; The default value is no.
+ ;
+ ;accelerate=no
+ ;
+-; Defines the status of tokens that Asterisk will validate.
+-; 0 - signed tokens only
+-; 1 - unsigned tokens only
++; Enable security features.
++; If security features are disabled, Asterisk cannot validate signed tokens and
++; all certificate file name parameters are ignored.
++; The default value is no.
++;
++;securityfeatures=no
++;
++; Defines the status of tokens that Asterisk will validate.
++; 0 - signed tokens only
++; 1 - unsigned tokens only
+ ; 2 - both signed and unsigned
+ ; The default value is 0, i.e. the Asterisk will only validate signed tokens.
++; If securityfeatures are disabled, Asterisk cannot validate signed tokens.
+ ;
+ ;tokenformat=0
+ ;
+@@ -36,34 +45,37 @@
+ ;source=domain name or [IP address in brackets]
+ ;
+ ; Define path and file name of crypto files.
+-; The default path for crypto file is /var/lib/asterisk/keys. If no path is
++; The default path for crypto file is /var/lib/asterisk/keys. If no path is
+ ; defined, crypto files will in /var/lib/asterisk/keys directory.
+ ;
+-; Specify the private key file name.
+-; If this parameter is unspecified or not present, the default name will be the
+-; osp.conf section name followed by "-privatekey.pem" (for example:
++; Specify the private key file name.
++; If this parameter is unspecified or not present, the default name will be the
++; osp.conf section name followed by "-privatekey.pem" (for example:
+ ; default-privatekey.pem)
++; If securityfeatures are disabled, this parameter is ignored.
+ ;
+ ;privatekey=pkey.pem
+ ;
+-; Specify the local certificate file.
+-; If this parameter is unspecified or not present, the default name will be the
+-; osp.conf section name followed by "- localcert.pem " (for example:
+-; default-localcert.pem)
++; Specify the local certificate file.
++; If this parameter is unspecified or not present, the default name will be the
++; osp.conf section name followed by "- localcert.pem " (for example:
++; default-localcert.pem)
++; If securityfeatures are disabled, this parameter is ignored.
+ ;
+ ;localcert=localcert.pem
+ ;
+-; Specify one or more Certificate Authority key file names. If none are listed,
+-; a single Certificate Authority key file name is added with the default name of
+-; the osp.conf section name followed by "-cacert_0.pem " (for example:
++; Specify one or more Certificate Authority key file names. If none are listed,
++; a single Certificate Authority key file name is added with the default name of
++; the osp.conf section name followed by "-cacert_0.pem " (for example:
+ ; default-cacert_0.pem)
++; If securityfeatures are disabled, this parameter is ignored.
+ ;
+ ;cacert=cacert_0.pem
+ ;
+-; Configure parameters for OSP communication between Asterisk OSP client and OSP
+-; servers.
++; Configure parameters for OSP communication between Asterisk OSP client and OSP
++; servers.
+ ;
+-; maxconnections: Max number of simultaneous connections to the provider OSP
++; maxconnections: Max number of simultaneous connections to the provider OSP
+ ; server (default=20)
+ ; retrydelay: Extra delay between retries (default=0)
+ ; retrylimit: Max number of retries before giving up (default=2)
+@@ -74,17 +86,18 @@
+ ;retrylimit=2
+ ;timeout=500
+ ;
+-; Set the authentication policy.
++; Set the authentication policy.
+ ; 0 - NO - Accept all calls.
+-; 1 - YES - Accept calls with valid token or no token. Block calls with
+-; invalid token.
+-; 2 - EXCLUSIVE - Accept calls with valid token. Block calls with invalid token
++; 1 - YES - Accept calls with valid token or no token. Block calls with
++; invalid token.
++; 2 - EXCLUSIVE - Accept calls with valid token. Block calls with invalid token
+ ; or no token.
+ ; Default is 1,
++; If securityfeatures are disabled, Asterisk cannot validate signed tokens.
+ ;
+ ;authpolicy=1
+ ;
+-; Set the default destination protocol. The OSP module supports SIP, H323, and
++; Set the default destination protocol. The OSP module supports SIP, H323, and
+ ; IAX protocols. The default protocol is set to SIP.
+ ;
+ ;defaultprotocol=SIP
+Index: configs/cdr_custom.conf.sample
+===================================================================
+--- a/configs/cdr_custom.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/cdr_custom.conf.sample (.../trunk) (revision 202568)
+@@ -1,10 +1,12 @@
+ ;
+ ; Mappings for custom config file
+ ;
+-; to get your csv output in a format tailored to your liking, uncomment the following
+-; and look for the output in the cdr-custom/Master.csv file (usually in /var/log/asterisk).
+-;
++; To get your CSV output in a format tailored to your liking, uncomment the
++; following lines and look for the output in the cdr-custom directory (usually
++; in /var/log/asterisk). Depending on which mapping you uncomment, you may see
++; Master.csv, Simple.csv, or both.
+ ;
+ ;[mappings]
+ ;Master.csv => "${CDR(clid)}","${CDR(src)}","${CDR(dst)}","${CDR(dcontext)}","${CDR(channel)}","${CDR(dstchannel)}","${CDR(lastapp)}","${CDR(lastdata)}","${CDR(start)}","${CDR(answer)}","${CDR(end)}","${CDR(duration)}","${CDR(billsec)}","${CDR(disposition)}","${CDR(amaflags)}","${CDR(accountcode)}","${CDR(uniqueid)}","${CDR(userfield)}"
++;Simple.csv => "${EPOCH}","${CDR(src)}","${CDR(dst)}"
+
+Index: configs/chan_dahdi.conf.sample
+===================================================================
+--- a/configs/chan_dahdi.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/chan_dahdi.conf.sample (.../trunk) (revision 202568)
+@@ -6,7 +6,7 @@
+ ; will reload the configuration file, but not all configuration options
+ ; are re-configured during a reload (signalling, as well as PRI and
+ ; SS7-related settings cannot be changed on a reload).
+-;
++;
+ ; This file documents many configuration variables. Normally unless you know
+ ; what a variable means or that it should be changed, there's no reason to
+ ; un-comment those lines.
+@@ -21,11 +21,11 @@
+ ;
+ ; Trunk groups are used for NFAS or GR-303 connections.
+ ;
+-; Group: Defines a trunk group.
++; Group: Defines a trunk group.
+ ; trunkgroup => <trunkgroup>,<dchannel>[,<backup1>...]
+ ;
+ ; trunkgroup is the numerical trunk group to create
+-; dchannel is the DAHDI channel which will have the
++; dchannel is the DAHDI channel which will have the
+ ; d-channel for the trunk.
+ ; backup1 is an optional list of backup d-channels.
+ ;
+@@ -74,6 +74,9 @@
+ ;
+ ;nsf=none
+ ;
++;service_message_support=yes
++; Enable service message support for channel. Must be set after switchtype.
++;
+ ; PRI Dialplan: The ISDN-level Type Of Number (TON) or numbering plan, used for
+ ; the dialed number. For most installations, leaving this as 'unknown' (the
+ ; default) works in the most cases. In some very unusual circumstances, you
+@@ -82,7 +85,7 @@
+ ; example, if you set 'national', you will be unable to dial local or
+ ; international numbers.
+ ;
+-; PRI Local Dialplan: Only RARELY used for PRI (sets the calling number's
++; PRI Local Dialplan: Only RARELY used for PRI (sets the calling number's
+ ; numbering plan). In North America, the typical use is sending the 10 digit
+ ; callerID number and setting the prilocaldialplan to 'national' (the default).
+ ; Only VERY rarely will you need to change this.
+@@ -95,12 +98,12 @@
+ ; national: National ISDN
+ ; international: International ISDN
+ ; dynamic: Dynamically selects the appropriate dialplan
+-; redundant: Same as dynamic, except that the underlying number is not
++; redundant: Same as dynamic, except that the underlying number is not
+ ; changed (not common)
+ ;
+ ;pridialplan=unknown
+ ;prilocaldialplan=national
+-;
++;
+ ; pridialplan may be also set at dialtime, by prefixing the dialled number with
+ ; one of the following letters:
+ ; U - Unknown
+@@ -130,27 +133,27 @@
+ ;
+ ; PRI caller ID prefixes based on the given TON/NPI (dialplan)
+ ; This is especially needed for EuroISDN E1-PRIs
+-;
++;
+ ; None of the prefix settings can be changed on reload.
+ ;
+-; sample 1 for Germany
++; sample 1 for Germany
+ ;internationalprefix = 00
+ ;nationalprefix = 0
+ ;localprefix = 0711
+ ;privateprefix = 07115678
+-;unknownprefix =
++;unknownprefix =
+ ;
+-; sample 2 for Germany
++; sample 2 for Germany
+ ;internationalprefix = +
+ ;nationalprefix = +49
+ ;localprefix = +49711
+ ;privateprefix = +497115678
+-;unknownprefix =
++;unknownprefix =
+ ;
+ ; PRI resetinterval: sets the time in seconds between restart of unused
+ ; B channels; defaults to 'never'.
+ ;
+-;resetinterval = 3600
++;resetinterval = 3600
+ ;
+ ; Overlap dialing mode (sending overlap digits)
+ ; Cannot be changed on a reload.
+@@ -165,7 +168,7 @@
+ ; Enable this to report Busy and Congestion on a PRI using out-of-band
+ ; notification. Inband indication, as used by Asterisk doesn't seem to work
+ ; with all telcos.
+-;
++;
+ ; outofband: Signal Busy/Congestion out of band with RELEASE/DISCONNECT
+ ; inband: Signal Busy/Congestion using in-band tones (default)
+ ;
+@@ -203,7 +206,7 @@
+ ; T203: Layer 2 max time without frames being exchanged (default 10000 ms)
+ ; T305: Wait for DISCONNECT acknowledge (default 30000 ms)
+ ; T308: Wait for RELEASE acknowledge (default 4000 ms)
+-; T309: Maintain active calls on Layer 2 disconnection (default -1,
++; T309: Maintain active calls on Layer 2 disconnection (default -1,
+ ; Asterisk clears calls)
+ ; EuroISDN: 6000 to 12000 ms, according to (N200 + 1) x T200 + 2s
+ ; May vary in other ISDN standards (Q.931 1993 : 90000 ms)
+@@ -281,11 +284,11 @@
+ ; (see below). The 'signalling' format specified will be the inbound signalling
+ ; format. If you only specify 'signalling', then it will be the format for
+ ; both inbound and outbound.
+-;
+-; outsignalling can only be one of:
++;
++; outsignalling can only be one of:
+ ; em, em_e1, em_w, sf, sf_w, sf_featd, sf_featdmf, sf_featb, featd,
+ ; featdmf, featdmf_ta, e911, fgccama, fgccamamf
+-;
++;
+ ; outsignalling cannot be changed on a reload.
+ ;
+ ;signalling=featdmf
+@@ -315,9 +318,9 @@
+ ; None of them will update on a reload.
+ ;
+ ; How long generated tones (DTMF and MF) will be played on the channel
+-; (in milliseconds).
++; (in milliseconds).
+ ;
+-; This is a global, rather than a per-channel setting. It will not be
++; This is a global, rather than a per-channel setting. It will not be
+ ; updated on a reload.
+ ;
+ ;toneduration=100
+@@ -351,7 +354,7 @@
+ ; What signals the start of caller ID
+ ; ring = a ring signals the start (default)
+ ; polarity = polarity reversal signals the start
+-; polarity_IN = polarity reversal signals the start, for India,
++; polarity_IN = polarity reversal signals the start, for India,
+ ; for dtmf dialtone detection; using DTMF.
+ ; (see doc/India-CID.txt)
+ ;
+@@ -378,7 +381,7 @@
+ ; fsk,rpas - the FXO line is monitored for MWI FSK spills preceded
+ ; by a ring pulse alert signal.
+ ; neon - The fxo line is monitored for the presence of NEON pulses
+-; indicating MWI.
++; indicating MWI.
+ ; When detected, an internal Asterisk MWI event is generated so that any other
+ ; part of Asterisk that cares about MWI state changes is notified, just as if
+ ; the state change came from app_voicemail.
+@@ -429,7 +432,7 @@
+ ;
+ ; Some countries (UK) have ring tones with different ring tones (ring-ring),
+ ; which means the caller ID needs to be set later on, and not just after
+-; the first ring, as per the default (1).
++; the first ring, as per the default (1).
+ ;
+ ;sendcalleridafter = 2
+ ;
+@@ -469,10 +472,10 @@
+ ;
+ callreturn=yes
+ ;
+-; Stutter dialtone support: If a mailbox is specified without a voicemail
+-; context, then when voicemail is received in a mailbox in the default
++; Stutter dialtone support: If a mailbox is specified without a voicemail
++; context, then when voicemail is received in a mailbox in the default
+ ; voicemail context in voicemail.conf, taking the phone off hook will cause a
+-; stutter dialtone instead of a normal one.
++; stutter dialtone instead of a normal one.
+ ;
+ ; If a mailbox is specified *with* a voicemail context, the same will result
+ ; if voicemail received in mailbox in the specified voicemail context.
+@@ -483,9 +486,9 @@
+ ;
+ ; for any other voicemail context, the following will produce the stutter tone:
+ ;
+-;mailbox=1234@context
++;mailbox=1234@context
+ ;
+-; Enable echo cancellation
++; Enable echo cancellation
+ ; Use either "yes", "no", or a power of two from 32 to 256 if you wish to
+ ; actually set the number of taps of cancellation.
+ ;
+@@ -549,7 +552,7 @@
+ ;
+ ; There are several independent gain settings:
+ ; rxgain: gain for the rx (receive - into Asterisk) channel. Default: 0.0
+-; txgain: gain for the tx (transmit - out of Asterisk Asterisk) channel.
++; txgain: gain for the tx (transmit - out of Asterisk Asterisk) channel.
+ ; Default: 0.0
+ ; cid_rxgain: set the gain just for the caller ID sounds Asterisk
+ ; emits. Default: 5.0 .
+@@ -597,10 +600,10 @@
+ ;
+ ; caller ID can be set to "asreceived" or a specific number if you want to
+ ; override it. Note that "asreceived" only applies to trunk interfaces.
+-; fullname sets just the
++; fullname sets just the
+ ;
+ ; fullname: sets just the name part.
+-; cid_number: sets just the number part:
++; cid_number: sets just the number part:
+ ;
+ ;callerid = 123456
+ ;
+@@ -639,7 +642,7 @@
+ ;smdiport=/dev/ttyS0
+ ;
+ ; On trunk interfaces (FXS) and E&M interfaces (E&M, Wink, Feature Group D
+-; etc, it can be useful to perform busy detection either in an effort to
++; etc, it can be useful to perform busy detection either in an effort to
+ ; detect hangup or for detecting busies. This enables listening for
+ ; the beep-beep busy pattern.
+ ;
+@@ -682,8 +685,8 @@
+ ;
+ ;hanguponpolarityswitch=yes
+ ;
+-; polarityonanswerdelay: minimal time period (ms) between the answer
+-; polarity switch and hangup polarity switch.
++; polarityonanswerdelay: minimal time period (ms) between the answer
++; polarity switch and hangup polarity switch.
+ ; (default: 600ms)
+ ;
+ ; On trunk interfaces (FXS) it can be useful to attempt to follow the progress
+@@ -696,7 +699,7 @@
+ ; with "progzone".
+ ;
+ ; progzone also affects the pattern used for buzydetect (unless
+-; busypattern is set explicitly). The possible values are:
++; busypattern is set explicitly). The possible values are:
+ ; us (default)
+ ; ca (alias for 'us')
+ ; cr (Costa Rica)
+@@ -738,7 +741,7 @@
+ ;faxdetect=no
+ ;
+ ; When 'faxdetect' is used, one could use 'faxbuffers' to configure the DAHDI
+-; transmit buffer policy. The default is *OFF*. When this configuration
++; transmit buffer policy. The default is *OFF*. When this configuration
+ ; option is used, the faxbuffer policy will be used for the life of the call
+ ; after a fax tone is detected. The faxbuffer policy is reverted after the
+ ; call is torn down. The sample below will result in 6 buffers and a full
+@@ -831,7 +834,7 @@
+ ; parameters that were specified above its declaration.
+ ;
+ ; For GR-303, CRV's are created like channels except they must start with the
+-; trunk group followed by a colon, e.g.:
++; trunk group followed by a colon, e.g.:
+ ;
+ ; crv => 1:1
+ ; crv => 2:1-2,5-8
+@@ -905,15 +908,15 @@
+ ; A range of -1 will force it to always match.
+ ; Anything lower than -1 would presumably cause it to never match.
+ ;
+-;dring1=95,0,0
+-;dring1context=internal1
++;dring1=95,0,0
++;dring1context=internal1
+ ;dring1range=10
+-;dring2=325,95,0
+-;dring2context=internal2
++;dring2=325,95,0
++;dring2context=internal2
+ ;dring2range=10
+ ; If no pattern is matched here is where we go.
+ ;context=default
+-;channel => 1
++;channel => 1
+
+ ; ---------------- Options for use with signalling=ss7 -----------------
+ ; None of them can be changed by a reload.
+@@ -942,12 +945,12 @@
+ ;
+ ;ss7_calling_nai=dynamic
+ ;
+-;
+-; sample 1 for Germany
++;
++; sample 1 for Germany
+ ;ss7_internationalprefix = 00
+ ;ss7_nationalprefix = 0
+-;ss7_subscriberprefix =
+-;ss7_unknownprefix =
++;ss7_subscriberprefix =
++;ss7_unknownprefix =
+ ;
+
+ ; This option is used to disable automatic sending of ACM when the call is started
+@@ -997,8 +1000,19 @@
+
+ ; ---------------- Options for use with signalling=mfcr2 --------------
+
++; MFC-R2 signaling has lots of variants from country to country and even sometimes
++; minor variants inside the same country. The only mandatory parameters here are:
++; mfcr2_variant, mfcr2_max_ani and mfcr2_max_dnis.
++; IT IS RECOMMENDED that you leave the default values (leaving it commented) for the
++; other parameters unless you have problems or you have been instructed to change some
++; parameter. OpenR2 library uses the mfcr2_variant parameter to try to determine the
++; best defaults for your country, also refer to the OpenR2 package directory
++; doc/asterisk/ where you can find sample configurations for some countries. If you
++; want to contribute your configs for a particular country send them to the e-mail
++; of the primary OpenR2 developer that you can find in the AUTHORS file of the OpenR2 package
++
+ ; MFC/R2 variant. This depends on the OpenR2 supported variants
+-; A list of values can be found at libopenr2.org
++; A list of values can be found by executing the openr2 command r2test -l
+ ; some valid values are:
+ ; ar (Argentina)
+ ; br (Brazil)
+@@ -1007,17 +1021,17 @@
+ ; itu (per ITU spec)
+ ; mfcr2_variant=mx
+
+-; whether or not to get the ANI before getting DNIS.
+-; some telcos require ANI first some others do not care
+-; if this go wrong, change this value
+-; mfcr2_get_ani_first=no
+-
+ ; Max amount of ANI to ask for
+ ; mfcr2_max_ani=10
+
+ ; Max amount of DNIS to ask for
+ ; mfcr2_max_dnis=4
+
++; whether or not to get the ANI before getting DNIS.
++; some telcos require ANI first some others do not care
++; if this go wrong, change this value
++; mfcr2_get_ani_first=no
++
+ ; Caller Category to send
+ ; national_subscriber
+ ; national_priority_subscriber
+@@ -1028,9 +1042,8 @@
+ ; you can change this setting from the dialplan
+ ; by setting the variable MFCR2_CATEGORY
+ ; (remember to set _MFCR2_CATEGORY from originating channels)
+-; MFCR2_CATEGORY will also be a variable available
+-; on incoming calls set to the value received from
+-; the far end
++; MFCR2_CATEGORY will also be a variable available in your context
++; on incoming calls set to the value received from the far end
+ ; mfcr2_category=national_subscriber
+
+ ; Call logging is stored at the Asterisk
+@@ -1053,7 +1066,7 @@
+ ; 'stack' is for very verbose output of the channel and context call stack, only useful
+ ; if you are debugging a crash or want to learn how the library works. The stack logging
+ ; will be only enabled if the openr2 library was compiled with -DOR2_TRACE_STACKS
+-; You can mix up values, like: loglevel=error,debug,mf to log just error, debug and
++; You can mix up values, like: loglevel=error,debug,mf to log just error, debug and
+ ; multi frequency messages
+ ; 'all' is a special value to log all the activity
+ ; 'nothing' is a clean-up value, in case you want to not log any activity for
+@@ -1107,20 +1120,24 @@
+
+ ; You most likely dont need this feature. Default is yes.
+ ; When this is set to yes, all calls that are offered (incoming calls) which
+-; DNIS is valid (exists in extensions.conf) and pass collect call validation
++; DNIS is valid (exists in extensions.conf) and pass collect call validation
+ ; will be accepted with a Group B tone (either call with charge or not, depending on mfcr2_charge_calls)
+ ; with this set to 'no' then the call will NOT be accepted on offered, and the call will start its
+ ; execution in extensions.conf without being accepted until the channel is answered (either with Answer() or
+-; any other application resulting in the channel being answered).
++; any other application resulting in the channel being answered).
+ ; This can be set to 'no' if your telco or PBX needs the hangup cause to be set accurately
+ ; when this option is set to no you must explicitly accept the call with DAHDIAcceptR2Call
+-; or implicitly through the Answer() application.
++; or implicitly through the Answer() application.
+ ; mfcr2_accept_on_offer=yes
+
++; Skip request of calling party category and ANI
++; you need openr2 >= 1.2.0 to use this feature
++; mfcr2_skip_category=no
++
+ ; WARNING: advanced users only! I really mean it
+ ; this parameter is commented by default because
+ ; YOU DON'T NEED IT UNLESS YOU REALLY GROK MFC/R2
+-; READ COMMENTS on doc/r2proto.conf in openr2 package
++; READ COMMENTS on doc/r2proto.conf in openr2 package
+ ; for more info
+ ; mfcr2_advanced_protocol_file=/path/to/r2proto.conf
+
+@@ -1168,7 +1185,7 @@
+ ; chan_dahdi.conf and [general] in users.conf - one section's configuration
+ ; does not affect another one's.
+ ;
+-; Instead of letting common configuration values "slide through" you can
++; Instead of letting common configuration values "slide through" you can
+ ; use configuration templates to easily keep the common part in one
+ ; place and override where needed.
+ ;
+Index: configs/console.conf.sample
+===================================================================
+--- a/configs/console.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/console.conf.sample (.../trunk) (revision 202568)
+@@ -5,7 +5,7 @@
+ [general]
+
+ ; Set this option to "yes" to enable automatically answering calls on the
+-; console. This is very useful if the console is used as an intercom.
++; console. This is very useful if the console is used as an intercom.
+ ; The default value is "no".
+ ;
+ ;autoanswer = no
+@@ -21,7 +21,7 @@
+ ;extension = s
+
+ ; Set the default CallerID for created channels.
+-;
++;
+ ;callerid = MyName Here <(256) 428-6000>
+
+ ; Set the default language for created channels.
+Index: configs/dundi.conf.sample
+===================================================================
+--- a/configs/dundi.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/dundi.conf.sample (.../trunk) (revision 202568)
+@@ -1,6 +1,6 @@
+ ;
+ ; DUNDi configuration file
+-;
++;
+ ; For more information about DUNDi, see http://www.dundi.com
+ ;
+ ;
+@@ -50,9 +50,9 @@
+ ttl=32
+ ;
+ ; If we don't get ACK to our DPDISCOVER within 2000ms, and autokill is set
+-; to yes, then we cancel the whole thing (that's enough time for one
++; to yes, then we cancel the whole thing (that's enough time for one
+ ; retransmission only). This is used to keep things from stalling for a long
+-; time for a host that is not available, but would be ill advised for bad
++; time for a host that is not available, but would be ill advised for bad
+ ; connections. In addition to 'yes' or 'no' you can also specify a number
+ ; of milliseconds. See 'qualify' for individual peers to turn on for just
+ ; a specific peer.
+@@ -60,7 +60,7 @@
+ autokill=yes
+ ;
+ ; pbx_dundi creates a rotating key called "secret", under the family
+-; 'secretpath'. The default family is dundi (resulting in
++; 'secretpath'. The default family is dundi (resulting in
+ ; the key being held at dundi/secret).
+ ;
+ ;secretpath=dundi
+@@ -78,8 +78,8 @@
+ ;
+ ; The "mappings" section maps DUNDi contexts
+ ; to contexts on the local asterisk system. Remember
+-; that numbers that are made available under the e164
+-; DUNDi context are regulated by the DUNDi General Peering
++; that numbers that are made available under the e164
++; DUNDi context are regulated by the DUNDi General Peering
+ ; Agreement (GPA) if you are a member of the DUNDi E.164
+ ; Peering System.
+ ;
+@@ -108,14 +108,14 @@
+ ;
+ ; Further options may include:
+ ;
+-; nounsolicited: No unsolicited calls of any type permitted via this
++; nounsolicited: No unsolicited calls of any type permitted via this
+ ; route
+-; nocomunsolicit: No commercial unsolicited calls permitted via
++; nocomunsolicit: No commercial unsolicited calls permitted via
+ ; this route
+ ; residential: This number is known to be a residence
+ ; commercial: This number is known to be a business
+ ; mobile: This number is known to be a mobile phone
+-; nocomunsolicit: No commercial unsolicited calls permitted via
++; nocomunsolicit: No commercial unsolicited calls permitted via
+ ; this route
+ ; nopartial: Do not search for partial matches
+ ;
+@@ -163,7 +163,7 @@
+ ;
+ ; host - What their host is
+ ;
+-; order - What search order to use. May be 'primary', 'secondary',
++; order - What search order to use. May be 'primary', 'secondary',
+ ; 'tertiary' or 'quartiary'. In large systems, it is beneficial
+ ; to only query one up-stream host in order to maximize caching
+ ; value. Adding one with primary and one with secondary gives you
+@@ -187,7 +187,7 @@
+ ; the local system. Set "all" to deny this host to
+ ; lookup all contexts.
+ ;
+-; model - inbound, outbound, or symmetric for whether we receive
++; model - inbound, outbound, or symmetric for whether we receive
+ ; requests only, transmit requests only, or do both.
+ ;
+ ; precache - Utilize/Permit precaching with this peer (to pre
+@@ -241,7 +241,7 @@
+ ;inkey = littleguy
+ ;outkey = ourkey
+ ;include = e164 ; In this case used only for precaching
+-;permit = e164
++;permit = e164
+ ;qualify = yes
+
+ ;
+@@ -254,7 +254,7 @@
+ ;register = yes
+ ;inkey = dhcp34
+ ;permit = all ; In this case used only for precaching
+-;include = all
++;include = all
+ ;qualify = yes
+ ;outkey=foo
+
+Index: configs/oss.conf.sample
+===================================================================
+--- a/configs/oss.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/oss.conf.sample (.../trunk) (revision 202568)
+@@ -130,7 +130,7 @@
+ region = # rect 152 146 201 146 28
+ region = pickup rect 229 15 267 15 40
+ region = hangup rect 230 66 270 64 40
+- region = mute circle 232 141 264 141 33
++ region = mute circle 232 141 264 141 33
+ region = sendvideo circle 235 185 266 185 33
+ region = autoanswer rect 228 212 275 212 50
+
+Index: configs/queues.conf.sample
+===================================================================
+--- a/configs/queues.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/queues.conf.sample (.../trunk) (revision 202568)
+@@ -13,12 +13,12 @@
+ ; Keep queue statistics during a reload. Default is 'no'
+ ;
+ keepstats = no
+-;
++;
+ ; AutoFill Behavior
+-; The old/current behavior of the queue has a serial type behavior
++; The old/current behavior of the queue has a serial type behavior
+ ; in that the queue will make all waiting callers wait in the queue
+ ; even if there is more than one available member ready to take
+-; calls until the head caller is connected with the member they
++; calls until the head caller is connected with the member they
+ ; were trying to get to. The next waiting caller in line then
+ ; becomes the head caller, and they are then connected with the
+ ; next available member and all available members and waiting callers
+@@ -26,8 +26,8 @@
+ ; autofill=yes makes sure that when the waiting callers are connecting
+ ; with available members in a parallel fashion until there are
+ ; no more available members or no more waiting callers. This is
+-; probably more along the lines of how a queue should work and
+-; in most cases, you will want to enable this behavior. If you
++; probably more along the lines of how a queue should work and
++; in most cases, you will want to enable this behavior. If you
+ ; do not specify or comment out this option, it will default to no
+ ; to keep backward compatibility with the old behavior.
+ ;
+@@ -36,22 +36,22 @@
+ ; Monitor Type
+ ; By setting monitor-type = MixMonitor, when specifying monitor-format
+ ; to enable recording of queue member conversations, app_queue will
+-; now use the new MixMonitor application instead of Monitor so
++; now use the new MixMonitor application instead of Monitor so
+ ; the concept of "joining/mixing" the in/out files now goes away
+ ; when this is enabled. You can set the default type for all queues
+ ; here, and then also change monitor-type for individual queues within
+-; queue by using the same configuration parameter within a queue
++; queue by using the same configuration parameter within a queue
+ ; configuration block. If you do not specify or comment out this option,
+ ; it will default to the old 'Monitor' behavior to keep backward
+-; compatibility.
++; compatibility.
+ ;
+ monitor-type = MixMonitor
+ ;
+-; UpdateCDR behavior.
++; UpdateCDR behavior.
+ ; This option is implemented to mimic chan_agents behavior of populating
+-; CDR dstchannel field of a call with an agent name, which you can set
+-; at the login time with AddQueueMember membername parameter.
+-;
++; CDR dstchannel field of a call with an agent name, which you can set
++; at the login time with AddQueueMember membername parameter.
++;
+ ; updatecdr = no
+
+ ;
+@@ -134,7 +134,7 @@
+ ; The member's phone is rung for 5 seconds and he does not answer.
+ ; The retry time of 4 seconds occurs.
+ ; The queue selects a second member to call.
+-;
++;
+ ; How long does that second member's phone ring? Does it ring for 5 seconds
+ ; since the timeout set in app_queue is 5 seconds? Does it ring for 1 second since
+ ; the caller has been in the queue for 9 seconds and is supposed to be removed after
+@@ -143,8 +143,8 @@
+ ; rather use the time specified in the configuration file even if it means having the
+ ; caller stay in the queue longer than the time specified in the application argument.
+ ; For the scenario described above, timeoutpriority=conf would result in the second
+-; member's phone ringing for 5 seconds. By specifying "app" as the value for
+-; timeoutpriority, you are saying that the timeout specified as the argument to the
++; member's phone ringing for 5 seconds. By specifying "app" as the value for
++; timeoutpriority, you are saying that the timeout specified as the argument to the
+ ; Queue application is more important. In the scenario above, timeoutpriority=app
+ ; would result in the second member's phone ringing for 1 second.
+ ;
+@@ -152,7 +152,7 @@
+ ; and the configuration file timeout is set to 0, but the application argument timeout is
+ ; non-zero, then the timeoutpriority is ignored and the application argument is used as
+ ; the timeout. Furthermore, if no application argument timeout is specified, then the
+-; timeoutpriority option is ignored and the configuration file timeout is always used
++; timeoutpriority option is ignored and the configuration file timeout is always used
+ ; when calling queue members.
+ ;
+ ; In timeoutpriority=conf mode however timeout specified in config file will take higher
+@@ -170,8 +170,8 @@
+ ;timeoutpriority = app|conf
+ ;
+ ;-----------------------END QUEUE TIMING OPTIONS---------------------------------
+-; Weight of queue - when compared to other queues, higher weights get
+-; first shot at available channels when the same channel is included in
++; Weight of queue - when compared to other queues, higher weights get
++; first shot at available channels when the same channel is included in
+ ; more than one queue.
+ ;
+ ;weight=0
+@@ -196,21 +196,21 @@
+ ;
+ ;maxlen = 0
+ ;
+-; If set to yes, just prior to the caller being bridged with a queue member
++; If set to yes, just prior to the caller being bridged with a queue member
+ ; the following variables will be set
+ ; MEMBERINTERFACE is the interface name (eg. Agent/1234)
+ ; MEMBERNAME is the member name (eg. Joe Soap)
+-; MEMBERCALLS is the number of calls that interface has taken,
+-; MEMBERLASTCALL is the last time the member took a call.
+-; MEMBERPENALTY is the penalty of the member
++; MEMBERCALLS is the number of calls that interface has taken,
++; MEMBERLASTCALL is the last time the member took a call.
++; MEMBERPENALTY is the penalty of the member
+ ; MEMBERDYNAMIC indicates if a member is dynamic or not
+ ; MEMBERREALTIME indicates if a member is realtime or not
+ ;
+ ;setinterfacevar=no
+ ;
+-; If set to yes, just prior to the caller being bridged with a queue member
++; If set to yes, just prior to the caller being bridged with a queue member
+ ; the following variables will be set:
+-; QEHOLDTIME callers hold time
++; QEHOLDTIME callers hold time
+ ; QEORIGINALPOS original position of the caller in the queue
+ ;
+ ;setqueueentryvar=no
+@@ -220,7 +220,7 @@
+ ; and just prior to the caller leaving the queue
+ ; QUEUENAME name of the queue
+ ; QUEUEMAX maxmimum number of calls allowed
+-; QUEUESTRATEGY the strategy of the queue;
++; QUEUESTRATEGY the strategy of the queue;
+ ; QUEUECALLS number of calls currently in the queue
+ ; QUEUEHOLDTIME current average hold time
+ ; QUEUECOMPLETED number of completed calls for the queue
+@@ -231,17 +231,17 @@
+ ;setqueuevar=no
+ ;
+ ; if set, run this macro when connected to the queue member
+-; you can override this macro by setting the macro option on
++; you can override this macro by setting the macro option on
+ ; the queue application
+ ;
+ ; membermacro=somemacro
+
+-; How often to announce queue position and/or estimated
++; How often to announce queue position and/or estimated
+ ; holdtime to caller (0=off)
+ ; Note that this value is ignored if the caller's queue
+ ; position has changed (see min-announce-frequency)
+ ;
+-;announce-frequency = 90
++;announce-frequency = 90
+ ;
+ ; The absolute minimum time between the start of each
+ ; queue position and/or estimated holdtime announcement
+@@ -301,7 +301,7 @@
+ ; queue-thankyou=
+ ;
+ ; ("You are now first in line.")
+-;queue-youarenext = queue-youarenext
++;queue-youarenext = queue-youarenext
+ ; ("There are")
+ ;queue-thereare = queue-thereare
+ ; ("calls waiting.")
+@@ -319,7 +319,7 @@
+ ; ("All reps busy / wait for next")
+ ;periodic-announce = queue-periodic-announce
+ ;
+-; A set of periodic announcements can be defined by separating
++; A set of periodic announcements can be defined by separating
+ ; periodic announcements to reproduce by commas. For example:
+ ;periodic-announce = queue-periodic-announce,your-call-is-important,please-wait
+ ;
+@@ -358,7 +358,7 @@
+ ;
+ ; You can specify the options supplied to MixMonitor by calling
+ ; Set(MONITOR_OPTIONS=av(<x>)V(<x>)W(<x>))
+-; The 'b' option for MixMonitor (only save audio to the file while bridged) is
++; The 'b' option for MixMonitor (only save audio to the file while bridged) is
+ ; implied.
+ ;
+ ; You can specify a post recording command to be executed after the end of
+@@ -379,9 +379,9 @@
+ ; whether a caller may join a queue depending on several factors of member availability.
+ ; Similarly, then leavewhenempty option controls whether a caller may remain in a queue
+ ; he has already joined. Both options take a comma-separated list of factors which
+-; contribute towards whether a caller may join/remain in the queue. The list of
++; contribute towards whether a caller may join/remain in the queue. The list of
+ ; factors which contribute to these option is as follows:
+-;
++;
+ ; paused: a member is not considered available if he is paused
+ ; penalty: a member is not considered available if his penalty is less than QUEUE_MAX_PENALTY
+ ; inuse: a member is not considered available if he is currently on a call
+@@ -394,14 +394,14 @@
+ ; current device state.
+ ; wrapup: A member is not considered available if he is currently in his wrapuptime after
+ ; taking a call.
+-;
++;
+ ; For the "joinempty" option, when a caller attempts to enter a queue, the members of that
+ ; queue are examined. If all members are deemed to be unavailable due to any of the conditions
+ ; listed for the "joinempty" option, then the caller will be unable to enter the queue. For the
+ ; "leavewhenempty" option, the state of the members of the queue are checked periodically during
+ ; the caller's stay in the queue. If all of the members are unavailable due to any of the above
+ ; conditions, then the caller will be removed from the queue.
+-;
++;
+ ; Some examples:
+ ;
+ ;joinempty = paused,inuse,invalid
+@@ -411,7 +411,7 @@
+ ;
+ ;leavewhenempty = inuse,ringing
+ ;
+-; A caller will be removed from the queue if at least one member cannot be found
++; A caller will be removed from the queue if at least one member cannot be found
+ ; who is not on the phone, or whose phone is not ringing.
+ ;
+ ; For the sake of backwards-compatibility, the joinempty and leavewhenempty
+@@ -461,7 +461,7 @@
+ ;
+ ; timeoutrestart = no
+ ;
+-; If you wish to implement a rule defined in queuerules.conf (see
++; If you wish to implement a rule defined in queuerules.conf (see
+ ; configs/queuerules.conf.sample from the asterisk source directory for
+ ; more information about penalty rules) by default, you may specify this
+ ; by setting defaultrule to the rule's name
+Index: configs/cdr.conf.sample
+===================================================================
+--- a/configs/cdr.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/cdr.conf.sample (.../trunk) (revision 202568)
+@@ -14,12 +14,12 @@
+ ;enable=yes
+
+ ; Define whether or not to log unanswered calls. Setting this to "yes" will
+-; report every attempt to ring a phone in dialing attempts, when it was not
++; report every attempt to ring a phone in dialing attempts, when it was not
+ ; answered. For example, if you try to dial 3 extensions, and this option is "yes",
+ ; you will get 3 CDR's, one for each phone that was rung. Default is "no". Some
+ ; find this information horribly useless. Others find it very valuable. Note, in "yes"
+ ; mode, you will see one CDR, with one of the call targets on one side, and the originating
+-; channel on the other, and then one CDR for each channel attempted. This may seem
++; channel on the other, and then one CDR for each channel attempted. This may seem
+ ; redundant, but cannot be helped.
+ ;unanswered = no
+
+@@ -67,7 +67,7 @@
+
+ ; Normally, the 'billsec' field logged to the backends (text files or databases)
+ ; is simply the end time (hangup time) minus the answer time in seconds. Internally,
+-; asterisk stores the time in terms of microseconds and seconds. By setting
++; asterisk stores the time in terms of microseconds and seconds. By setting
+ ; initiatedseconds to 'yes', you can force asterisk to report any seconds
+ ; that were initiated (a sort of round up method). Technically, this is
+ ; when the microsecond part of the end time is greater than the microsecond
+@@ -78,19 +78,19 @@
+ ;
+ ; CHOOSING A CDR "BACKEND" (what kind of output to generate)
+ ;
+-; To choose a backend, you have to make sure either the right category is
+-; defined in this file, or that the appropriate config file exists, and has the
++; To choose a backend, you have to make sure either the right category is
++; defined in this file, or that the appropriate config file exists, and has the
+ ; proper definitions in it. If there are any problems, usually, the entry will
+ ; silently ignored, and you get no output.
+-;
+-; Also, please note that you can generate CDR records in as many formats as you
++;
++; Also, please note that you can generate CDR records in as many formats as you
+ ; wish. If you configure 5 different CDR formats, then each event will be logged
+ ; in 5 different places! In the example config files, all formats are commented
+ ; out except for the cdr-csv format.
+ ;
+ ; Here are all the possible back ends:
+ ;
+-; csv, custom, manager, odbc, pgsql, radius, sqlite, tds
++; csv, custom, manager, odbc, pgsql, radius, sqlite, tds
+ ; (also, mysql is available via the asterisk-addons, due to licensing
+ ; requirements)
+ ; (please note, also, that other backends can be created, by creating
+@@ -104,7 +104,7 @@
+ ; backend is marked with XXX, you know that the "configure" command could not find
+ ; the required libraries for that option.
+ ;
+-; To get CDRs to be logged to the plain-jane /var/log/asterisk/cdr-csv/Master.csv
++; To get CDRs to be logged to the plain-jane /var/log/asterisk/cdr-csv/Master.csv
+ ; file, define the [csv] category in this file. No database necessary. The example
+ ; config files are set up to provide this kind of output by default.
+ ;
+@@ -126,7 +126,7 @@
+ ; shows that the modules are available, and the cdr_pgsql.conf file exists, and
+ ; has a [global] section with the proper variables defined.
+ ;
+-; For logging to radius databases, make sure all the proper libs are installed, that
++; For logging to radius databases, make sure all the proper libs are installed, that
+ ; "make menuselect" shows that the modules are available, and the [radius]
+ ; category is defined in this file, and in that section, make sure the 'radiuscfg'
+ ; variable is properly pointing to an existing radiusclient.conf file.
+@@ -135,7 +135,7 @@
+ ; which is usually /var/log/asterisk. Of course, the proper libraries should be available
+ ; during the 'configure' operation.
+ ;
+-; For tds logging, make sure the proper libraries are available during the 'configure'
++; For tds logging, make sure the proper libraries are available during the 'configure'
+ ; phase, and that cdr_tds.conf exists and is properly set up with a [global] category.
+ ;
+ ; Also, remember, that if you wish to log CDR info to a database, you will have to define
+Index: configs/calendar.conf.sample
+===================================================================
+--- a/configs/calendar.conf.sample (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/configs/calendar.conf.sample (.../trunk) (revision 202568)
+@@ -0,0 +1,84 @@
++;[calendar1]
++;type = ical ; type of calendar--currently supported: ical, caldav, or exchange
++;url = https://example.com/home/jdoe/Calendar/ ; URL to shared calendar (Zimbra example)
++;user = jdoe ; web username
++;secret = supersecret ; web password
++;refresh = 15 ; refresh calendar every n minutes
++;timeframe = 60 ; number of minutes of calendar data to pull for each refresh period
++; ; should always be >= refresh
++;
++; You can set up res_icalendar to execute a call upon an upcoming busy status
++; The following fields are available from the ${CALENDAR_EVENT(<field>)} dialplan function:
++;
++; summary : The VEVENT Summary property or Exchange subject
++; description : The text description of the vent
++; organizer : The organizer of the event
++; location : The location field of the event
++; calendar : The name of the calendar tied to the event
++; uid : The unique ID for this event
++; start : Start time of the event
++; end : The end time of the event
++; busystate : 0=FREE, 1=TENTATIVE, 2=BUSY
++;
++;autoreminder = 10 ; Override event-defined reminder before each busy status (in mins)
++;
++;channel = SIP/60001 ; Channel to dial
++;context = default ; Context to connect to on answer
++;extension = 123 ; Extension to connect to on answer
++;
++; or
++;
++;app = Playback ; Application to execute on answer (instead of context/extension)
++;appdata = tt-weasels ; Data part of application to execute on answer
++;
++;waittime = 30 ; How long to wait for an answer
++
++;[calendar2]
++; Note: Exchange support has only been tested on Exchange Server 2003
++; Forms-based authentication is not supported at this time
++; Querying attendees is not supported with Exchange at this time
++;
++;type = exchange ; type of calendar--currently supported: ical, caldav, or exchange
++;url = https://example.com/exchange/jdoe ; URL to MS Exchange OWA for user (usually includes exchange/user)
++;user = jdoe ; Exchange username
++;secret = mysecret ; Exchange password
++;refresh = 15 ; refresh calendar every n minutes
++;timeframe = 60 ; number of minutes of calendar data to pull for each refresh period
++; ; should always be >= refresh
++;
++; You can set up res_icalendar to execute a call upon an upcoming busy status
++;autoreminder = 10 ; Override event-defined reminder before each busy status (in mins)
++;
++;channel = SIP/1234 ; Channel to dial
++;context = default ; Context to connect to on answer
++;extension = 1234 ; Extension to connect to on answer
++;
++; or
++;
++;app = Playback ; Application to execute on answer (instead of context/extension)
++;appdata = tt-weasels ; Data part of application to execute on answer
++;
++;waittime = 30 ; How long to wait for an answer
++
++;[calendar3]
++;type = caldav ; type of calendar--currently supported: ical, caldav, or exchange
++;url = https://www.google.com/calendar/dav/username@gmail.com/events/ ; Main GMail calendar (the trailing slash is significant!)
++;user = jdoe@gmail.com ; username
++;secret = mysecret ; password
++;refresh = 15 ; refresh calendar every n minutes
++;timeframe = 60 ; number of minutes of calendar data to pull for each refresh period
++; ; should always be >= refresh
++;
++; You can set up res_icalendar to execute a call upon an upcoming busy status
++;autoreminder = 10 ; Override event-defined reminder before each busy status (in mins)
++;
++;channel = SIP/1234 ; Channel to dial
++;context = default ; Context to connect to on answer
++;extension = 1234 ; Extension to connect to on answer
++;
++; or
++;
++;app = Playback ; Application to execute on answer (instead of context/extension)
++;appdata = tt-weasels ; Data part of application to execute on answer
++;
++;waittime = 30 ; How long to wait for an answer
+
+Property changes on: configs/calendar.conf.sample
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+
+Index: configs/manager.conf.sample
+===================================================================
+--- a/configs/manager.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/manager.conf.sample (.../trunk) (revision 202568)
+@@ -1,6 +1,6 @@
+ ;
+ ; AMI - The Asterisk Manager Interface
+-;
++;
+ ; Third party application call management support and PBX event supervision
+ ;
+ ; This configuration file is read every time someone logs in
+@@ -13,11 +13,11 @@
+ ; ---------------------------- SECURITY NOTE -------------------------------
+ ; Note that you should not enable the AMI on a public IP address. If needed,
+ ; block this TCP port with iptables (or another FW software) and reach it
+-; with IPsec, SSH, or SSL vpn tunnel. You can also make the manager
++; with IPsec, SSH, or SSL vpn tunnel. You can also make the manager
+ ; interface available over http/https if Asterisk's http server is enabled in
+ ; http.conf and if both "enabled" and "webenabled" are set to yes in
+-; this file. Both default to no. httptimeout provides the maximum
+-; timeout in seconds before a web based session is discarded. The
++; this file. Both default to no. httptimeout provides the maximum
++; timeout in seconds before a web based session is discarded. The
+ ; default is 60 seconds.
+ ;
+ [general]
+@@ -27,9 +27,9 @@
+
+ ;httptimeout = 60
+ ; a) httptimeout sets the Max-Age of the http cookie
+-; b) httptimeout is the amount of time the webserver waits
++; b) httptimeout is the amount of time the webserver waits
+ ; on a action=waitevent request (actually its httptimeout-10)
+-; c) httptimeout is also the amount of time the webserver keeps
++; c) httptimeout is also the amount of time the webserver keeps
+ ; a http session alive after completing a successful action
+
+ bindaddr = 0.0.0.0
+@@ -39,13 +39,14 @@
+ ;
+ ; openssl s_client -connect my_host:5039
+ ;
+-; sslenable=no ; set to YES to enable it
+-; sslbindport=5039 ; the port to bind to
+-; sslbindaddr=0.0.0.0 ; address to bind to, default to bindaddr
+-; sslcert=/tmp/asterisk.pem ; path to the certificate.
+-; sslcipher=<cipher string> ; string specifying which SSL ciphers to use or not use
+-
+-
++;tlsenable=no ; set to YES to enable it
++;tlsbindport=5039 ; the port to bind to
++;tlsbindaddr=0.0.0.0 ; address to bind to, default to bindaddr
++;tlscertfile=/tmp/asterisk.pem ; path to the certificate.
++;tlsprivatekey=/tmp/private.pem ; path to the private key, if no private given,
++ ; if no tlsprivatekey is given, default is to search
++ ; tlscertfile for private key.
++;tlscipher=<cipher string> ; string specifying which SSL ciphers to use or not use
+ ;
+ ;allowmultiplelogin = yes ; IF set to no, rejects manager logins that are already in use.
+ ; ; The default is yes.
+@@ -71,7 +72,7 @@
+ ;
+ ;displayconnects = yes ; Display on CLI user login/logoff
+ ;
+-; Authorization for various classes
++; Authorization for various classes
+ ;
+ ; Read authorization permits you to receive asynchronous events, in general.
+ ; Write authorization permits you to send commands and get back responses. The
+Index: configs/features.conf.sample
+===================================================================
+--- a/configs/features.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/features.conf.sample (.../trunk) (revision 202568)
+@@ -9,12 +9,12 @@
+ ; and increments with one for the next parked call.
+ context => parkedcalls ; Which context parked calls are in (default parking lot)
+ ;parkinghints = no ; Add hints priorities automatically for parking slots (default is no).
+-;parkingtime => 45 ; Number of seconds a call can be parked for
++;parkingtime => 45 ; Number of seconds a call can be parked for
+ ; (default is 45 seconds)
+ ;comebacktoorigin = yes ; Whether to return to the original calling extension upon parking
+ ; timeout or to send the call to context 'parkedcallstimeout' at
+ ; extension 's', priority '1' (default is yes).
+-;courtesytone = beep ; Sound file to play to the parked caller
++;courtesytone = beep ; Sound file to play to the parked caller
+ ; when someone dials a parked call
+ ; or the Touch Monitor is activated/deactivated.
+ ;parkedplay = caller ; Who to play the courtesy tone to when picking up a parked call
+@@ -28,7 +28,7 @@
+ ;parkedcallrecording = caller ; Enables or disables DTMF based one-touch recording when picking up a parked call.
+ ; one of: callee, caller, both, no (default is no)
+ ;adsipark = yes ; if you want ADSI parking announcements
+-;findslot => next ; Continue to the 'next' free parking space.
++;findslot => next ; Continue to the 'next' free parking space.
+ ; Defaults to 'first' available
+ ;parkedmusicclass=default ; This is the MOH class to use for the parked channel
+ ; as long as the class is not set on the channel directly
+@@ -41,7 +41,7 @@
+ ;pickupexten = *8 ; Configure the pickup extension. (default is *8)
+ ;pickupsound = beep ; to indicate a successful pickup (default: no sound)
+ ;pickupfailsound = beeperr ; to indicate that the pickup failed (default: no sound)
+-;featuredigittimeout = 1000 ; Max time (ms) between digits for
++;featuredigittimeout = 1000 ; Max time (ms) between digits for
+ ; feature activation (default is 1000 ms)
+ ;atxfernoanswertimeout = 15 ; Timeout for answer on attended transfer default is 15 seconds.
+ ;atxferdropcall = no ; If someone does an attended transfer, then hangs up before the transferred
+Index: configs/logger.conf.sample
+===================================================================
+--- a/configs/logger.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/logger.conf.sample (.../trunk) (revision 202568)
+@@ -15,7 +15,7 @@
+ ; see strftime(3) Linux manual for format specifiers. Note that there is also
+ ; a fractional second parameter which may be used in this field. Use %1q
+ ; for tenths, %2q for hundredths, etc.
+-;
++;
+ ;dateformat=%F %T ; ISO 8601 date format
+ ;dateformat=%F %T.%3q ; with milliseconds
+ ;
+@@ -47,11 +47,7 @@
+ ;
+ ; exec_after_rotate=gzip -9 ${filename}.2
+ ;
+-; This determines whether or not we log generic events to a file
+-; (defaults to yes).
+-;event_log = no
+ ;
+-;
+ ; For each file, specify what to log.
+ ;
+ ; For console logging, you set options at start of
+@@ -94,7 +90,7 @@
+ messages => notice,warning,error
+ ;full => notice,warning,error,debug,verbose
+
+-;syslog keyword : This special keyword logs to syslog facility
++;syslog keyword : This special keyword logs to syslog facility
+ ;
+ ;syslog.local0 => notice,warning,error
+ ;
+Index: configs/h323.conf.sample
+===================================================================
+--- a/configs/h323.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/h323.conf.sample (.../trunk) (revision 202568)
+@@ -44,7 +44,7 @@
+ ; or
+ ;dtmfmode=cisco:121
+ ;
+-; Set the gatekeeper
++; Set the gatekeeper
+ ; DISCOVER - Find the Gk address using multicast
+ ; DISABLE - Disable the use of a GK
+ ; <IP address> or <Host name> - The acutal IP address or hostname of your GK
+@@ -70,9 +70,9 @@
+ ;
+ ;UserByAlias=no
+ ;
+-; Default context gets used in siutations where you are using
+-; the GK routed model or no type=user was found. This gives you
+-; the ability to either play an invalid message or to simply not
++; Default context gets used in siutations where you are using
++; the GK routed model or no type=user was found. This gives you
++; the ability to either play an invalid message or to simply not
+ ; use user authentication at all.
+ ;
+ ;context=default
+@@ -153,7 +153,7 @@
+ ; and Gatekeeper, if there is one.
+ ;
+ ; Example: if someone calls time@your.asterisk.box.com
+-; Asterisk will send the call to the extension 'time'
++; Asterisk will send the call to the extension 'time'
+ ; in the context default
+ ;
+ ; [default]
+@@ -161,13 +161,13 @@
+ ; exten => time,2,Playback,current-time
+ ;
+ ; Keyword's 'prefix' and 'e164' are only make sense when
+-; used with a gatekeeper. You can specify either a prefix
++; used with a gatekeeper. You can specify either a prefix
+ ; or E.164 this endpoint is responsible for terminating.
+-;
++;
+ ; Example: The H.323 alias 'det-gw' will tell the gatekeeper
+ ; to route any call with the prefix 1248 to this alias. Keyword
+ ; e164 is used when you want to specifiy a full telephone
+-; number. So a call to the number 18102341212 would be
++; number. So a call to the number 18102341212 would be
+ ; routed to the H.323 alias 'time'.
+ ;
+ ;[time]
+@@ -182,10 +182,10 @@
+ ;
+ ;
+ ; Inbound H.323 calls from BillyBob would land in the incoming
+-; context with a maximum of 4 concurrent incoming calls
+-;
++; context with a maximum of 4 concurrent incoming calls
+ ;
+-; Note: If keyword 'incominglimit' are omitted Asterisk will not
++;
++; Note: If keyword 'incominglimit' are omitted Asterisk will not
+ ; enforce any maximum number of concurrent calls.
+ ;
+ ;[BillyBob]
+Index: configs/sla.conf.sample
+===================================================================
+--- a/configs/sla.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/sla.conf.sample (.../trunk) (revision 202568)
+@@ -27,12 +27,12 @@
+ ; require some indirect configuration which is
+ ; described in doc/asterisk.pdf.
+
+-;autocontext=line1 ; This supports automatic generation of the dialplan entries
+- ; if the autocontext option is used. Each trunk should have
++;autocontext=line1 ; This supports automatic generation of the dialplan entries
++ ; if the autocontext option is used. Each trunk should have
+ ; a unique context name. Then, in chan_dahdi.conf, this device
+ ; should be configured to have incoming calls go to this context.
+
+-;ringtimeout=30 ; Set how long to allow this trunk to ring on an inbound call before hanging
++;ringtimeout=30 ; Set how long to allow this trunk to ring on an inbound call before hanging
+ ; it up as an unanswered call. The value is in seconds.
+
+ ;barge=no ; If this option is set to "no", then no station will be
+@@ -75,12 +75,12 @@
+
+ ;device=SIP/station1 ; Each station must be mapped to a device.
+
+-;autocontext=sla_stations ; This supports automatic generation of the dialplan entries if
+- ; the autocontext option is used. All stations can use the same
+- ; context without conflict. The device for this station should
++;autocontext=sla_stations ; This supports automatic generation of the dialplan entries if
++ ; the autocontext option is used. All stations can use the same
++ ; context without conflict. The device for this station should
+ ; have its context configured to the same one listed here.
+
+-;ringtimeout=10 ; Set a timeout for how long to allow the station to ring for an
++;ringtimeout=10 ; Set a timeout for how long to allow the station to ring for an
+ ; incoming call, in seconds.
+
+ ;ringdelay=10 ; Set a time for how long to wait before beginning to ring this station
+@@ -97,8 +97,8 @@
+ ; "private" - This means that once this station puts a
+ ; call on hold, no other station will be
+ ; allowed to retrieve the call from hold.
+-
+
++
+ ;trunk=line1 ; Individually list all of the trunks that will appear on this station. This
+ ; order is significant. It should be the same order as they appear on the
+ ; phone. The order here defines the order of preference that the trunks will
+@@ -121,9 +121,9 @@
+ ;type=station
+ ;autocontext=sla_stations
+ ;trunk=line1
+-;trunk=line2
++;trunk=line2
+ ;trunk=line3
+-;trunk=line4
++;trunk=line4
+
+ ;[station2](station) ; Define a station that uses the configuration from the template "station".
+ ;device=SIP/station2
+Index: configs/res_odbc.conf.sample
+===================================================================
+--- a/configs/res_odbc.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/res_odbc.conf.sample (.../trunk) (revision 202568)
+@@ -1,4 +1,4 @@
+-;;; odbc setup file
++;;; odbc setup file
+
+ ; ENV is a global set of environmental variables that will get set.
+ ; Note that all environmental variables can be seen by all connections,
+Index: configs/agents.conf.sample
+===================================================================
+--- a/configs/agents.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/agents.conf.sample (.../trunk) (revision 202568)
+@@ -3,13 +3,6 @@
+ ;
+
+ [general]
+-;
+-; Define whether callbacklogins should be stored in astdb for
+-; persistence. Persistent logins will be reloaded after
+-; Asterisk restarts.
+-;
+-persistentagents=yes
+-
+ ; Enable or disable a single extension from logging in as multiple agents.
+ ; The default value is "yes".
+ ;multiplelogin=yes
+@@ -32,16 +25,15 @@
+ ; Define autologoffunavail to have agents automatically logged
+ ; out when the extension that they are at returns a CHANUNAVAIL
+ ; status when a call is attempted to be sent there.
+-; Default is "no".
++; Default is "no".
+ ;
+ ;autologoffunavail=yes
+ ;
+ ; Define ackcall to require a DTMF acknowledgement when
+-; an agent logs in using agentcallbacklogin. Default is "no".
+-; Can also be set to "always", which will also require AgentLogin
+-; agents to acknowledge calls. Use the acceptdtmf option to
+-; configure what DTMF key press should be used to acknowledge the
+-; call. The default is '#'.
++; an agent logs in using AgentLogin. Default is "no".
++; Use the acceptdtmf option to configure what DTMF key
++; press should be used to acknowledge the call. The
++; default is '#'.
+ ;
+ ;ackcall=no
+ ;acceptdtmf=#
+@@ -70,14 +62,14 @@
+ ;
+ ;goodbye => goodbye_file
+ ;
+-; Define updatecdr. This is whether or not to change the source
+-; channel in the CDR record for this call to agent/agent_id so
++; Define updatecdr. This is whether or not to change the source
++; channel in the CDR record for this call to agent/agent_id so
+ ; that we know which agent generates the call
+ ;
+ ;updatecdr=no
+ ;
+ ; Group memberships for agents (may change in mid-file)
+-;
++;
+ ;group=3
+ ;group=1,2
+ ;group=
+@@ -85,7 +77,7 @@
+ ; --------------------------------------------------
+ ; This section is devoted to recording agent's calls
+ ; The keywords are global to the chan_agent channel driver
+-;
++;
+ ; Enable recording calls addressed to agents. It's turned off by default.
+ ;recordagentcalls=yes
+ ;
+@@ -100,7 +92,7 @@
+ ; /var/spool/asterisk/monitor
+ ;savecallsin=/var/calls
+ ;
+-; An optional custom beep sound file to play to always-connected agents.
++; An optional custom beep sound file to play to always-connected agents.
+ ;custom_beep=beep
+ ;
+ ; --------------------------------------------------
+Index: configs/res_snmp.conf.sample
+===================================================================
+--- a/configs/res_snmp.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/res_snmp.conf.sample (.../trunk) (revision 202568)
+@@ -15,7 +15,7 @@
+
+ [general]
+ ; We run as a subagent per default -- to run as a full agent
+-; we must run as root (to be able to bind to port 161)
++; we must run as root (to be able to bind to port 161)
+ ;subagent = yes
+ ; SNMP must be explicitly enabled to be active
+ ;enabled = yes
+Index: configs/extconfig.conf.sample
+===================================================================
+--- a/configs/extconfig.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/extconfig.conf.sample (.../trunk) (revision 202568)
+@@ -7,7 +7,7 @@
+ ;
+ [settings]
+ ;
+-; Static configuration files:
++; Static configuration files:
+ ;
+ ; file.conf => driver,database[,table]
+ ;
+Index: configs/modules.conf.sample
+===================================================================
+--- a/configs/modules.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/modules.conf.sample (.../trunk) (revision 202568)
+@@ -21,7 +21,7 @@
+ ; Uncomment the following if you wish to use the Speech Recognition API
+ ;preload => res_speech.so
+ ;
+-; If you want, load the GTK console right away.
++; If you want, load the GTK console right away.
+ ;
+ noload => pbx_gtkconsole.so
+ ;load => pbx_gtkconsole.so
+Index: configs/phone.conf.sample
+===================================================================
+--- a/configs/phone.conf.sample (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/configs/phone.conf.sample (.../trunk) (revision 202568)
+@@ -6,8 +6,8 @@
+ [interfaces]
+ ;
+ ; Select a mode, either the phone jack provides dialtone, reads digits,
+-; then starts PBX with the given extension (dialtone mode), or
+-; immediately provides the PBX without reading any digits or providing
++; then starts PBX with the given extension (dialtone mode), or
++; immediately provides the PBX without reading any digits or providing
+ ; any dialtone (this is the immediate mode, the default). Also, you
+ ; can set the mode to "fxo" if you have a linejack to make it operate
+ ; properly. If you are using a Sigma Designs board you may set this to
+Index: makeopts.in
+===================================================================
+--- a/makeopts.in (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/makeopts.in (.../trunk) (revision 202568)
+@@ -47,6 +47,8 @@
+ PTHREAD_CFLAGS=@PTHREAD_CFLAGS@
+ PTHREAD_LIBS=@PTHREAD_LIBS@
+
++GNU_LD=@GNU_LD@
++
+ prefix = @prefix@
+ exec_prefix = @exec_prefix@
+
+@@ -103,6 +105,9 @@
+ GTK2_INCLUDE=@GTK2_INCLUDE@
+ GTK2_LIB=@GTK2_LIB@
+
++ICAL_INCLUDE=@ICAL_INCLUDE@
++ICAL_LIB=@ICAL_LIB@
++
+ ICONV_INCLUDE=@ICONV_INCLUDE@
+ ICONV_LIB=@ICONV_LIB@
+
+@@ -131,6 +136,9 @@
+ NCURSES_LIB=@NCURSES_LIB@
+ NCURSES_DIR=@NCURSES_DIR@
+
++NEON_INCLUDE=@NEON_INCLUDE@
++NEON_LIB=@NEON_LIB@
++
+ NETSNMP_INCLUDE=@NETSNMP_INCLUDE@
+ NETSNMP_LIB=@NETSNMP_LIB@
+
+Index: res/res_config_sqlite.c
+===================================================================
+--- a/res/res_config_sqlite.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/res/res_config_sqlite.c (.../trunk) (revision 202568)
+@@ -1862,7 +1862,7 @@
+ return 0;
+ }
+
+-AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Realtime SQLite configuration",
++AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Realtime SQLite configuration",
+ .load = load_module,
+ .unload = unload_module,
+ );
+Index: res/res_speech.exports
+===================================================================
+--- a/res/res_speech.exports (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/res/res_speech.exports (.../trunk) (revision 202568)
+@@ -0,0 +1,21 @@
++{
++ global:
++ ast_speech_change;
++ ast_speech_change_results_type;
++ ast_speech_change_state;
++ ast_speech_destroy;
++ ast_speech_dtmf;
++ ast_speech_grammar_activate;
++ ast_speech_grammar_deactivate;
++ ast_speech_grammar_load;
++ ast_speech_grammar_unload;
++ ast_speech_new;
++ ast_speech_register;
++ ast_speech_results_free;
++ ast_speech_results_get;
++ ast_speech_start;
++ ast_speech_unregister;
++ ast_speech_write;
++ local:
++ *;
++};
+
+Property changes on: res/res_speech.exports
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+
+Index: res/res_config_odbc.c
+===================================================================
+--- a/res/res_config_odbc.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/res/res_config_odbc.c (.../trunk) (revision 202568)
+@@ -903,6 +903,9 @@
+ case SQL_CHAR:
+ case SQL_VARCHAR:
+ case SQL_LONGVARCHAR:
++ case SQL_WCHAR:
++ case SQL_WVARCHAR:
++ case SQL_WLONGVARCHAR:
+ case SQL_BINARY:
+ case SQL_VARBINARY:
+ case SQL_LONGVARBINARY:
+@@ -984,7 +987,7 @@
+ if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 &&
+ type != RQ_UINTEGER2 && type != RQ_INTEGER2 &&
+ type != RQ_UINTEGER3 && type != RQ_INTEGER3 &&
+- type != RQ_UINTEGER4) {
++ type != RQ_INTEGER4) {
+ WARN_TYPE_OR_LENGTH(size)
+ }
+ break;
+@@ -1003,7 +1006,7 @@
+ type != RQ_UINTEGER2 && type != RQ_INTEGER2 &&
+ type != RQ_UINTEGER3 && type != RQ_INTEGER3 &&
+ type != RQ_UINTEGER4 && type != RQ_INTEGER4 &&
+- type != RQ_UINTEGER8) {
++ type != RQ_INTEGER8) {
+ WARN_TYPE_OR_LENGTH(size)
+ }
+ break;
+@@ -1067,7 +1070,7 @@
+ return 0;
+ }
+
+-AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Realtime ODBC configuration",
++AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Realtime ODBC configuration",
+ .load = load_module,
+ .unload = unload_module,
+ .reload = reload_module,
+Index: res/res_agi.c
+===================================================================
+--- a/res/res_agi.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/res/res_agi.c (.../trunk) (revision 202568)
+@@ -130,6 +130,32 @@
+ </enumlist>
+ </description>
+ </agi>
++ <agi name="control stream file" language="en_US">
++ <synopsis>
++ Sends audio file on channel and allows the listner to control the stream.
++ </synopsis>
++ <syntax>
++ <parameter name="filename" required="true">
++ <para>The file extension must not be included in the filename.</para>
++ </parameter>
++ <parameter name="escape_digits" required="true" />
++ <parameter name="skipms" />
++ <parameter name="ffchar">
++ <para>Defaults to <literal>*</literal></para>
++ </parameter>
++ <parameter name="rewchr">
++ <para>Defaults to <literal>#</literal></para>
++ </parameter>
++ <parameter name="pausechr" />
++ </syntax>
++ <description>
++ <para>Send the given file, allowing playback to be controled by the given
++ digits, if any. Use double quotes for the digits if you wish none to be
++ permitted. Returns <literal>0</literal> if playback completes without a digit
++ being pressed, or the ASCII numerical value of the digit if one was pressed,
++ or <literal>-1</literal> on error or if the channel was disconnected.</para>
++ </description>
++ </agi>
+ <agi name="database del" language="en_US">
+ <synopsis>
+ Removes database key/value
+@@ -288,6 +314,265 @@
+ <para>Does nothing.</para>
+ </description>
+ </agi>
++ <agi name="receive char" language="en_US">
++ <synopsis>
++ Receives one character from channels supporting it.
++ </synopsis>
++ <syntax>
++ <parameter name="timeout" required="true">
++ <para>The maximum time to wait for input in milliseconds, or <literal>0</literal>
++ for infinite. Most channels</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Receives a character of text on a channel. Most channels do not support
++ the reception of text. Returns the decimal value of the character
++ if one is received, or <literal>0</literal> if the channel does not support
++ text reception. Returns <literal>-1</literal> only on error/hangup.</para>
++ </description>
++ </agi>
++ <agi name="receive text" language="en_US">
++ <synopsis>
++ Receives text from channels supporting it.
++ </synopsis>
++ <syntax>
++ <parameter name="timeout" required="true">
++ <para>The timeout to be the maximum time to wait for input in
++ milliseconds, or <literal>0</literal> for infinite.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Receives a string of text on a channel. Most channels
++ do not support the reception of text. Returns <literal>-1</literal> for failure
++ or <literal>1</literal> for success, and the string in parenthesis.</para>
++ </description>
++ </agi>
++ <agi name="record file" language="en_US">
++ <synopsis>
++ Records to a given file.
++ </synopsis>
++ <syntax>
++ <parameter name="filename" required="true" />
++ <parameter name="format" required="true" />
++ <parameter name="escape_digits" required="true" />
++ <parameter name="timeout" required="true" />
++ <parameter name="offset samples" />
++ <parameter name="BEEP" />
++ <parameter name="s=silence" />
++ </syntax>
++ <description>
++ <para>Record to a file until a given dtmf digit in the sequence is received.
++ Returns <literal>-1</literal> on hangup or error. The format will specify what kind of file
++ will be recorded. The <replaceable>timeout</replaceable> is the maximum record time in
++ milliseconds, or <literal>-1</literal> for no <replaceable>timeout</replaceable>.
++ <replaceable>offset samples</replaceable> is optional, and, if provided, will seek
++ to the offset without exceeding the end of the file. <replaceable>silence</replaceable> is
++ the number of seconds of silence allowed before the function returns despite the
++ lack of dtmf digits or reaching <replaceable>timeout</replaceable>. <replaceable>silence</replaceable>
++ value must be preceeded by <literal>s=</literal> and is also optional.</para>
++ </description>
++ </agi>
++ <agi name="say alpha" language="en_US">
++ <synopsis>
++ Says a given character string.
++ </synopsis>
++ <syntax>
++ <parameter name="number" required="true" />
++ <parameter name="escape_digits" required="true" />
++ </syntax>
++ <description>
++ <para>Say a given character string, returning early if any of the given DTMF digits
++ are received on the channel. Returns <literal>0</literal> if playback completes
++ without a digit being pressed, or the ASCII numerical value of the digit if one
++ was pressed or <literal>-1</literal> on error/hangup.</para>
++ </description>
++ </agi>
++ <agi name="say digits" language="en_US">
++ <synopsis>
++ Says a given digit string.
++ </synopsis>
++ <syntax>
++ <parameter name="number" required="true" />
++ <parameter name="escape_digits" required="true" />
++ </syntax>
++ <description>
++ <para>Say a given digit string, returning early if any of the given DTMF digits
++ are received on the channel. Returns <literal>0</literal> if playback completes
++ without a digit being pressed, or the ASCII numerical value of the digit if one
++ was pressed or <literal>-1</literal> on error/hangup.</para>
++ </description>
++ </agi>
++ <agi name="say number" language="en_US">
++ <synopsis>
++ Says a given number.
++ </synopsis>
++ <syntax>
++ <parameter name="number" required="true" />
++ <parameter name="escape_digits" required="true" />
++ <parameter name="gender" />
++ </syntax>
++ <description>
++ <para>Say a given number, returning early if any of the given DTMF digits
++ are received on the channel. Returns <literal>0</literal> if playback
++ completes without a digit being pressed, or the ASCII numerical value of
++ the digit if one was pressed or <literal>-1</literal> on error/hangup.</para>
++ </description>
++ </agi>
++ <agi name="say phonetic" language="en_US">
++ <synopsis>
++ Says a given character string with phonetics.
++ </synopsis>
++ <syntax>
++ <parameter name="string" required="true" />
++ <parameter name="escape_digits" required="true" />
++ </syntax>
++ <description>
++ <para>Say a given character string with phonetics, returning early if any of the
++ given DTMF digits are received on the channel. Returns <literal>0</literal> if
++ playback completes without a digit pressed, the ASCII numerical value of the digit
++ if one was pressed, or <literal>-1</literal> on error/hangup.</para>
++ </description>
++ </agi>
++ <agi name="say date" language="en_US">
++ <synopsis>
++ Says a given date.
++ </synopsis>
++ <syntax>
++ <parameter name="date" required="true">
++ <para>Is number of seconds elapsed since 00:00:00 on January 1, 1970.
++ Coordinated Universal Time (UTC).</para>
++ </parameter>
++ <parameter name="escape_digits" required="true" />
++ </syntax>
++ <description>
++ <para>Say a given date, returning early if any of the given DTMF digits are
++ received on the channel. Returns <literal>0</literal> if playback
++ completes without a digit being pressed, or the ASCII numerical value of the
++ digit if one was pressed or <literal>-1</literal> on error/hangup.</para>
++ </description>
++ </agi>
++ <agi name="say time" language="en_US">
++ <synopsis>
++ Says a given time.
++ </synopsis>
++ <syntax>
++ <parameter name="time" required="true">
++ <para>Is number of seconds elapsed since 00:00:00 on January 1, 1970.
++ Coordinated Universal Time (UTC).</para>
++ </parameter>
++ <parameter name="escape_digits" required="true" />
++ </syntax>
++ <description>
++ <para>Say a given time, returning early if any of the given DTMF digits are
++ received on the channel. Returns <literal>0</literal> if playback completes
++ without a digit being pressed, or the ASCII numerical value of the digit if
++ one was pressed or <literal>-1</literal> on error/hangup.</para>
++ </description>
++ </agi>
++ <agi name="say datetime" language="en_US">
++ <synopsis>
++ Says a given time as specfied by the format given.
++ </synopsis>
++ <syntax>
++ <parameter name="time" required="true">
++ <para>Is number of seconds elapsed since 00:00:00
++ on January 1, 1970, Coordinated Universal Time (UTC)</para>
++ </parameter>
++ <parameter name="escape_digits" required="true" />
++ <parameter name="format">
++ <para>Is the format the time should be said in. See
++ <filename>voicemail.conf</filename> (defaults to <literal>ABdY
++ 'digits/at' IMp</literal>).</para>
++ </parameter>
++ <parameter name="timezone">
++ <para>Acceptable values can be found in <filename>/usr/share/zoneinfo</filename>
++ Defaults to machine default.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Say a given time, returning early if any of the given DTMF digits are
++ received on the channel. Returns <literal>0</literal> if playback
++ completes without a digit being pressed, or the ASCII numerical value of the
++ digit if one was pressed or <literal>-1</literal> on error/hangup.</para>
++ </description>
++ </agi>
++ <agi name="send image" language="en_US">
++ <synopsis>
++ Sends images to channels supporting it.
++ </synopsis>
++ <syntax>
++ <parameter name="image" required="true" />
++ </syntax>
++ <description>
++ <para>Sends the given image on a channel. Most channels do not support the
++ transmission of images. Returns <literal>0</literal> if image is sent, or if
++ the channel does not support image transmission. Returns <literal>-1</literal>
++ only on error/hangup. Image names should not include extensions.</para>
++ </description>
++ </agi>
++ <agi name="send text" language="en_US">
++ <synopsis>
++ Sends text to channels supporting it.
++ </synopsis>
++ <syntax>
++ <parameter name="text to send" required="true">
++ <para>Text consisting of greater than one word should be placed
++ in quotes since the command only accepts a single argument.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Sends the given text on a channel. Most channels do not support the
++ transmission of text. Returns <literal>0</literal> if text is sent, or if the
++ channel does not support text transmission. Returns <literal>-1</literal> only
++ on error/hangup.</para>
++ </description>
++ </agi>
++ <agi name="set autohangup" language="en_US">
++ <synopsis>
++ Autohangup channel in some time.
++ </synopsis>
++ <syntax>
++ <parameter name="time" required="true" />
++ </syntax>
++ <description>
++ <para>Cause the channel to automatically hangup at <replaceable>time</replaceable>
++ seconds in the future. Of course it can be hungup before then as well. Setting to
++ <literal>0</literal> will cause the autohangup feature to be disabled on this channel.</para>
++ </description>
++ </agi>
++ <agi name="set callerid" language="en_US">
++ <synopsis>
++ Sets callerid for the current channel.
++ </synopsis>
++ <syntax>
++ <parameter name="number" required="true" />
++ </syntax>
++ <description>
++ <para>Changes the callerid of the current channel.</para>
++ </description>
++ </agi>
++ <agi name="set context" language="en_US">
++ <synopsis>
++ Sets channel context.
++ </synopsis>
++ <syntax>
++ <parameter name="desired context" required="true" />
++ </syntax>
++ <description>
++ <para>Sets the context for continuation upon exiting the application.</para>
++ </description>
++ </agi>
++ <agi name="set extension" language="en_US">
++ <synopsis>
++ Changes channel extension.
++ </synopsis>
++ <syntax>
++ <parameter name="new extension" required="true" />
++ </syntax>
++ <description>
++ <para>Changes the extension for continuation upon exiting the application.</para>
++ </description>
++ </agi>
+ <agi name="set music" language="en_US">
+ <synopsis>
+ Enable/Disable Music on hold generator
+@@ -312,6 +597,300 @@
+ <para>Always returns <literal>0</literal>.</para>
+ </description>
+ </agi>
++ <agi name="set priority" language="en_US">
++ <synopsis>
++ Set channel dialplan priority.
++ </synopsis>
++ <syntax>
++ <parameter name="priority" required="true" />
++ </syntax>
++ <description>
++ <para>Changes the priority for continuation upon exiting the application.
++ The priority must be a valid priority or label.</para>
++ </description>
++ </agi>
++ <agi name="set variable" language="en_US">
++ <synopsis>
++ Sets a channel variable.
++ </synopsis>
++ <syntax>
++ <parameter name="variablename" required="true" />
++ <parameter name="value" required="true" />
++ </syntax>
++ <description>
++ <para>Sets a variable to the current channel.</para>
++ </description>
++ </agi>
++ <agi name="stream file" language="en_US">
++ <synopsis>
++ Sends audio file on channel.
++ </synopsis>
++ <syntax>
++ <parameter name="filename" required="true">
++ <para>File name to play. The file extension must not be
++ included in the <replaceable>filename</replaceable>.</para>
++ </parameter>
++ <parameter name="escape_digits" required="true">
++ <para>Use double quotes for the digits if you wish none to be
++ permitted.</para>
++ </parameter>
++ <parameter name="sample offset">
++ <para>If sample offset is provided then the audio will seek to sample
++ offset before play starts.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Send the given file, allowing playback to be interrupted by the given
++ digits, if any. Returns <literal>0</literal> if playback completes without a digit
++ being pressed, or the ASCII numerical value of the digit if one was pressed,
++ or <literal>-1</literal> on error or if the channel was disconnected.</para>
++ </description>
++ <see-also>
++ <ref type="agi">control stream file</ref>
++ </see-also>
++ </agi>
++ <agi name="tdd mode" language="en_US">
++ <synopsis>
++ Toggles TDD mode (for the deaf).
++ </synopsis>
++ <syntax>
++ <parameter name="boolean" required="true">
++ <enumlist>
++ <enum name="on" />
++ <enum name="off" />
++ </enumlist>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Enable/Disable TDD transmission/reception on a channel. Returns <literal>1</literal> if
++ successful, or <literal>0</literal> if channel is not TDD-capable.</para>
++ </description>
++ </agi>
++ <agi name="verbose" language="en_US">
++ <synopsis>
++ Logs a message to the asterisk verbose log.
++ </synopsis>
++ <syntax>
++ <parameter name="message" required="true" />
++ <parameter name="level" required="true" />
++ </syntax>
++ <description>
++ <para>Sends <replaceable>message</replaceable> to the console via verbose
++ message system. <replaceable>level</replaceable> is the the verbose level (1-4).
++ Always returns <literal>1</literal></para>
++ </description>
++ </agi>
++ <agi name="wait for digit" language="en_US">
++ <synopsis>
++ Waits for a digit to be pressed.
++ </synopsis>
++ <syntax>
++ <parameter name="timeout" required="true" />
++ </syntax>
++ <description>
++ <para>Waits up to <replaceable>timeout</replaceable> milliseconds for channel to
++ receive a DTMF digit. Returns <literal>-1</literal> on channel failure, <literal>0</literal>
++ if no digit is received in the timeout, or the numerical value of the ascii of the digit if
++ one is received. Use <literal>-1</literal> for the <replaceable>timeout</replaceable> value if
++ you desire the call to block indefinitely.</para>
++ </description>
++ </agi>
++ <agi name="speech create" language="en_US">
++ <synopsis>
++ Creates a speech object.
++ </synopsis>
++ <syntax>
++ <parameter name="engine" required="true" />
++ </syntax>
++ <description>
++ <para>Create a speech object to be used by the other Speech AGI commands.</para>
++ </description>
++ </agi>
++ <agi name="speech set" language="en_US">
++ <synopsis>
++ Sets a speech engine setting.
++ </synopsis>
++ <syntax>
++ <parameter name="name" required="true" />
++ <parameter name="value" required="true" />
++ </syntax>
++ <description>
++ <para>Set an engine-specific setting.</para>
++ </description>
++ </agi>
++ <agi name="speech destroy" language="en_US">
++ <synopsis>
++ Destroys a speech object.
++ </synopsis>
++ <syntax>
++ </syntax>
++ <description>
++ <para>Destroy the speech object created by <literal>SPEECH CREATE</literal>.</para>
++ </description>
++ <see-also>
++ <ref type="agi">speech create</ref>
++ </see-also>
++ </agi>
++ <agi name="speech load grammar" language="en_US">
++ <synopsis>
++ Loads a grammar.
++ </synopsis>
++ <syntax>
++ <parameter name="grammar name" required="true" />
++ <parameter name="path to grammar" required="true" />
++ </syntax>
++ <description>
++ <para>Loads the specified grammar as the specified name.</para>
++ </description>
++ </agi>
++ <agi name="speech unload grammar" language="en_US">
++ <synopsis>
++ Unloads a grammar.
++ </synopsis>
++ <syntax>
++ <parameter name="grammar name" required="true" />
++ </syntax>
++ <description>
++ <para>Unloads the specified grammar.</para>
++ </description>
++ </agi>
++ <agi name="speech activate grammar" language="en_US">
++ <synopsis>
++ Activates a grammar.
++ </synopsis>
++ <syntax>
++ <parameter name="grammar name" required="true" />
++ </syntax>
++ <description>
++ <para>Activates the specified grammar on the speech object.</para>
++ </description>
++ </agi>
++ <agi name="speech deactivate grammar" language="en_US">
++ <synopsis>
++ Deactivates a grammar.
++ </synopsis>
++ <syntax>
++ <parameter name="grammar name" required="true" />
++ </syntax>
++ <description>
++ <para>Deactivates the specified grammar on the speech object.</para>
++ </description>
++ </agi>
++ <agi name="speech recognize" language="en_US">
++ <synopsis>
++ Recognizes speech.
++ </synopsis>
++ <syntax>
++ <parameter name="prompt" required="true" />
++ <parameter name="timeout" required="true" />
++ <parameter name="offset" />
++ </syntax>
++ <description>
++ <para>Plays back given <replaceable>prompt</replaceable> while listening for
++ speech and dtmf.</para>
++ </description>
++ </agi>
++ <application name="AGI" language="en_US">
++ <synopsis>
++ Executes an AGI compliant application.
++ </synopsis>
++ <syntax>
++ <parameter name="command" required="true" />
++ <parameter name="args">
++ <argument name="arg1" required="true" />
++ <argument name="arg2" multiple="yes" />
++ </parameter>
++ </syntax>
++ <description>
++ <para>Executes an Asterisk Gateway Interface compliant
++ program on a channel. AGI allows Asterisk to launch external programs written
++ in any language to control a telephony channel, play audio, read DTMF digits,
++ etc. by communicating with the AGI protocol on <emphasis>stdin</emphasis> and
++ <emphasis>stdout</emphasis>. As of <literal>1.6.0</literal>, this channel will
++ not stop dialplan execution on hangup inside of this application. Dialplan
++ execution will continue normally, even upon hangup until the AGI application
++ signals a desire to stop (either by exiting or, in the case of a net script, by
++ closing the connection). A locally executed AGI script will receive SIGHUP on
++ hangup from the channel except when using DeadAGI. A fast AGI server will
++ correspondingly receive a HANGUP in OOB data. Both of these signals may be disabled
++ by setting the <variable>AGISIGHUP</variable> channel variable to <literal>no</literal>
++ before executing the AGI application.</para>
++ <para>Use the CLI command <literal>agi show commnands</literal> to list available agi
++ commands.</para>
++ <para>This application sets the following channel variable upon completion:</para>
++ <variablelist>
++ <variable name="AGISTATUS">
++ <para>The status of the attempt to the run the AGI script
++ text string, one of:</para>
++ <value name="SUCCESS" />
++ <value name="FAILURE" />
++ <value name="NOTFOUND" />
++ <value name="HANGUP" />
++ </variable>
++ </variablelist>
++ </description>
++ <see-also>
++ <ref type="application">EAGI</ref>
++ <ref type="application">DeadAGI</ref>
++ </see-also>
++ </application>
++ <application name="EAGI" language="en_US">
++ <synopsis>
++ Executes an EAGI compliant application.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/application[@name='AGI']/syntax/parameter[@name='command'])" />
++ <xi:include xpointer="xpointer(/docs/application[@name='AGI']/syntax/parameter[@name='args'])" />
++ </syntax>
++ <description>
++ <para>Using 'EAGI' provides enhanced AGI, with incoming audio available out of band
++ on file descriptor 3.</para>
++ <xi:include xpointer="xpointer(/docs/application[@name='AGI']/description/para)" />
++ <xi:include xpointer="xpointer(/docs/application[@name='AGI']/description/variablelist)" />
++ </description>
++ <see-also>
++ <ref type="application">AGI</ref>
++ <ref type="application">DeadAGI</ref>
++ </see-also>
++ </application>
++ <application name="DeadAGI" language="en_US">
++ <synopsis>
++ Executes AGI on a hungup channel.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/application[@name='AGI']/syntax/parameter[@name='command'])" />
++ <xi:include xpointer="xpointer(/docs/application[@name='AGI']/syntax/parameter[@name='args'])" />
++ </syntax>
++ <description>
++ <xi:include xpointer="xpointer(/docs/application[@name='AGI']/description/para)" />
++ <xi:include xpointer="xpointer(/docs/application[@name='AGI']/description/variablelist)" />
++ </description>
++ <see-also>
++ <ref type="application">AGI</ref>
++ <ref type="application">EAGI</ref>
++ </see-also>
++ </application>
++ <manager name="AGI" language="en_US">
++ <synopsis>
++ Add an AGI command to execute by Async AGI.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Channel" required="true">
++ <para>Channel that is currently in Async AGI.</para>
++ </parameter>
++ <parameter name="Command" required="true">
++ <para>Application to execute.</para>
++ </parameter>
++ <parameter name="CommandID">
++ <para>This will be sent back in CommandID header of AsyncAGI exec
++ event notification.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Add an AGI command to the execute queue of the channel in Async AGI.</para>
++ </description>
++ </manager>
+ ***/
+
+ #define MAX_ARGS 128
+@@ -325,30 +904,6 @@
+
+ static char *deadapp = "DeadAGI";
+
+-static char *synopsis = "Executes an AGI compliant application";
+-static char *esynopsis = "Executes an EAGI compliant application";
+-static char *deadsynopsis = "Executes AGI on a hungup channel";
+-
+-static char *descrip =
+-" [E|Dead]AGI(command,args): Executes an Asterisk Gateway Interface compliant\n"
+-"program on a channel. AGI allows Asterisk to launch external programs written\n"
+-"in any language to control a telephony channel, play audio, read DTMF digits,\n"
+-"etc. by communicating with the AGI protocol on stdin and stdout.\n"
+-" As of 1.6.0, this channel will not stop dialplan execution on hangup inside\n"
+-"of this application. Dialplan execution will continue normally, even upon\n"
+-"hangup until the AGI application signals a desire to stop (either by exiting\n"
+-"or, in the case of a net script, by closing the connection).\n"
+-" A locally executed AGI script will receive SIGHUP on hangup from the channel\n"
+-"except when using DeadAGI. A fast AGI server will correspondingly receive a\n"
+-"HANGUP in OOB data. Both of these signals may be disabled by setting the\n"
+-"AGISIGHUP channel variable to \"no\" before executing the AGI application.\n"
+-" Using 'EAGI' provides enhanced AGI, with incoming audio available out of band\n"
+-"on file descriptor 3.\n\n"
+-" Use the CLI command 'agi show commnands' to list available agi commands.\n"
+-" This application sets the following channel variable upon completion:\n"
+-" AGISTATUS The status of the attempt to the run the AGI script\n"
+-" text string, one of SUCCESS | FAILURE | NOTFOUND | HANGUP\n";
+-
+ static int agidebug = 0;
+
+ #define TONE_BLOCK_SIZE 200
+@@ -367,12 +922,12 @@
+ AGI_RESULT_HANGUP,
+ };
+
+-static agi_command *find_command(char *cmds[], int exact);
++static agi_command *find_command(const char * const cmds[], int exact);
+
+ AST_THREADSTORAGE(agi_buf);
+ #define AGI_BUF_INITSIZE 256
+
+-int ast_agi_send(int fd, struct ast_channel *chan, char *fmt, ...)
++int AST_OPTIONAL_API_NAME(ast_agi_send)(int fd, struct ast_channel *chan, char *fmt, ...)
+ {
+ int res = 0;
+ va_list ap;
+@@ -435,14 +990,6 @@
+ .destroy = agi_destroy_commands_cb
+ };
+
+-static const char mandescr_asyncagi[] =
+-"Description: Add an AGI command to the execute queue of the channel in Async AGI\n"
+-"Variables:\n"
+-" *Channel: Channel that is currently in Async AGI\n"
+-" *Command: Application to execute\n"
+-" CommandID: comand id. This will be sent back in CommandID header of AsyncAGI exec event notification\n"
+-"\n";
+-
+ static struct agi_cmd *get_agi_cmd(struct ast_channel *chan)
+ {
+ struct ast_datastore *store;
+@@ -556,20 +1103,27 @@
+ return NULL;
+ }
+
+- if (a->argc < 4)
++ if (a->argc < 4) {
+ return CLI_SHOWUSAGE;
+- chan = ast_get_channel_by_name_locked(a->argv[2]);
+- if (!chan) {
++ }
++
++ if (!(chan = ast_channel_get_by_name(a->argv[2]))) {
+ ast_log(LOG_WARNING, "Channel %s does not exists or cannot lock it\n", a->argv[2]);
+ return CLI_FAILURE;
+ }
++
+ if (add_agi_cmd(chan, a->argv[3], (a->argc > 4 ? a->argv[4] : ""))) {
+ ast_log(LOG_WARNING, "failed to add AGI command to queue of channel %s\n", chan->name);
+ ast_channel_unlock(chan);
++ chan = ast_channel_unref(chan);
+ return CLI_FAILURE;
+ }
++
+ ast_log(LOG_DEBUG, "Added AGI command to channel %s queue\n", chan->name);
++
+ ast_channel_unlock(chan);
++ chan = ast_channel_unref(chan);
++
+ return CLI_SUCCESS;
+ }
+
+@@ -591,24 +1145,33 @@
+ const char *cmdid = astman_get_header(m, "CommandID");
+ struct ast_channel *chan;
+ char buf[256];
++
+ if (ast_strlen_zero(channel) || ast_strlen_zero(cmdbuff)) {
+ astman_send_error(s, m, "Both, Channel and Command are *required*");
+ return 0;
+ }
+- chan = ast_get_channel_by_name_locked(channel);
+- if (!chan) {
++
++ if (!(chan = ast_channel_get_by_name(channel))) {
+ snprintf(buf, sizeof(buf), "Channel %s does not exists or cannot get its lock", channel);
+ astman_send_error(s, m, buf);
+ return 0;
+ }
++
++ ast_channel_lock(chan);
++
+ if (add_agi_cmd(chan, cmdbuff, cmdid)) {
+ snprintf(buf, sizeof(buf), "Failed to add AGI command to channel %s queue", chan->name);
+ astman_send_error(s, m, buf);
+ ast_channel_unlock(chan);
++ chan = ast_channel_unref(chan);
+ return 0;
+ }
++
++ ast_channel_unlock(chan);
++ chan = ast_channel_unref(chan);
++
+ astman_send_ack(s, m, "Added AGI command to queue");
+- ast_channel_unlock(chan);
++
+ return 0;
+ }
+
+@@ -1019,7 +1582,7 @@
+ ast_agi_send(fd, chan, "\n");
+ }
+
+-static int handle_answer(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
++static int handle_answer(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ int res = 0;
+
+@@ -1031,13 +1594,13 @@
+ return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
+ }
+
+-static int handle_asyncagi_break(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
++static int handle_asyncagi_break(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ ast_agi_send(agi->fd, chan, "200 result=0\n");
+ return RESULT_FAILURE;
+ }
+
+-static int handle_waitfordigit(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
++static int handle_waitfordigit(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ int res, to;
+
+@@ -1050,7 +1613,7 @@
+ return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
+ }
+
+-static int handle_sendtext(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
++static int handle_sendtext(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ int res;
+
+@@ -1069,7 +1632,7 @@
+ return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
+ }
+
+-static int handle_recvchar(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
++static int handle_recvchar(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ int res;
+
+@@ -1089,7 +1652,7 @@
+ return RESULT_FAILURE;
+ }
+
+-static int handle_recvtext(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
++static int handle_recvtext(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ char *buf;
+
+@@ -1106,7 +1669,7 @@
+ return RESULT_SUCCESS;
+ }
+
+-static int handle_tddmode(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
++static int handle_tddmode(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ int res, x;
+
+@@ -1133,7 +1696,7 @@
+ return RESULT_SUCCESS;
+ }
+
+-static int handle_sendimage(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
++static int handle_sendimage(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ int res;
+
+@@ -1149,10 +1712,10 @@
+ return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
+ }
+
+-static int handle_controlstreamfile(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
++static int handle_controlstreamfile(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ int res = 0, skipms = 3000;
+- char *fwd = "#", *rev = "*", *suspend = NULL, *stop = NULL; /* Default values */
++ const char *fwd = "#", *rev = "*", *suspend = NULL, *stop = NULL; /* Default values */
+
+ if (argc < 5 || argc > 9) {
+ return RESULT_SHOWUSAGE;
+@@ -1185,12 +1748,12 @@
+ return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
+ }
+
+-static int handle_streamfile(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
++static int handle_streamfile(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ int res, vres;
+ struct ast_filestream *fs, *vfs;
+ long sample_offset = 0, max_length;
+- char *edigits = "";
++ const char *edigits = "";
+
+ if (argc < 4 || argc > 5)
+ return RESULT_SHOWUSAGE;
+@@ -1235,13 +1798,13 @@
+ }
+
+ /*! \brief get option - really similar to the handle_streamfile, but with a timeout */
+-static int handle_getoption(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
++static int handle_getoption(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ int res, vres;
+ struct ast_filestream *fs, *vfs;
+ long sample_offset = 0, max_length;
+ int timeout = 0;
+- char *edigits = "";
++ const char *edigits = "";
+
+ if ( argc < 4 || argc > 5 )
+ return RESULT_SHOWUSAGE;
+@@ -1304,7 +1867,7 @@
+
+ /*! \brief Say number in various language syntaxes */
+ /* While waiting, we're sending a NULL. */
+-static int handle_saynumber(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
++static int handle_saynumber(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ int res, num;
+
+@@ -1319,7 +1882,7 @@
+ return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
+ }
+
+-static int handle_saydigits(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
++static int handle_saydigits(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ int res, num;
+
+@@ -1335,7 +1898,7 @@
+ return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
+ }
+
+-static int handle_sayalpha(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
++static int handle_sayalpha(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ int res;
+
+@@ -1349,7 +1912,7 @@
+ return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
+ }
+
+-static int handle_saydate(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
++static int handle_saydate(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ int res, num;
+
+@@ -1364,7 +1927,7 @@
+ return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
+ }
+
+-static int handle_saytime(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
++static int handle_saytime(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ int res, num;
+
+@@ -1379,11 +1942,11 @@
+ return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
+ }
+
+-static int handle_saydatetime(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
++static int handle_saydatetime(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ int res = 0;
+ time_t unixtime;
+- char *format, *zone = NULL;
++ const char *format, *zone = NULL;
+
+ if (argc < 4)
+ return RESULT_SHOWUSAGE;
+@@ -1413,7 +1976,7 @@
+ return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
+ }
+
+-static int handle_sayphonetic(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
++static int handle_sayphonetic(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ int res;
+
+@@ -1427,7 +1990,7 @@
+ return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
+ }
+
+-static int handle_getdata(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
++static int handle_getdata(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ int res, max, timeout;
+ char data[1024];
+@@ -1454,7 +2017,7 @@
+ return RESULT_SUCCESS;
+ }
+
+-static int handle_setcontext(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
++static int handle_setcontext(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+
+ if (argc != 3)
+@@ -1464,7 +2027,7 @@
+ return RESULT_SUCCESS;
+ }
+
+-static int handle_setextension(struct ast_channel *chan, AGI *agi, int argc, char **argv)
++static int handle_setextension(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ if (argc != 3)
+ return RESULT_SHOWUSAGE;
+@@ -1473,7 +2036,7 @@
+ return RESULT_SUCCESS;
+ }
+
+-static int handle_setpriority(struct ast_channel *chan, AGI *agi, int argc, char **argv)
++static int handle_setpriority(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ int pri;
+
+@@ -1490,7 +2053,7 @@
+ return RESULT_SUCCESS;
+ }
+
+-static int handle_recordfile(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
++static int handle_recordfile(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ struct ast_filestream *fs;
+ struct ast_frame *f;
+@@ -1667,7 +2230,7 @@
+ return RESULT_SUCCESS;
+ }
+
+-static int handle_autohangup(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
++static int handle_autohangup(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ double timeout;
+ struct timeval whentohangup = { 0, 0 };
+@@ -1687,7 +2250,7 @@
+ return RESULT_SUCCESS;
+ }
+
+-static int handle_hangup(struct ast_channel *chan, AGI *agi, int argc, char **argv)
++static int handle_hangup(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ struct ast_channel *c;
+
+@@ -1698,12 +2261,11 @@
+ return RESULT_SUCCESS;
+ } else if (argc == 2) {
+ /* one argument: look for info on the specified channel */
+- c = ast_get_channel_by_name_locked(argv[1]);
+- if (c) {
++ if ((c = ast_channel_get_by_name(argv[1]))) {
+ /* we have a matching channel */
+- ast_softhangup(c,AST_SOFTHANGUP_EXPLICIT);
++ ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
++ c = ast_channel_unref(c);
+ ast_agi_send(agi->fd, chan, "200 result=1\n");
+- ast_channel_unlock(c);
+ return RESULT_SUCCESS;
+ }
+ /* if we get this far no channel name matched the argument given */
+@@ -1714,7 +2276,7 @@
+ }
+ }
+
+-static int handle_exec(struct ast_channel *chan, AGI *agi, int argc, char **argv)
++static int handle_exec(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ int res;
+ struct ast_app *app_to_exec;
+@@ -1729,7 +2291,8 @@
+ ast_masq_park_call(chan, NULL, 0, NULL);
+ }
+ if (ast_compat_res_agi && !ast_strlen_zero(argv[2])) {
+- char *compat = alloca(strlen(argv[2]) * 2 + 1), *cptr, *vptr;
++ char *compat = alloca(strlen(argv[2]) * 2 + 1), *cptr;
++ const char *vptr;
+ for (cptr = compat, vptr = argv[2]; *vptr; vptr++) {
+ if (*vptr == ',') {
+ *cptr++ = '\\';
+@@ -1755,7 +2318,7 @@
+ return res;
+ }
+
+-static int handle_setcallerid(struct ast_channel *chan, AGI *agi, int argc, char **argv)
++static int handle_setcallerid(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ char tmp[256]="";
+ char *l = NULL, *n = NULL;
+@@ -1776,7 +2339,7 @@
+ return RESULT_SUCCESS;
+ }
+
+-static int handle_channelstatus(struct ast_channel *chan, AGI *agi, int argc, char **argv)
++static int handle_channelstatus(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ struct ast_channel *c;
+ if (argc == 2) {
+@@ -1785,10 +2348,9 @@
+ return RESULT_SUCCESS;
+ } else if (argc == 3) {
+ /* one argument: look for info on the specified channel */
+- c = ast_get_channel_by_name_locked(argv[2]);
+- if (c) {
++ if ((c = ast_channel_get_by_name(argv[2]))) {
+ ast_agi_send(agi->fd, chan, "200 result=%d\n", c->_state);
+- ast_channel_unlock(c);
++ c = ast_channel_unref(c);
+ return RESULT_SUCCESS;
+ }
+ /* if we get this far no channel name matched the argument given */
+@@ -1799,7 +2361,7 @@
+ }
+ }
+
+-static int handle_setvariable(struct ast_channel *chan, AGI *agi, int argc, char **argv)
++static int handle_setvariable(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ if (argv[3])
+ pbx_builtin_setvar_helper(chan, argv[2], argv[3]);
+@@ -1808,7 +2370,7 @@
+ return RESULT_SUCCESS;
+ }
+
+-static int handle_getvariable(struct ast_channel *chan, AGI *agi, int argc, char **argv)
++static int handle_getvariable(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ char *ret;
+ char tempstr[1024];
+@@ -1831,30 +2393,41 @@
+ return RESULT_SUCCESS;
+ }
+
+-static int handle_getvariablefull(struct ast_channel *chan, AGI *agi, int argc, char **argv)
++static int handle_getvariablefull(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+- char tmp[4096];
+- struct ast_channel *chan2=NULL;
++ struct ast_channel *chan2 = NULL;
+
+- if ((argc != 4) && (argc != 5))
++ if (argc != 4 && argc != 5) {
+ return RESULT_SHOWUSAGE;
++ }
++
+ if (argc == 5) {
+- chan2 = ast_get_channel_by_name_locked(argv[4]);
++ chan2 = ast_channel_get_by_name(argv[4]);
+ } else {
+- chan2 = chan;
++ chan2 = ast_channel_ref(chan);
+ }
++
+ if (chan2) {
+- pbx_substitute_variables_helper(chan2, argv[3], tmp, sizeof(tmp) - 1);
+- ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", tmp);
++ struct ast_str *str = ast_str_create(16);
++ if (!str) {
++ ast_agi_send(agi->fd, chan, "200 result=0\n");
++ return RESULT_SUCCESS;
++ }
++ ast_str_substitute_variables(&str, 0, chan2, argv[3]);
++ ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", ast_str_buffer(str));
++ ast_free(str);
+ } else {
+ ast_agi_send(agi->fd, chan, "200 result=0\n");
+ }
+- if (chan2 && (chan2 != chan))
+- ast_channel_unlock(chan2);
++
++ if (chan2) {
++ chan2 = ast_channel_unref(chan2);
++ }
++
+ return RESULT_SUCCESS;
+ }
+
+-static int handle_verbose(struct ast_channel *chan, AGI *agi, int argc, char **argv)
++static int handle_verbose(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ int level = 0;
+
+@@ -1871,7 +2444,7 @@
+ return RESULT_SUCCESS;
+ }
+
+-static int handle_dbget(struct ast_channel *chan, AGI *agi, int argc, char **argv)
++static int handle_dbget(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ int res;
+ struct ast_str *buf;
+@@ -1904,7 +2477,7 @@
+ return RESULT_SUCCESS;
+ }
+
+-static int handle_dbput(struct ast_channel *chan, AGI *agi, int argc, char **argv)
++static int handle_dbput(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ int res;
+
+@@ -1915,7 +2488,7 @@
+ return RESULT_SUCCESS;
+ }
+
+-static int handle_dbdel(struct ast_channel *chan, AGI *agi, int argc, char **argv)
++static int handle_dbdel(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ int res;
+
+@@ -1926,7 +2499,7 @@
+ return RESULT_SUCCESS;
+ }
+
+-static int handle_dbdeltree(struct ast_channel *chan, AGI *agi, int argc, char **argv)
++static int handle_dbdeltree(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ int res;
+
+@@ -1970,13 +2543,13 @@
+ return CLI_SUCCESS;
+ }
+
+-static int handle_noop(struct ast_channel *chan, AGI *agi, int arg, char *argv[])
++static int handle_noop(struct ast_channel *chan, AGI *agi, int arg, const char * const argv[])
+ {
+ ast_agi_send(agi->fd, chan, "200 result=0\n");
+ return RESULT_SUCCESS;
+ }
+
+-static int handle_setmusic(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
++static int handle_setmusic(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ if (!strncasecmp(argv[2], "on", 2))
+ ast_moh_start(chan, argc > 3 ? argv[3] : NULL, NULL);
+@@ -1986,7 +2559,7 @@
+ return RESULT_SUCCESS;
+ }
+
+-static int handle_speechcreate(struct ast_channel *chan, AGI *agi, int argc, char **argv)
++static int handle_speechcreate(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ /* If a structure already exists, return an error */
+ if (agi->speech) {
+@@ -2002,7 +2575,7 @@
+ return RESULT_SUCCESS;
+ }
+
+-static int handle_speechset(struct ast_channel *chan, AGI *agi, int argc, char **argv)
++static int handle_speechset(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ /* Check for minimum arguments */
+ if (argc != 3)
+@@ -2020,7 +2593,7 @@
+ return RESULT_SUCCESS;
+ }
+
+-static int handle_speechdestroy(struct ast_channel *chan, AGI *agi, int argc, char **argv)
++static int handle_speechdestroy(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ if (agi->speech) {
+ ast_speech_destroy(agi->speech);
+@@ -2033,7 +2606,7 @@
+ return RESULT_SUCCESS;
+ }
+
+-static int handle_speechloadgrammar(struct ast_channel *chan, AGI *agi, int argc, char **argv)
++static int handle_speechloadgrammar(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ if (argc != 5)
+ return RESULT_SHOWUSAGE;
+@@ -2051,7 +2624,7 @@
+ return RESULT_SUCCESS;
+ }
+
+-static int handle_speechunloadgrammar(struct ast_channel *chan, AGI *agi, int argc, char **argv)
++static int handle_speechunloadgrammar(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ if (argc != 4)
+ return RESULT_SHOWUSAGE;
+@@ -2069,7 +2642,7 @@
+ return RESULT_SUCCESS;
+ }
+
+-static int handle_speechactivategrammar(struct ast_channel *chan, AGI *agi, int argc, char **argv)
++static int handle_speechactivategrammar(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ if (argc != 4)
+ return RESULT_SHOWUSAGE;
+@@ -2087,7 +2660,7 @@
+ return RESULT_SUCCESS;
+ }
+
+-static int handle_speechdeactivategrammar(struct ast_channel *chan, AGI *agi, int argc, char **argv)
++static int handle_speechdeactivategrammar(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ if (argc != 4)
+ return RESULT_SHOWUSAGE;
+@@ -2124,10 +2697,11 @@
+ return 0;
+ }
+
+-static int handle_speechrecognize(struct ast_channel *chan, AGI *agi, int argc, char **argv)
++static int handle_speechrecognize(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
+ {
+ struct ast_speech *speech = agi->speech;
+- char *prompt, dtmf = 0, tmp[4096] = "", *buf = tmp;
++ const char *prompt;
++ char dtmf = 0, tmp[4096] = "", *buf = tmp;
+ int timeout = 0, offset = 0, old_read_format = 0, res = 0, i = 0;
+ long current_offset = 0;
+ const char *reason = NULL;
+@@ -2271,198 +2845,6 @@
+ return RESULT_SUCCESS;
+ }
+
+-static char usage_verbose[] =
+-" Usage: VERBOSE <message> <level>\n"
+-" Sends <message> to the console via verbose message system.\n"
+-" <level> is the the verbose level (1-4)\n"
+-" Always returns 1.\n";
+-
+-static char usage_setvariable[] =
+-" Usage: SET VARIABLE <variablename> <value>\n";
+-
+-static char usage_setcallerid[] =
+-" Usage: SET CALLERID <number>\n"
+-" Changes the callerid of the current channel.\n";
+-
+-static char usage_waitfordigit[] =
+-" Usage: WAIT FOR DIGIT <timeout>\n"
+-" Waits up to 'timeout' milliseconds for channel to receive a DTMF digit.\n"
+-" Returns -1 on channel failure, 0 if no digit is received in the timeout, or\n"
+-" the numerical value of the ascii of the digit if one is received. Use -1\n"
+-" for the timeout value if you desire the call to block indefinitely.\n";
+-
+-static char usage_sendtext[] =
+-" Usage: SEND TEXT \"<text to send>\"\n"
+-" Sends the given text on a channel. Most channels do not support the\n"
+-" transmission of text. Returns 0 if text is sent, or if the channel does not\n"
+-" support text transmission. Returns -1 only on error/hangup. Text\n"
+-" consisting of greater than one word should be placed in quotes since the\n"
+-" command only accepts a single argument.\n";
+-
+-static char usage_recvchar[] =
+-" Usage: RECEIVE CHAR <timeout>\n"
+-" Receives a character of text on a channel. Specify timeout to be the\n"
+-" maximum time to wait for input in milliseconds, or 0 for infinite. Most channels\n"
+-" do not support the reception of text. Returns the decimal value of the character\n"
+-" if one is received, or 0 if the channel does not support text reception. Returns\n"
+-" -1 only on error/hangup.\n";
+-
+-static char usage_recvtext[] =
+-" Usage: RECEIVE TEXT <timeout>\n"
+-" Receives a string of text on a channel. Specify timeout to be the\n"
+-" maximum time to wait for input in milliseconds, or 0 for infinite. Most channels\n"
+-" do not support the reception of text. Returns -1 for failure or 1 for success, and the string in parentheses.\n";
+-
+-static char usage_tddmode[] =
+-" Usage: TDD MODE <on|off>\n"
+-" Enable/Disable TDD transmission/reception on a channel. Returns 1 if\n"
+-" successful, or 0 if channel is not TDD-capable.\n";
+-
+-static char usage_sendimage[] =
+-" Usage: SEND IMAGE <image>\n"
+-" Sends the given image on a channel. Most channels do not support the\n"
+-" transmission of images. Returns 0 if image is sent, or if the channel does not\n"
+-" support image transmission. Returns -1 only on error/hangup. Image names\n"
+-" should not include extensions.\n";
+-
+-static char usage_streamfile[] =
+-" Usage: STREAM FILE <filename> <escape digits> [sample offset]\n"
+-" Send the given file, allowing playback to be interrupted by the given\n"
+-" digits, if any. Use double quotes for the digits if you wish none to be\n"
+-" permitted. If sample offset is provided then the audio will seek to sample\n"
+-" offset before play starts. Returns 0 if playback completes without a digit\n"
+-" being pressed, or the ASCII numerical value of the digit if one was pressed,\n"
+-" or -1 on error or if the channel was disconnected. Remember, the file\n"
+-" extension must not be included in the filename.\n";
+-
+-static char usage_controlstreamfile[] =
+-" Usage: CONTROL STREAM FILE <filename> <escape digits> [skipms] [ffchar] [rewchr] [pausechr]\n"
+-" Send the given file, allowing playback to be controled by the given\n"
+-" digits, if any. Use double quotes for the digits if you wish none to be\n"
+-" permitted. Returns 0 if playback completes without a digit\n"
+-" being pressed, or the ASCII numerical value of the digit if one was pressed,\n"
+-" or -1 on error or if the channel was disconnected. Remember, the file\n"
+-" extension must not be included in the filename.\n\n"
+-" Note: ffchar and rewchar default to * and # respectively.\n";
+-
+-static char usage_saynumber[] =
+-" Usage: SAY NUMBER <number> <escape digits> [gender]\n"
+-" Say a given number, returning early if any of the given DTMF digits\n"
+-" are received on the channel. Returns 0 if playback completes without a digit\n"
+-" being pressed, or the ASCII numerical value of the digit if one was pressed or\n"
+-" -1 on error/hangup.\n";
+-
+-static char usage_saydigits[] =
+-" Usage: SAY DIGITS <number> <escape digits>\n"
+-" Say a given digit string, returning early if any of the given DTMF digits\n"
+-" are received on the channel. Returns 0 if playback completes without a digit\n"
+-" being pressed, or the ASCII numerical value of the digit if one was pressed or\n"
+-" -1 on error/hangup.\n";
+-
+-static char usage_sayalpha[] =
+-" Usage: SAY ALPHA <number> <escape digits>\n"
+-" Say a given character string, returning early if any of the given DTMF digits\n"
+-" are received on the channel. Returns 0 if playback completes without a digit\n"
+-" being pressed, or the ASCII numerical value of the digit if one was pressed or\n"
+-" -1 on error/hangup.\n";
+-
+-static char usage_saydate[] =
+-" Usage: SAY DATE <date> <escape digits>\n"
+-" Say a given date, returning early if any of the given DTMF digits are\n"
+-" received on the channel. <date> is number of seconds elapsed since 00:00:00\n"
+-" on January 1, 1970, Coordinated Universal Time (UTC). Returns 0 if playback\n"
+-" completes without a digit being pressed, or the ASCII numerical value of the\n"
+-" digit if one was pressed or -1 on error/hangup.\n";
+-
+-static char usage_saytime[] =
+-" Usage: SAY TIME <time> <escape digits>\n"
+-" Say a given time, returning early if any of the given DTMF digits are\n"
+-" received on the channel. <time> is number of seconds elapsed since 00:00:00\n"
+-" on January 1, 1970, Coordinated Universal Time (UTC). Returns 0 if playback\n"
+-" completes without a digit being pressed, or the ASCII numerical value of the\n"
+-" digit if one was pressed or -1 on error/hangup.\n";
+-
+-static char usage_saydatetime[] =
+-" Usage: SAY DATETIME <time> <escape digits> [format] [timezone]\n"
+-" Say a given time, returning early if any of the given DTMF digits are\n"
+-" received on the channel. <time> is number of seconds elapsed since 00:00:00\n"
+-" on January 1, 1970, Coordinated Universal Time (UTC). [format] is the format\n"
+-" the time should be said in. See voicemail.conf (defaults to \"ABdY\n"
+-" 'digits/at' IMp\"). Acceptable values for [timezone] can be found in\n"
+-" /usr/share/zoneinfo. Defaults to machine default. Returns 0 if playback\n"
+-" completes without a digit being pressed, or the ASCII numerical value of the\n"
+-" digit if one was pressed or -1 on error/hangup.\n";
+-
+-static char usage_sayphonetic[] =
+-" Usage: SAY PHONETIC <string> <escape digits>\n"
+-" Say a given character string with phonetics, returning early if any of the\n"
+-" given DTMF digits are received on the channel. Returns 0 if playback\n"
+-" completes without a digit pressed, the ASCII numerical value of the digit\n"
+-" if one was pressed, or -1 on error/hangup.\n";
+-
+-static char usage_setcontext[] =
+-" Usage: SET CONTEXT <desired context>\n"
+-" Sets the context for continuation upon exiting the application.\n";
+-
+-static char usage_setextension[] =
+-" Usage: SET EXTENSION <new extension>\n"
+-" Changes the extension for continuation upon exiting the application.\n";
+-
+-static char usage_setpriority[] =
+-" Usage: SET PRIORITY <priority>\n"
+-" Changes the priority for continuation upon exiting the application.\n"
+-" The priority must be a valid priority or label.\n";
+-
+-static char usage_recordfile[] =
+-" Usage: RECORD FILE <filename> <format> <escape digits> <timeout> \\\n"
+-" [offset samples] [BEEP] [s=silence]\n"
+-" Record to a file until a given dtmf digit in the sequence is received\n"
+-" Returns -1 on hangup or error. The format will specify what kind of file\n"
+-" will be recorded. The timeout is the maximum record time in milliseconds, or\n"
+-" -1 for no timeout. \"Offset samples\" is optional, and, if provided, will seek\n"
+-" to the offset without exceeding the end of the file. \"silence\" is the number\n"
+-" of seconds of silence allowed before the function returns despite the\n"
+-" lack of dtmf digits or reaching timeout. Silence value must be\n"
+-" preceeded by \"s=\" and is also optional.\n";
+-
+-static char usage_autohangup[] =
+-" Usage: SET AUTOHANGUP <time>\n"
+-" Cause the channel to automatically hangup at <time> seconds in the\n"
+-" future. Of course it can be hungup before then as well. Setting to 0 will\n"
+-" cause the autohangup feature to be disabled on this channel.\n";
+-
+-static char usage_speechcreate[] =
+-" Usage: SPEECH CREATE <engine>\n"
+-" Create a speech object to be used by the other Speech AGI commands.\n";
+-
+-static char usage_speechset[] =
+-" Usage: SPEECH SET <name> <value>\n"
+-" Set an engine-specific setting.\n";
+-
+-static char usage_speechdestroy[] =
+-" Usage: SPEECH DESTROY\n"
+-" Destroy the speech object created by SPEECH CREATE.\n";
+-
+-static char usage_speechloadgrammar[] =
+-" Usage: SPEECH LOAD GRAMMAR <grammar name> <path to grammar>\n"
+-" Loads the specified grammar as the specified name.\n";
+-
+-static char usage_speechunloadgrammar[] =
+-" Usage: SPEECH UNLOAD GRAMMAR <grammar name>\n"
+-" Unloads the specified grammar.\n";
+-
+-static char usage_speechactivategrammar[] =
+-" Usage: SPEECH ACTIVATE GRAMMAR <grammar name>\n"
+-" Activates the specified grammar on the speech object.\n";
+-
+-static char usage_speechdeactivategrammar[] =
+-" Usage: SPEECH DEACTIVATE GRAMMAR <grammar name>\n"
+-" Deactivates the specified grammar on the speech object.\n";
+-
+-static char usage_speechrecognize[] =
+-" Usage: SPEECH RECOGNIZE <prompt> <timeout> [<offset>]\n"
+-" Plays back given prompt while listening for speech and dtmf.\n";
+-
+ /*!
+ * \brief AGI commands list
+ */
+@@ -2481,43 +2863,43 @@
+ { { "get", "variable", NULL }, handle_getvariable, NULL, NULL, 1 },
+ { { "hangup", NULL }, handle_hangup, NULL, NULL, 0 },
+ { { "noop", NULL }, handle_noop, NULL, NULL, 1 },
+- { { "receive", "char", NULL }, handle_recvchar, "Receives one character from channels supporting it", usage_recvchar , 0 },
+- { { "receive", "text", NULL }, handle_recvtext, "Receives text from channels supporting it", usage_recvtext , 0 },
+- { { "record", "file", NULL }, handle_recordfile, "Records to a given file", usage_recordfile , 0 },
+- { { "say", "alpha", NULL }, handle_sayalpha, "Says a given character string", usage_sayalpha , 0 },
+- { { "say", "digits", NULL }, handle_saydigits, "Says a given digit string", usage_saydigits , 0 },
+- { { "say", "number", NULL }, handle_saynumber, "Says a given number", usage_saynumber , 0 },
+- { { "say", "phonetic", NULL }, handle_sayphonetic, "Says a given character string with phonetics", usage_sayphonetic , 0 },
+- { { "say", "date", NULL }, handle_saydate, "Says a given date", usage_saydate , 0 },
+- { { "say", "time", NULL }, handle_saytime, "Says a given time", usage_saytime , 0 },
+- { { "say", "datetime", NULL }, handle_saydatetime, "Says a given time as specfied by the format given", usage_saydatetime , 0 },
+- { { "send", "image", NULL }, handle_sendimage, "Sends images to channels supporting it", usage_sendimage , 0 },
+- { { "send", "text", NULL }, handle_sendtext, "Sends text to channels supporting it", usage_sendtext , 0 },
+- { { "set", "autohangup", NULL }, handle_autohangup, "Autohangup channel in some time", usage_autohangup , 0 },
+- { { "set", "callerid", NULL }, handle_setcallerid, "Sets callerid for the current channel", usage_setcallerid , 0 },
+- { { "set", "context", NULL }, handle_setcontext, "Sets channel context", usage_setcontext , 0 },
+- { { "set", "extension", NULL }, handle_setextension, "Changes channel extension", usage_setextension , 0 },
++ { { "receive", "char", NULL }, handle_recvchar, NULL, NULL, 0 },
++ { { "receive", "text", NULL }, handle_recvtext, NULL, NULL, 0 },
++ { { "record", "file", NULL }, handle_recordfile, NULL, NULL, 0 },
++ { { "say", "alpha", NULL }, handle_sayalpha, NULL, NULL, 0},
++ { { "say", "digits", NULL }, handle_saydigits, NULL, NULL, 0 },
++ { { "say", "number", NULL }, handle_saynumber, NULL, NULL, 0 },
++ { { "say", "phonetic", NULL }, handle_sayphonetic, NULL, NULL, 0},
++ { { "say", "date", NULL }, handle_saydate, NULL, NULL, 0},
++ { { "say", "time", NULL }, handle_saytime, NULL, NULL, 0},
++ { { "say", "datetime", NULL }, handle_saydatetime, NULL, NULL, 0},
++ { { "send", "image", NULL }, handle_sendimage, NULL, NULL, 0},
++ { { "send", "text", NULL }, handle_sendtext, NULL, NULL, 0},
++ { { "set", "autohangup", NULL }, handle_autohangup, NULL, NULL, 0},
++ { { "set", "callerid", NULL }, handle_setcallerid, NULL, NULL, 0},
++ { { "set", "context", NULL }, handle_setcontext, NULL, NULL, 0},
++ { { "set", "extension", NULL }, handle_setextension, NULL, NULL, 0},
+ { { "set", "music", NULL }, handle_setmusic, NULL, NULL, 0 },
+- { { "set", "priority", NULL }, handle_setpriority, "Set channel dialplan priority", usage_setpriority , 0 },
+- { { "set", "variable", NULL }, handle_setvariable, "Sets a channel variable", usage_setvariable , 1 },
+- { { "stream", "file", NULL }, handle_streamfile, "Sends audio file on channel", usage_streamfile , 0 },
+- { { "control", "stream", "file", NULL }, handle_controlstreamfile, "Sends audio file on channel and allows the listner to control the stream", usage_controlstreamfile , 0 },
+- { { "tdd", "mode", NULL }, handle_tddmode, "Toggles TDD mode (for the deaf)", usage_tddmode , 0 },
+- { { "verbose", NULL }, handle_verbose, "Logs a message to the asterisk verbose log", usage_verbose , 1 },
+- { { "wait", "for", "digit", NULL }, handle_waitfordigit, "Waits for a digit to be pressed", usage_waitfordigit , 0 },
+- { { "speech", "create", NULL }, handle_speechcreate, "Creates a speech object", usage_speechcreate, 0 },
+- { { "speech", "set", NULL }, handle_speechset, "Sets a speech engine setting", usage_speechset, 0 },
+- { { "speech", "destroy", NULL }, handle_speechdestroy, "Destroys a speech object", usage_speechdestroy, 1 },
+- { { "speech", "load", "grammar", NULL }, handle_speechloadgrammar, "Loads a grammar", usage_speechloadgrammar, 0 },
+- { { "speech", "unload", "grammar", NULL }, handle_speechunloadgrammar, "Unloads a grammar", usage_speechunloadgrammar, 1 },
+- { { "speech", "activate", "grammar", NULL }, handle_speechactivategrammar, "Activates a grammar", usage_speechactivategrammar, 0 },
+- { { "speech", "deactivate", "grammar", NULL }, handle_speechdeactivategrammar, "Deactivates a grammar", usage_speechdeactivategrammar, 0 },
+- { { "speech", "recognize", NULL }, handle_speechrecognize, "Recognizes speech", usage_speechrecognize, 0 },
++ { { "set", "priority", NULL }, handle_setpriority, NULL, NULL, 0 },
++ { { "set", "variable", NULL }, handle_setvariable, NULL, NULL, 1 },
++ { { "stream", "file", NULL }, handle_streamfile, NULL, NULL, 0 },
++ { { "control", "stream", "file", NULL }, handle_controlstreamfile, NULL, NULL, 0 },
++ { { "tdd", "mode", NULL }, handle_tddmode, NULL, NULL, 0 },
++ { { "verbose", NULL }, handle_verbose, NULL, NULL, 1 },
++ { { "wait", "for", "digit", NULL }, handle_waitfordigit, NULL, NULL, 0 },
++ { { "speech", "create", NULL }, handle_speechcreate, NULL, NULL, 0 },
++ { { "speech", "set", NULL }, handle_speechset, NULL, NULL, 0 },
++ { { "speech", "destroy", NULL }, handle_speechdestroy, NULL, NULL, 1 },
++ { { "speech", "load", "grammar", NULL }, handle_speechloadgrammar, NULL, NULL, 0 },
++ { { "speech", "unload", "grammar", NULL }, handle_speechunloadgrammar, NULL, NULL, 1 },
++ { { "speech", "activate", "grammar", NULL }, handle_speechactivategrammar, NULL, NULL, 0 },
++ { { "speech", "deactivate", "grammar", NULL }, handle_speechdeactivategrammar, NULL, NULL, 0 },
++ { { "speech", "recognize", NULL }, handle_speechrecognize, NULL, NULL, 0 },
+ };
+
+ static AST_RWLIST_HEAD_STATIC(agi_commands, agi_command);
+
+-static char *help_workhorse(int fd, char *match[])
++static char *help_workhorse(int fd, const char * const match[])
+ {
+ char fullcmd[MAX_CMD_LEN], matchstr[MAX_CMD_LEN];
+ struct agi_command *e;
+@@ -2543,21 +2925,21 @@
+ return CLI_SUCCESS;
+ }
+
+-int ast_agi_register(struct ast_module *mod, agi_command *cmd)
++int AST_OPTIONAL_API_NAME(ast_agi_register)(struct ast_module *mod, agi_command *cmd)
+ {
+ char fullcmd[MAX_CMD_LEN];
+
+ ast_join(fullcmd, sizeof(fullcmd), cmd->cmda);
+
+- if (!find_command(cmd->cmda,1)) {
+- cmd->docsrc = AST_STATIC_DOC;
++ if (!find_command(cmd->cmda, 1)) {
+ #ifdef AST_XML_DOCS
++ *((enum ast_doc_src *) &cmd->docsrc) = AST_STATIC_DOC;
+ if (ast_strlen_zero(cmd->summary) && ast_strlen_zero(cmd->usage)) {
+- cmd->summary = ast_xmldoc_build_synopsis("agi", fullcmd);
+- cmd->usage = ast_xmldoc_build_description("agi", fullcmd);
+- cmd->syntax = ast_xmldoc_build_syntax("agi", fullcmd);
+- cmd->seealso = ast_xmldoc_build_seealso("agi", fullcmd);
+- cmd->docsrc = AST_XML_DOC;
++ *((char **) &cmd->summary) = ast_xmldoc_build_synopsis("agi", fullcmd);
++ *((char **) &cmd->usage) = ast_xmldoc_build_description("agi", fullcmd);
++ *((char **) &cmd->syntax) = ast_xmldoc_build_syntax("agi", fullcmd);
++ *((char **) &cmd->seealso) = ast_xmldoc_build_seealso("agi", fullcmd);
++ *((enum ast_doc_src *) &cmd->docsrc) = AST_XML_DOC;
+ }
+ #endif
+ cmd->mod = mod;
+@@ -2574,7 +2956,7 @@
+ }
+ }
+
+-int ast_agi_unregister(struct ast_module *mod, agi_command *cmd)
++int AST_OPTIONAL_API_NAME(ast_agi_unregister)(struct ast_module *mod, agi_command *cmd)
+ {
+ struct agi_command *e;
+ int unregistered = 0;
+@@ -2590,12 +2972,14 @@
+ ast_module_unref(ast_module_info->self);
+ #ifdef AST_XML_DOCS
+ if (e->docsrc == AST_XML_DOC) {
+- ast_free(e->summary);
+- ast_free(e->usage);
+- ast_free(e->syntax);
+- ast_free(e->seealso);
+- e->summary = NULL, e->usage = NULL;
+- e->syntax = NULL, e->seealso = NULL;
++ ast_free((char *) e->summary);
++ ast_free((char *) e->usage);
++ ast_free((char *) e->syntax);
++ ast_free((char *) e->seealso);
++ *((char **) &e->summary) = NULL;
++ *((char **) &e->usage) = NULL;
++ *((char **) &e->syntax) = NULL;
++ *((char **) &e->seealso) = NULL;
+ }
+ #endif
+ unregistered=1;
+@@ -2611,7 +2995,7 @@
+ return unregistered;
+ }
+
+-int ast_agi_register_multiple(struct ast_module *mod, struct agi_command *cmd, unsigned int len)
++int AST_OPTIONAL_API_NAME(ast_agi_register_multiple)(struct ast_module *mod, struct agi_command *cmd, unsigned int len)
+ {
+ unsigned int i, x = 0;
+
+@@ -2641,7 +3025,7 @@
+ return 0;
+ }
+
+-int ast_agi_unregister_multiple(struct ast_module *mod, struct agi_command *cmd, unsigned int len)
++int AST_OPTIONAL_API_NAME(ast_agi_unregister_multiple)(struct ast_module *mod, struct agi_command *cmd, unsigned int len)
+ {
+ unsigned int i;
+ int res = 0;
+@@ -2657,7 +3041,7 @@
+ return res;
+ }
+
+-static agi_command *find_command(char *cmds[], int exact)
++static agi_command *find_command(const char * const cmds[], int exact)
+ {
+ int y, match;
+ struct agi_command *e;
+@@ -2695,7 +3079,7 @@
+ return NULL;
+ }
+
+-static int parse_args(char *s, int *max, char *argv[])
++static int parse_args(char *s, int *max, const char *argv[])
+ {
+ int x = 0, quoted = 0, escaped = 0, whitespace = 1;
+ char *cur;
+@@ -2760,7 +3144,7 @@
+
+ static int agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf, int dead)
+ {
+- char *argv[MAX_ARGS];
++ const char *argv[MAX_ARGS];
+ int argc = MAX_ARGS, res;
+ agi_command *c;
+ const char *ami_res = "Unknown Result";
+@@ -3107,7 +3491,7 @@
+ return;
+ }
+
+-static int write_htmldump(char *filename)
++static int write_htmldump(const char *filename)
+ {
+ struct agi_command *command;
+ char fullcmd[MAX_CMD_LEN];
+@@ -3138,9 +3522,9 @@
+ fprintf(htmlfile, "<TR><TH ALIGN=\"CENTER\"><B>%s - %s</B></TH></TR>\n", fullcmd, command->summary);
+ #ifdef AST_XML_DOCS
+ stringptmp = ast_xmldoc_printable(command->usage, 0);
+- stringp = stringptmp;
++ stringp = ast_strdup(stringptmp);
+ #else
+- stringp = command->usage;
++ stringp = ast_strdup(command->usage);
+ #endif
+ tempstr = strsep(&stringp, "\n");
+
+@@ -3155,6 +3539,7 @@
+ }
+ fprintf(htmlfile, "</TD></TR>\n");
+ fprintf(htmlfile, "</TABLE></TD></TR>\n\n");
++ ast_free(stringp);
+ #ifdef AST_XML_DOCS
+ ast_free(stringptmp);
+ #endif
+@@ -3189,10 +3574,10 @@
+ return CLI_SUCCESS;
+ }
+
+-static int agi_exec_full(struct ast_channel *chan, void *data, int enhanced, int dead)
++static int agi_exec_full(struct ast_channel *chan, const char *data, int enhanced, int dead)
+ {
+ enum agi_result res;
+- char buf[AGI_BUF_LEN] = "", *tmp = buf;
++ char *buf;
+ int fds[2], efd = -1, pid;
+ AST_DECLARE_APP_ARGS(args,
+ AST_APP_ARG(arg)[MAX_ARGS];
+@@ -3205,9 +3590,9 @@
+ }
+ if (dead)
+ ast_debug(3, "Hungup channel detected, running agi in dead mode.\n");
+- ast_copy_string(buf, data, sizeof(buf));
+ memset(&agi, 0, sizeof(agi));
+- AST_STANDARD_APP_ARGS(args, tmp);
++ buf = ast_strdupa(data);
++ AST_STANDARD_APP_ARGS(args, buf);
+ args.argv[args.argc] = NULL;
+ #if 0
+ /* Answer if need be */
+@@ -3256,7 +3641,7 @@
+ return 0;
+ }
+
+-static int agi_exec(struct ast_channel *chan, void *data)
++static int agi_exec(struct ast_channel *chan, const char *data)
+ {
+ if (!ast_check_hangup(chan))
+ return agi_exec_full(chan, data, 0, 0);
+@@ -3264,7 +3649,7 @@
+ return agi_exec_full(chan, data, 0, 1);
+ }
+
+-static int eagi_exec(struct ast_channel *chan, void *data)
++static int eagi_exec(struct ast_channel *chan, const char *data)
+ {
+ int readformat, res;
+
+@@ -3286,7 +3671,7 @@
+ return res;
+ }
+
+-static int deadagi_exec(struct ast_channel *chan, void *data)
++static int deadagi_exec(struct ast_channel *chan, const char *data)
+ {
+ ast_log(LOG_WARNING, "DeadAGI has been deprecated, please use AGI in all cases!\n");
+ return agi_exec(chan, data);
+@@ -3319,10 +3704,10 @@
+ no other commands have been registered yet
+ */
+ (void) ast_agi_register_multiple(ast_module_info->self, commands, ARRAY_LEN(commands));
+- ast_register_application(deadapp, deadagi_exec, deadsynopsis, descrip);
+- ast_register_application(eapp, eagi_exec, esynopsis, descrip);
+- ast_manager_register2("AGI", EVENT_FLAG_AGI, action_add_agi_cmd, "Add an AGI command to execute by Async AGI", mandescr_asyncagi);
+- return ast_register_application(app, agi_exec, synopsis, descrip);
++ ast_register_application_xml(deadapp, deadagi_exec);
++ ast_register_application_xml(eapp, eagi_exec);
++ ast_manager_register_xml("AGI", EVENT_FLAG_AGI, action_add_agi_cmd);
++ return ast_register_application_xml(app, agi_exec);
+ }
+
+ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Asterisk Gateway Interface (AGI)",
+Index: res/res_adsi.exports
+===================================================================
+--- a/res/res_adsi.exports (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/res/res_adsi.exports (.../trunk) (revision 202568)
+@@ -0,0 +1,33 @@
++{
++ global:
++ ast_adsi_available;
++ ast_adsi_begin_download;
++ ast_adsi_channel_restore;
++ ast_adsi_clear_screen;
++ ast_adsi_clear_soft_keys;
++ ast_adsi_connect_session;
++ ast_adsi_data_mode;
++ ast_adsi_disconnect_session;
++ ast_adsi_display;
++ ast_adsi_download_connect;
++ ast_adsi_download_disconnect;
++ ast_adsi_end_download;
++ ast_adsi_get_cpeid;
++ ast_adsi_get_cpeinfo;
++ ast_adsi_input_control;
++ ast_adsi_input_format;
++ ast_adsi_load_session;
++ ast_adsi_load_soft_key;
++ ast_adsi_print;
++ ast_adsi_query_cpeid;
++ ast_adsi_query_cpeinfo;
++ ast_adsi_read_encoded_dtmf;
++ ast_adsi_set_keys;
++ ast_adsi_set_line;
++ ast_adsi_transmit_message;
++ ast_adsi_transmit_message_full;
++ ast_adsi_unload_session;
++ ast_adsi_voice_mode;
++ local:
++ *;
++};
+
+Property changes on: res/res_adsi.exports
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+
+Index: res/res_config_ldap.c
+===================================================================
+--- a/res/res_config_ldap.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/res/res_config_ldap.c (.../trunk) (revision 202568)
+@@ -1271,10 +1271,8 @@
+ ldap_err2string(result));
+
+ ast_mutex_unlock(&ldap_lock);
+- if (filter)
+- free(filter);
+- if (clean_basedn)
+- free(clean_basedn);
++ free(filter);
++ free(clean_basedn);
+ ldap_msgfree(ldap_result_msg);
+ ldap_mods_free(ldap_mods, 0);
+ return -1;
+@@ -1297,10 +1295,8 @@
+ }
+
+ ast_mutex_unlock(&ldap_lock);
+- if (filter)
+- free(filter);
+- if (clean_basedn)
+- free(clean_basedn);
++ free(filter);
++ free(clean_basedn);
+ ldap_msgfree(ldap_result_msg);
+ ldap_mods_free(ldap_mods, 0);
+ return num_entries;
+@@ -1458,10 +1454,8 @@
+ ldap_err2string(result));
+
+ ast_mutex_unlock(&ldap_lock);
+- if (filter)
+- free(filter);
+- if (clean_basedn)
+- free(clean_basedn);
++ free(filter);
++ free(clean_basedn);
+ ldap_msgfree(ldap_result_msg);
+ ldap_mods_free(ldap_mods, 0);
+ return -1;
+@@ -1758,7 +1752,7 @@
+ return CLI_SUCCESS;
+ }
+
+-AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "LDAP realtime interface",
++AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "LDAP realtime interface",
+ .load = load_module,
+ .unload = unload_module,
+ .reload = reload,
+Index: res/ael/ael_lex.c
+===================================================================
+--- a/res/ael/ael_lex.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/res/ael/ael_lex.c (.../trunk) (revision 202568)
+@@ -3221,8 +3221,7 @@
+
+ void ael_yyfree(void *ptr, yyscan_t yyscanner)
+ {
+- if (ptr)
+- free( (char*) ptr );
++ free( (char*) ptr );
+ }
+
+ static int pbcpop(char x)
+@@ -3361,8 +3360,7 @@
+ *errors = 1;
+ return 0;
+ }
+- if (my_file)
+- free(my_file);
++ free(my_file);
+ my_file = strdup(filename);
+ stat(filename, &stats);
+ buffer = (char*)malloc(stats.st_size+2);
+Index: res/res_odbc.c
+===================================================================
+--- a/res/res_odbc.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/res/res_odbc.c (.../trunk) (revision 202568)
+@@ -133,7 +133,7 @@
+ struct ao2_container *obj_container;
+ };
+
+-struct ao2_container *class_container;
++static struct ao2_container *class_container;
+
+ static AST_RWLIST_HEAD_STATIC(odbc_tables, odbc_cache_tables);
+
+@@ -1045,7 +1045,7 @@
+ return obj->parent->backslash_is_escape;
+ }
+
+-static int commit_exec(struct ast_channel *chan, void *data)
++static int commit_exec(struct ast_channel *chan, const char *data)
+ {
+ struct odbc_txn_frame *tx;
+ SQLINTEGER nativeerror=0, numfields=0;
+@@ -1082,7 +1082,7 @@
+ return 0;
+ }
+
+-static int rollback_exec(struct ast_channel *chan, void *data)
++static int rollback_exec(struct ast_channel *chan, const char *data)
+ {
+ struct odbc_txn_frame *tx;
+ SQLINTEGER nativeerror=0, numfields=0;
+@@ -1594,8 +1594,8 @@
+ .write = acf_transaction_write,
+ };
+
+-static const char *app_commit = "ODBC_Commit";
+-static const char *app_rollback = "ODBC_Rollback";
++static const char * const app_commit = "ODBC_Commit";
++static const char * const app_rollback = "ODBC_Rollback";
+
+ static int reload(void)
+ {
+Index: res/res_calendar.c
+===================================================================
+--- a/res/res_calendar.c (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/res/res_calendar.c (.../trunk) (revision 202568)
+@@ -0,0 +1,1607 @@
++/*
++ * Asterisk -- An open source telephony toolkit.
++ *
++ * Copyright (C) 2008 - 2009, Digium, Inc.
++ *
++ * Terry Wilson <twilson@digium.com>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * 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.
++ */
++
++/*! \file
++ * \brief Calendaring API
++ *
++ * \todo Support responding to a meeting invite
++ * \todo Support writing attendees
++ */
++
++#include "asterisk.h"
++
++ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
++
++#include "asterisk/_private.h"
++#include "asterisk/calendar.h"
++#include "asterisk/utils.h"
++#include "asterisk/astobj2.h"
++#include "asterisk/module.h"
++#include "asterisk/config.h"
++#include "asterisk/channel.h"
++#include "asterisk/devicestate.h"
++#include "asterisk/linkedlists.h"
++#include "asterisk/sched.h"
++#include "asterisk/dial.h"
++#include "asterisk/cli.h"
++#include "asterisk/pbx.h"
++#include "asterisk/app.h"
++
++/*** DOCUMENTATION
++ <function name="CALENDAR_BUSY" language="en_US">
++ <synopsis>
++ Determine if the calendar is marked busy at this time.
++ </synopsis>
++ <syntax>
++ <parameter name="calendar" required="true" />
++ </syntax>
++ <description>
++ <para>Check the specified calendar's current busy status.</para>
++ </description>
++ </function>
++ <function name="CALENDAR_EVENT" language="en_US">
++ <synopsis>
++ Get calendar event notification data from a notification call.
++ </synopsis>
++ <syntax>
++ <parameter name="field" required="true">
++ <enumlist>
++ <enum name="summary"><para>The VEVENT SUMMARY property or Exchange event 'subject'</para></enum>
++ <enum name="description"><para>The text description of the event</para></enum>
++ <enum name="organizer"><para>The organizer of the event</para></enum>
++ <enum name="location"><para>The location of the eventt</para></enum>
++ <enum name="calendar"><para>The name of the calendar associated with the event</para></enum>
++ <enum name="uid"><para>The unique identifier for this event</para></enum>
++ <enum name="start"><para>The start time of the event</para></enum>
++ <enum name="end"><para>The end time of the event</para></enum>
++ <enum name="busystate"><para>The busy state of the event 0=FREE, 1=TENTATIVE, 2=BUSY</para></enum>
++ </enumlist>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Whenever a calendar event notification call is made, the event data
++ may be accessed with this function.</para>
++ </description>
++ </function>
++ <function name="CALENDAR_QUERY" language="en_US">
++ <synopsis>Query a calendar server and store the data on a channel
++ </synopsis>
++ <syntax>
++ <parameter name="calendar" required="true">
++ <para>The calendar that should be queried</para>
++ </parameter>
++ <parameter name="start" required="false">
++ <para>The start time of the query (in seconds since epoch)</para>
++ </parameter>
++ <parameter name="end" required="false">
++ <para>The end time of the query (in seconds since epoch)</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Get a list of events in the currently accessible timeframe of the <replaceable>calendar</replaceable>
++ The function returns the id for accessing the result with CALENDAR_QUERY_RESULT()</para>
++ </description>
++ </function>
++ <function name="CALENDAR_QUERY_RESULT" language="en_US">
++ <synopsis>
++ Retrieve data from a previously run CALENDAR_QUERY() call
++ </synopsis>
++ <syntax>
++ <parameter name="id" required="true">
++ <para>The query ID returned by <literal>CALENDAR_QUERY</literal></para>
++ </parameter>
++ <parameter name="field" required="true">
++ <enumlist>
++ <enum name="getnum"><para>number of events occurring during time range</para></enum>
++ <enum name="summary"><para>A summary of the event</para></enum>
++ <enum name="description"><para>The full event description</para></enum>
++ <enum name="organizer"><para>The event organizer</para></enum>
++ <enum name="location"><para>The event location</para></enum>
++ <enum name="calendar"><para>The name of the calendar associted with the event</para></enum>
++ <enum name="uid"><para>The unique identifier for the event</para></enum>
++ <enum name="start"><para>The start time of the event (in seconds since epoch)</para></enum>
++ <enum name="end"><para>The end time of the event (in seconds since epoch)</para></enum>
++ <enum name="busystate"><para>The busy status of the event 0=FREE, 1=TENTATIVE, 2=BUSY</para></enum>
++ </enumlist>
++ </parameter>
++ <parameter name="entry" required="false" default="1">
++ <para>Return data from a specific event returned by the query</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>After running CALENDAR_QUERY and getting a result <replaceable>id</replaceable>, calling
++ <literal>CALENDAR_QUERY</literal> with that <replaceable>id</replaceable> and a <replaceable>field</replaceable>
++ will return the data for that field. If multiple events matched the query, and <replaceable>entry</replaceable>
++ is provided, information from that event will be returned.</para>
++ </description>
++ </function>
++ <function name="CALENDAR_WRITE" language="en_US">
++ <synopsis>Write an event to a calendar</synopsis>
++ <syntax>
++ <parameter name="calendar" required="true">
++ <para>The calendar to write to</para>
++ </parameter>
++ <parameter name="field" multiple="true" required="true">
++ <enumlist>
++ <enum name="summary"><para>A summary of the event</para></enum>
++ <enum name="description"><para>The full event description</para></enum>
++ <enum name="organizer"><para>The event organizer</para></enum>
++ <enum name="location"><para>The event location</para></enum>
++ <enum name="uid"><para>The unique identifier for the event</para></enum>
++ <enum name="start"><para>The start time of the event (in seconds since epoch)</para></enum>
++ <enum name="end"><para>The end time of the event (in seconds since epoch)</para></enum>
++ <enum name="busystate"><para>The busy status of the event 0=FREE, 1=TENTATIVE, 2=BUSY</para></enum>
++ </enumlist>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Example: CALENDAR_WRITE(calendar,field1,field2,field3)=val1,val2,val3</para>
++ <para>The field and value arguments can easily be set/passed using the HASHKEYS() and HASH() functions</para>
++ </description>
++ </function>
++
++***/
++#define CALENDAR_BUCKETS 19
++
++static struct ao2_container *calendars;
++static struct sched_context *sched;
++static pthread_t refresh_thread = AST_PTHREADT_NULL;
++static ast_mutex_t refreshlock;
++static ast_cond_t refresh_condition;
++static ast_mutex_t reloadlock;
++
++static void event_notification_destroy(void *data);
++static void *event_notification_duplicate(void *data);
++static void eventlist_destroy(void *data);
++static void *eventlist_duplicate(void *data);
++
++static const struct ast_datastore_info event_notification_datastore = {
++ .type = "EventNotification",
++ .destroy = event_notification_destroy,
++ .duplicate = event_notification_duplicate,
++};
++
++static const struct ast_datastore_info eventlist_datastore_info = {
++ .type = "CalendarEventList",
++ .destroy = eventlist_destroy,
++ .duplicate = eventlist_duplicate,
++};
++
++struct evententry {
++ struct ast_calendar_event *event;
++ AST_LIST_ENTRY(evententry) list;
++};
++
++static AST_LIST_HEAD_STATIC(techs, ast_calendar_tech);
++AST_LIST_HEAD_NOLOCK(eventlist, evententry); /* define the type */
++
++struct ast_config *ast_calendar_config;
++
++static struct ast_calendar *unref_calendar(struct ast_calendar *cal)
++{
++ ao2_ref(cal, -1);
++ return NULL;
++}
++
++static int calendar_hash_fn(const void *obj, const int flags)
++{
++ const struct ast_calendar *cal = obj;
++ return ast_str_case_hash(cal->name);
++}
++
++static int calendar_cmp_fn(void *obj, void *arg, int flags)
++{
++ const struct ast_calendar *one = obj, *two = arg;
++ return !strcasecmp(one->name, two->name) ? CMP_MATCH | CMP_STOP: 0;
++}
++
++static struct ast_calendar *find_calendar(const char *name)
++{
++ struct ast_calendar tmp = {
++ .name = name,
++ };
++ return ao2_find(calendars, &tmp, OBJ_POINTER);
++}
++
++static int event_hash_fn(const void *obj, const int flags)
++{
++ const struct ast_calendar_event *event = obj;
++ return ast_str_hash(event->uid);
++}
++
++static int event_cmp_fn(void *obj, void *arg, int flags)
++{
++ const struct ast_calendar_event *one = obj, *two = arg;
++ return !strcmp(one->uid, two->uid) ? CMP_MATCH | CMP_STOP : 0;
++}
++
++static struct ast_calendar_event *find_event(struct ao2_container *events, const char *uid)
++{
++ struct ast_calendar_event tmp = {
++ .uid = uid,
++ };
++ return ao2_find(events, &tmp, OBJ_POINTER);
++}
++
++struct ast_calendar_event *ast_calendar_unref_event(struct ast_calendar_event *event)
++{
++ ao2_ref(event, -1);
++ return NULL;
++}
++
++static void calendar_destructor(void *obj)
++{
++ struct ast_calendar *cal = obj;
++
++ ast_debug(3, "Destroying calendar %s\n", cal->name);
++
++ ao2_lock(cal);
++ cal->unloading = 1;
++ ast_cond_signal(&cal->unload);
++ pthread_join(cal->thread, NULL);
++ if (cal->tech_pvt) {
++ cal->tech_pvt = cal->tech->unref_calendar(cal->tech_pvt);
++ }
++ ast_calendar_clear_events(cal);
++ ast_string_field_free_memory(cal);
++ ao2_ref(cal->events, -1);
++ ao2_unlock(cal);
++}
++
++static void eventlist_destructor(void *obj)
++{
++ struct eventlist *events = obj;
++ struct evententry *entry;
++
++ while ((entry = AST_LIST_REMOVE_HEAD(events, list))) {
++ ao2_ref(entry->event, -1);
++ ast_free(entry);
++ }
++}
++
++static int calendar_busy_callback(void *obj, void *arg, int flags)
++{
++ struct ast_calendar_event *event = obj;
++ int *is_busy = arg;
++ struct timeval tv = ast_tvnow();
++
++ if (tv.tv_sec >= event->start && tv.tv_sec <= event->end && event->busy_state > AST_CALENDAR_BS_FREE) {
++ *is_busy = 1;
++ return CMP_STOP;
++ }
++
++ return 0;
++}
++
++static int calendar_is_busy(struct ast_calendar *cal)
++{
++ int is_busy = 0;
++
++ ao2_callback(cal->events, OBJ_NODATA, calendar_busy_callback, &is_busy);
++
++ return is_busy;
++}
++
++static enum ast_device_state calendarstate(const char *data)
++{
++ struct ast_calendar *cal;
++
++ if (ast_strlen_zero(data) || (!(cal = find_calendar(data)))) {
++ return AST_DEVICE_INVALID;
++ }
++
++ if (cal->tech->is_busy) {
++ return cal->tech->is_busy(cal) ? AST_DEVICE_INUSE : AST_DEVICE_NOT_INUSE;
++ }
++
++ return calendar_is_busy(cal) ? AST_DEVICE_INUSE : AST_DEVICE_NOT_INUSE;
++}
++
++static struct ast_calendar *build_calendar(struct ast_config *cfg, const char *cat, const struct ast_calendar_tech *tech)
++{
++ struct ast_calendar *cal;
++ struct ast_variable *v;
++ int new_calendar = 0;
++
++ if (!(cal = find_calendar(cat))) {
++ new_calendar = 1;
++ if (!(cal = ao2_alloc(sizeof(*cal), calendar_destructor))) {
++ ast_log(LOG_ERROR, "Could not allocate calendar structure. Stopping.\n");
++ return NULL;
++ }
++
++ if (!(cal->events = ao2_container_alloc(CALENDAR_BUCKETS, event_hash_fn, event_cmp_fn))) {
++ ast_log(LOG_ERROR, "Could not allocate events container for %s\n", cat);
++ cal = unref_calendar(cal);
++ return NULL;
++ }
++
++ if (ast_string_field_init(cal, 32)) {
++ ast_log(LOG_ERROR, "Couldn't create string fields for %s\n", cat);
++ cal = unref_calendar(cal);
++ return NULL;
++ }
++ } else {
++ cal->pending_deletion = 0;
++ }
++
++ ast_string_field_set(cal, name, cat);
++ cal->tech = tech;
++
++ cal->refresh = 3600;
++ cal->timeframe = 60;
++
++ for (v = ast_variable_browse(cfg, cat); v; v = v->next) {
++ if (!strcasecmp(v->name, "autoreminder")) {
++ cal->autoreminder = atoi(v->value);
++ } else if (!strcasecmp(v->name, "channel")) {
++ ast_string_field_set(cal, notify_channel, v->value);
++ } else if (!strcasecmp(v->name, "context")) {
++ ast_string_field_set(cal, notify_context, v->value);
++ } else if (!strcasecmp(v->name, "extension")) {
++ ast_string_field_set(cal, notify_extension, v->value);
++ } else if (!strcasecmp(v->name, "waittime")) {
++ cal->notify_waittime = atoi(v->value);
++ } else if (!strcasecmp(v->name, "app")) {
++ ast_string_field_set(cal, notify_app, v->value);
++ } else if (!strcasecmp(v->name, "appdata")) {
++ ast_string_field_set(cal, notify_appdata, v->value);
++ } else if (!strcasecmp(v->name, "refresh")) {
++ cal->refresh = atoi(v->value);
++ } else if (!strcasecmp(v->name, "timeframe")) {
++ cal->timeframe = atoi(v->value);
++ }
++ }
++
++ if (new_calendar) {
++ cal->thread = AST_PTHREADT_NULL;
++ ast_cond_init(&cal->unload, NULL);
++ ao2_link(calendars, cal);
++ if (ast_pthread_create(&cal->thread, NULL, cal->tech->load_calendar, cal)) {
++ /* If we start failing to create threads, go ahead and return NULL
++ * and the tech module will be unregistered
++ */
++ ao2_unlink(calendars, cal);
++ cal = unref_calendar(cal);
++ }
++ }
++
++ return cal;
++}
++
++static int load_tech_calendars(struct ast_calendar_tech *tech)
++{
++ struct ast_calendar *cal;
++ const char *cat = NULL;
++ const char *val;
++
++ if (!ast_calendar_config) {
++ ast_log(LOG_WARNING, "Calendar support disabled, not loading %s calendar module\n", tech->type);
++ return -1;
++ }
++
++ while ((cat = ast_category_browse(ast_calendar_config, cat))) {
++ if (!strcasecmp(cat, "general")) {
++ continue;
++ }
++
++ if (!(val = ast_variable_retrieve(ast_calendar_config, cat, "type")) || strcasecmp(val, tech->type)) {
++ continue;
++ }
++
++ /* A serious error occurred loading calendars from this tech and it should be disabled */
++ if (!(cal = build_calendar(ast_calendar_config, cat, tech))) {
++ ast_calendar_unregister(tech);
++ return -1;
++ }
++
++ cal = unref_calendar(cal);
++ }
++
++ return 0;
++}
++
++int ast_calendar_register(struct ast_calendar_tech *tech)
++{
++ struct ast_calendar_tech *iter;
++
++ AST_LIST_LOCK(&techs);
++ AST_LIST_TRAVERSE(&techs, iter, list) {
++ if(!strcasecmp(tech->type, iter->type)) {
++ ast_log(LOG_WARNING, "Already have a handler for calendar type '%s'\n", tech->type);
++ AST_LIST_UNLOCK(&techs);
++ return -1;
++ }
++ }
++ AST_LIST_INSERT_HEAD(&techs, tech, list);
++ AST_LIST_UNLOCK(&techs);
++
++ ast_verb(2, "Registered calendar type '%s' (%s)\n", tech->type, tech->description);
++
++ return load_tech_calendars(tech);
++}
++
++static int match_caltech_cb(void *user_data, void *arg, int flags)
++{
++ struct ast_calendar *cal = user_data;
++ struct ast_calendar_tech *tech = arg;
++
++ if (cal->tech == tech) {
++ return CMP_MATCH;
++ }
++
++ return 0;
++}
++
++void ast_calendar_unregister(struct ast_calendar_tech *tech)
++{
++ struct ast_calendar_tech *iter;
++
++ AST_LIST_LOCK(&techs);
++ AST_LIST_TRAVERSE_SAFE_BEGIN(&techs, iter, list) {
++ if (iter != tech) {
++ continue;
++ }
++
++ ao2_callback(calendars, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, match_caltech_cb, tech);
++
++ AST_LIST_REMOVE_CURRENT(list);
++ ast_verb(2, "Unregistered calendar type '%s'\n", tech->type);
++ break;
++ }
++ AST_LIST_TRAVERSE_SAFE_END;
++ AST_LIST_UNLOCK(&techs);
++
++}
++
++static void calendar_event_destructor(void *obj)
++{
++ struct ast_calendar_event *event = obj;
++ struct ast_calendar_attendee *attendee;
++
++ ast_debug(3, "Destroying event for calendar '%s'\n", event->owner->name);
++ ast_string_field_free_memory(event);
++ while ((attendee = AST_LIST_REMOVE_HEAD(&event->attendees, next))) {
++ if (attendee->data) {
++ ast_free(attendee->data);
++ }
++ ast_free(attendee);
++ }
++}
++
++/* This is only called from ao2_callbacks that are going to unref the event for us,
++ * so we don't unref the event here. */
++static struct ast_calendar_event *destroy_event(struct ast_calendar_event *event)
++{
++ if (event->notify_sched > -1 && ast_sched_del(sched, event->notify_sched)) {
++ ast_debug(3, "Notification running, can't delete sched entry\n");
++ }
++ if (event->bs_start_sched > -1 && ast_sched_del(sched, event->bs_start_sched)) {
++ ast_debug(3, "Devicestate update (start) running, can't delete sched entry\n");
++ }
++ if (event->bs_end_sched > -1 && ast_sched_del(sched, event->bs_end_sched)) {
++ ast_debug(3, "Devicestate update (end) running, can't delete sched entry\n");
++ }
++
++ /* If an event is being deleted and we've fired an event changing the status at the beginning,
++ * but haven't hit the end event yet, go ahead and set the devicestate to the current busy status */
++ if (event->bs_start_sched < 0 && event->bs_end_sched >= 0) {
++ if (!calendar_is_busy(event->owner)) {
++ ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Calendar/%s", event->owner->name);
++ } else {
++ ast_devstate_changed(AST_DEVICE_BUSY, "Calendar/%s", event->owner->name);
++ }
++ }
++
++ return NULL;
++}
++
++static int clear_events_cb(void *user_data, void *arg, int flags)
++{
++ struct ast_calendar_event *event = user_data;
++
++ event = destroy_event(event);
++
++ return CMP_MATCH;
++}
++
++void ast_calendar_clear_events(struct ast_calendar *cal)
++{
++ ast_debug(3, "Clearing all events for calendar %s\n", cal->name);
++
++ ao2_callback(cal->events, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, clear_events_cb, NULL);
++}
++
++struct ast_calendar_event *ast_calendar_event_alloc(struct ast_calendar *cal)
++{
++ struct ast_calendar_event *event;
++ if (!(event = ao2_alloc(sizeof(*event), calendar_event_destructor))) {
++ return NULL;
++ }
++
++ if (ast_string_field_init(event, 32)) {
++ event = ast_calendar_unref_event(event);
++ return NULL;
++ }
++
++ event->owner = cal;
++ event->notify_sched = -1;
++ event->bs_start_sched = -1;
++ event->bs_end_sched = -1;
++
++ AST_LIST_HEAD_INIT_NOLOCK(&event->attendees);
++
++ return event;
++}
++
++struct ao2_container *ast_calendar_event_container_alloc(void)
++{
++ return ao2_container_alloc(CALENDAR_BUCKETS, event_hash_fn, event_cmp_fn);
++}
++
++static void event_notification_destroy(void *data)
++{
++ struct ast_calendar_event *event = data;
++
++ event = ast_calendar_unref_event(event);
++
++}
++
++static void *event_notification_duplicate(void *data)
++{
++ struct ast_calendar_event *event = data;
++
++ if (!event) {
++ return NULL;
++ }
++
++ ao2_ref(event, +1);
++
++ return event;
++}
++
++/*! \brief Generate 32 byte random string (stolen from chan_sip.c)*/
++static char *generate_random_string(char *buf, size_t size)
++{
++ long val[4];
++ int x;
++
++ for (x = 0; x < 4; x++) {
++ val[x] = ast_random();
++ }
++ snprintf(buf, size, "%08lx%08lx%08lx%08lx", val[0], val[1], val[2], val[3]);
++
++ return buf;
++}
++
++static int calendar_event_notify(const void *data)
++{
++ struct ast_calendar_event *event = (void *)data;
++ char tech[256], dest[256], buf[8], *tmp;
++ struct ast_dial *dial = NULL;
++ struct ast_channel *chan = NULL;
++ struct ast_str *apptext = NULL;
++ int res = -1;
++ char start[12], end[12], busystate[2];
++ struct ast_datastore *datastore;
++
++ if (!(event && event->owner)) {
++ ast_log(LOG_ERROR, "Extremely low-cal...in fact cal is NULL!\n");
++ goto notify_cleanup;
++ }
++
++ ao2_ref(event, +1);
++ event->notify_sched = -1;
++
++ ast_copy_string(tech, event->owner->notify_channel, sizeof(tech));
++
++ if ((tmp = strchr(tech, '/'))) {
++ *tmp = '\0';
++ tmp++;
++ ast_copy_string(dest, tmp, sizeof(dest));
++ } else {
++ ast_log(LOG_WARNING, "Channel should be in form Tech/Dest\n");
++ goto notify_cleanup;
++ }
++
++ if (!(dial = ast_dial_create())) {
++ ast_log(LOG_ERROR, "Could not create dial structure\n");
++ goto notify_cleanup;
++ }
++
++ if (ast_dial_append(dial, tech, dest) < 0) {
++ ast_log(LOG_ERROR, "Could not append channel\n");
++ goto notify_cleanup;
++ }
++
++ ast_dial_set_global_timeout(dial, event->owner->notify_waittime);
++ generate_random_string(buf, sizeof(buf));
++ if (!(chan = ast_channel_alloc(1, AST_STATE_DOWN, 0, 0, 0, 0, 0, 0, "Calendar/%s-%s", event->owner->name, buf))) {
++ ast_log(LOG_ERROR, "Could not allocate notification channel\n");
++ goto notify_cleanup;
++ }
++
++ snprintf(busystate, sizeof(busystate), "%d", event->busy_state);
++ snprintf(start, sizeof(start), "%lu", event->start);
++ snprintf(end, sizeof(end), "%lu", event->end);
++
++ chan->nativeformats = AST_FORMAT_SLINEAR;
++
++ if (!(datastore = ast_datastore_alloc(&event_notification_datastore, NULL))) {
++ ast_log(LOG_ERROR, "Could not allocate datastore, notification not being sent!\n");
++ goto notify_cleanup;
++ }
++
++ datastore->data = event;
++ datastore->inheritance = DATASTORE_INHERIT_FOREVER;
++
++ ao2_ref(event, +1);
++ res = ast_channel_datastore_add(chan, datastore);
++
++ if (!(apptext = ast_str_create(32))) {
++ goto notify_cleanup;
++ }
++
++ if (!ast_strlen_zero(event->owner->notify_app)) {
++ ast_str_set(&apptext, 0, "%s,%s", event->owner->notify_app, event->owner->notify_appdata);
++ } else {
++ ast_str_set(&apptext, 0, "Dial,Local/%s@%s", event->owner->notify_extension, event->owner->notify_context);
++ }
++ ast_dial_option_global_enable(dial, AST_DIAL_OPTION_ANSWER_EXEC, ast_str_buffer(apptext));
++
++ ast_dial_run(dial, chan, 1);
++ res = 0;
++
++notify_cleanup:
++ event = ast_calendar_unref_event(event);
++ if (res == -1 && dial) {
++ ast_dial_destroy(dial);
++ }
++ if (apptext) {
++ ast_free(apptext);
++ }
++ if (chan) {
++ ast_channel_release(chan);
++ }
++
++ return res;
++}
++
++static int calendar_devstate_change(const void *data)
++{
++ struct ast_calendar_event *event = (struct ast_calendar_event *)data;
++ struct timeval now = ast_tvnow();
++ int is_end_event;
++
++ if (!event) {
++ ast_log(LOG_WARNING, "Event was NULL!\n");
++ return 0;
++ }
++
++ ao2_ref(event, +1);
++
++ is_end_event = event->end <= now.tv_sec;
++
++ if (is_end_event) {
++ event->bs_end_sched = -1;
++ } else {
++ event->bs_start_sched = -1;
++ }
++
++ /* We can have overlapping events, so ignore the event->busy_state and check busy state
++ * based on all events in the calendar */
++ if (!calendar_is_busy(event->owner)) {
++ ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Calendar/%s", event->owner->name);
++ } else {
++ ast_devstate_changed(AST_DEVICE_BUSY, "Calendar/%s", event->owner->name);
++ }
++
++ event = ast_calendar_unref_event(event);
++
++ return 0;
++}
++
++static void copy_event_data(struct ast_calendar_event *dst, struct ast_calendar_event *src)
++{
++ struct ast_calendar_attendee *attendee;
++
++ ast_string_field_set(dst, summary, src->summary);
++ ast_string_field_set(dst, description, src->description);
++ ast_string_field_set(dst, organizer, src->organizer);
++ ast_string_field_set(dst, location, src->location);
++ ast_string_field_set(dst, uid, src->uid);
++ dst->owner = src->owner;
++ dst->start = src->start;
++ dst->end = src->end;
++ dst->alarm = src->alarm;
++ dst->busy_state = src->busy_state;
++
++ while ((attendee = AST_LIST_REMOVE_HEAD(&src->attendees, next))) {
++ AST_LIST_INSERT_TAIL(&dst->attendees, attendee, next);
++ }
++}
++
++static int schedule_calendar_event(struct ast_calendar *cal, struct ast_calendar_event *old_event, struct ast_calendar_event *cmp_event)
++{
++ struct timeval now = ast_tvnow();
++ struct ast_calendar_event *event;
++ time_t alarm_notify_sched = 0, devstate_sched_start, devstate_sched_end;
++ int changed = 0;
++
++ event = cmp_event ? cmp_event : old_event;
++
++ ao2_lock(event);
++ if (!cmp_event || old_event->alarm != event->alarm) {
++ changed = 1;
++ if (cal->autoreminder) {
++ alarm_notify_sched = (event->start - (60 * cal->autoreminder) - now.tv_sec) * 1000;
++ } else if (event->alarm) {
++ alarm_notify_sched = (event->alarm - now.tv_sec) * 1000;
++ }
++
++ /* For now, send the notification if we missed it, but the meeting hasn't happened yet */
++ if (event->start >= now.tv_sec) {
++ if (alarm_notify_sched <= 0) {
++ alarm_notify_sched = 1;
++ }
++ ast_mutex_lock(&refreshlock);
++ AST_SCHED_REPLACE(old_event->notify_sched, sched, alarm_notify_sched, calendar_event_notify, old_event);
++ ast_mutex_unlock(&refreshlock);
++ ast_debug(3, "Calendar alarm event notification scheduled to happen in %ld ms\n", alarm_notify_sched);
++ }
++ }
++
++ if (!cmp_event || old_event->start != event->start) {
++ changed = 1;
++ devstate_sched_start = (event->start - now.tv_sec) * 1000;
++
++ if (devstate_sched_start < 1) {
++ devstate_sched_start = 1;
++ }
++
++ ast_mutex_lock(&refreshlock);
++ AST_SCHED_REPLACE(old_event->bs_start_sched, sched, devstate_sched_start, calendar_devstate_change, old_event);
++ ast_mutex_unlock(&refreshlock);
++ ast_debug(3, "Calendar bs_start event notification scheduled to happen in %ld ms\n", devstate_sched_start);
++ }
++
++ if (!cmp_event || old_event->end != event->end) {
++ changed = 1;
++ devstate_sched_end = (event->end - now.tv_sec) * 1000;
++ ast_mutex_lock(&refreshlock);
++ AST_SCHED_REPLACE(old_event->bs_end_sched, sched, devstate_sched_end, calendar_devstate_change, old_event);
++ ast_mutex_unlock(&refreshlock);
++ ast_debug(3, "Calendar bs_end event notification scheduled to happen in %ld ms\n", devstate_sched_end);
++ }
++
++ if (changed) {
++ ast_cond_signal(&refresh_condition);
++ }
++
++ ao2_unlock(event);
++
++ return 0;
++}
++
++static int merge_events_cb(void *obj, void *arg, int flags)
++{
++ struct ast_calendar_event *old_event = obj, *new_event;
++ struct ao2_container *new_events = arg;
++
++ /* If we don't find the old_event in new_events, then we can safely delete the old_event */
++ if (!(new_event = find_event(new_events, old_event->uid))) {
++ old_event = destroy_event(old_event);
++ return CMP_MATCH;
++ }
++
++ /* We have events to merge. If any data that will affect a scheduler event has changed,
++ * then we need to replace the scheduler event */
++ schedule_calendar_event(old_event->owner, old_event, new_event);
++
++ /* Since we don't want to mess with cancelling sched events and adding new ones, just
++ * copy the internals of the new_event to the old_event */
++ copy_event_data(old_event, new_event);
++
++ /* Now we can go ahead and unlink the new_event from new_events and unref it so that only completely
++ * new events remain in the container */
++ ao2_unlink(new_events, new_event);
++ new_event = ast_calendar_unref_event(new_event);
++
++ return 0;
++}
++
++static int add_new_event_cb(void *obj, void *arg, int flags)
++{
++ struct ast_calendar_event *new_event = obj;
++ struct ao2_container *events = arg;
++
++ ao2_link(events, new_event);
++ schedule_calendar_event(new_event->owner, new_event, NULL);
++ return CMP_MATCH;
++}
++
++void ast_calendar_merge_events(struct ast_calendar *cal, struct ao2_container *new_events)
++{
++ /* Loop through all events attached to the calendar. If there is a matching new event
++ * merge its data over and handle any schedule changes that need to be made. Then remove
++ * the new_event from new_events so that we are left with only new_events that we can add later. */
++ ao2_callback(cal->events, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, merge_events_cb, new_events);
++
++ /* Now, we should only have completely new events in new_events. Loop through and add them */
++ ao2_callback(new_events, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, add_new_event_cb, cal->events);
++}
++
++
++static int load_config(void *data)
++{
++ struct ast_flags config_flags = { CONFIG_FLAG_FILEUNCHANGED };
++ struct ast_config *tmpcfg;
++
++ if (!(tmpcfg = ast_config_load2("calendar.conf", "calendar", config_flags)) ||
++ tmpcfg == CONFIG_STATUS_FILEINVALID) {
++ ast_log(LOG_ERROR, "Unable to load config calendar.conf\n");
++ return -1;
++ }
++
++ if (tmpcfg == CONFIG_STATUS_FILEUNCHANGED) {
++ return 0;
++ }
++
++ if (ast_calendar_config) {
++ ast_config_destroy(ast_calendar_config);
++ }
++
++ ast_calendar_config = tmpcfg;
++
++ return 0;
++}
++
++/*! \brief A dialplan function that can be used to determine the busy status of a calendar */
++static int calendar_busy_exec(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
++{
++ struct ast_calendar *cal;
++
++ if (ast_strlen_zero(data)) {
++ ast_log(LOG_WARNING, "CALENDAR_BUSY requires an argument: CALENDAR_BUSY(<calendar_name>)\n");
++ return -1;
++ }
++
++ cal = find_calendar(data);
++
++ if (!cal) {
++ ast_log(LOG_WARNING, "Could not find calendar '%s'\n", data);
++ return -1;
++ }
++
++ strcpy(buf, calendar_is_busy(cal) ? "1" : "0");
++
++ return 0;
++}
++
++static struct ast_custom_function calendar_busy_function = {
++ .name = "CALENDAR_BUSY",
++ .read = calendar_busy_exec,
++};
++
++static int add_event_to_list(struct eventlist *events, struct ast_calendar_event *event, time_t start, time_t end)
++{
++ struct evententry *entry, *iter;
++ int event_startdiff = abs(start - event->start);
++ int event_enddiff = abs(end - event->end);
++ int i = 0;
++
++ if (!(entry = ast_calloc(1, sizeof(*entry)))) {
++ ast_log(LOG_ERROR, "Unable to allocate memory for event list\n");
++ return -1;
++ }
++
++ entry->event = event;
++ ao2_ref(event, +1);
++
++ if (start == end) {
++ AST_LIST_TRAVERSE_SAFE_BEGIN(events, iter, list) {
++ int startdiff = abs(iter->event->start - start);
++
++ ast_debug(10, "Comparing %s with startdiff %d to %s with startdiff %d\n", event->summary, event_startdiff, iter->event->summary, startdiff);
++ ++i;
++ if (startdiff > event_startdiff) {
++ AST_LIST_INSERT_BEFORE_CURRENT(entry, list);
++ return i;
++ }
++ if (startdiff == event_startdiff) {
++ int enddiff = abs(iter->event->end - end);
++
++ if (enddiff > event_enddiff) {
++ AST_LIST_INSERT_BEFORE_CURRENT(entry, list);
++ return i;
++ }
++ if (event_startdiff == enddiff) {
++ if (strcmp(event->uid, iter->event->uid) < 0) {
++ AST_LIST_INSERT_BEFORE_CURRENT(entry, list);
++ return i;
++ }
++ }
++ }
++ }
++ AST_LIST_TRAVERSE_SAFE_END;
++
++ AST_LIST_INSERT_TAIL(events, entry, list);
++
++ return i;
++ }
++
++ AST_LIST_TRAVERSE_SAFE_BEGIN(events, iter, list) {
++ ++i;
++ if (iter->event->start > event->start) {
++ AST_LIST_INSERT_BEFORE_CURRENT(entry, list);
++ return i;
++ }
++
++ if (iter->event->start == event->start) {
++ if ((iter->event->end - iter->event->start) == (event->end - event->start)) {
++ if (strcmp(event->uid, iter->event->uid) < 0) {
++ AST_LIST_INSERT_BEFORE_CURRENT(entry, list);
++ return i;
++ }
++ }
++ if ((iter->event->end - iter->event->start) < (event->end - event->start)) {
++ AST_LIST_INSERT_BEFORE_CURRENT(entry, list);
++ return i;
++ }
++ }
++ }
++ AST_LIST_TRAVERSE_SAFE_END;
++
++ AST_LIST_INSERT_TAIL(events, entry, list);
++
++ return i;
++}
++
++static void eventlist_destroy(void *data)
++{
++ struct eventlist *events = data;
++
++ ao2_ref(events, -1);
++}
++
++static void *eventlist_duplicate(void *data)
++{
++ struct eventlist *events = data;
++
++ if (!events) {
++ return NULL;
++ }
++
++ ao2_ref(events, +1);
++
++ return events;
++}
++
++static int calendar_query_exec(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
++{
++ struct ast_calendar *cal;
++ struct ao2_iterator i;
++ struct ast_calendar_event *event;
++ struct eventlist *events;
++ time_t start = INT_MIN, end = INT_MAX;
++ struct ast_datastore *eventlist_datastore;
++ AST_DECLARE_APP_ARGS(args,
++ AST_APP_ARG(calendar);
++ AST_APP_ARG(start);
++ AST_APP_ARG(end);
++ );
++
++ if (!chan) {
++ ast_log(LOG_WARNING, "%s requires a channel to store the data on\n", cmd);
++ return -1;
++ }
++
++ AST_STANDARD_APP_ARGS(args, data);
++
++ if (ast_strlen_zero(args.calendar)) {
++ ast_log(LOG_WARNING, "%s requires a calendar argument\n", cmd);
++ return -1;
++ }
++
++ if (!(cal = find_calendar(args.calendar))) {
++ ast_log(LOG_WARNING, "Unknown calendar '%s'\n", args.calendar);
++ return -1;
++ }
++
++ if (!(events = ao2_alloc(sizeof(*events), eventlist_destructor))) {
++ ast_log(LOG_ERROR, "Unable to allocate memory for event list\n");
++ cal = unref_calendar(cal);
++ return -1;
++ }
++
++ if (!ast_strlen_zero(args.start)) {
++ start = atoi(args.start);
++ }
++
++ if (!ast_strlen_zero(args.end)) {
++ end = atoi(args.end);
++ }
++
++ i = ao2_iterator_init(cal->events, 0);
++ while ((event = ao2_iterator_next(&i))) {
++ if (!(start > event->end || end < event->start)) {
++ ast_debug(10, "%s (%ld - %ld) overlapped with (%ld - %ld)\n", event->summary, event->start, event->end, start, end);
++ if (add_event_to_list(events, event, start, end) < 0) {
++ event = ast_calendar_unref_event(event);
++ return -1;
++ }
++ }
++
++ event = ast_calendar_unref_event(event);
++ }
++
++ ast_channel_lock(chan);
++ do {
++ generate_random_string(buf, len);
++ } while (ast_channel_datastore_find(chan, &eventlist_datastore_info, buf));
++ ast_channel_unlock(chan);
++
++ if (!(eventlist_datastore = ast_datastore_alloc(&eventlist_datastore_info, buf))) {
++ ast_log(LOG_ERROR, "Could not allocate datastore!\n");
++ return -1;
++ }
++
++ eventlist_datastore->inheritance = DATASTORE_INHERIT_FOREVER;
++ eventlist_datastore->data = events;
++
++ ast_channel_lock(chan);
++ ast_channel_datastore_add(chan, eventlist_datastore);
++ ast_channel_unlock(chan);
++
++ return 0;
++}
++
++static struct ast_custom_function calendar_query_function = {
++ .name = "CALENDAR_QUERY",
++ .read = calendar_query_exec,
++};
++
++static void calendar_join_attendees(struct ast_calendar_event *event, char *buf, size_t len)
++{
++ struct ast_str *tmp;
++ struct ast_calendar_attendee *attendee;
++
++ if (!(tmp = ast_str_create(32))) {
++ ast_log(LOG_ERROR, "Could not allocate memory for attendees!\n");
++ return;
++ }
++
++ AST_LIST_TRAVERSE(&event->attendees, attendee, next) {
++ ast_str_append(&tmp, 0, "%s%s", attendee == AST_LIST_FIRST(&event->attendees) ? "" : ",", attendee->data);
++ }
++
++ ast_copy_string(buf, ast_str_buffer(tmp), len);
++ ast_free(tmp);
++}
++
++static int calendar_query_result_exec(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
++{
++ struct ast_datastore *datastore;
++ struct eventlist *events;
++ struct evententry *entry;
++ int row = 1;
++ AST_DECLARE_APP_ARGS(args,
++ AST_APP_ARG(id);
++ AST_APP_ARG(field);
++ AST_APP_ARG(row);
++ );
++
++ if (!chan) {
++ ast_log(LOG_WARNING, "%s requires a channel\n", cmd);
++ return -1;
++ }
++
++ AST_STANDARD_APP_ARGS(args, data);
++
++ if (ast_strlen_zero(args.id) || ast_strlen_zero(args.field)) {
++ ast_log(LOG_WARNING, "%s requires an id and a field", cmd);
++ return -1;
++ }
++
++ ast_channel_lock(chan);
++ if (!(datastore = ast_channel_datastore_find(chan, &eventlist_datastore_info, args.id))) {
++ ast_log(LOG_WARNING, "There is no event notification datastore with id '%s' on '%s'!\n", args.id, chan->name);
++ ast_channel_unlock(chan);
++ return -1;
++ }
++ ast_channel_unlock(chan);
++
++ if (!(events = datastore->data)) {
++ ast_log(LOG_WARNING, "The datastore contains no data!\n");
++ return -1;
++ }
++
++ if (!ast_strlen_zero(args.row)) {
++ row = atoi(args.row);
++ }
++
++ AST_LIST_TRAVERSE(events, entry, list) {
++ if (--row) {
++ continue;
++ }
++ if (!strcasecmp(args.field, "summary")) {
++ ast_copy_string(buf, entry->event->summary, len);
++ } else if (!strcasecmp(args.field, "description")) {
++ ast_copy_string(buf, entry->event->description, len);
++ } else if (!strcasecmp(args.field, "organizer")) {
++ ast_copy_string(buf, entry->event->organizer, len);
++ } else if (!strcasecmp(args.field, "location")) {
++ ast_copy_string(buf, entry->event->location, len);
++ } else if (!strcasecmp(args.field, "calendar")) {
++ ast_copy_string(buf, entry->event->owner->name, len);
++ } else if (!strcasecmp(args.field, "uid")) {
++ ast_copy_string(buf, entry->event->uid, len);
++ } else if (!strcasecmp(args.field, "start")) {
++ snprintf(buf, len, "%ld", entry->event->start);
++ } else if (!strcasecmp(args.field, "end")) {
++ snprintf(buf, len, "%ld", entry->event->end);
++ } else if (!strcasecmp(args.field, "busystate")) {
++ snprintf(buf, len, "%d", entry->event->busy_state);
++ } else if (!strcasecmp(args.field, "attendees")) {
++ calendar_join_attendees(entry->event, buf, len);
++ } else {
++ ast_log(LOG_WARNING, "Unknown field '%s'\n", args.field);
++ }
++ break;
++ }
++
++ return 0;
++}
++
++static struct ast_custom_function calendar_query_result_function = {
++ .name = "CALENDAR_QUERY_RESULT",
++ .read = calendar_query_result_exec,
++};
++
++static int calendar_write_exec(struct ast_channel *chan, const char *cmd, char *data, const char *value)
++{
++ int i, j, ret = -1;
++ char *val_dup = NULL;
++ struct ast_calendar *cal = NULL;
++ struct ast_calendar_event *event = NULL;
++ AST_DECLARE_APP_ARGS(fields,
++ AST_APP_ARG(field)[10];
++ );
++ AST_DECLARE_APP_ARGS(values,
++ AST_APP_ARG(value)[10];
++ );
++
++ if (!(val_dup = ast_strdup(value))) {
++ ast_log(LOG_ERROR, "Could not allocate memory for values\n");
++ return -1;
++ }
++
++ AST_STANDARD_APP_ARGS(fields, data);
++ AST_STANDARD_APP_ARGS(values, val_dup);
++
++ /* XXX Eventually we will support unnamed calendars, so if we don't find one, we parse
++ * for a calendar type and create it */
++ if (!(cal = find_calendar(fields.field[0]))) {
++ ast_log(LOG_WARNING, "Couldn't find calendar '%s'\n", fields.field[0]);
++ goto write_cleanup;
++ }
++
++ if (!(cal->tech->write_event)) {
++ ast_log(LOG_WARNING, "Calendar '%s' has no write function!\n", cal->name);
++ goto write_cleanup;
++ }
++
++ if (!(event = ast_calendar_event_alloc(cal))) {
++ goto write_cleanup;
++ }
++
++ if (ast_strlen_zero(fields.field[0])) {
++ ast_log(LOG_WARNING, "CALENDAR_WRITE requires a calendar name!\n");
++ goto write_cleanup;
++ }
++
++ if (fields.argc - 1 != values.argc) {
++ ast_log(LOG_WARNING, "CALENDAR_WRITE should have the same number of fields (%d) and values (%d)!\n", fields.argc - 1, values.argc);
++ goto write_cleanup;
++ }
++
++ event->owner = cal;
++
++ for (i = 1, j = 0; i < fields.argc; i++, j++) {
++ if (!strcasecmp(fields.field[i], "summary")) {
++ ast_string_field_set(event, summary, values.value[j]);
++ } else if (!strcasecmp(fields.field[i], "description")) {
++ ast_string_field_set(event, description, values.value[j]);
++ } else if (!strcasecmp(fields.field[i], "organizer")) {
++ ast_string_field_set(event, organizer, values.value[j]);
++ } else if (!strcasecmp(fields.field[i], "location")) {
++ ast_string_field_set(event, location, values.value[j]);
++ } else if (!strcasecmp(fields.field[i], "uid")) {
++ ast_string_field_set(event, uid, values.value[j]);
++ } else if (!strcasecmp(fields.field[i], "start")) {
++ event->start = atoi(values.value[j]);
++ } else if (!strcasecmp(fields.field[i], "end")) {
++ event->end = atoi(values.value[j]);
++ } else if (!strcasecmp(fields.field[i], "busystate")) {
++ event->busy_state = atoi(values.value[j]);
++ } else {
++ ast_log(LOG_WARNING, "Unknown calendar event field '%s'\n", fields.field[i]);
++ }
++ }
++
++ if((ret = cal->tech->write_event(event))) {
++ ast_log(LOG_WARNING, "Writing event to calendar '%s' failed!\n", cal->name);
++ }
++
++write_cleanup:
++ if (cal) {
++ cal = unref_calendar(cal);
++ }
++ if (event) {
++ event = ast_calendar_unref_event(event);
++ }
++ if (val_dup) {
++ ast_free(val_dup);
++ }
++
++ return ret;
++}
++
++static struct ast_custom_function calendar_write_function = {
++ .name = "CALENDAR_WRITE",
++ .write = calendar_write_exec,
++};
++
++/*! \brief CLI command to list available calendars */
++static char *handle_show_calendars(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
++{
++#define FORMAT "%-20.20s %-10.10s %-6.6s\n"
++ struct ao2_iterator i;
++ struct ast_calendar *cal;
++
++ switch(cmd) {
++ case CLI_INIT:
++ e->command = "calendar show calendars";
++ e->usage =
++ "Usage: calendar show calendars\n"
++ " Lists all registered calendars.\n";
++ return NULL;
++ case CLI_GENERATE:
++ return NULL;
++ }
++
++ ast_cli(a->fd, FORMAT, "Calendar", "Type", "Status");
++ ast_cli(a->fd, FORMAT, "--------", "----", "------");
++ i = ao2_iterator_init(calendars, 0);
++ while ((cal = ao2_iterator_next(&i))) {
++ ast_cli(a->fd, FORMAT, cal->name, cal->tech->type, calendar_is_busy(cal) ? "busy" : "free");
++ cal = unref_calendar(cal);
++ }
++
++ return CLI_SUCCESS;
++#undef FORMAT
++}
++
++static char *epoch_to_string(char *buf, size_t buflen, time_t epoch)
++{
++ struct ast_tm tm;
++ struct timeval tv = {
++ .tv_sec = epoch,
++ };
++
++ if (!epoch) {
++ *buf = '\0';
++ return buf;
++ }
++ ast_localtime(&tv, &tm, NULL);
++ ast_strftime(buf, buflen, "%F %r", &tm);
++
++ return buf;
++}
++
++static char *handle_show_calendar(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
++{
++#define FORMAT "%-17.17s : %-20.20s\n"
++#define FORMAT2 "%-12.12s: %-40.60s\n"
++ struct ao2_iterator i;
++ struct ast_calendar *cal;
++ struct ast_calendar_event *event;
++ int which = 0;
++ char *ret = NULL;
++
++ switch(cmd) {
++ case CLI_INIT:
++ e->command = "calendar show calendar";
++ e->usage =
++ "Usage: calendar show calendar <calendar name>\n"
++ " Displays information about a calendar\n";
++ return NULL;
++
++ case CLI_GENERATE:
++ if (a->pos != 3) {
++ return NULL;
++ }
++ i = ao2_iterator_init(calendars, 0);
++ while ((cal = ao2_iterator_next(&i))) {
++ if (!strncasecmp(a->word, cal->name, strlen(a->word)) && ++which > a->n) {
++ ret = ast_strdup(cal->name);
++ cal = unref_calendar(cal);
++ break;
++ }
++ cal = unref_calendar(cal);
++ }
++ return ret;
++ }
++
++ if (a->argc != 4) {
++ return CLI_SHOWUSAGE;
++ }
++
++ if (!(cal = find_calendar(a->argv[3]))) {
++ return NULL;
++ }
++
++ ast_cli(a->fd, FORMAT, "Name", cal->name);
++ ast_cli(a->fd, FORMAT, "Notify channel", cal->notify_channel);
++ ast_cli(a->fd, FORMAT, "Notify context", cal->notify_context);
++ ast_cli(a->fd, FORMAT, "Notify extension", cal->notify_extension);
++ ast_cli(a->fd, FORMAT, "Notify application", cal->notify_app);
++ ast_cli(a->fd, FORMAT, "Notify appdata", cal->notify_appdata);
++ ast_cli(a->fd, "%-17.17s : %d\n", "Refresh time", cal->refresh);
++ ast_cli(a->fd, "%-17.17s : %d\n", "Timeframe", cal->timeframe);
++ ast_cli(a->fd, "%-17.17s : %d\n", "Autoreminder", cal->autoreminder);
++ ast_cli(a->fd, "%s\n", "Events");
++ ast_cli(a->fd, "%s\n", "------");
++
++ i = ao2_iterator_init(cal->events, 0);
++ while ((event = ao2_iterator_next(&i))) {
++ char buf[100];
++
++ ast_cli(a->fd, FORMAT2, "Summary", event->summary);
++ ast_cli(a->fd, FORMAT2, "Description", event->description);
++ ast_cli(a->fd, FORMAT2, "Organizer", event->organizer);
++ ast_cli(a->fd, FORMAT2, "Location", event->location);
++ ast_cli(a->fd, FORMAT2, "UID", event->uid);
++ ast_cli(a->fd, FORMAT2, "Start", epoch_to_string(buf, sizeof(buf), event->start));
++ ast_cli(a->fd, FORMAT2, "End", epoch_to_string(buf, sizeof(buf), event->end));
++ ast_cli(a->fd, FORMAT2, "Alarm", epoch_to_string(buf, sizeof(buf), event->alarm));
++ ast_cli(a->fd, "\n");
++
++ event = ast_calendar_unref_event(event);
++ }
++ cal = unref_calendar(cal);
++ return CLI_SUCCESS;
++#undef FORMAT
++#undef FORMAT2
++}
++
++static char *handle_dump_sched(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
++{
++ switch(cmd) {
++ case CLI_INIT:
++ e->command = "calendar dump sched";
++ e->usage =
++ "Usage: calendar dump sched\n"
++ " Dump the calendar sched context";
++ return NULL;
++
++ case CLI_GENERATE:
++ return NULL;
++ }
++
++ ast_sched_dump(sched);
++
++ return CLI_SUCCESS;
++}
++
++static struct ast_cli_entry calendar_cli[] = {
++ AST_CLI_DEFINE(handle_show_calendar, "Display information about a calendar"),
++ AST_CLI_DEFINE(handle_show_calendars, "Show registered calendars"),
++ AST_CLI_DEFINE(handle_dump_sched, "Dump calendar sched context"),
++};
++
++static int calendar_event_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
++{
++ struct ast_datastore *datastore;
++ struct ast_calendar_event *event;
++
++ if (ast_strlen_zero(data)) {
++ ast_log(LOG_WARNING, "%s requires an argument\n", cmd);
++ return -1;
++ }
++
++ ast_channel_lock(chan);
++ if (!(datastore = ast_channel_datastore_find(chan, &event_notification_datastore, NULL))) {
++ ast_log(LOG_WARNING, "There is no event notification datastore on '%s'!\n", chan->name);
++ ast_channel_unlock(chan);
++ return -1;
++ }
++ ast_channel_unlock(chan);
++
++ if (!(event = datastore->data)) {
++ ast_log(LOG_WARNING, "The datastore contains no data!\n");
++ return -1;
++ }
++
++ if (!strcasecmp(data, "summary")) {
++ ast_copy_string(buf, event->summary, len);
++ } else if (!strcasecmp(data, "description")) {
++ ast_copy_string(buf, event->description, len);
++ } else if (!strcasecmp(data, "organizer")) {
++ ast_copy_string(buf, event->organizer, len);
++ } else if (!strcasecmp(data, "location")) {
++ ast_copy_string(buf, event->location, len);
++ } else if (!strcasecmp(data, "calendar")) {
++ ast_copy_string(buf, event->owner->name, len);
++ } else if (!strcasecmp(data, "uid")) {
++ ast_copy_string(buf, event->uid, len);
++ } else if (!strcasecmp(data, "start")) {
++ snprintf(buf, len, "%ld", (long)event->start);
++ } else if (!strcasecmp(data, "end")) {
++ snprintf(buf, len, "%ld", (long)event->end);
++ } else if (!strcasecmp(data, "busystate")) {
++ snprintf(buf, len, "%d", event->busy_state);
++ } else if (!strcasecmp(data, "attendees")) {
++ calendar_join_attendees(event, buf, len);
++ }
++
++
++ return 0;
++}
++
++static struct ast_custom_function calendar_event_function = {
++ .name = "CALENDAR_EVENT",
++ .read = calendar_event_read,
++};
++
++static int cb_pending_deletion(void *user_data, void *arg, int flags)
++{
++ struct ast_calendar *cal = user_data;
++
++ cal->pending_deletion = 1;
++
++ return CMP_MATCH;
++}
++
++static int cb_rm_pending_deletion(void *user_data, void *arg, int flags)
++{
++ struct ast_calendar *cal = user_data;
++
++ return cal->pending_deletion ? CMP_MATCH : 0;
++}
++
++static int reload(void)
++{
++ struct ast_calendar_tech *iter;
++
++ ast_mutex_lock(&reloadlock);
++
++ /* Mark existing calendars for deletion */
++ ao2_callback(calendars, OBJ_NODATA | OBJ_MULTIPLE, cb_pending_deletion, NULL);
++ load_config(NULL);
++
++ AST_LIST_LOCK(&techs);
++ AST_LIST_TRAVERSE(&techs, iter, list) {
++ if (load_tech_calendars(iter)) {
++ ast_log(LOG_WARNING, "Failed to reload %s calendars, module disabled\n", iter->type);
++ }
++ }
++ AST_LIST_UNLOCK(&techs);
++
++ /* Delete calendars that no longer show up in the config */
++ ao2_callback(calendars, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, cb_rm_pending_deletion, NULL);
++
++ ast_mutex_unlock(&reloadlock);
++
++ return 0;
++}
++
++static void *do_refresh(void *data)
++{
++ for (;;) {
++ struct timeval now = ast_tvnow();
++ struct timespec ts = {0,};
++ int res, wait;
++
++ ast_mutex_lock(&refreshlock);
++
++ if ((wait = ast_sched_wait(sched)) < 0) {
++ wait = 1000;
++ }
++
++ ts.tv_sec = (now.tv_sec + wait / 1000) + 1;
++ res = ast_cond_timedwait(&refresh_condition, &refreshlock, &ts);
++
++ ast_mutex_unlock(&refreshlock);
++
++ ast_sched_runq(sched);
++ }
++
++ return NULL;
++}
++
++/* If I were to allow unloading it would look something like this */
++static int unload_module(void)
++{
++ struct ast_calendar_tech *tech;
++
++ ast_devstate_prov_del("calendar");
++ ast_custom_function_unregister(&calendar_busy_function);
++ ast_custom_function_unregister(&calendar_event_function);
++ ast_custom_function_unregister(&calendar_query_function);
++ ast_custom_function_unregister(&calendar_query_result_function);
++ ast_custom_function_unregister(&calendar_write_function);
++ ast_cli_unregister_multiple(calendar_cli, ARRAY_LEN(calendar_cli));
++
++ /* Remove all calendars */
++ ao2_callback(calendars, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL);
++
++ AST_LIST_LOCK(&techs);
++ AST_LIST_TRAVERSE_SAFE_BEGIN(&techs, tech, list) {
++ ast_unload_resource(tech->module, 0);
++ }
++ AST_LIST_TRAVERSE_SAFE_END;
++ AST_LIST_UNLOCK(&techs);
++
++ return 0;
++}
++
++static int load_module(void)
++{
++ if (load_config(NULL)) {
++ /* We don't have calendar support enabled */
++ return 0;
++ }
++
++ if (!(calendars = ao2_container_alloc(CALENDAR_BUCKETS, calendar_hash_fn, calendar_cmp_fn))) {
++ ast_log(LOG_ERROR, "Unable to allocate calendars container!\n");
++ return -1;
++ }
++
++ ast_mutex_init(&refreshlock);
++ ast_cond_init(&refresh_condition, NULL);
++ ast_mutex_init(&reloadlock);
++
++ if (!(sched = sched_context_create())) {
++ ast_log(LOG_ERROR, "Unable to create sched context\n");
++ return -1;
++ }
++
++ if (ast_pthread_create_background(&refresh_thread, NULL, do_refresh, NULL) < 0) {
++ ast_log(LOG_ERROR, "Unable to start refresh thread--notifications disabled!\n");
++ }
++
++ ast_custom_function_register(&calendar_busy_function);
++ ast_custom_function_register(&calendar_event_function);
++ ast_custom_function_register(&calendar_query_function);
++ ast_custom_function_register(&calendar_query_result_function);
++ ast_custom_function_register(&calendar_write_function);
++ ast_cli_register_multiple(calendar_cli, ARRAY_LEN(calendar_cli));
++
++ ast_devstate_prov_add("Calendar", calendarstate);
++
++ /* Since other modules depend on this, disable unloading */
++ ast_module_ref(ast_module_info->self);
++
++ return 0;
++}
++AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Asterisk Calendar integration",
++ .load = load_module,
++ .unload = unload_module,
++ .reload = reload,
++ );
+
+Property changes on: res/res_calendar.c
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+
+Index: res/res_calendar_exchange.c
+===================================================================
+--- a/res/res_calendar_exchange.c (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/res/res_calendar_exchange.c (.../trunk) (revision 202568)
+@@ -0,0 +1,757 @@
++/*
++ * Asterisk -- An open source telephony toolkit.
++ *
++ * Copyright (C) 2008 - 2009, Digium, Inc.
++ *
++ * Terry Wilson <twilson@digium.com>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * 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.
++ */
++
++/*! \file
++ * \brief Resource for handling iCalnedar calendars
++ */
++
++/*** MODULEINFO
++ <depend>neon</depend>
++ <depend>ical</depend>
++ <depend>iksemel</depend>
++***/
++#include "asterisk.h"
++
++ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
++
++#include <libical/ical.h>
++#include <neon/ne_session.h>
++#include <neon/ne_uri.h>
++#include <neon/ne_request.h>
++#include <neon/ne_auth.h>
++#include <iksemel.h>
++
++#include "asterisk/module.h"
++#include "asterisk/calendar.h"
++#include "asterisk/lock.h"
++#include "asterisk/config.h"
++#include "asterisk/astobj2.h"
++
++static void *exchangecal_load_calendar(void *data);
++static void *unref_exchangecal(void *obj);
++static int exchangecal_write_event(struct ast_calendar_event *event);
++
++static struct ast_calendar_tech exchangecal_tech = {
++ .type = "exchange",
++ .description = "MS Exchange calendars",
++ .module = AST_MODULE,
++ .load_calendar = exchangecal_load_calendar,
++ .unref_calendar = unref_exchangecal,
++ .write_event = exchangecal_write_event,
++};
++
++struct exchangecal_pvt {
++ AST_DECLARE_STRING_FIELDS(
++ AST_STRING_FIELD(url);
++ AST_STRING_FIELD(user);
++ AST_STRING_FIELD(secret);
++ );
++ struct ast_calendar *owner;
++ ne_uri uri;
++ ne_session *session;
++ struct ao2_container *events;
++};
++
++struct xmlstate {
++ char tag[80];
++ int in_response;
++ int in_propstat;
++ int in_prop;
++ void *ptr;
++ struct exchangecal_pvt *pvt;
++};
++
++static int parse_tag(void *data, char *name, char **atts, int type)
++{
++ struct xmlstate *state = data;
++ char *tmp;
++
++ if ((tmp = strchr(name, ':'))) {
++ tmp++;
++ } else {
++ return IKS_HOOK;
++ }
++
++ ast_copy_string(state->tag, tmp, sizeof(state->tag));
++
++ switch (type) {
++ case IKS_OPEN:
++ if (!strcasecmp(state->tag, "response")) {
++ struct ast_calendar_event *event;
++
++ state->in_response = 1;
++ if (!(event = ast_calendar_event_alloc(state->pvt->owner))) {
++ return IKS_NOMEM;
++ }
++ state->ptr = event;
++ } else if (!strcasecmp(state->tag, "propstat")) {
++ state->in_propstat = 1;
++ } else if (!strcasecmp(state->tag, "prop")) {
++ state->in_prop = 1;
++ }
++ break;
++
++ case IKS_CLOSE:
++ if (!strcasecmp(state->tag, "response")) {
++ struct ao2_container *events = state->pvt->events;
++ struct ast_calendar_event *event = state->ptr;
++
++ state->in_response = 0;
++ if (ast_strlen_zero(event->uid)) {
++ ast_log(LOG_ERROR, "This event has no UID, something has gone wrong\n");
++ event = ast_calendar_unref_event(event);
++ return IKS_HOOK;
++ }
++ ao2_link(events, event);
++ event = ast_calendar_unref_event(event);
++ } else if (!strcasecmp(state->tag, "propstat")) {
++ state->in_propstat = 0;
++ } else if (!strcasecmp(state->tag, "prop")) {
++ state->in_prop = 0;
++ }
++ break;
++
++ default:
++ return IKS_OK;
++ }
++
++ return IKS_OK;
++}
++
++static time_t mstime_to_time_t(char *mstime)
++{
++ char *read, *write;
++ icaltimetype tt;
++ for (read = write = mstime; *read; read++) {
++ if (*read == '.') {
++ *write++ = 'Z';
++ *write = '\0';
++ break;
++ }
++ if (*read == '-' || *read == ':')
++ continue;
++ *write = *read;
++ write++;
++ }
++
++ tt = icaltime_from_string(mstime);
++ return icaltime_as_timet(tt);
++}
++
++static enum ast_calendar_busy_state msbusy_to_bs(const char *msbusy)
++{
++ if (!strcasecmp(msbusy, "FREE")) {
++ return AST_CALENDAR_BS_FREE;
++ } else if (!strcasecmp(msbusy, "TENTATIVE")) {
++ return AST_CALENDAR_BS_BUSY_TENTATIVE;
++ } else {
++ return AST_CALENDAR_BS_BUSY;
++ }
++}
++
++static int parse_cdata(void *data, char *value, size_t len)
++{
++ char *str;
++ struct xmlstate *state = data;
++ struct ast_calendar_event *event = state->ptr;
++
++
++ str = ast_skip_blanks(value);
++
++ if (str == value + len)
++ return IKS_OK;
++
++ if (!(str = ast_calloc(1, len + 1))) {
++ return IKS_NOMEM;
++ }
++ memcpy(str, value, len);
++ if (!(state->in_response && state->in_propstat && state->in_prop)) {
++ ast_free(str);
++ return IKS_OK;
++ }
++ /* We use ast_string_field_build here because libiksemel is parsing CDATA with &lt; as
++ * new elements which is a bit odd and shouldn't happen */
++ if (!strcasecmp(state->tag, "subject")) {
++ ast_string_field_build(event, summary, "%s%s", event->summary, str);
++ } else if (!strcasecmp(state->tag, "location")) {
++ ast_string_field_build(event, location, "%s%s", event->location, str);
++ } else if (!strcasecmp(state->tag, "uid")) {
++ ast_string_field_build(event, uid, "%s%s", event->location, str);
++ } else if (!strcasecmp(state->tag, "organizer")) {
++ ast_string_field_build(event, organizer, "%s%s", event->organizer, str);
++ } else if (!strcasecmp(state->tag, "textdescription")) {
++ ast_string_field_build(event, description, "%s%s", event->description, str);
++ } else if (!strcasecmp(state->tag, "dtstart")) {
++ event->start = mstime_to_time_t(str);
++ } else if (!strcasecmp(state->tag, "dtend")) {
++ event->end = mstime_to_time_t(str);
++ } else if (!strcasecmp(state->tag, "busystatus")) {
++ event->busy_state = msbusy_to_bs(str);
++ } else if (!strcasecmp(state->tag, "reminderoffset")) {
++ /*XXX Currently we rely on event->start being set first which means we rely on the response order
++ * which technically should be fine since the query returns in the order we ask for, but ... */
++ event->alarm = event->start - atoi(str);
++ }
++
++ ast_free(str);
++ return IKS_OK;
++}
++
++static int cb_true(void *user_data, void *arg, int flags)
++{
++ return CMP_MATCH;
++}
++
++static void exchangecal_destructor(void *obj)
++{
++ struct exchangecal_pvt *pvt = obj;
++
++ ast_debug(1, "Destroying pvt for Exchange calendar %s\n", pvt->owner->name);
++ if (pvt->session) {
++ ne_session_destroy(pvt->session);
++ }
++ ast_string_field_free_memory(pvt);
++
++ ao2_callback(pvt->events, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, cb_true, NULL);
++
++ ao2_ref(pvt->events, -1);
++}
++
++static void *unref_exchangecal(void *obj)
++{
++ struct exchangecal_pvt *pvt = obj;
++
++ ao2_ref(pvt, -1);
++ return NULL;
++}
++
++/* It is very important to use the return value of this function as a realloc could occur */
++static struct ast_str *generate_exchange_uuid(struct ast_str *uid)
++{
++ unsigned short val[8];
++ int x;
++
++ for (x = 0; x < 8; x++) {
++ val[x] = ast_random();
++ }
++ ast_str_set(&uid, 0, "%04x%04x-%04x-%04x-%04x-%04x%04x%04x", val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7]);
++
++ return uid;
++}
++
++static int is_valid_uuid(struct ast_str *uid)
++{
++ int i;
++
++ if (ast_str_strlen(uid) != 36) {
++ return 0;
++ }
++
++ for (i = 0; i < ast_str_strlen(uid); i++) {
++ if (i == 8 || i == 13 || i == 18 || i == 23) {
++ if (ast_str_buffer(uid)[i] != '-') {
++ return 0;
++ }
++ } else if (!((ast_str_buffer(uid)[i] > 47 && ast_str_buffer(uid)[i] < 58) || (ast_str_buffer(uid)[i] > 96 && ast_str_buffer(uid)[i] < 103))) {
++ return 0;
++ }
++ }
++
++ return 1;
++}
++
++static struct ast_str *xml_encode_str(struct ast_str *dst, const char *src)
++{
++ const char *tmp;
++ char buf[7];
++
++ for (tmp = src; *tmp; tmp++) {
++ switch (*tmp) {
++ case '\"':
++ strcpy(buf, "&quot;");
++ break;
++
++ case '\'':
++ strcpy(buf, "&apos;");
++ break;
++
++ case '&':
++ strcpy(buf, "&amp;");
++ break;
++
++ case '<':
++ strcpy(buf, "&lt;");
++ break;
++
++ case '>':
++ strcpy(buf, "&gt;");
++ break;
++
++ default:
++ sprintf(buf, "%c", *tmp);
++ }
++
++ ast_str_append(&dst, 0, "%s", buf);
++ }
++
++ return dst;
++}
++
++static struct ast_str *epoch_to_exchange_time(struct ast_str *dst, time_t epoch)
++{
++ icaltimezone *utc = icaltimezone_get_utc_timezone();
++ icaltimetype tt = icaltime_from_timet_with_zone(epoch, 0, utc);
++ char tmp[30];
++ int i;
++
++ ast_copy_string(tmp, icaltime_as_ical_string(tt), sizeof(tmp));
++ for (i = 0; tmp[i]; i++) {
++ ast_str_append(&dst, 0, "%c", tmp[i]);
++ if (i == 3 || i == 5)
++ ast_str_append(&dst, 0, "%c", '-');
++ if (i == 10 || i == 12)
++ ast_str_append(&dst, 0, "%c", ':');
++ if (i == 14)
++ ast_str_append(&dst, 0, "%s", ".000");
++ }
++
++ return dst;
++}
++
++static struct ast_str *bs_to_exchange_bs(struct ast_str *dst, enum ast_calendar_busy_state bs)
++{
++ switch (bs) {
++ case AST_CALENDAR_BS_BUSY:
++ ast_str_set(&dst, 0, "%s", "BUSY");
++ break;
++
++ case AST_CALENDAR_BS_BUSY_TENTATIVE:
++ ast_str_set(&dst, 0, "%s", "TENTATIVE");
++ break;
++
++ default:
++ ast_str_set(&dst, 0, "%s", "FREE");
++ }
++
++ return dst;
++}
++
++static int fetch_response_reader(void *data, const char *block, size_t len)
++{
++ struct ast_str **response = data;
++ unsigned char *tmp;
++
++ if (!(tmp = ast_malloc(len + 1))) {
++ return -1;
++ }
++ memcpy(tmp, block, len);
++ tmp[len] = '\0';
++ ast_str_append(response, 0, "%s", tmp);
++ ast_free(tmp);
++
++ return 0;
++}
++
++static int auth_credentials(void *userdata, const char *realm, int attempts, char *username, char *secret)
++{
++ struct exchangecal_pvt *pvt = userdata;
++
++ if (attempts > 1) {
++ ast_log(LOG_WARNING, "Invalid username or password for Exchange calendar '%s'\n", pvt->owner->name);
++ return -1;
++ }
++
++ ne_strnzcpy(username, pvt->user, NE_ABUFSIZ);
++ ne_strnzcpy(secret, pvt->secret, NE_ABUFSIZ);
++
++ return 0;
++}
++
++static struct ast_str *exchangecal_request(struct exchangecal_pvt *pvt, const char *method, struct ast_str *req_body, struct ast_str *subdir)
++{
++ struct ast_str *response;
++ ne_request *req;
++ int ret;
++ char buf[1000];
++
++ if (!pvt) {
++ ast_log(LOG_ERROR, "There is no private!\n");
++ return NULL;
++ }
++
++ if (!(response = ast_str_create(512))) {
++ ast_log(LOG_ERROR, "Could not allocate memory for response.\n");
++ return NULL;
++ }
++
++ snprintf(buf, sizeof(buf), "%s%s", pvt->uri.path, subdir ? ast_str_buffer(subdir) : "");
++
++ req = ne_request_create(pvt->session, method, buf);
++ ne_add_response_body_reader(req, ne_accept_2xx, fetch_response_reader, &response);
++ ne_set_request_body_buffer(req, ast_str_buffer(req_body), ast_str_strlen(req_body));
++ ne_add_request_header(req, "Content-type", "text/xml");
++
++ ret = ne_request_dispatch(req);
++
++ if (ret != NE_OK || !ast_str_strlen(response)) {
++ ast_log(LOG_WARNING, "Unknown response to CalDAV calendar %s, request %s to %s: %s\n", pvt->owner->name, method, pvt->url, ne_get_error(pvt->session));
++ ast_free(response);
++ return NULL;
++ }
++
++ return response;
++}
++
++static int exchangecal_write_event(struct ast_calendar_event *event)
++{
++ struct ast_str *body = NULL, *response = NULL, *subdir = NULL;
++ struct ast_str *uid = NULL, *summary = NULL, *description = NULL, *organizer = NULL,
++ *location = NULL, *start = NULL, *end = NULL, *busystate = NULL;
++ int ret = -1;
++
++ if (!event) {
++ ast_log(LOG_WARNING, "No event passed!\n");
++ return -1;
++ }
++
++ if (!(event->start && event->end)) {
++ ast_log(LOG_WARNING, "The event must contain a start and an end\n");
++ return -1;
++ }
++ if (!(body = ast_str_create(512)) ||
++ !(subdir = ast_str_create(32)) ||
++ !(response = ast_str_create(512))) {
++ ast_log(LOG_ERROR, "Could not allocate memory for request and response!\n");
++ goto write_cleanup;
++ }
++
++ if (!(uid = ast_str_create(32)) ||
++ !(summary = ast_str_create(32)) ||
++ !(description = ast_str_create(32)) ||
++ !(organizer = ast_str_create(32)) ||
++ !(location = ast_str_create(32)) ||
++ !(start = ast_str_create(32)) ||
++ !(end = ast_str_create(32)) ||
++ !(busystate = ast_str_create(32))) {
++ ast_log(LOG_ERROR, "Unable to allocate memory for request values\n");
++ goto write_cleanup;
++ }
++
++ if (ast_strlen_zero(event->uid)) {
++ uid = generate_exchange_uuid(uid);
++ } else {
++ ast_str_set(&uid, 36, "%s", event->uid);
++ }
++
++ if (!is_valid_uuid(uid)) {
++ ast_log(LOG_WARNING, "An invalid uid was provided, you may leave this field blank to have one generated for you\n");
++ goto write_cleanup;
++ }
++
++ summary = xml_encode_str(summary, event->summary);
++ description = xml_encode_str(description, event->description);
++ organizer = xml_encode_str(organizer, event->organizer);
++ location = xml_encode_str(location, event->location);
++ start = epoch_to_exchange_time(start, event->start);
++ end = epoch_to_exchange_time(end, event->end);
++ busystate = bs_to_exchange_bs(busystate, event->busy_state);
++
++ ast_str_append(&body, 0,
++ "<?xml version=\"1.0\"?>\n"
++ "<a:propertyupdate\n"
++ " xmlns:a=\"DAV:\"\n"
++ " xmlns:e=\"http://schemas.microsoft.com/exchange/\"\n"
++ " xmlns:mapi=\"http://schemas.microsoft.com/mapi/\"\n"
++ " xmlns:mapit=\"http://schemas.microsoft.com/mapi/proptag/\"\n"
++ " xmlns:x=\"xml:\" xmlns:cal=\"urn:schemas:calendar:\"\n"
++ " xmlns:dt=\"uuid:%s/\"\n" /* uid */
++ " xmlns:header=\"urn:schemas:mailheader:\"\n"
++ " xmlns:mail=\"urn:schemas:httpmail:\"\n"
++ ">\n"
++ " <a:set>\n"
++ " <a:prop>\n"
++ " <a:contentclass>urn:content-classes:appointment</a:contentclass>\n"
++ " <e:outlookmessageclass>IPM.Appointment</e:outlookmessageclass>\n"
++ " <mail:subject>%s</mail:subject>\n" /* summary */
++ " <mail:description>%s</mail:description>\n" /* description */
++ " <header:to>%s</header:to>\n" /* organizer */
++ " <cal:location>%s</cal:location>\n" /* location */
++ " <cal:dtstart dt:dt=\"dateTime.tz\">%s</cal:dtstart>\n" /* start */
++ " <cal:dtend dt:dt=\"dateTime.tz\">%s</cal:dtend>\n" /* end */
++ " <cal:instancetype dt:dt=\"int\">0</cal:instancetype>\n"
++ " <cal:busystatus>%s</cal:busystatus>\n" /* busy_state (BUSY, FREE, BUSY_TENTATIVE) */
++ " <cal:meetingstatus>CONFIRMED</cal:meetingstatus>\n"
++ " <cal:alldayevent dt:dt=\"boolean\">0</cal:alldayevent>\n" /* XXX need to add event support for all day events */
++ " <cal:responserequested dt:dt=\"boolean\">0</cal:responserequested>\n"
++ " <mapi:finvited dt:dt=\"boolean\">1</mapi:finvited>\n"
++ " </a:prop>\n"
++ " </a:set>\n"
++ "</a:propertyupdate>\n",
++ ast_str_buffer(uid), ast_str_buffer(summary), ast_str_buffer(description), ast_str_buffer(organizer), ast_str_buffer(location), ast_str_buffer(start), ast_str_buffer(end), ast_str_buffer(busystate));
++ ast_verb(0, "\n\n%s\n\n", ast_str_buffer(body));
++ ast_str_set(&subdir, 0, "/Calendar/%s.eml", ast_str_buffer(uid));
++
++ response = exchangecal_request(event->owner->tech_pvt, "PROPPATCH", body, subdir);
++
++ ret = 0;
++write_cleanup:
++ if (uid) {
++ ast_free(uid);
++ }
++ if (summary) {
++ ast_free(summary);
++ }
++ if (description) {
++ ast_free(description);
++ }
++ if (organizer) {
++ ast_free(organizer);
++ }
++ if (location) {
++ ast_free(location);
++ }
++ if (start) {
++ ast_free(start);
++ }
++ if (end) {
++ ast_free(end);
++ }
++ if (busystate) {
++ ast_free(busystate);
++ }
++ if (body) {
++ ast_free(body);
++ }
++ if (response) {
++ ast_free(response);
++ }
++ if (subdir) {
++ ast_free(subdir);
++ }
++
++ return ret;
++}
++
++
++static struct ast_str *exchangecal_get_events_between(struct exchangecal_pvt *pvt, time_t start_time, time_t end_time)
++{
++ struct ast_str *body, *response;
++ char start[80], end[80];
++ struct timeval tv = {0,};
++ struct ast_tm tm;
++
++ tv.tv_sec = start_time;
++ ast_localtime(&tv, &tm, "UTC");
++ ast_strftime(start, sizeof(start), "%Y/%m/%d %T", &tm);
++
++ tv.tv_sec = end_time;
++ ast_localtime(&tv, &tm, "UTC");
++ ast_strftime(end, sizeof(end), "%Y/%m/%d %T", &tm);
++
++ if (!(body = ast_str_create(512))) {
++ ast_log(LOG_ERROR, "Could not allocate memory for body of request!\n");
++ return NULL;
++ }
++
++ ast_str_append(&body, 0,
++ "<?xml version=\"1.0\"?>\n"
++ "<g:searchrequest xmlns:g=\"DAV:\">\n"
++ " <g:sql> SELECT \"urn:schemas:calendar:location\", \"urn:schemas:httpmail:subject\",\n"
++ " \"urn:schemas:calendar:dtstart\", \"urn:schemas:calendar:dtend\",\n"
++ " \"urn:schemas:calendar:busystatus\", \"urn:schemas:calendar:instancetype\",\n"
++ " \"urn:schemas:calendar:uid\", \"urn:schemas:httpmail:textdescription\",\n"
++ " \"urn:schemas:calendar:organizer\", \"urn:schemas:calendar:reminderoffset\"\n"
++ " FROM Scope('SHALLOW TRAVERSAL OF \"%s/Calendar\"')\n"
++ " WHERE NOT \"urn:schemas:calendar:instancetype\" = 1\n"
++ " AND \"DAV:contentclass\" = 'urn:content-classes:appointment'\n"
++ " AND NOT (\"urn:schemas:calendar:dtend\" &lt; '%s'\n"
++ " OR \"urn:schemas:calendar:dtstart\" &gt; '%s')\n"
++ " ORDER BY \"urn:schemas:calendar:dtstart\" ASC\n"
++ " </g:sql>\n"
++ "</g:searchrequest>\n", pvt->url, start, end);
++
++ ast_debug(5, "Request:\n%s\n", ast_str_buffer(body));
++ response = exchangecal_request(pvt, "SEARCH", body, NULL);
++ ast_debug(5, "Response:\n%s\n", ast_str_buffer(response));
++ ast_free(body);
++
++ return response;
++}
++
++static int update_exchangecal(struct exchangecal_pvt *pvt)
++{
++ struct xmlstate state;
++ struct timeval now = ast_tvnow();
++ time_t start, end;
++ struct ast_str *response;
++ iksparser *p;
++
++ state.pvt = pvt;
++ start = now.tv_sec;
++ end = now.tv_sec + 60 * pvt->owner->timeframe;
++ if (!(response = exchangecal_get_events_between(pvt, start, end))) {
++ return -1;
++ }
++
++ p = iks_sax_new(&state, parse_tag, parse_cdata);
++ iks_parse(p, ast_str_buffer(response), ast_str_strlen(response), 1);
++ ast_calendar_merge_events(pvt->owner, pvt->events);
++ ast_free(response);
++
++ return 0;
++}
++
++static void *exchangecal_load_calendar(void *void_data)
++{
++ struct exchangecal_pvt *pvt;
++ struct ast_variable *v;
++ struct ast_calendar *cal = void_data;
++ ast_mutex_t refreshlock;
++
++ if (!(cal && ast_calendar_config)) {
++ ast_log(LOG_ERROR, "You must enable calendar support for res_exchangecal to load\n");
++ return NULL;
++ }
++
++ if (ao2_trylock(cal)) {
++ if (cal->unloading) {
++ ast_log(LOG_WARNING, "Unloading module, load_calendar cancelled.\n");
++ } else {
++ ast_log(LOG_WARNING, "Could not lock calendar, aborting!\n");
++ }
++ return NULL;
++ }
++
++ if (!(pvt = ao2_alloc(sizeof(*pvt), exchangecal_destructor))) {
++ ast_log(LOG_ERROR, "Could not allocate exchangecal_pvt structure for calendar: %s\n", cal->name);
++ return NULL;
++ }
++
++ pvt->owner = cal;
++
++ if (!(pvt->events = ast_calendar_event_container_alloc())) {
++ ast_log(LOG_ERROR, "Could not allocate space for fetching events for calendar: %s\n", cal->name);
++ pvt = unref_exchangecal(pvt);
++ ao2_unlock(cal);
++ return NULL;
++ }
++
++ if (ast_string_field_init(pvt, 32)) {
++ ast_log(LOG_ERROR, "Couldn't allocate string field space for calendar: %s\n", cal->name);
++ pvt = unref_exchangecal(pvt);
++ ao2_unlock(cal);
++ return NULL;
++ }
++
++ for (v = ast_variable_browse(ast_calendar_config, cal->name); v; v = v->next) {
++ if (!strcasecmp(v->name, "url")) {
++ ast_string_field_set(pvt, url, v->value);
++ } else if (!strcasecmp(v->name, "user")) {
++ ast_string_field_set(pvt, user, v->value);
++ } else if (!strcasecmp(v->name, "secret")) {
++ ast_string_field_set(pvt, secret, v->value);
++ }
++ }
++
++ if (ast_strlen_zero(pvt->url)) {
++ ast_log(LOG_WARNING, "No URL was specified for Exchange calendar '%s' - skipping.\n", cal->name);
++ pvt = unref_exchangecal(pvt);
++ ao2_unlock(cal);
++ return NULL;
++ }
++
++ if (ne_uri_parse(pvt->url, &pvt->uri) || pvt->uri.host == NULL || pvt->uri.path == NULL) {
++ ast_log(LOG_WARNING, "Could not parse url '%s' for Exchange calendar '%s' - skipping.\n", pvt->url, cal->name);
++ pvt = unref_exchangecal(pvt);
++ ao2_unlock(cal);
++ return NULL;
++ }
++
++ if (pvt->uri.scheme == NULL) {
++ pvt->uri.scheme = "http";
++ }
++
++ if (pvt->uri.port == 0) {
++ pvt->uri.port = ne_uri_defaultport(pvt->uri.scheme);
++ }
++
++ pvt->session = ne_session_create(pvt->uri.scheme, pvt->uri.host, pvt->uri.port);
++ ne_set_server_auth(pvt->session, auth_credentials, pvt);
++ if (!strncasecmp(pvt->uri.scheme, "https", sizeof(pvt->uri.scheme))) {
++ ne_ssl_trust_default_ca(pvt->session);
++ }
++
++ cal->tech_pvt = pvt;
++
++ ast_mutex_init(&refreshlock);
++
++ /* Load it the first time */
++ update_exchangecal(pvt);
++
++ ao2_unlock(cal);
++
++ /* The only writing from another thread will be if unload is true */
++ for (;;) {
++ struct timeval tv = ast_tvnow();
++ struct timespec ts = {0,};
++
++ ts.tv_sec = tv.tv_sec + (60 * pvt->owner->refresh);
++
++ ast_mutex_lock(&refreshlock);
++ while (!pvt->owner->unloading) {
++ if (ast_cond_timedwait(&pvt->owner->unload, &refreshlock, &ts) == ETIMEDOUT) {
++ break;
++ }
++ }
++ ast_mutex_unlock(&refreshlock);
++
++ if (pvt->owner->unloading) {
++ ast_debug(10, "Skipping refresh since we got a shutdown signal\n");
++ return NULL;
++ }
++
++ ast_debug(10, "Refreshing after %d minute timeout\n", pvt->owner->refresh);
++
++ update_exchangecal(pvt);
++ }
++
++ return NULL;
++}
++
++static int load_module(void)
++{
++ ne_sock_init();
++ if (ast_calendar_register(&exchangecal_tech)) {
++ ne_sock_exit();
++ return AST_MODULE_LOAD_DECLINE;
++ }
++
++ return AST_MODULE_LOAD_SUCCESS;
++}
++
++static int unload_module(void)
++{
++ ast_calendar_unregister(&exchangecal_tech);
++ ne_sock_exit();
++ return 0;
++}
++
++AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Asterisk MS Exchange Calendar Integration",
++ .load = load_module,
++ .unload = unload_module,
++ );
+
+Property changes on: res/res_calendar_exchange.c
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+
+Index: res/res_snmp.c
+===================================================================
+--- a/res/res_snmp.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/res/res_snmp.c (.../trunk) (revision 202568)
+@@ -34,7 +34,7 @@
+
+ int res_snmp_agentx_subagent;
+ int res_snmp_dont_stop;
+-int res_snmp_enabled;
++static int res_snmp_enabled;
+
+ static pthread_t thread = AST_PTHREADT_NULL;
+
+@@ -115,7 +115,7 @@
+ return ((thread != AST_PTHREADT_NULL) ? pthread_join(thread, NULL) : 0);
+ }
+
+-AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "SNMP [Sub]Agent for Asterisk",
++AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "SNMP [Sub]Agent for Asterisk",
+ .load = load_module,
+ .unload = unload_module,
+ );
+Index: res/res_limit.c
+===================================================================
+--- a/res/res_limit.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/res/res_limit.c (.../trunk) (revision 202568)
+@@ -40,7 +40,7 @@
+ #endif
+ #endif
+
+-static struct limits {
++static const struct limits {
+ int resource;
+ char limit[3];
+ char desc[40];
+@@ -154,7 +154,7 @@
+
+ if (a->argc == 1) {
+ char arg2[15];
+- char *newargv[2] = { "ulimit", arg2 };
++ const char * const newargv[2] = { "ulimit", arg2 };
+ for (resource = 0; resource < ARRAY_LEN(limits); resource++) {
+ struct ast_cli_args newArgs = { .argv = newargv, .argc = 2 };
+ ast_copy_string(arg2, limits[resource].clicmd, sizeof(arg2));
+Index: res/res_agi.exports
+===================================================================
+--- a/res/res_agi.exports (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/res/res_agi.exports (.../trunk) (revision 202568)
+@@ -0,0 +1,10 @@
++{
++ global:
++ *ast_agi_register;
++ *ast_agi_unregister;
++ *ast_agi_register_multiple;
++ *ast_agi_unregister_multiple;
++ *ast_agi_send;
++ local:
++ *;
++};
+
+Property changes on: res/res_agi.exports
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+
+Index: res/res_jabber.c
+===================================================================
+--- a/res/res_jabber.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/res/res_jabber.c (.../trunk) (revision 202568)
+@@ -166,6 +166,26 @@
+ </enumlist>
+ </description>
+ </function>
++ <manager name="JabberSend" language="en_US">
++ <synopsis>
++ Sends a message to a Jabber Client.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Jabber" required="true">
++ <para>Client or transport Asterisk uses to connect to JABBER.</para>
++ </parameter>
++ <parameter name="JID" required="true">
++ <para>XMPP/Jabber JID (Name) of recipient.</para>
++ </parameter>
++ <parameter name="Message" required="true">
++ <para>Message to be sent to the buddy.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Sends a message to a Jabber Client.</para>
++ </description>
++ </manager>
+ ***/
+
+ /*! \todo This should really be renamed to xmpp.conf. For backwards compatibility, we
+@@ -183,8 +203,6 @@
+ /*-- Forward declarations */
+ static void aji_buddy_destroy(struct aji_buddy *obj);
+ static void aji_client_destroy(struct aji_client *obj);
+-static int aji_send_exec(struct ast_channel *chan, void *data);
+-static int aji_status_exec(struct ast_channel *chan, void *data);
+ static int aji_is_secure(struct aji_client *client);
+ #ifdef HAVE_OPENSSL
+ static int aji_start_tls(struct aji_client *client);
+@@ -243,8 +261,8 @@
+
+ static char *app_ajistatus = "JabberStatus";
+
+-struct aji_client_container clients;
+-struct aji_capabilities *capabilities = NULL;
++static struct aji_client_container clients;
++static struct aji_capabilities *capabilities = NULL;
+
+ /*! \brief Global flags, initialized to default values */
+ static struct ast_flags globalflags = { AJI_AUTOREGISTER };
+@@ -429,7 +447,7 @@
+ * \param data
+ * \return 0 on success, -1 on error
+ */
+-static int aji_status_exec(struct ast_channel *chan, void *data)
++static int aji_status_exec(struct ast_channel *chan, const char *data)
+ {
+ struct aji_client *client = NULL;
+ struct aji_buddy *buddy = NULL;
+@@ -545,7 +563,7 @@
+ * \param data Data is sender|reciever|message.
+ * \return 0 on success,-1 on error.
+ */
+-static int aji_send_exec(struct ast_channel *chan, void *data)
++static int aji_send_exec(struct ast_channel *chan, const char *data)
+ {
+ struct aji_client *client = NULL;
+ char *s;
+@@ -563,7 +581,7 @@
+
+ AST_STANDARD_APP_ARGS(args, s);
+ if (args.argc < 3) {
+- ast_log(LOG_ERROR, "JabberSend requires 3 arguments: '%s'\n", (char *) data);
++ ast_log(LOG_ERROR, "JabberSend requires 3 arguments: '%s'\n", data);
+ return -1;
+ }
+
+@@ -2982,13 +3000,6 @@
+ return &clients;
+ }
+
+-static char mandescr_jabber_send[] =
+-"Description: Sends a message to a Jabber Client.\n"
+-"Variables: \n"
+-" Jabber: Client or transport Asterisk uses to connect to JABBER\n"
+-" JID: XMPP/Jabber JID (Name) of recipient\n"
+-" Message: Message to be sent to the buddy\n";
+-
+ /*!
+ * \brief Send a Jabber Message via call from the Manager
+ * \param s mansession Manager session
+@@ -3091,8 +3102,7 @@
+ ASTOBJ_CONTAINER_INIT(&clients);
+ if(!aji_reload(0))
+ return AST_MODULE_LOAD_DECLINE;
+- ast_manager_register2("JabberSend", EVENT_FLAG_SYSTEM, manager_jabber_send,
+- "Sends a message to a Jabber Client", mandescr_jabber_send);
++ ast_manager_register_xml("JabberSend", EVENT_FLAG_SYSTEM, manager_jabber_send);
+ ast_register_application_xml(app_ajisend, aji_send_exec);
+ ast_register_application_xml(app_ajistatus, aji_status_exec);
+ ast_cli_register_multiple(aji_cli, ARRAY_LEN(aji_cli));
+Index: res/res_monitor.c
+===================================================================
+--- a/res/res_monitor.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/res/res_monitor.c (.../trunk) (revision 202568)
+@@ -45,6 +45,200 @@
+ #include "asterisk/config.h"
+ #include "asterisk/options.h"
+
++/*** DOCUMENTATION
++ <application name="Monitor" language="en_US">
++ <synopsis>
++ Monitor a channel.
++ </synopsis>
++ <syntax>
++ <parameter name="file_format" argsep=":">
++ <argument name="file_format" required="true">
++ <para>optional, if not set, defaults to <literal>wav</literal></para>
++ </argument>
++ <argument name="urlbase" />
++ </parameter>
++ <parameter name="fname_base">
++ <para>if set, changes the filename used to the one specified.</para>
++ </parameter>
++ <parameter name="options">
++ <optionlist>
++ <option name="m">
++ <para>when the recording ends mix the two leg files into one and
++ delete the two leg files. If the variable <variable>MONITOR_EXEC</variable>
++ is set, the application referenced in it will be executed instead of
++ soxmix/sox and the raw leg files will NOT be deleted automatically.
++ soxmix/sox or <variable>MONITOR_EXEC</variable> is handed 3 arguments,
++ the two leg files and a target mixed file name which is the same as
++ the leg file names only without the in/out designator.</para>
++ <para>If <variable>MONITOR_EXEC_ARGS</variable> is set, the contents
++ will be passed on as additional arguments to <variable>MONITOR_EXEC</variable>.
++ Both <variable>MONITOR_EXEC</variable> and the Mix flag can be set from the
++ administrator interface.</para>
++ </option>
++ <option name="b">
++ <para>Don't begin recording unless a call is bridged to another channel.</para>
++ </option>
++ <option name="i">
++ <para>Skip recording of input stream (disables <literal>m</literal> option).</para>
++ </option>
++ <option name="o">
++ <para>Skip recording of output stream (disables <literal>m</literal> option).</para>
++ </option>
++ </optionlist>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Used to start monitoring a channel. The channel's input and output
++ voice packets are logged to files until the channel hangs up or
++ monitoring is stopped by the StopMonitor application.</para>
++ <para>By default, files are stored to <filename>/var/spool/asterisk/monitor/</filename>.
++ Returns <literal>-1</literal> if monitor files can't be opened or if the channel is
++ already monitored, otherwise <literal>0</literal>.</para>
++ </description>
++ <see-also>
++ <ref type="application">StopMonitor</ref>
++ </see-also>
++ </application>
++ <application name="StopMonitor" language="en_US">
++ <synopsis>
++ Stop monitoring a channel.
++ </synopsis>
++ <syntax />
++ <description>
++ <para>Stops monitoring a channel. Has no effect if the channel is not monitored.</para>
++ </description>
++ </application>
++ <application name="ChangeMonitor" language="en_US">
++ <synopsis>
++ Change monitoring filename of a channel.
++ </synopsis>
++ <syntax>
++ <parameter name="filename_base" required="true">
++ <para>The new filename base to use for monitoring this channel.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Changes monitoring filename of a channel. Has no effect if the
++ channel is not monitored.</para>
++ </description>
++ </application>
++ <application name="PauseMonitor" language="en_US">
++ <synopsis>
++ Pause monitoring of a channel.
++ </synopsis>
++ <syntax />
++ <description>
++ <para>Pauses monitoring of a channel until it is re-enabled by a call to UnpauseMonitor.</para>
++ </description>
++ <see-also>
++ <ref type="application">UnpauseMonitor</ref>
++ </see-also>
++ </application>
++ <application name="UnpauseMonitor" language="en_US">
++ <synopsis>
++ Unpause monitoring of a channel.
++ </synopsis>
++ <syntax />
++ <description>
++ <para>Unpauses monitoring of a channel on which monitoring had
++ previously been paused with PauseMonitor.</para>
++ </description>
++ <see-also>
++ <ref type="application">PauseMonitor</ref>
++ </see-also>
++ </application>
++ <manager name="Monitor" language="en_US">
++ <synopsis>
++ Monitor a channel.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Channel" required="true">
++ <para>Used to specify the channel to record.</para>
++ </parameter>
++ <parameter name="File">
++ <para>Is the name of the file created in the monitor spool directory.
++ Defaults to the same name as the channel (with slashes replaced with dashes).</para>
++ </parameter>
++ <parameter name="Format">
++ <para>Is the audio recording format. Defaults to <literal>wav</literal>.</para>
++ </parameter>
++ <parameter name="Mix">
++ <para>Boolean parameter as to whether to mix the input and output channels
++ together after the recording is finished.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>This action may be used to record the audio on a
++ specified channel.</para>
++ </description>
++ </manager>
++ <manager name="StopMonitor" language="en_US">
++ <synopsis>
++ Stop monitoring a channel.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Channel" required="true">
++ <para>The name of the channel monitored.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>This action may be used to end a previously started 'Monitor' action.</para>
++ </description>
++ </manager>
++ <manager name="ChangeMonitor" language="en_US">
++ <synopsis>
++ Change monitoring filename of a channel.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Channel" required="true">
++ <para>Used to specify the channel to record.</para>
++ </parameter>
++ <parameter name="File" required="true">
++ <para>Is the new name of the file created in the
++ monitor spool directory.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>This action may be used to change the file
++ started by a previous 'Monitor' action.</para>
++ </description>
++ </manager>
++ <manager name="PauseMonitor" language="en_US">
++ <synopsis>
++ Pause monitoring of a channel.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Channel" required="true">
++ <para>Used to specify the channel to record.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>This action may be used to temporarily stop the
++ recording of a channel.</para>
++ </description>
++ </manager>
++ <manager name="UnpauseMonitor" language="en_US">
++ <synopsis>
++ Unpause monitoring of a channel.
++ </synopsis>
++ <syntax>
++ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
++ <parameter name="Channel" required="true">
++ <para>Used to specify the channel to record.</para>
++ </parameter>
++ </syntax>
++ <description>
++ <para>This action may be used to re-enable recording
++ of a channel after calling PauseMonitor.</para>
++ </description>
++ </manager>
++
++ ***/
++
+ AST_MUTEX_DEFINE_STATIC(monitorlock);
+
+ #define LOCK_IF_NEEDED(lock, needed) do { \
+@@ -59,62 +253,6 @@
+
+ static unsigned long seq = 0;
+
+-static char *monitor_synopsis = "Monitor a channel";
+-
+-static char *monitor_descrip = " Monitor([file_format[:urlbase],[fname_base],[options]]):\n"
+-"Used to start monitoring a channel. The channel's input and output\n"
+-"voice packets are logged to files until the channel hangs up or\n"
+-"monitoring is stopped by the StopMonitor application.\n"
+-" file_format optional, if not set, defaults to \"wav\"\n"
+-" fname_base if set, changes the filename used to the one specified.\n"
+-" options:\n"
+-" m - when the recording ends mix the two leg files into one and\n"
+-" delete the two leg files. If the variable MONITOR_EXEC is set, the\n"
+-" application referenced in it will be executed instead of\n"
+-#ifdef HAVE_SOXMIX
+-" soxmix and the raw leg files will NOT be deleted automatically.\n"
+-" soxmix or MONITOR_EXEC is handed 3 arguments, the two leg files\n"
+-#else
+-" sox and the raw leg files will NOT be deleted automatically.\n"
+-" sox or MONITOR_EXEC is handed 3 arguments, the two leg files\n"
+-#endif
+-" and a target mixed file name which is the same as the leg file names\n"
+-" only without the in/out designator.\n"
+-" If MONITOR_EXEC_ARGS is set, the contents will be passed on as\n"
+-" additional arguments to MONITOR_EXEC\n"
+-" Both MONITOR_EXEC and the Mix flag can be set from the\n"
+-" administrator interface\n"
+-"\n"
+-" b - Don't begin recording unless a call is bridged to another channel\n"
+-" i - Skip recording of input stream (disables m option)\n"
+-" o - Skip recording of output stream (disables m option)\n"
+-"\nBy default, files are stored to /var/spool/asterisk/monitor/.\n"
+-"\nReturns -1 if monitor files can't be opened or if the channel is already\n"
+-"monitored, otherwise 0.\n"
+-;
+-
+-static char *stopmonitor_synopsis = "Stop monitoring a channel";
+-
+-static char *stopmonitor_descrip = " StopMonitor():\n"
+- "Stops monitoring a channel. Has no effect if the channel is not monitored\n";
+-
+-static char *changemonitor_synopsis = "Change monitoring filename of a channel";
+-
+-static char *changemonitor_descrip = " ChangeMonitor(filename_base):\n"
+- "Changes monitoring filename of a channel. Has no effect if the channel is not monitored.\n"
+- "The argument is the new filename base to use for monitoring this channel.\n";
+-
+-static char *pausemonitor_synopsis = "Pause monitoring of a channel";
+-
+-static char *pausemonitor_descrip = " PauseMonitor():\n"
+- "Pauses monitoring of a channel until it is re-enabled by a call to UnpauseMonitor.\n";
+-
+-static char *unpausemonitor_synopsis = "Unpause monitoring of a channel";
+-
+-static char *unpausemonitor_descrip = " UnpauseMonitor():\n"
+- "Unpauses monitoring of a channel on which monitoring had\n"
+- "previously been paused with PauseMonitor.\n";
+-
+ /*!
+ * \brief Change state of monitored channel
+ * \param chan
+@@ -145,8 +283,8 @@
+ * \retval 0 on success
+ * \retval -1 on failure
+ */
+-int ast_monitor_start( struct ast_channel *chan, const char *format_spec,
+- const char *fname_base, int need_lock, int stream_action)
++int AST_OPTIONAL_API_NAME(ast_monitor_start)(struct ast_channel *chan, const char *format_spec,
++ const char *fname_base, int need_lock, int stream_action)
+ {
+ int res = 0;
+
+@@ -285,7 +423,7 @@
+ * Stop the recording, close any open streams, mix in/out channels if required
+ * \return Always 0
+ */
+-int ast_monitor_stop(struct ast_channel *chan, int need_lock)
++int AST_OPTIONAL_API_NAME(ast_monitor_stop)(struct ast_channel *chan, int need_lock)
+ {
+ int delfiles = 0;
+
+@@ -378,25 +516,25 @@
+
+
+ /*! \brief Pause monitoring of channel */
+-int ast_monitor_pause(struct ast_channel *chan)
++int AST_OPTIONAL_API_NAME(ast_monitor_pause)(struct ast_channel *chan)
+ {
+ return ast_monitor_set_state(chan, AST_MONITOR_PAUSED);
+ }
+
+ /*! \brief Unpause monitoring of channel */
+-int ast_monitor_unpause(struct ast_channel *chan)
++int AST_OPTIONAL_API_NAME(ast_monitor_unpause)(struct ast_channel *chan)
+ {
+ return ast_monitor_set_state(chan, AST_MONITOR_RUNNING);
+ }
+
+ /*! \brief Wrapper for ast_monitor_pause */
+-static int pause_monitor_exec(struct ast_channel *chan, void *data)
++static int pause_monitor_exec(struct ast_channel *chan, const char *data)
+ {
+ return ast_monitor_pause(chan);
+ }
+
+ /*! \brief Wrapper for ast_monitor_unpause */
+-static int unpause_monitor_exec(struct ast_channel *chan, void *data)
++static int unpause_monitor_exec(struct ast_channel *chan, const char *data)
+ {
+ return ast_monitor_unpause(chan);
+ }
+@@ -409,7 +547,7 @@
+ * \retval 0 on success.
+ * \retval -1 on failure.
+ */
+-int ast_monitor_change_fname(struct ast_channel *chan, const char *fname_base, int need_lock)
++int AST_OPTIONAL_API_NAME(ast_monitor_change_fname)(struct ast_channel *chan, const char *fname_base, int need_lock)
+ {
+ if (ast_strlen_zero(fname_base)) {
+ ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to null\n", chan->name);
+@@ -457,7 +595,7 @@
+ * \retval 0 on success.
+ * \retval -1 on failure.
+ */
+-static int start_monitor_exec(struct ast_channel *chan, void *data)
++static int start_monitor_exec(struct ast_channel *chan, const char *data)
+ {
+ char *arg = NULL;
+ char *options = NULL;
+@@ -476,12 +614,12 @@
+ );
+
+ /* Parse arguments. */
+- if (ast_strlen_zero((char*)data)) {
++ if (ast_strlen_zero(data)) {
+ ast_log(LOG_ERROR, "Monitor requires an argument\n");
+ return 0;
+ }
+
+- parse = ast_strdupa((char*)data);
++ parse = ast_strdupa(data);
+ AST_STANDARD_APP_ARGS(args, parse);
+
+ if (!ast_strlen_zero(args.options)) {
+@@ -541,31 +679,17 @@
+ }
+
+ /*! \brief Wrapper function \see ast_monitor_stop */
+-static int stop_monitor_exec(struct ast_channel *chan, void *data)
++static int stop_monitor_exec(struct ast_channel *chan, const char *data)
+ {
+ return ast_monitor_stop(chan, 1);
+ }
+
+ /*! \brief Wrapper function \see ast_monitor_change_fname */
+-static int change_monitor_exec(struct ast_channel *chan, void *data)
++static int change_monitor_exec(struct ast_channel *chan, const char *data)
+ {
+- return ast_monitor_change_fname(chan, (const char*)data, 1);
++ return ast_monitor_change_fname(chan, data, 1);
+ }
+
+-static char start_monitor_action_help[] =
+-"Description: The 'Monitor' action may be used to record the audio on a\n"
+-" specified channel. The following parameters may be used to control\n"
+-" this:\n"
+-" Channel - Required. Used to specify the channel to record.\n"
+-" File - Optional. Is the name of the file created in the\n"
+-" monitor spool directory. Defaults to the same name\n"
+-" as the channel (with slashes replaced with dashes).\n"
+-" Format - Optional. Is the audio recording format. Defaults\n"
+-" to \"wav\".\n"
+-" Mix - Optional. Boolean parameter as to whether to mix\n"
+-" the input and output channels together after the\n"
+-" recording is finished.\n";
+-
+ /*! \brief Start monitoring a channel by manager connection */
+ static int start_monitor_action(struct mansession *s, const struct message *m)
+ {
+@@ -580,105 +704,111 @@
+ astman_send_error(s, m, "No channel specified");
+ return 0;
+ }
+- c = ast_get_channel_by_name_locked(name);
+- if (!c) {
++
++ if (!(c = ast_channel_get_by_name(name))) {
+ astman_send_error(s, m, "No such channel");
+ return 0;
+ }
+
+ if (ast_strlen_zero(fname)) {
+- /* No filename base specified, default to channel name as per CLI */
++ /* No filename base specified, default to channel name as per CLI */
++ ast_channel_lock(c);
+ fname = ast_strdupa(c->name);
++ ast_channel_unlock(c);
+ /* Channels have the format technology/channel_name - have to replace that / */
+- if ((d = strchr(fname, '/')))
++ if ((d = strchr(fname, '/'))) {
+ *d = '-';
++ }
+ }
+
+ if (ast_monitor_start(c, format, fname, 1, X_REC_IN | X_REC_OUT)) {
+ if (ast_monitor_change_fname(c, fname, 1)) {
+ astman_send_error(s, m, "Could not start monitoring channel");
+- ast_channel_unlock(c);
++ c = ast_channel_unref(c);
+ return 0;
+ }
+ }
+
+ if (ast_true(mix)) {
++ ast_channel_lock(c);
+ ast_monitor_setjoinfiles(c, 1);
++ ast_channel_unlock(c);
+ }
+
+- ast_channel_unlock(c);
++ c = ast_channel_unref(c);
++
+ astman_send_ack(s, m, "Started monitoring channel");
++
+ return 0;
+ }
+
+-static char stop_monitor_action_help[] =
+-"Description: The 'StopMonitor' action may be used to end a previously\n"
+-" started 'Monitor' action. The only parameter is 'Channel', the name\n"
+-" of the channel monitored.\n";
+-
+ /*! \brief Stop monitoring a channel by manager connection */
+ static int stop_monitor_action(struct mansession *s, const struct message *m)
+ {
+ struct ast_channel *c = NULL;
+ const char *name = astman_get_header(m, "Channel");
+ int res;
++
+ if (ast_strlen_zero(name)) {
+ astman_send_error(s, m, "No channel specified");
+ return 0;
+ }
+- c = ast_get_channel_by_name_locked(name);
+- if (!c) {
++
++ if (!(c = ast_channel_get_by_name(name))) {
+ astman_send_error(s, m, "No such channel");
+ return 0;
+ }
++
+ res = ast_monitor_stop(c, 1);
+- ast_channel_unlock(c);
++
++ c = ast_channel_unref(c);
++
+ if (res) {
+ astman_send_error(s, m, "Could not stop monitoring channel");
+ return 0;
+ }
++
+ astman_send_ack(s, m, "Stopped monitoring channel");
++
+ return 0;
+ }
+
+-static char change_monitor_action_help[] =
+-"Description: The 'ChangeMonitor' action may be used to change the file\n"
+-" started by a previous 'Monitor' action. The following parameters may\n"
+-" be used to control this:\n"
+-" Channel - Required. Used to specify the channel to record.\n"
+-" File - Required. Is the new name of the file created in the\n"
+-" monitor spool directory.\n";
+-
+ /*! \brief Change filename of a monitored channel by manager connection */
+ static int change_monitor_action(struct mansession *s, const struct message *m)
+ {
+ struct ast_channel *c = NULL;
+ const char *name = astman_get_header(m, "Channel");
+ const char *fname = astman_get_header(m, "File");
++
+ if (ast_strlen_zero(name)) {
+ astman_send_error(s, m, "No channel specified");
+ return 0;
+ }
++
+ if (ast_strlen_zero(fname)) {
+ astman_send_error(s, m, "No filename specified");
+ return 0;
+ }
+- c = ast_get_channel_by_name_locked(name);
+- if (!c) {
++
++ if (!(c = ast_channel_get_by_name(name))) {
+ astman_send_error(s, m, "No such channel");
+ return 0;
+ }
++
+ if (ast_monitor_change_fname(c, fname, 1)) {
++ c = ast_channel_unref(c);
+ astman_send_error(s, m, "Could not change monitored filename of channel");
+- ast_channel_unlock(c);
+ return 0;
+ }
+- ast_channel_unlock(c);
++
++ c = ast_channel_unref(c);
++
+ astman_send_ack(s, m, "Changed monitor filename");
++
+ return 0;
+ }
+
+-void ast_monitor_setjoinfiles(struct ast_channel *chan, int turnon)
++void AST_OPTIONAL_API_NAME(ast_monitor_setjoinfiles)(struct ast_channel *chan, int turnon)
+ {
+ if (chan->monitor)
+ chan->monitor->joinfiles = turnon;
+@@ -689,50 +819,40 @@
+ MONITOR_ACTION_PAUSE,
+ MONITOR_ACTION_UNPAUSE
+ };
+-
++
+ static int do_pause_or_unpause(struct mansession *s, const struct message *m, int action)
+ {
+ struct ast_channel *c = NULL;
+ const char *name = astman_get_header(m, "Channel");
+-
++
+ if (ast_strlen_zero(name)) {
+ astman_send_error(s, m, "No channel specified");
+ return -1;
+ }
+-
+- c = ast_get_channel_by_name_locked(name);
+- if (!c) {
++
++ if (!(c = ast_channel_get_by_name(name))) {
+ astman_send_error(s, m, "No such channel");
+ return -1;
+ }
+
+- if (action == MONITOR_ACTION_PAUSE)
++ if (action == MONITOR_ACTION_PAUSE) {
+ ast_monitor_pause(c);
+- else
++ } else {
+ ast_monitor_unpause(c);
+-
+- ast_channel_unlock(c);
++ }
++
++ c = ast_channel_unref(c);
++
+ astman_send_ack(s, m, (action == MONITOR_ACTION_PAUSE ? "Paused monitoring of the channel" : "Unpaused monitoring of the channel"));
+- return 0;
++
++ return 0;
+ }
+
+-static char pause_monitor_action_help[] =
+- "Description: The 'PauseMonitor' action may be used to temporarily stop the\n"
+- " recording of a channel. The following parameters may\n"
+- " be used to control this:\n"
+- " Channel - Required. Used to specify the channel to record.\n";
+-
+ static int pause_monitor_action(struct mansession *s, const struct message *m)
+ {
+ return do_pause_or_unpause(s, m, MONITOR_ACTION_PAUSE);
+ }
+
+-static char unpause_monitor_action_help[] =
+- "Description: The 'UnpauseMonitor' action may be used to re-enable recording\n"
+- " of a channel after calling PauseMonitor. The following parameters may\n"
+- " be used to control this:\n"
+- " Channel - Required. Used to specify the channel to record.\n";
+-
+ static int unpause_monitor_action(struct mansession *s, const struct message *m)
+ {
+ return do_pause_or_unpause(s, m, MONITOR_ACTION_UNPAUSE);
+@@ -741,16 +861,16 @@
+
+ static int load_module(void)
+ {
+- ast_register_application("Monitor", start_monitor_exec, monitor_synopsis, monitor_descrip);
+- ast_register_application("StopMonitor", stop_monitor_exec, stopmonitor_synopsis, stopmonitor_descrip);
+- ast_register_application("ChangeMonitor", change_monitor_exec, changemonitor_synopsis, changemonitor_descrip);
+- ast_register_application("PauseMonitor", pause_monitor_exec, pausemonitor_synopsis, pausemonitor_descrip);
+- ast_register_application("UnpauseMonitor", unpause_monitor_exec, unpausemonitor_synopsis, unpausemonitor_descrip);
+- ast_manager_register2("Monitor", EVENT_FLAG_CALL, start_monitor_action, monitor_synopsis, start_monitor_action_help);
+- ast_manager_register2("StopMonitor", EVENT_FLAG_CALL, stop_monitor_action, stopmonitor_synopsis, stop_monitor_action_help);
+- ast_manager_register2("ChangeMonitor", EVENT_FLAG_CALL, change_monitor_action, changemonitor_synopsis, change_monitor_action_help);
+- ast_manager_register2("PauseMonitor", EVENT_FLAG_CALL, pause_monitor_action, pausemonitor_synopsis, pause_monitor_action_help);
+- ast_manager_register2("UnpauseMonitor", EVENT_FLAG_CALL, unpause_monitor_action, unpausemonitor_synopsis, unpause_monitor_action_help);
++ ast_register_application_xml("Monitor", start_monitor_exec);
++ ast_register_application_xml("StopMonitor", stop_monitor_exec);
++ ast_register_application_xml("ChangeMonitor", change_monitor_exec);
++ ast_register_application_xml("PauseMonitor", pause_monitor_exec);
++ ast_register_application_xml("UnpauseMonitor", unpause_monitor_exec);
++ ast_manager_register_xml("Monitor", EVENT_FLAG_CALL, start_monitor_action);
++ ast_manager_register_xml("StopMonitor", EVENT_FLAG_CALL, stop_monitor_action);
++ ast_manager_register_xml("ChangeMonitor", EVENT_FLAG_CALL, change_monitor_action);
++ ast_manager_register_xml("PauseMonitor", EVENT_FLAG_CALL, pause_monitor_action);
++ ast_manager_register_xml("UnpauseMonitor", EVENT_FLAG_CALL, unpause_monitor_action);
+
+ return AST_MODULE_LOAD_SUCCESS;
+ }
+Index: res/res_odbc.exports
+===================================================================
+--- a/res/res_odbc.exports (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/res/res_odbc.exports (.../trunk) (revision 202568)
+@@ -0,0 +1,20 @@
++{
++ global:
++ ast_odbc_ast_str_SQLGetData;
++ ast_odbc_backslash_is_escape;
++ ast_odbc_clear_cache;
++ ast_odbc_direct_execute;
++ ast_odbc_find_column;
++ ast_odbc_find_table;
++ ast_odbc_prepare_and_execute;
++ ast_odbc_release_obj;
++ ast_odbc_request_obj;
++ _ast_odbc_request_obj;
++ ast_odbc_request_obj2;
++ _ast_odbc_request_obj2;
++ ast_odbc_retrieve_transaction_obj;
++ ast_odbc_sanity_check;
++ ast_odbc_smart_execute;
++ local:
++ *;
++};
+
+Property changes on: res/res_odbc.exports
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+
+Index: res/res_config_curl.c
+===================================================================
+--- a/res/res_config_curl.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/res/res_config_curl.c (.../trunk) (revision 202568)
+@@ -43,7 +43,11 @@
+ #include "asterisk/module.h"
+ #include "asterisk/lock.h"
+ #include "asterisk/utils.h"
++#include "asterisk/threadstorage.h"
+
++AST_THREADSTORAGE(query_buf);
++AST_THREADSTORAGE(result_buf);
++
+ /*!
+ * \brief Execute a curl query and return ast_variable list
+ * \param url The base URL from which to retrieve data
+@@ -55,25 +59,24 @@
+ */
+ static struct ast_variable *realtime_curl(const char *url, const char *unused, va_list ap)
+ {
+- struct ast_str *query;
+- char buf1[200], buf2[200];
++ struct ast_str *query, *buffer;
++ char buf1[256], buf2[256];
+ const char *newparam, *newval;
+ char *stringp, *pair, *key;
+ int i;
+- struct ast_variable *var=NULL, *prev=NULL;
+- const int EncodeSpecialChars = 1, bufsize = 64000;
+- char *buffer;
++ struct ast_variable *var = NULL, *prev = NULL;
++ const int EncodeSpecialChars = 1;
+
+ if (!ast_custom_function_find("CURL")) {
+ ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
+ return NULL;
+ }
+
+- if (!(query = ast_str_create(1000)))
++ if (!(query = ast_str_thread_get(&query_buf, 16))) {
+ return NULL;
++ }
+
+- if (!(buffer = ast_malloc(bufsize))) {
+- ast_free(query);
++ if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
+ return NULL;
+ }
+
+@@ -88,31 +91,33 @@
+ va_end(ap);
+
+ ast_str_append(&query, 0, ")}");
+- pbx_substitute_variables_helper(NULL, ast_str_buffer(query), buffer, bufsize);
++ ast_str_substitute_variables(&buffer, 0, NULL, ast_str_buffer(query));
+
+ /* Remove any trailing newline characters */
+- if ((stringp = strchr(buffer, '\r')) || (stringp = strchr(buffer, '\n')))
++ if ((stringp = strchr(ast_str_buffer(buffer), '\r')) || (stringp = strchr(ast_str_buffer(buffer), '\n'))) {
+ *stringp = '\0';
++ }
+
+- stringp = buffer;
++ stringp = ast_str_buffer(buffer);
+ while ((pair = strsep(&stringp, "&"))) {
+ key = strsep(&pair, "=");
+ ast_uri_decode(key);
+- if (pair)
++ if (pair) {
+ ast_uri_decode(pair);
++ }
+
+ if (!ast_strlen_zero(key)) {
+ if (prev) {
+ prev->next = ast_variable_new(key, S_OR(pair, ""), "");
+- if (prev->next)
++ if (prev->next) {
+ prev = prev->next;
+- } else
++ }
++ } else {
+ prev = var = ast_variable_new(key, S_OR(pair, ""), "");
++ }
+ }
+ }
+
+- ast_free(buffer);
+- ast_free(query);
+ return var;
+ }
+
+@@ -127,27 +132,26 @@
+ */
+ static struct ast_config *realtime_multi_curl(const char *url, const char *unused, va_list ap)
+ {
+- struct ast_str *query;
+- char buf1[200], buf2[200];
++ struct ast_str *query, *buffer;
++ char buf1[256], buf2[256];
+ const char *newparam, *newval;
+ char *stringp, *line, *pair, *key, *initfield = NULL;
+ int i;
+- const int EncodeSpecialChars = 1, bufsize = 256000;
+- struct ast_variable *var=NULL;
+- struct ast_config *cfg=NULL;
+- struct ast_category *cat=NULL;
+- char *buffer;
++ const int EncodeSpecialChars = 1;
++ struct ast_variable *var = NULL;
++ struct ast_config *cfg = NULL;
++ struct ast_category *cat = NULL;
+
+ if (!ast_custom_function_find("CURL")) {
+ ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
+ return NULL;
+ }
+
+- if (!(query = ast_str_create(1000)))
++ if (!(query = ast_str_thread_get(&query_buf, 16))) {
+ return NULL;
++ }
+
+- if (!(buffer = ast_malloc(bufsize))) {
+- ast_free(query);
++ if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
+ return NULL;
+ }
+
+@@ -170,28 +174,33 @@
+ ast_str_append(&query, 0, ")}");
+
+ /* Do the CURL query */
+- pbx_substitute_variables_helper(NULL, ast_str_buffer(query), buffer, bufsize);
++ ast_str_substitute_variables(&buffer, 0, NULL, ast_str_buffer(query));
+
+- if (!(cfg = ast_config_new()))
+- goto exit_multi;
++ if (!(cfg = ast_config_new())) {
++ return NULL;
++ }
+
+ /* Line oriented output */
+- stringp = buffer;
++ stringp = ast_str_buffer(buffer);
+ while ((line = strsep(&stringp, "\r\n"))) {
+- if (ast_strlen_zero(line))
++ if (ast_strlen_zero(line)) {
+ continue;
++ }
+
+- if (!(cat = ast_category_new("", "", 99999)))
++ if (!(cat = ast_category_new("", "", 99999))) {
+ continue;
++ }
+
+ while ((pair = strsep(&line, "&"))) {
+ key = strsep(&pair, "=");
+ ast_uri_decode(key);
+- if (pair)
++ if (pair) {
+ ast_uri_decode(pair);
++ }
+
+- if (!strcasecmp(key, initfield) && pair)
++ if (!strcasecmp(key, initfield) && pair) {
+ ast_category_rename(cat, pair);
++ }
+
+ if (!ast_strlen_zero(key)) {
+ var = ast_variable_new(key, S_OR(pair, ""), "");
+@@ -201,9 +210,6 @@
+ ast_category_append(cfg, cat);
+ }
+
+-exit_multi:
+- ast_free(buffer);
+- ast_free(query);
+ return cfg;
+ }
+
+@@ -224,24 +230,23 @@
+ */
+ static int update_curl(const char *url, const char *unused, const char *keyfield, const char *lookup, va_list ap)
+ {
+- struct ast_str *query;
+- char buf1[200], buf2[200];
++ struct ast_str *query, *buffer;
++ char buf1[256], buf2[256];
+ const char *newparam, *newval;
+ char *stringp;
+ int i, rowcount = -1;
+- const int EncodeSpecialChars = 1, bufsize = 100;
+- char *buffer;
++ const int EncodeSpecialChars = 1;
+
+ if (!ast_custom_function_find("CURL")) {
+ ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
+ return -1;
+ }
+
+- if (!(query = ast_str_create(1000)))
++ if (!(query = ast_str_thread_get(&query_buf, 16))) {
+ return -1;
++ }
+
+- if (!(buffer = ast_malloc(bufsize))) {
+- ast_free(query);
++ if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
+ return -1;
+ }
+
+@@ -258,43 +263,40 @@
+ va_end(ap);
+
+ ast_str_append(&query, 0, ")}");
+- pbx_substitute_variables_helper(NULL, ast_str_buffer(query), buffer, bufsize);
++ ast_str_substitute_variables(&buffer, 0, NULL, ast_str_buffer(query));
+
+ /* Line oriented output */
+- stringp = buffer;
+- while (*stringp <= ' ')
++ stringp = ast_str_buffer(buffer);
++ while (*stringp <= ' ') {
+ stringp++;
++ }
+ sscanf(stringp, "%d", &rowcount);
+
+- ast_free(buffer);
+- ast_free(query);
+-
+- if (rowcount >= 0)
++ if (rowcount >= 0) {
+ return (int)rowcount;
++ }
+
+ return -1;
+ }
+
+ static int update2_curl(const char *url, const char *unused, va_list ap)
+ {
+- struct ast_str *query;
++ struct ast_str *query, *buffer;
+ char buf1[200], buf2[200];
+ const char *newparam, *newval;
+ char *stringp;
+ int rowcount = -1, lookup = 1, first = 1;
+- const int EncodeSpecialChars = 1, bufsize = 100;
+- char *buffer;
++ const int EncodeSpecialChars = 1;
+
+ if (!ast_custom_function_find("CURL")) {
+ ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
+ return -1;
+ }
+
+- if (!(query = ast_str_create(1000)))
++ if (!(query = ast_str_thread_get(&query_buf, 1000)))
+ return -1;
+
+- if (!(buffer = ast_malloc(bufsize))) {
+- ast_free(query);
++ if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
+ return -1;
+ }
+
+@@ -316,24 +318,27 @@
+ ast_uri_encode(newparam, buf1, sizeof(buf1), EncodeSpecialChars);
+ ast_uri_encode(newval, buf2, sizeof(buf2), EncodeSpecialChars);
+ ast_str_append(&query, 0, "%s%s=%s", first ? "" : "&", buf1, buf2);
++ first = 0;
+ }
+ va_end(ap);
+
+ ast_str_append(&query, 0, ")}");
+- /* TODO: Make proxies work */
+- pbx_substitute_variables_helper(NULL, ast_str_buffer(query), buffer, bufsize);
++ /* Proxies work, by setting CURLOPT options in the [globals] section of
++ * extensions.conf. Unfortunately, this means preloading pbx_config.so
++ * so that they have an opportunity to be set prior to startup realtime
++ * queries. */
++ ast_str_substitute_variables(&buffer, 0, NULL, ast_str_buffer(query));
+
+ /* Line oriented output */
+- stringp = buffer;
+- while (*stringp <= ' ')
++ stringp = ast_str_buffer(buffer);
++ while (*stringp <= ' ') {
+ stringp++;
++ }
+ sscanf(stringp, "%d", &rowcount);
+
+- ast_free(buffer);
+- ast_free(query);
+-
+- if (rowcount >= 0)
++ if (rowcount >= 0) {
+ return (int)rowcount;
++ }
+
+ return -1;
+ }
+@@ -353,24 +358,23 @@
+ */
+ static int store_curl(const char *url, const char *unused, va_list ap)
+ {
+- struct ast_str *query;
+- char buf1[200], buf2[200];
++ struct ast_str *query, *buffer;
++ char buf1[256], buf2[256];
+ const char *newparam, *newval;
+ char *stringp;
+ int i, rowcount = -1;
+- const int EncodeSpecialChars = 1, bufsize = 100;
+- char *buffer;
++ const int EncodeSpecialChars = 1;
+
+ if (!ast_custom_function_find("CURL")) {
+ ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
+ return -1;
+ }
+
+- if (!(query = ast_str_create(1000)))
++ if (!(query = ast_str_thread_get(&query_buf, 1000))) {
+ return -1;
++ }
+
+- if (!(buffer = ast_malloc(bufsize))) {
+- ast_free(query);
++ if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
+ return -1;
+ }
+
+@@ -385,19 +389,18 @@
+ va_end(ap);
+
+ ast_str_append(&query, 0, ")}");
+- pbx_substitute_variables_helper(NULL, ast_str_buffer(query), buffer, bufsize);
++ ast_str_substitute_variables(&buffer, 0, NULL, ast_str_buffer(query));
+
+- stringp = buffer;
+- while (*stringp <= ' ')
++ stringp = ast_str_buffer(buffer);
++ while (*stringp <= ' ') {
+ stringp++;
++ }
+ sscanf(stringp, "%d", &rowcount);
+
+- ast_free(buffer);
+- ast_free(query);
++ if (rowcount >= 0) {
++ return rowcount;
++ }
+
+- if (rowcount >= 0)
+- return (int)rowcount;
+-
+ return -1;
+ }
+
+@@ -418,24 +421,23 @@
+ */
+ static int destroy_curl(const char *url, const char *unused, const char *keyfield, const char *lookup, va_list ap)
+ {
+- struct ast_str *query;
++ struct ast_str *query, *buffer;
+ char buf1[200], buf2[200];
+ const char *newparam, *newval;
+ char *stringp;
+ int i, rowcount = -1;
+- const int EncodeSpecialChars = 1, bufsize = 100;
+- char *buffer;
++ const int EncodeSpecialChars = 1;
+
+ if (!ast_custom_function_find("CURL")) {
+ ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
+ return -1;
+ }
+
+- if (!(query = ast_str_create(1000)))
++ if (!(query = ast_str_thread_get(&query_buf, 1000))) {
+ return -1;
++ }
+
+- if (!(buffer = ast_malloc(bufsize))) {
+- ast_free(query);
++ if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
+ return -1;
+ }
+
+@@ -452,27 +454,26 @@
+ va_end(ap);
+
+ ast_str_append(&query, 0, ")}");
+- pbx_substitute_variables_helper(NULL, ast_str_buffer(query), buffer, bufsize);
++ ast_str_substitute_variables(&buffer, 0, NULL, ast_str_buffer(query));
+
+ /* Line oriented output */
+- stringp = buffer;
+- while (*stringp <= ' ')
++ stringp = ast_str_buffer(buffer);
++ while (*stringp <= ' ') {
+ stringp++;
++ }
+ sscanf(stringp, "%d", &rowcount);
+
+- ast_free(buffer);
+- ast_free(query);
+-
+- if (rowcount >= 0)
++ if (rowcount >= 0) {
+ return (int)rowcount;
++ }
+
+ return -1;
+ }
+
+ static int require_curl(const char *url, const char *unused, va_list ap)
+ {
+- struct ast_str *query;
+- char *elm, field[256], buffer[128];
++ struct ast_str *query, *buffer;
++ char *elm, field[256];
+ int type, size;
+ const int EncodeSpecialChars = 1;
+
+@@ -481,10 +482,14 @@
+ return -1;
+ }
+
+- if (!(query = ast_str_create(100))) {
++ if (!(query = ast_str_thread_get(&query_buf, 100))) {
+ return -1;
+ }
+
++ if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
++ return -1;
++ }
++
+ ast_str_set(&query, 0, "${CURL(%s/require,", url);
+
+ while ((elm = va_arg(ap, char *))) {
+@@ -511,19 +516,19 @@
+ va_end(ap);
+
+ ast_str_append(&query, 0, ")}");
+- pbx_substitute_variables_helper(NULL, ast_str_buffer(query), buffer, sizeof(buffer));
+- return atoi(buffer);
++ ast_str_substitute_variables(&buffer, 0, NULL, ast_str_buffer(query));
++ return atoi(ast_str_buffer(buffer));
+ }
+
+ static struct ast_config *config_curl(const char *url, const char *unused, const char *file, struct ast_config *cfg, struct ast_flags flags, const char *sugg_incl, const char *who_asked)
+ {
+- struct ast_str *query;
++ struct ast_str *query, *buffer;
+ char buf1[200];
+ char *stringp, *line, *pair, *key;
+- const int EncodeSpecialChars = 1, bufsize = 256000;
++ const int EncodeSpecialChars = 1;
+ int last_cat_metric = -1, cat_metric = -1;
+- struct ast_category *cat=NULL;
+- char *buffer, *cur_cat = "";
++ struct ast_category *cat = NULL;
++ char *cur_cat = "";
+ char *category = "", *var_name = "", *var_val = "";
+ struct ast_flags loader_flags = { 0 };
+
+@@ -532,11 +537,11 @@
+ return NULL;
+ }
+
+- if (!(query = ast_str_create(1000)))
++ if (!(query = ast_str_thread_get(&query_buf, 100))) {
+ return NULL;
++ }
+
+- if (!(buffer = ast_malloc(bufsize))) {
+- ast_free(query);
++ if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
+ return NULL;
+ }
+
+@@ -544,30 +549,33 @@
+ ast_str_set(&query, 0, "${CURL(%s/static?file=%s)}", url, buf1);
+
+ /* Do the CURL query */
+- pbx_substitute_variables_helper(NULL, ast_str_buffer(query), buffer, bufsize);
++ ast_str_substitute_variables(&buffer, 0, NULL, ast_str_buffer(query));
+
+ /* Line oriented output */
+- stringp = buffer;
++ stringp = ast_str_buffer(buffer);
+ cat = ast_config_get_current_category(cfg);
+
+ while ((line = strsep(&stringp, "\r\n"))) {
+- if (ast_strlen_zero(line))
++ if (ast_strlen_zero(line)) {
+ continue;
++ }
+
+ while ((pair = strsep(&line, "&"))) {
+ key = strsep(&pair, "=");
+ ast_uri_decode(key);
+- if (pair)
++ if (pair) {
+ ast_uri_decode(pair);
++ }
+
+- if (!strcasecmp(key, "category"))
++ if (!strcasecmp(key, "category")) {
+ category = S_OR(pair, "");
+- else if (!strcasecmp(key, "var_name"))
++ } else if (!strcasecmp(key, "var_name")) {
+ var_name = S_OR(pair, "");
+- else if (!strcasecmp(key, "var_val"))
++ } else if (!strcasecmp(key, "var_val")) {
+ var_val = S_OR(pair, "");
+- else if (!strcasecmp(key, "cat_metric"))
++ } else if (!strcasecmp(key, "cat_metric")) {
+ cat_metric = pair ? atoi(pair) : 0;
++ }
+ }
+
+ if (!strcmp(var_name, "#include")) {
+@@ -585,8 +593,6 @@
+ ast_variable_append(cat, ast_variable_new(var_name, var_val, ""));
+ }
+
+- ast_free(buffer);
+- ast_free(query);
+ return cfg;
+ }
+
+Index: res/res_calendar.exports
+===================================================================
+--- a/res/res_calendar.exports (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/res/res_calendar.exports (.../trunk) (revision 202568)
+@@ -0,0 +1,7 @@
++{
++ global:
++ ast_*;
++ calendar_config;
++ local:
++ *;
++};
+
+Property changes on: res/res_calendar.exports
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+
+Index: res/res_smdi.c
+===================================================================
+--- a/res/res_smdi.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/res/res_smdi.c (.../trunk) (revision 202568)
+@@ -57,6 +57,100 @@
+ /* Message expiry time in milliseconds */
+ #define SMDI_MSG_EXPIRY_TIME 30000 /* 30 seconds */
+
++/*** DOCUMENTATION
++
++ <function name="SMDI_MSG_RETRIEVE" language="en_US">
++ <synopsis>
++ Retrieve an SMDI message.
++ </synopsis>
++ <syntax>
++ <parameter name="smdi port" required="true" />
++ <parameter name="search key" required="true" />
++ <parameter name="timeout" />
++ <parameter name="options">
++ <enumlist>
++ <enum name="t">
++ <para>Instead of searching on the forwarding station, search on the message desk terminal.</para>
++ </enum>
++ <enum name="n">
++ <para>Instead of searching on the forwarding station, search on the message desk number.</para>
++ </enum>
++ </enumlist>
++ </parameter>
++ </syntax>
++ <description>
++ <para>This function is used to retrieve an incoming SMDI message. It returns
++ an ID which can be used with the SMDI_MSG() function to access details of
++ the message. Note that this is a destructive function in the sense that
++ once an SMDI message is retrieved using this function, it is no longer in
++ the global SMDI message queue, and can not be accessed by any other Asterisk
++ channels. The timeout for this function is optional, and the default is
++ 3 seconds. When providing a timeout, it should be in milliseconds.
++ </para>
++ <para>The default search is done on the forwarding station ID. However, if
++ you set one of the search key options in the options field, you can change
++ this behavior.
++ </para>
++ </description>
++ <see-also>
++ <ref type="function">SMDI_MSG</ref>
++ </see-also>
++ </function>
++ <function name="SMDI_MSG" language="en_US">
++ <synopsis>
++ Retrieve details about an SMDI message.
++ </synopsis>
++ <syntax>
++ <parameter name="message_id" required="true" />
++ <parameter name="component" required="true">
++ <para>Valid message components are:</para>
++ <enumlist>
++ <enum name="number">
++ <para>The message desk number</para>
++ </enum>
++ <enum name="terminal">
++ <para>The message desk terminal</para>
++ </enum>
++ <enum name="station">
++ <para>The forwarding station</para>
++ </enum>
++ <enum name="callerid">
++ <para>The callerID of the calling party that was forwarded</para>
++ </enum>
++ <enum name="type">
++ <para>The call type. The value here is the exact character
++ that came in on the SMDI link. Typically, example values
++ are:</para>
++ <para>Options:</para>
++ <enumlist>
++ <enum name="D">
++ <para>Direct Calls</para>
++ </enum>
++ <enum name="A">
++ <para>Forward All Calls</para>
++ </enum>
++ <enum name="B">
++ <para>Forward Busy Calls</para>
++ </enum>
++ <enum name="N">
++ <para>Forward No Answer Calls</para>
++ </enum>
++ </enumlist>
++ </enum>
++ </enumlist>
++ </parameter>
++ </syntax>
++ <description>
++ <para>This function is used to access details of an SMDI message that was
++ pulled from the incoming SMDI message queue using the SMDI_MSG_RETRIEVE()
++ function.</para>
++ </description>
++ <see-also>
++ <ref type="function">SMDI_MSG_RETRIEVE</ref>
++ </see-also>
++ </function>
++ ***/
++
+ static const char config_file[] = "smdi.conf";
+
+ /*! \brief SMDI message desk message queue. */
+@@ -86,7 +180,7 @@
+ };
+
+ /*! \brief SMDI interface container. */
+-struct ast_smdi_interface_container {
++static struct ast_smdi_interface_container {
+ ASTOBJ_CONTAINER_COMPONENTS(struct ast_smdi_interface);
+ } smdi_ifaces;
+
+@@ -157,7 +251,7 @@
+ ast_module_unref(ast_module_info->self);
+ }
+
+-void ast_smdi_interface_unref(struct ast_smdi_interface *iface)
++void AST_OPTIONAL_API_NAME(ast_smdi_interface_unref)(struct ast_smdi_interface *iface)
+ {
+ ASTOBJ_UNREF(iface, ast_smdi_interface_destroy);
+ }
+@@ -217,17 +311,17 @@
+ return 0;
+ }
+
+-int ast_smdi_mwi_set(struct ast_smdi_interface *iface, const char *mailbox)
++int AST_OPTIONAL_API_NAME(ast_smdi_mwi_set)(struct ast_smdi_interface *iface, const char *mailbox)
+ {
+ return smdi_toggle_mwi(iface, mailbox, 1);
+ }
+
+-int ast_smdi_mwi_unset(struct ast_smdi_interface *iface, const char *mailbox)
++int AST_OPTIONAL_API_NAME(ast_smdi_mwi_unset)(struct ast_smdi_interface *iface, const char *mailbox)
+ {
+ return smdi_toggle_mwi(iface, mailbox, 0);
+ }
+
+-void ast_smdi_md_message_putback(struct ast_smdi_interface *iface, struct ast_smdi_md_message *md_msg)
++void AST_OPTIONAL_API_NAME(ast_smdi_md_message_putback)(struct ast_smdi_interface *iface, struct ast_smdi_md_message *md_msg)
+ {
+ ast_mutex_lock(&iface->md_q_lock);
+ ASTOBJ_CONTAINER_LINK_START(&iface->md_q, md_msg);
+@@ -235,7 +329,7 @@
+ ast_mutex_unlock(&iface->md_q_lock);
+ }
+
+-void ast_smdi_mwi_message_putback(struct ast_smdi_interface *iface, struct ast_smdi_mwi_message *mwi_msg)
++void AST_OPTIONAL_API_NAME(ast_smdi_mwi_message_putback)(struct ast_smdi_interface *iface, struct ast_smdi_mwi_message *mwi_msg)
+ {
+ ast_mutex_lock(&iface->mwi_q_lock);
+ ASTOBJ_CONTAINER_LINK_START(&iface->mwi_q, mwi_msg);
+@@ -496,36 +590,36 @@
+ return NULL;
+ }
+
+-struct ast_smdi_md_message *ast_smdi_md_message_pop(struct ast_smdi_interface *iface)
++struct ast_smdi_md_message * AST_OPTIONAL_API_NAME(ast_smdi_md_message_pop)(struct ast_smdi_interface *iface)
+ {
+ return smdi_msg_pop(iface, SMDI_MD);
+ }
+
+-struct ast_smdi_md_message *ast_smdi_md_message_wait(struct ast_smdi_interface *iface, int timeout)
++struct ast_smdi_md_message * AST_OPTIONAL_API_NAME(ast_smdi_md_message_wait)(struct ast_smdi_interface *iface, int timeout)
+ {
+ struct ast_flags options = { 0 };
+ return smdi_message_wait(iface, timeout, SMDI_MD, NULL, options);
+ }
+
+-struct ast_smdi_mwi_message *ast_smdi_mwi_message_pop(struct ast_smdi_interface *iface)
++struct ast_smdi_mwi_message * AST_OPTIONAL_API_NAME(ast_smdi_mwi_message_pop)(struct ast_smdi_interface *iface)
+ {
+ return smdi_msg_pop(iface, SMDI_MWI);
+ }
+
+-struct ast_smdi_mwi_message *ast_smdi_mwi_message_wait(struct ast_smdi_interface *iface, int timeout)
++struct ast_smdi_mwi_message * AST_OPTIONAL_API_NAME(ast_smdi_mwi_message_wait)(struct ast_smdi_interface *iface, int timeout)
+ {
+ struct ast_flags options = { 0 };
+ return smdi_message_wait(iface, timeout, SMDI_MWI, NULL, options);
+ }
+
+-struct ast_smdi_mwi_message *ast_smdi_mwi_message_wait_station(struct ast_smdi_interface *iface, int timeout,
++struct ast_smdi_mwi_message * AST_OPTIONAL_API_NAME(ast_smdi_mwi_message_wait_station)(struct ast_smdi_interface *iface, int timeout,
+ const char *station)
+ {
+ struct ast_flags options = { 0 };
+ return smdi_message_wait(iface, timeout, SMDI_MWI, station, options);
+ }
+
+-struct ast_smdi_interface *ast_smdi_interface_find(const char *iface_name)
++struct ast_smdi_interface * AST_OPTIONAL_API_NAME(ast_smdi_interface_find)(const char *iface_name)
+ {
+ return (ASTOBJ_CONTAINER_FIND(&smdi_ifaces, iface_name));
+ }
+@@ -722,12 +816,12 @@
+ return NULL;
+ }
+
+-void ast_smdi_md_message_destroy(struct ast_smdi_md_message *msg)
++void AST_OPTIONAL_API_NAME(ast_smdi_md_message_destroy)(struct ast_smdi_md_message *msg)
+ {
+ ast_free(msg);
+ }
+
+-void ast_smdi_mwi_message_destroy(struct ast_smdi_mwi_message *msg)
++void AST_OPTIONAL_API_NAME(ast_smdi_mwi_message_destroy)(struct ast_smdi_mwi_message *msg)
+ {
+ ast_free(msg);
+ }
+@@ -1044,7 +1138,7 @@
+ ASTOBJ_UNREF(iface, ast_smdi_interface_destroy);
+
+ if (!(iface = ASTOBJ_CONTAINER_FIND(&smdi_ifaces, v->value))) {
+- ast_log(LOG_NOTICE, "SMDI interface %s not found\n", iface->name);
++ ast_log(LOG_NOTICE, "SMDI interface %s not found\n", v->value);
+ continue;
+ }
+ } else if (!strcasecmp(v->name, "pollinginterval")) {
+@@ -1292,46 +1386,11 @@
+
+ static struct ast_custom_function smdi_msg_retrieve_function = {
+ .name = "SMDI_MSG_RETRIEVE",
+- .synopsis = "Retrieve an SMDI message.",
+- .syntax = "SMDI_MSG_RETRIEVE(<smdi port>,<search key>[,timeout[,options]])",
+- .desc =
+- " This function is used to retrieve an incoming SMDI message. It returns\n"
+- "an ID which can be used with the SMDI_MSG() function to access details of\n"
+- "the message. Note that this is a destructive function in the sense that\n"
+- "once an SMDI message is retrieved using this function, it is no longer in\n"
+- "the global SMDI message queue, and can not be accessed by any other Asterisk\n"
+- "channels. The timeout for this function is optional, and the default is\n"
+- "3 seconds. When providing a timeout, it should be in milliseconds.\n"
+- " The default search is done on the forwarding station ID. However, if\n"
+- "you set one of the search key options in the options field, you can change\n"
+- "this behavior.\n"
+- " Options:\n"
+- " t - Instead of searching on the forwarding station, search on the message\n"
+- " desk terminal.\n"
+- " n - Instead of searching on the forwarding station, search on the message\n"
+- " desk number.\n"
+- "",
+ .read = smdi_msg_retrieve_read,
+ };
+
+ static struct ast_custom_function smdi_msg_function = {
+ .name = "SMDI_MSG",
+- .synopsis = "Retrieve details about an SMDI message.",
+- .syntax = "SMDI_MSG(<message_id>,<component>)",
+- .desc =
+- " This function is used to access details of an SMDI message that was\n"
+- "pulled from the incoming SMDI message queue using the SMDI_MSG_RETRIEVE()\n"
+- "function.\n"
+- " Valid message components are:\n"
+- " number - The message desk number\n"
+- " terminal - The message desk terminal\n"
+- " station - The forwarding station\n"
+- " callerid - The callerID of the calling party that was forwarded\n"
+- " type - The call type. The value here is the exact character\n"
+- " that came in on the SMDI link. Typically, example values\n"
+- " are: D - Direct Calls, A - Forward All Calls,\n"
+- " B - Forward Busy Calls, N - Forward No Answer Calls\n"
+- "",
+ .read = smdi_msg_read,
+ };
+
+Index: res/res_features.exports
+===================================================================
+--- a/res/res_features.exports (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/res/res_features.exports (.../trunk) (revision 202568)
+@@ -0,0 +1,13 @@
++{
++ global:
++ ast_bridge_call;
++ ast_masq_park_call;
++ ast_park_call;
++ ast_parking_ext;
++ ast_pickup_call;
++ ast_pickup_ext;
++ ast_register_feature;
++ ast_unregister_feature;
++ local:
++ *;
++};
+
+Property changes on: res/res_features.exports
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+
+Index: res/res_curl.c
+===================================================================
+--- a/res/res_curl.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/res/res_curl.c (.../trunk) (revision 202568)
+@@ -71,5 +71,3 @@
+ }
+
+ AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "cURL Resource Module");
+-
+-
+Index: res/res_ael_share.exports
+===================================================================
+--- a/res/res_ael_share.exports (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/res/res_ael_share.exports (.../trunk) (revision 202568)
+@@ -0,0 +1,4 @@
++{
++ global:
++ *;
++};
+
+Property changes on: res/res_ael_share.exports
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+
+Index: res/res_jabber.exports
+===================================================================
+--- a/res/res_jabber.exports (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/res/res_jabber.exports (.../trunk) (revision 202568)
+@@ -0,0 +1,14 @@
++{
++ global:
++ ast_aji_create_chat;
++ ast_aji_disconnect;
++ ast_aji_get_client;
++ ast_aji_get_clients;
++ ast_aji_increment_mid;
++ ast_aji_invite_chat;
++ ast_aji_join_chat;
++ ast_aji_send;
++ ast_aji_send_chat;
++ local:
++ *;
++};
+
+Property changes on: res/res_jabber.exports
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+
+Index: res/res_speech.c
+===================================================================
+--- a/res/res_speech.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/res/res_speech.c (.../trunk) (revision 202568)
+@@ -40,7 +40,7 @@
+ static struct ast_speech_engine *default_engine = NULL;
+
+ /*! \brief Find a speech recognition engine of specified name, if NULL then use the default one */
+-static struct ast_speech_engine *find_engine(char *engine_name)
++static struct ast_speech_engine *find_engine(const char *engine_name)
+ {
+ struct ast_speech_engine *engine = NULL;
+
+@@ -60,25 +60,25 @@
+ }
+
+ /*! \brief Activate a loaded (either local or global) grammar */
+-int ast_speech_grammar_activate(struct ast_speech *speech, char *grammar_name)
++int ast_speech_grammar_activate(struct ast_speech *speech, const char *grammar_name)
+ {
+ return (speech->engine->activate ? speech->engine->activate(speech, grammar_name) : -1);
+ }
+
+ /*! \brief Deactivate a loaded grammar on a speech structure */
+-int ast_speech_grammar_deactivate(struct ast_speech *speech, char *grammar_name)
++int ast_speech_grammar_deactivate(struct ast_speech *speech, const char *grammar_name)
+ {
+ return (speech->engine->deactivate ? speech->engine->deactivate(speech, grammar_name) : -1);
+ }
+
+ /*! \brief Load a local grammar on a speech structure */
+-int ast_speech_grammar_load(struct ast_speech *speech, char *grammar_name, char *grammar)
++int ast_speech_grammar_load(struct ast_speech *speech, const char *grammar_name, const char *grammar)
+ {
+ return (speech->engine->load ? speech->engine->load(speech, grammar_name, grammar) : -1);
+ }
+
+ /*! \brief Unload a local grammar from a speech structure */
+-int ast_speech_grammar_unload(struct ast_speech *speech, char *grammar_name)
++int ast_speech_grammar_unload(struct ast_speech *speech, const char *grammar_name)
+ {
+ return (speech->engine->unload ? speech->engine->unload(speech, grammar_name) : -1);
+ }
+@@ -163,13 +163,13 @@
+ }
+
+ /*! \brief Change an engine specific attribute */
+-int ast_speech_change(struct ast_speech *speech, char *name, const char *value)
++int ast_speech_change(struct ast_speech *speech, const char *name, const char *value)
+ {
+ return (speech->engine->change ? speech->engine->change(speech, name, value) : -1);
+ }
+
+ /*! \brief Create a new speech structure using the engine specified */
+-struct ast_speech *ast_speech_new(char *engine_name, int formats)
++struct ast_speech *ast_speech_new(const char *engine_name, int formats)
+ {
+ struct ast_speech_engine *engine = NULL;
+ struct ast_speech *new_speech = NULL;
+@@ -299,7 +299,7 @@
+ }
+
+ /*! \brief Unregister a speech recognition engine */
+-int ast_speech_unregister(char *engine_name)
++int ast_speech_unregister(const char *engine_name)
+ {
+ struct ast_speech_engine *engine = NULL;
+ int res = -1;
+Index: res/res_monitor.exports
+===================================================================
+--- a/res/res_monitor.exports (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/res/res_monitor.exports (.../trunk) (revision 202568)
+@@ -0,0 +1,11 @@
++{
++ global:
++ *ast_monitor_change_fname;
++ *ast_monitor_pause;
++ *ast_monitor_setjoinfiles;
++ *ast_monitor_start;
++ *ast_monitor_stop;
++ *ast_monitor_unpause;
++ local:
++ *;
++};
+
+Property changes on: res/res_monitor.exports
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+
+Index: res/res_clioriginate.c
+===================================================================
+--- a/res/res_clioriginate.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/res/res_clioriginate.c (.../trunk) (revision 202568)
+@@ -16,12 +16,12 @@
+ * at the top of the source tree.
+ */
+
+-/*!
++/*!
+ * \file
+ * \author Russell Bryant <russell@digium.com>
+ *
+ * \brief Originate calls via the CLI
+- *
++ *
+ */
+
+ #include "asterisk.h"
+@@ -52,12 +52,12 @@
+ char *chantech;
+ char *chandata;
+ int reason = 0;
+-
++
+ if (ast_strlen_zero(app))
+ return CLI_SHOWUSAGE;
+
+ chandata = ast_strdupa(chan);
+-
++
+ chantech = strsep(&chandata, "/");
+ if (!chandata) {
+ ast_cli(fd, "*** No data provided after channel type! ***\n");
+@@ -86,7 +86,7 @@
+ int reason = 0;
+
+ chandata = ast_strdupa(chan);
+-
++
+ chantech = strsep(&chandata, "/");
+ if (!chandata) {
+ ast_cli(fd, "*** No data provided after channel type! ***\n");
+@@ -102,7 +102,7 @@
+ exten = "s";
+ if (ast_strlen_zero(context))
+ context = "default";
+-
++
+ ast_pbx_outgoing_exten(chantech, AST_FORMAT_SLINEAR, chandata, TIMEOUT * 1000, context, exten, 1, &reason, 0, NULL, NULL, NULL, NULL, NULL);
+
+ return CLI_SUCCESS;
+@@ -114,16 +114,15 @@
+ * \param cmd operation to execute
+ * \param a structure that contains either application or extension arguments
+ * \retval CLI_SUCCESS on success.
+- * \retval CLI_SHOWUSAGE on failure.
+-*/
++ * \retval CLI_SHOWUSAGE on failure.*/
+ static char *handle_orig(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+ {
+- static char *choices[] = { "application", "extension", NULL };
+- char *res;
++ static const char * const choices[] = { "application", "extension", NULL };
++ char *res = NULL;
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "channel originate";
+- e->usage =
++ e->usage =
+ " There are two ways to use this command. A call can be originated between a\n"
+ "channel and a specific application, or between a channel and an extension in\n"
+ "the dialplan. This is similar to call files or the manager originate action.\n"
+@@ -141,14 +140,16 @@
+ "used. If no extension is given, the 's' extension will be used.\n";
+ return NULL;
+ case CLI_GENERATE:
+- if (a->pos != 3)
+- return NULL;
+-
+ /* ugly, can be removed when CLI entries have ast_module pointers */
+ ast_module_ref(ast_module_info->self);
+- res = ast_cli_complete(a->word, choices, a->n);
++ if (a->pos == 3) {
++ res = ast_cli_complete(a->word, choices, a->n);
++ } else if (a->pos == 4) {
++ if (!strcasecmp("application", a->argv[3])) {
++ res = ast_complete_applications(a->line, a->word, a->n);
++ }
++ }
+ ast_module_unref(ast_module_info->self);
+-
+ return res;
+ }
+
+@@ -159,7 +160,7 @@
+ ast_module_ref(ast_module_info->self);
+
+ if (!strcasecmp("application", a->argv[3])) {
+- res = orig_app(a->fd, a->argv[2], a->argv[4], a->argv[5]);
++ res = orig_app(a->fd, a->argv[2], a->argv[4], a->argv[5]);
+ } else if (!strcasecmp("extension", a->argv[3])) {
+ res = orig_exten(a->fd, a->argv[2], a->argv[4]);
+ } else {
+@@ -201,15 +202,14 @@
+ name = a->argv[2];
+ dest = a->argv[3];
+
+- chan = ast_get_channel_by_name_locked(name);
+- if (!chan) {
++ if (!(chan = ast_channel_get_by_name(name))) {
+ ast_cli(a->fd, "Channel '%s' not found\n", name);
+ return CLI_FAILURE;
+ }
+
+ res = ast_async_parseable_goto(chan, dest);
+
+- ast_channel_unlock(chan);
++ chan = ast_channel_unref(chan);
+
+ if (!res) {
+ ast_cli(a->fd, "Channel '%s' successfully redirected to %s\n", name, dest);
+Index: res/res_rtp_asterisk.c
+===================================================================
+--- a/res/res_rtp_asterisk.c (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/res/res_rtp_asterisk.c (.../trunk) (revision 202568)
+@@ -0,0 +1,2649 @@
++/*
++ * Asterisk -- An open source telephony toolkit.
++ *
++ * Copyright (C) 1999 - 2008, Digium, Inc.
++ *
++ * Mark Spencer <markster@digium.com>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * 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.
++ */
++
++/*!
++ * \file
++ *
++ * \brief Supports RTP and RTCP with Symmetric RTP support for NAT traversal.
++ *
++ * \author Mark Spencer <markster@digium.com>
++ *
++ * \note RTP is defined in RFC 3550.
++ */
++
++#include "asterisk.h"
++
++ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
++
++#include <sys/time.h>
++#include <signal.h>
++#include <fcntl.h>
++#include <math.h>
++
++#include "asterisk/stun.h"
++#include "asterisk/pbx.h"
++#include "asterisk/frame.h"
++#include "asterisk/channel.h"
++#include "asterisk/acl.h"
++#include "asterisk/config.h"
++#include "asterisk/lock.h"
++#include "asterisk/utils.h"
++#include "asterisk/netsock.h"
++#include "asterisk/cli.h"
++#include "asterisk/manager.h"
++#include "asterisk/unaligned.h"
++#include "asterisk/module.h"
++#include "asterisk/rtp_engine.h"
++
++#define MAX_TIMESTAMP_SKEW 640
++
++#define RTP_SEQ_MOD (1<<16) /*!< A sequence number can't be more than 16 bits */
++#define RTCP_DEFAULT_INTERVALMS 5000 /*!< Default milli-seconds between RTCP reports we send */
++#define RTCP_MIN_INTERVALMS 500 /*!< Min milli-seconds between RTCP reports we send */
++#define RTCP_MAX_INTERVALMS 60000 /*!< Max milli-seconds between RTCP reports we send */
++
++#define DEFAULT_RTP_START 5000 /*!< Default port number to start allocating RTP ports from */
++#define DEFAULT_RTP_END 31000 /*!< Default maximum port number to end allocating RTP ports at */
++
++#define MINIMUM_RTP_PORT 1024 /*!< Minimum port number to accept */
++#define MAXIMUM_RTP_PORT 65535 /*!< Maximum port number to accept */
++
++#define RTCP_PT_FUR 192
++#define RTCP_PT_SR 200
++#define RTCP_PT_RR 201
++#define RTCP_PT_SDES 202
++#define RTCP_PT_BYE 203
++#define RTCP_PT_APP 204
++
++#define RTP_MTU 1200
++
++#define DEFAULT_DTMF_TIMEOUT (150 * (8000 / 1000)) /*!< samples */
++
++#define ZFONE_PROFILE_ID 0x505a
++
++static int dtmftimeout = DEFAULT_DTMF_TIMEOUT;
++
++static int rtpstart = DEFAULT_RTP_START; /*!< First port for RTP sessions (set in rtp.conf) */
++static int rtpend = DEFAULT_RTP_END; /*!< Last port for RTP sessions (set in rtp.conf) */
++static int rtpdebug; /*!< Are we debugging? */
++static int rtcpdebug; /*!< Are we debugging RTCP? */
++static int rtcpstats; /*!< Are we debugging RTCP? */
++static int rtcpinterval = RTCP_DEFAULT_INTERVALMS; /*!< Time between rtcp reports in millisecs */
++static struct sockaddr_in rtpdebugaddr; /*!< Debug packets to/from this host */
++static struct sockaddr_in rtcpdebugaddr; /*!< Debug RTCP packets to/from this host */
++#ifdef SO_NO_CHECK
++static int nochecksums;
++#endif
++static int strictrtp;
++
++enum strict_rtp_state {
++ STRICT_RTP_OPEN = 0, /*! No RTP packets should be dropped, all sources accepted */
++ STRICT_RTP_LEARN, /*! Accept next packet as source */
++ STRICT_RTP_CLOSED, /*! Drop all RTP packets not coming from source that was learned */
++};
++
++#define FLAG_3389_WARNING (1 << 0)
++#define FLAG_NAT_ACTIVE (3 << 1)
++#define FLAG_NAT_INACTIVE (0 << 1)
++#define FLAG_NAT_INACTIVE_NOWARN (1 << 1)
++#define FLAG_NEED_MARKER_BIT (1 << 3)
++#define FLAG_DTMF_COMPENSATE (1 << 4)
++
++/*! \brief RTP session description */
++struct ast_rtp {
++ int s;
++ struct ast_frame f;
++ unsigned char rawdata[8192 + AST_FRIENDLY_OFFSET];
++ unsigned int ssrc; /*!< Synchronization source, RFC 3550, page 10. */
++ unsigned int themssrc; /*!< Their SSRC */
++ unsigned int rxssrc;
++ unsigned int lastts;
++ unsigned int lastrxts;
++ unsigned int lastividtimestamp;
++ unsigned int lastovidtimestamp;
++ unsigned int lastitexttimestamp;
++ unsigned int lastotexttimestamp;
++ unsigned int lasteventseqn;
++ int lastrxseqno; /*!< Last received sequence number */
++ unsigned short seedrxseqno; /*!< What sequence number did they start with?*/
++ unsigned int seedrxts; /*!< What RTP timestamp did they start with? */
++ unsigned int rxcount; /*!< How many packets have we received? */
++ unsigned int rxoctetcount; /*!< How many octets have we received? should be rxcount *160*/
++ unsigned int txcount; /*!< How many packets have we sent? */
++ unsigned int txoctetcount; /*!< How many octets have we sent? (txcount*160)*/
++ unsigned int cycles; /*!< Shifted count of sequence number cycles */
++ double rxjitter; /*!< Interarrival jitter at the moment */
++ double rxtransit; /*!< Relative transit time for previous packet */
++ int lasttxformat;
++ int lastrxformat;
++
++ int rtptimeout; /*!< RTP timeout time (negative or zero means disabled, negative value means temporarily disabled) */
++ int rtpholdtimeout; /*!< RTP timeout when on hold (negative or zero means disabled, negative value means temporarily disabled). */
++ int rtpkeepalive; /*!< Send RTP comfort noice packets for keepalive */
++
++ /* DTMF Reception Variables */
++ char resp;
++ unsigned int lastevent;
++ unsigned int dtmf_duration; /*!< Total duration in samples since the digit start event */
++ unsigned int dtmf_timeout; /*!< When this timestamp is reached we consider END frame lost and forcibly abort digit */
++ unsigned int dtmfsamples;
++ /* DTMF Transmission Variables */
++ unsigned int lastdigitts;
++ char sending_digit; /*!< boolean - are we sending digits */
++ char send_digit; /*!< digit we are sending */
++ int send_payload;
++ int send_duration;
++ unsigned int flags;
++ struct timeval rxcore;
++ struct timeval txcore;
++ double drxcore; /*!< The double representation of the first received packet */
++ struct timeval lastrx; /*!< timeval when we last received a packet */
++ struct timeval dtmfmute;
++ struct ast_smoother *smoother;
++ int *ioid;
++ unsigned short seqno; /*!< Sequence number, RFC 3550, page 13. */
++ unsigned short rxseqno;
++ struct sched_context *sched;
++ struct io_context *io;
++ void *data;
++ struct ast_rtcp *rtcp;
++ struct ast_rtp *bridged; /*!< Who we are Packet bridged to */
++
++ enum strict_rtp_state strict_rtp_state; /*!< Current state that strict RTP protection is in */
++ struct sockaddr_in strict_rtp_address; /*!< Remote address information for strict RTP purposes */
++ struct sockaddr_in alt_rtp_address; /*!<Alternate remote address information */
++
++ struct rtp_red *red;
++};
++
++/*!
++ * \brief Structure defining an RTCP session.
++ *
++ * The concept "RTCP session" is not defined in RFC 3550, but since
++ * this structure is analogous to ast_rtp, which tracks a RTP session,
++ * it is logical to think of this as a RTCP session.
++ *
++ * RTCP packet is defined on page 9 of RFC 3550.
++ *
++ */
++struct ast_rtcp {
++ int rtcp_info;
++ int s; /*!< Socket */
++ struct sockaddr_in us; /*!< Socket representation of the local endpoint. */
++ struct sockaddr_in them; /*!< Socket representation of the remote endpoint. */
++ unsigned int soc; /*!< What they told us */
++ unsigned int spc; /*!< What they told us */
++ unsigned int themrxlsr; /*!< The middle 32 bits of the NTP timestamp in the last received SR*/
++ struct timeval rxlsr; /*!< Time when we got their last SR */
++ struct timeval txlsr; /*!< Time when we sent or last SR*/
++ unsigned int expected_prior; /*!< no. packets in previous interval */
++ unsigned int received_prior; /*!< no. packets received in previous interval */
++ int schedid; /*!< Schedid returned from ast_sched_add() to schedule RTCP-transmissions*/
++ unsigned int rr_count; /*!< number of RRs we've sent, not including report blocks in SR's */
++ unsigned int sr_count; /*!< number of SRs we've sent */
++ unsigned int lastsrtxcount; /*!< Transmit packet count when last SR sent */
++ double accumulated_transit; /*!< accumulated a-dlsr-lsr */
++ double rtt; /*!< Last reported rtt */
++ unsigned int reported_jitter; /*!< The contents of their last jitter entry in the RR */
++ unsigned int reported_lost; /*!< Reported lost packets in their RR */
++
++ double reported_maxjitter;
++ double reported_minjitter;
++ double reported_normdev_jitter;
++ double reported_stdev_jitter;
++ unsigned int reported_jitter_count;
++
++ double reported_maxlost;
++ double reported_minlost;
++ double reported_normdev_lost;
++ double reported_stdev_lost;
++
++ double rxlost;
++ double maxrxlost;
++ double minrxlost;
++ double normdev_rxlost;
++ double stdev_rxlost;
++ unsigned int rxlost_count;
++
++ double maxrxjitter;
++ double minrxjitter;
++ double normdev_rxjitter;
++ double stdev_rxjitter;
++ unsigned int rxjitter_count;
++ double maxrtt;
++ double minrtt;
++ double normdevrtt;
++ double stdevrtt;
++ unsigned int rtt_count;
++};
++
++struct rtp_red {
++ struct ast_frame t140; /*!< Primary data */
++ struct ast_frame t140red; /*!< Redundant t140*/
++ unsigned char pt[AST_RED_MAX_GENERATION]; /*!< Payload types for redundancy data */
++ unsigned char ts[AST_RED_MAX_GENERATION]; /*!< Time stamps */
++ unsigned char len[AST_RED_MAX_GENERATION]; /*!< length of each generation */
++ int num_gen; /*!< Number of generations */
++ int schedid; /*!< Timer id */
++ int ti; /*!< How long to buffer data before send */
++ unsigned char t140red_data[64000];
++ unsigned char buf_data[64000]; /*!< buffered primary data */
++ int hdrlen;
++ long int prev_ts;
++};
++
++/* Forward Declarations */
++static int ast_rtp_new(struct ast_rtp_instance *instance, struct sched_context *sched, struct sockaddr_in *sin, void *data);
++static int ast_rtp_destroy(struct ast_rtp_instance *instance);
++static int ast_rtp_dtmf_begin(struct ast_rtp_instance *instance, char digit);
++static int ast_rtp_dtmf_end(struct ast_rtp_instance *instance, char digit);
++static void ast_rtp_new_source(struct ast_rtp_instance *instance);
++static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *frame);
++static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtcp);
++static void ast_rtp_prop_set(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value);
++static int ast_rtp_fd(struct ast_rtp_instance *instance, int rtcp);
++static void ast_rtp_remote_address_set(struct ast_rtp_instance *instance, struct sockaddr_in *sin);
++static void ast_rtp_alt_remote_address_set(struct ast_rtp_instance *instance, struct sockaddr_in *sin);
++static int rtp_red_init(struct ast_rtp_instance *instance, int buffer_time, int *payloads, int generations);
++static int rtp_red_buffer(struct ast_rtp_instance *instance, struct ast_frame *frame);
++static int ast_rtp_local_bridge(struct ast_rtp_instance *instance0, struct ast_rtp_instance *instance1);
++static int ast_rtp_get_stat(struct ast_rtp_instance *instance, struct ast_rtp_instance_stats *stats, enum ast_rtp_instance_stat stat);
++static int ast_rtp_dtmf_compatible(struct ast_channel *chan0, struct ast_rtp_instance *instance0, struct ast_channel *chan1, struct ast_rtp_instance *instance1);
++static void ast_rtp_stun_request(struct ast_rtp_instance *instance, struct sockaddr_in *suggestion, const char *username);
++static void ast_rtp_stop(struct ast_rtp_instance *instance);
++
++/* RTP Engine Declaration */
++static struct ast_rtp_engine asterisk_rtp_engine = {
++ .name = "asterisk",
++ .new = ast_rtp_new,
++ .destroy = ast_rtp_destroy,
++ .dtmf_begin = ast_rtp_dtmf_begin,
++ .dtmf_end = ast_rtp_dtmf_end,
++ .new_source = ast_rtp_new_source,
++ .write = ast_rtp_write,
++ .read = ast_rtp_read,
++ .prop_set = ast_rtp_prop_set,
++ .fd = ast_rtp_fd,
++ .remote_address_set = ast_rtp_remote_address_set,
++ .alt_remote_address_set = ast_rtp_alt_remote_address_set,
++ .red_init = rtp_red_init,
++ .red_buffer = rtp_red_buffer,
++ .local_bridge = ast_rtp_local_bridge,
++ .get_stat = ast_rtp_get_stat,
++ .dtmf_compatible = ast_rtp_dtmf_compatible,
++ .stun_request = ast_rtp_stun_request,
++ .stop = ast_rtp_stop,
++};
++
++static inline int rtp_debug_test_addr(struct sockaddr_in *addr)
++{
++ if (!rtpdebug) {
++ return 0;
++ }
++
++ if (rtpdebugaddr.sin_addr.s_addr) {
++ if (((ntohs(rtpdebugaddr.sin_port) != 0)
++ && (rtpdebugaddr.sin_port != addr->sin_port))
++ || (rtpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
++ return 0;
++ }
++
++ return 1;
++}
++
++static inline int rtcp_debug_test_addr(struct sockaddr_in *addr)
++{
++ if (!rtcpdebug) {
++ return 0;
++ }
++
++ if (rtcpdebugaddr.sin_addr.s_addr) {
++ if (((ntohs(rtcpdebugaddr.sin_port) != 0)
++ && (rtcpdebugaddr.sin_port != addr->sin_port))
++ || (rtcpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
++ return 0;
++ }
++
++ return 1;
++}
++
++static unsigned int ast_rtcp_calc_interval(struct ast_rtp *rtp)
++{
++ unsigned int interval;
++ /*! \todo XXX Do a more reasonable calculation on this one
++ * Look in RFC 3550 Section A.7 for an example*/
++ interval = rtcpinterval;
++ return interval;
++}
++
++/*! \brief Calculate normal deviation */
++static double normdev_compute(double normdev, double sample, unsigned int sample_count)
++{
++ normdev = normdev * sample_count + sample;
++ sample_count++;
++
++ return normdev / sample_count;
++}
++
++static double stddev_compute(double stddev, double sample, double normdev, double normdev_curent, unsigned int sample_count)
++{
++/*
++ for the formula check http://www.cs.umd.edu/~austinjp/constSD.pdf
++ return sqrt( (sample_count*pow(stddev,2) + sample_count*pow((sample-normdev)/(sample_count+1),2) + pow(sample-normdev_curent,2)) / (sample_count+1));
++ we can compute the sigma^2 and that way we would have to do the sqrt only 1 time at the end and would save another pow 2 compute
++ optimized formula
++*/
++#define SQUARE(x) ((x) * (x))
++
++ stddev = sample_count * stddev;
++ sample_count++;
++
++ return stddev +
++ ( sample_count * SQUARE( (sample - normdev) / sample_count ) ) +
++ ( SQUARE(sample - normdev_curent) / sample_count );
++
++#undef SQUARE
++}
++
++static int create_new_socket(const char *type)
++{
++ int sock = socket(AF_INET, SOCK_DGRAM, 0);
++
++ if (sock < 0) {
++ if (!type) {
++ type = "RTP/RTCP";
++ }
++ ast_log(LOG_WARNING, "Unable to allocate %s socket: %s\n", type, strerror(errno));
++ } else {
++ long flags = fcntl(sock, F_GETFL);
++ fcntl(sock, F_SETFL, flags | O_NONBLOCK);
++#ifdef SO_NO_CHECK
++ if (nochecksums) {
++ setsockopt(sock, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
++ }
++#endif
++ }
++
++ return sock;
++}
++
++static int ast_rtp_new(struct ast_rtp_instance *instance, struct sched_context *sched, struct sockaddr_in *sin, void *data)
++{
++ struct ast_rtp *rtp = NULL;
++ int x, startplace;
++
++ /* Create a new RTP structure to hold all of our data */
++ if (!(rtp = ast_calloc(1, sizeof(*rtp)))) {
++ return -1;
++ }
++
++ /* Set default parameters on the newly created RTP structure */
++ rtp->ssrc = ast_random();
++ rtp->seqno = ast_random() & 0xffff;
++ rtp->strict_rtp_state = (strictrtp ? STRICT_RTP_LEARN : STRICT_RTP_OPEN);
++
++ /* Create a new socket for us to listen on and use */
++ if ((rtp->s = create_new_socket("RTP")) < 0) {
++ ast_debug(1, "Failed to create a new socket for RTP instance '%p'\n", instance);
++ ast_free(rtp);
++ return -1;
++ }
++
++ /* Now actually find a free RTP port to use */
++ x = (rtpend == rtpstart) ? rtpstart : (ast_random() % (rtpend - rtpstart)) + rtpstart;
++ x = x & ~1;
++ startplace = x;
++
++ for (;;) {
++ sin->sin_port = htons(x);
++ /* Try to bind, this will tell us whether the port is available or not */
++ if (!bind(rtp->s, (struct sockaddr *)sin, sizeof(*sin))) {
++ ast_debug(1, "Allocated port %d for RTP instance '%p'\n", x, instance);
++ ast_rtp_instance_set_local_address(instance, sin);
++ break;
++ }
++
++ x += 2;
++ if (x > rtpend) {
++ x = (rtpstart + 1) & ~1;
++ }
++
++ /* See if we ran out of ports or if the bind actually failed because of something other than the address being in use */
++ if (x == startplace || errno != EADDRINUSE) {
++ ast_log(LOG_ERROR, "Oh dear... we couldn't allocate a port for RTP instance '%p'\n", instance);
++ return -1;
++ }
++ }
++
++ /* Record any information we may need */
++ rtp->sched = sched;
++
++ /* Associate the RTP structure with the RTP instance and be done */
++ ast_rtp_instance_set_data(instance, rtp);
++
++ return 0;
++}
++
++static int ast_rtp_destroy(struct ast_rtp_instance *instance)
++{
++ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
++
++ /* Destroy the smoother that was smoothing out audio if present */
++ if (rtp->smoother) {
++ ast_smoother_free(rtp->smoother);
++ }
++
++ /* Close our own socket so we no longer get packets */
++ if (rtp->s > -1) {
++ close(rtp->s);
++ }
++
++ /* Destroy RTCP if it was being used */
++ if (rtp->rtcp) {
++ AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
++ close(rtp->rtcp->s);
++ ast_free(rtp->rtcp);
++ }
++
++ /* Destroy RED if it was being used */
++ if (rtp->red) {
++ AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
++ ast_free(rtp->red);
++ }
++
++ /* Finally destroy ourselves */
++ ast_free(rtp);
++
++ return 0;
++}
++
++static int ast_rtp_dtmf_begin(struct ast_rtp_instance *instance, char digit)
++{
++ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
++ struct sockaddr_in remote_address = { 0, };
++ int hdrlen = 12, res = 0, i = 0, payload = 101;
++ char data[256];
++ unsigned int *rtpheader = (unsigned int*)data;
++
++ ast_rtp_instance_get_remote_address(instance, &remote_address);
++
++ /* If we have no remote address information bail out now */
++ if (!remote_address.sin_addr.s_addr || !remote_address.sin_port) {
++ return -1;
++ }
++
++ /* Convert given digit into what we want to transmit */
++ if ((digit <= '9') && (digit >= '0')) {
++ digit -= '0';
++ } else if (digit == '*') {
++ digit = 10;
++ } else if (digit == '#') {
++ digit = 11;
++ } else if ((digit >= 'A') && (digit <= 'D')) {
++ digit = digit - 'A' + 12;
++ } else if ((digit >= 'a') && (digit <= 'd')) {
++ digit = digit - 'a' + 12;
++ } else {
++ ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
++ return -1;
++ }
++
++ /* Grab the payload that they expect the RFC2833 packet to be received in */
++ payload = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 0, AST_RTP_DTMF);
++
++ rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
++ rtp->send_duration = 160;
++ rtp->lastdigitts = rtp->lastts + rtp->send_duration;
++
++ /* Create the actual packet that we will be sending */
++ rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
++ rtpheader[1] = htonl(rtp->lastdigitts);
++ rtpheader[2] = htonl(rtp->ssrc);
++
++ /* Actually send the packet */
++ for (i = 0; i < 2; i++) {
++ rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
++ res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &remote_address, sizeof(remote_address));
++ if (res < 0) {
++ ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n",
++ ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port), strerror(errno));
++ }
++ if (rtp_debug_test_addr(&remote_address)) {
++ ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
++ ast_inet_ntoa(remote_address.sin_addr),
++ ntohs(remote_address.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
++ }
++ rtp->seqno++;
++ rtp->send_duration += 160;
++ rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
++ }
++
++ /* Record that we are in the process of sending a digit and information needed to continue doing so */
++ rtp->sending_digit = 1;
++ rtp->send_digit = digit;
++ rtp->send_payload = payload;
++
++ return 0;
++}
++
++static int ast_rtp_dtmf_continuation(struct ast_rtp_instance *instance)
++{
++ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
++ struct sockaddr_in remote_address = { 0, };
++ int hdrlen = 12, res = 0;
++ char data[256];
++ unsigned int *rtpheader = (unsigned int*)data;
++
++ ast_rtp_instance_get_remote_address(instance, &remote_address);
++
++ /* Make sure we know where the other side is so we can send them the packet */
++ if (!remote_address.sin_addr.s_addr || !remote_address.sin_port) {
++ return -1;
++ }
++
++ /* Actually create the packet we will be sending */
++ rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno));
++ rtpheader[1] = htonl(rtp->lastdigitts);
++ rtpheader[2] = htonl(rtp->ssrc);
++ rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration));
++ rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
++
++ /* Boom, send it on out */
++ res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &remote_address, sizeof(remote_address));
++ if (res < 0) {
++ ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
++ ast_inet_ntoa(remote_address.sin_addr),
++ ntohs(remote_address.sin_port), strerror(errno));
++ }
++
++ if (rtp_debug_test_addr(&remote_address)) {
++ ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
++ ast_inet_ntoa(remote_address.sin_addr),
++ ntohs(remote_address.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
++ }
++
++ /* And now we increment some values for the next time we swing by */
++ rtp->seqno++;
++ rtp->send_duration += 160;
++
++ return 0;
++}
++
++static int ast_rtp_dtmf_end(struct ast_rtp_instance *instance, char digit)
++{
++ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
++ struct sockaddr_in remote_address = { 0, };
++ int hdrlen = 12, res = 0, i = 0;
++ char data[256];
++ unsigned int *rtpheader = (unsigned int*)data;
++
++ ast_rtp_instance_get_remote_address(instance, &remote_address);
++
++ /* Make sure we know where the remote side is so we can send them the packet we construct */
++ if (!remote_address.sin_addr.s_addr || !remote_address.sin_port) {
++ return -1;
++ }
++
++ /* Convert the given digit to the one we are going to send */
++ if ((digit <= '9') && (digit >= '0')) {
++ digit -= '0';
++ } else if (digit == '*') {
++ digit = 10;
++ } else if (digit == '#') {
++ digit = 11;
++ } else if ((digit >= 'A') && (digit <= 'D')) {
++ digit = digit - 'A' + 12;
++ } else if ((digit >= 'a') && (digit <= 'd')) {
++ digit = digit - 'a' + 12;
++ } else {
++ ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
++ return -1;
++ }
++
++ rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
++
++ /* Construct the packet we are going to send */
++ rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno));
++ rtpheader[1] = htonl(rtp->lastdigitts);
++ rtpheader[2] = htonl(rtp->ssrc);
++ rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
++ rtpheader[3] |= htonl((1 << 23));
++ rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
++
++ /* Send it 3 times, that's the magical number */
++ for (i = 0; i < 3; i++) {
++ res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &remote_address, sizeof(remote_address));
++ if (res < 0) {
++ ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
++ ast_inet_ntoa(remote_address.sin_addr),
++ ntohs(remote_address.sin_port), strerror(errno));
++ }
++ if (rtp_debug_test_addr(&remote_address)) {
++ ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
++ ast_inet_ntoa(remote_address.sin_addr),
++ ntohs(remote_address.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
++ }
++ }
++
++ /* Oh and we can't forget to turn off the stuff that says we are sending DTMF */
++ rtp->lastts += rtp->send_duration;
++ rtp->sending_digit = 0;
++ rtp->send_digit = 0;
++
++ return 0;
++}
++
++static void ast_rtp_new_source(struct ast_rtp_instance *instance)
++{
++ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
++
++ /* We simply set this bit so that the next packet sent will have the marker bit turned on */
++ ast_set_flag(rtp, FLAG_NEED_MARKER_BIT);
++
++ return;
++}
++
++static unsigned int calc_txstamp(struct ast_rtp *rtp, struct timeval *delivery)
++{
++ struct timeval t;
++ long ms;
++
++ if (ast_tvzero(rtp->txcore)) {
++ rtp->txcore = ast_tvnow();
++ rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
++ }
++
++ t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
++ if ((ms = ast_tvdiff_ms(t, rtp->txcore)) < 0) {
++ ms = 0;
++ }
++ rtp->txcore = t;
++
++ return (unsigned int) ms;
++}
++
++static void timeval2ntp(struct timeval tv, unsigned int *msw, unsigned int *lsw)
++{
++ unsigned int sec, usec, frac;
++ sec = tv.tv_sec + 2208988800u; /* Sec between 1900 and 1970 */
++ usec = tv.tv_usec;
++ frac = (usec << 12) + (usec << 8) - ((usec * 3650) >> 6);
++ *msw = sec;
++ *lsw = frac;
++}
++
++/*! \brief Send RTCP recipient's report */
++static int ast_rtcp_write_rr(const void *data)
++{
++ struct ast_rtp *rtp = (struct ast_rtp *)data;
++ int res;
++ int len = 32;
++ unsigned int lost;
++ unsigned int extended;
++ unsigned int expected;
++ unsigned int expected_interval;
++ unsigned int received_interval;
++ int lost_interval;
++ struct timeval now;
++ unsigned int *rtcpheader;
++ char bdata[1024];
++ struct timeval dlsr;
++ int fraction;
++
++ double rxlost_current;
++
++ if (!rtp || !rtp->rtcp || (&rtp->rtcp->them.sin_addr == 0))
++ return 0;
++
++ if (!rtp->rtcp->them.sin_addr.s_addr) {
++ ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted\n");
++ AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
++ return 0;
++ }
++
++ extended = rtp->cycles + rtp->lastrxseqno;
++ expected = extended - rtp->seedrxseqno + 1;
++ lost = expected - rtp->rxcount;
++ expected_interval = expected - rtp->rtcp->expected_prior;
++ rtp->rtcp->expected_prior = expected;
++ received_interval = rtp->rxcount - rtp->rtcp->received_prior;
++ rtp->rtcp->received_prior = rtp->rxcount;
++ lost_interval = expected_interval - received_interval;
++
++ if (lost_interval <= 0)
++ rtp->rtcp->rxlost = 0;
++ else rtp->rtcp->rxlost = rtp->rtcp->rxlost;
++ if (rtp->rtcp->rxlost_count == 0)
++ rtp->rtcp->minrxlost = rtp->rtcp->rxlost;
++ if (lost_interval < rtp->rtcp->minrxlost)
++ rtp->rtcp->minrxlost = rtp->rtcp->rxlost;
++ if (lost_interval > rtp->rtcp->maxrxlost)
++ rtp->rtcp->maxrxlost = rtp->rtcp->rxlost;
++
++ rxlost_current = normdev_compute(rtp->rtcp->normdev_rxlost, rtp->rtcp->rxlost, rtp->rtcp->rxlost_count);
++ rtp->rtcp->stdev_rxlost = stddev_compute(rtp->rtcp->stdev_rxlost, rtp->rtcp->rxlost, rtp->rtcp->normdev_rxlost, rxlost_current, rtp->rtcp->rxlost_count);
++ rtp->rtcp->normdev_rxlost = rxlost_current;
++ rtp->rtcp->rxlost_count++;
++
++ if (expected_interval == 0 || lost_interval <= 0)
++ fraction = 0;
++ else
++ fraction = (lost_interval << 8) / expected_interval;
++ gettimeofday(&now, NULL);
++ timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
++ rtcpheader = (unsigned int *)bdata;
++ rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_RR << 16) | ((len/4)-1));
++ rtcpheader[1] = htonl(rtp->ssrc);
++ rtcpheader[2] = htonl(rtp->themssrc);
++ rtcpheader[3] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff));
++ rtcpheader[4] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff)));
++ rtcpheader[5] = htonl((unsigned int)(rtp->rxjitter * 65536.));
++ rtcpheader[6] = htonl(rtp->rtcp->themrxlsr);
++ rtcpheader[7] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
++
++ /*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos
++ it can change mid call, and SDES can't) */
++ rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
++ rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */
++ rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */
++ len += 12;
++
++ res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
++
++ if (res < 0) {
++ ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno));
++ /* Remove the scheduler */
++ AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
++ return 0;
++ }
++
++ rtp->rtcp->rr_count++;
++ if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
++ ast_verbose("\n* Sending RTCP RR to %s:%d\n"
++ " Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n"
++ " IA jitter: %.4f\n"
++ " Their last SR: %u\n"
++ " DLSR: %4.4f (sec)\n\n",
++ ast_inet_ntoa(rtp->rtcp->them.sin_addr),
++ ntohs(rtp->rtcp->them.sin_port),
++ rtp->ssrc, rtp->themssrc, fraction, lost,
++ rtp->rxjitter,
++ rtp->rtcp->themrxlsr,
++ (double)(ntohl(rtcpheader[7])/65536.0));
++ }
++
++ return res;
++}
++
++/*! \brief Send RTCP sender's report */
++static int ast_rtcp_write_sr(const void *data)
++{
++ struct ast_rtp *rtp = (struct ast_rtp *)data;
++ int res;
++ int len = 0;
++ struct timeval now;
++ unsigned int now_lsw;
++ unsigned int now_msw;
++ unsigned int *rtcpheader;
++ unsigned int lost;
++ unsigned int extended;
++ unsigned int expected;
++ unsigned int expected_interval;
++ unsigned int received_interval;
++ int lost_interval;
++ int fraction;
++ struct timeval dlsr;
++ char bdata[512];
++
++ /* Commented condition is always not NULL if rtp->rtcp is not NULL */
++ if (!rtp || !rtp->rtcp/* || (&rtp->rtcp->them.sin_addr == 0)*/)
++ return 0;
++
++ if (!rtp->rtcp->them.sin_addr.s_addr) { /* This'll stop rtcp for this rtp session */
++ ast_verbose("RTCP SR transmission error, rtcp halted\n");
++ AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
++ return 0;
++ }
++
++ gettimeofday(&now, NULL);
++ timeval2ntp(now, &now_msw, &now_lsw); /* fill thses ones in from utils.c*/
++ rtcpheader = (unsigned int *)bdata;
++ rtcpheader[1] = htonl(rtp->ssrc); /* Our SSRC */
++ rtcpheader[2] = htonl(now_msw); /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970*/
++ rtcpheader[3] = htonl(now_lsw); /* now, LSW */
++ rtcpheader[4] = htonl(rtp->lastts); /* FIXME shouldn't be that, it should be now */
++ rtcpheader[5] = htonl(rtp->txcount); /* No. packets sent */
++ rtcpheader[6] = htonl(rtp->txoctetcount); /* No. bytes sent */
++ len += 28;
++
++ extended = rtp->cycles + rtp->lastrxseqno;
++ expected = extended - rtp->seedrxseqno + 1;
++ if (rtp->rxcount > expected)
++ expected += rtp->rxcount - expected;
++ lost = expected - rtp->rxcount;
++ expected_interval = expected - rtp->rtcp->expected_prior;
++ rtp->rtcp->expected_prior = expected;
++ received_interval = rtp->rxcount - rtp->rtcp->received_prior;
++ rtp->rtcp->received_prior = rtp->rxcount;
++ lost_interval = expected_interval - received_interval;
++ if (expected_interval == 0 || lost_interval <= 0)
++ fraction = 0;
++ else
++ fraction = (lost_interval << 8) / expected_interval;
++ timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
++ rtcpheader[7] = htonl(rtp->themssrc);
++ rtcpheader[8] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff));
++ rtcpheader[9] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff)));
++ rtcpheader[10] = htonl((unsigned int)(rtp->rxjitter * 65536.));
++ rtcpheader[11] = htonl(rtp->rtcp->themrxlsr);
++ rtcpheader[12] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
++ len += 24;
++
++ rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1));
++
++ /* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */
++ /* it can change mid call, and SDES can't) */
++ rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
++ rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */
++ rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */
++ len += 12;
++
++ res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
++ if (res < 0) {
++ ast_log(LOG_ERROR, "RTCP SR transmission error to %s:%d, rtcp halted %s\n",ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port), strerror(errno));
++ AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
++ return 0;
++ }
++
++ /* FIXME Don't need to get a new one */
++ gettimeofday(&rtp->rtcp->txlsr, NULL);
++ rtp->rtcp->sr_count++;
++
++ rtp->rtcp->lastsrtxcount = rtp->txcount;
++
++ if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
++ ast_verbose("* Sent RTCP SR to %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
++ ast_verbose(" Our SSRC: %u\n", rtp->ssrc);
++ ast_verbose(" Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096);
++ ast_verbose(" Sent(RTP): %u\n", rtp->lastts);
++ ast_verbose(" Sent packets: %u\n", rtp->txcount);
++ ast_verbose(" Sent octets: %u\n", rtp->txoctetcount);
++ ast_verbose(" Report block:\n");
++ ast_verbose(" Fraction lost: %u\n", fraction);
++ ast_verbose(" Cumulative loss: %u\n", lost);
++ ast_verbose(" IA jitter: %.4f\n", rtp->rxjitter);
++ ast_verbose(" Their last SR: %u\n", rtp->rtcp->themrxlsr);
++ ast_verbose(" DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0));
++ }
++ manager_event(EVENT_FLAG_REPORTING, "RTCPSent", "To %s:%d\r\n"
++ "OurSSRC: %u\r\n"
++ "SentNTP: %u.%010u\r\n"
++ "SentRTP: %u\r\n"
++ "SentPackets: %u\r\n"
++ "SentOctets: %u\r\n"
++ "ReportBlock:\r\n"
++ "FractionLost: %u\r\n"
++ "CumulativeLoss: %u\r\n"
++ "IAJitter: %.4f\r\n"
++ "TheirLastSR: %u\r\n"
++ "DLSR: %4.4f (sec)\r\n",
++ ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port),
++ rtp->ssrc,
++ (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096,
++ rtp->lastts,
++ rtp->txcount,
++ rtp->txoctetcount,
++ fraction,
++ lost,
++ rtp->rxjitter,
++ rtp->rtcp->themrxlsr,
++ (double)(ntohl(rtcpheader[12])/65536.0));
++ return res;
++}
++
++/*! \brief Write and RTCP packet to the far end
++ * \note Decide if we are going to send an SR (with Reception Block) or RR
++ * RR is sent if we have not sent any rtp packets in the previous interval */
++static int ast_rtcp_write(const void *data)
++{
++ struct ast_rtp *rtp = (struct ast_rtp *)data;
++ int res;
++
++ if (!rtp || !rtp->rtcp)
++ return 0;
++
++ if (rtp->txcount > rtp->rtcp->lastsrtxcount)
++ res = ast_rtcp_write_sr(data);
++ else
++ res = ast_rtcp_write_rr(data);
++
++ return res;
++}
++
++static int ast_rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame *frame, int codec)
++{
++ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
++ int pred, mark = 0;
++ unsigned int ms = calc_txstamp(rtp, &frame->delivery);
++ struct sockaddr_in remote_address = { 0, };
++
++ if (rtp->sending_digit) {
++ return 0;
++ }
++
++ if (frame->frametype == AST_FRAME_VOICE) {
++ pred = rtp->lastts + frame->samples;
++
++ /* Re-calculate last TS */
++ rtp->lastts = rtp->lastts + ms * 8;
++ if (ast_tvzero(frame->delivery)) {
++ /* If this isn't an absolute delivery time, Check if it is close to our prediction,
++ and if so, go with our prediction */
++ if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW) {
++ rtp->lastts = pred;
++ } else {
++ ast_debug(3, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms);
++ mark = 1;
++ }
++ }
++ } else if (frame->frametype == AST_FRAME_VIDEO) {
++ mark = frame->subclass & 0x1;
++ pred = rtp->lastovidtimestamp + frame->samples;
++ /* Re-calculate last TS */
++ rtp->lastts = rtp->lastts + ms * 90;
++ /* If it's close to our prediction, go for it */
++ if (ast_tvzero(frame->delivery)) {
++ if (abs(rtp->lastts - pred) < 7200) {
++ rtp->lastts = pred;
++ rtp->lastovidtimestamp += frame->samples;
++ } else {
++ ast_debug(3, "Difference is %d, ms is %d (%d), pred/ts/samples %d/%d/%d\n", abs(rtp->lastts - pred), ms, ms * 90, rtp->lastts, pred, frame->samples);
++ rtp->lastovidtimestamp = rtp->lastts;
++ }
++ }
++ } else {
++ pred = rtp->lastotexttimestamp + frame->samples;
++ /* Re-calculate last TS */
++ rtp->lastts = rtp->lastts + ms;
++ /* If it's close to our prediction, go for it */
++ if (ast_tvzero(frame->delivery)) {
++ if (abs(rtp->lastts - pred) < 7200) {
++ rtp->lastts = pred;
++ rtp->lastotexttimestamp += frame->samples;
++ } else {
++ ast_debug(3, "Difference is %d, ms is %d, pred/ts/samples %d/%d/%d\n", abs(rtp->lastts - pred), ms, rtp->lastts, pred, frame->samples);
++ rtp->lastotexttimestamp = rtp->lastts;
++ }
++ }
++ }
++
++ /* If we have been explicitly told to set the marker bit then do so */
++ if (ast_test_flag(rtp, FLAG_NEED_MARKER_BIT)) {
++ mark = 1;
++ ast_clear_flag(rtp, FLAG_NEED_MARKER_BIT);
++ }
++
++ /* If the timestamp for non-digt packets has moved beyond the timestamp for digits, update the digit timestamp */
++ if (rtp->lastts > rtp->lastdigitts) {
++ rtp->lastdigitts = rtp->lastts;
++ }
++
++ if (ast_test_flag(frame, AST_FRFLAG_HAS_TIMING_INFO)) {
++ rtp->lastts = frame->ts * 8;
++ }
++
++ ast_rtp_instance_get_remote_address(instance, &remote_address);
++
++ /* If we know the remote address construct a packet and send it out */
++ if (remote_address.sin_port && remote_address.sin_addr.s_addr) {
++ int hdrlen = 12, res;
++ unsigned char *rtpheader = (unsigned char *)(frame->data.ptr - hdrlen);
++
++ put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23)));
++ put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts));
++ put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc));
++
++ if ((res = sendto(rtp->s, (void *)rtpheader, frame->datalen + hdrlen, 0, (struct sockaddr *)&remote_address, sizeof(remote_address))) < 0) {
++ if (!ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT) || (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT) && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
++ ast_debug(1, "RTP Transmission error of packet %d to %s:%d: %s\n", rtp->seqno, ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port), strerror(errno));
++ } else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) {
++ /* Only give this error message once if we are not RTP debugging */
++ if (option_debug || rtpdebug)
++ ast_debug(0, "RTP NAT: Can't write RTP to private address %s:%d, waiting for other end to send audio...\n", ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port));
++ ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN);
++ }
++ } else {
++ rtp->txcount++;
++ rtp->txoctetcount += (res - hdrlen);
++
++ if (rtp->rtcp && rtp->rtcp->schedid < 1) {
++ ast_debug(1, "Starting RTCP transmission on RTP instance '%p'\n", instance);
++ rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
++ }
++ }
++
++ if (rtp_debug_test_addr(&remote_address)) {
++ ast_verbose("Sent RTP packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
++ ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port), codec, rtp->seqno, rtp->lastts, res - hdrlen);
++ }
++ }
++
++ rtp->seqno++;
++
++ return 0;
++}
++
++static struct ast_frame *red_t140_to_red(struct rtp_red *red) {
++ unsigned char *data = red->t140red.data.ptr;
++ int len = 0;
++ int i;
++
++ /* replace most aged generation */
++ if (red->len[0]) {
++ for (i = 1; i < red->num_gen+1; i++)
++ len += red->len[i];
++
++ memmove(&data[red->hdrlen], &data[red->hdrlen+red->len[0]], len);
++ }
++
++ /* Store length of each generation and primary data length*/
++ for (i = 0; i < red->num_gen; i++)
++ red->len[i] = red->len[i+1];
++ red->len[i] = red->t140.datalen;
++
++ /* write each generation length in red header */
++ len = red->hdrlen;
++ for (i = 0; i < red->num_gen; i++)
++ len += data[i*4+3] = red->len[i];
++
++ /* add primary data to buffer */
++ memcpy(&data[len], red->t140.data.ptr, red->t140.datalen);
++ red->t140red.datalen = len + red->t140.datalen;
++
++ /* no primary data and no generations to send */
++ if (len == red->hdrlen && !red->t140.datalen)
++ return NULL;
++
++ /* reset t.140 buffer */
++ red->t140.datalen = 0;
++
++ return &red->t140red;
++}
++
++static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
++{
++ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
++ struct sockaddr_in remote_address = { 0, };
++ int codec, subclass;
++
++ ast_rtp_instance_get_remote_address(instance, &remote_address);
++
++ /* If we don't actually know the remote address don't even bother doing anything */
++ if (!remote_address.sin_addr.s_addr) {
++ ast_debug(1, "No remote address on RTP instance '%p' so dropping frame\n", instance);
++ return 0;
++ }
++
++ /* If there is no data length we can't very well send the packet */
++ if (!frame->datalen) {
++ ast_debug(1, "Received frame with no data for RTP instance '%p' so dropping frame\n", instance);
++ return 0;
++ }
++
++ /* If the packet is not one our RTP stack supports bail out */
++ if (frame->frametype != AST_FRAME_VOICE && frame->frametype != AST_FRAME_VIDEO && frame->frametype != AST_FRAME_TEXT) {
++ ast_log(LOG_WARNING, "RTP can only send voice, video, and text\n");
++ return -1;
++ }
++
++ if (rtp->red) {
++ /* return 0; */
++ /* no primary data or generations to send */
++ if ((frame = red_t140_to_red(rtp->red)) == NULL)
++ return 0;
++ }
++
++ /* Grab the subclass and look up the payload we are going to use */
++ subclass = frame->subclass;
++ if (frame->frametype == AST_FRAME_VIDEO) {
++ subclass &= ~0x1;
++ }
++ if ((codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 1, subclass)) < 0) {
++ ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(frame->subclass));
++ return -1;
++ }
++
++ /* Oh dear, if the format changed we will have to set up a new smoother */
++ if (rtp->lasttxformat != subclass) {
++ ast_debug(1, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass));
++ rtp->lasttxformat = subclass;
++ if (rtp->smoother) {
++ ast_smoother_free(rtp->smoother);
++ rtp->smoother = NULL;
++ }
++ }
++
++ /* If no smoother is present see if we have to set one up */
++ if (!rtp->smoother) {
++ struct ast_format_list fmt = ast_codec_pref_getsize(&ast_rtp_instance_get_codecs(instance)->pref, subclass);
++
++ switch (subclass) {
++ case AST_FORMAT_SPEEX:
++ case AST_FORMAT_G723_1:
++ case AST_FORMAT_SIREN7:
++ case AST_FORMAT_SIREN14:
++ /* these are all frame-based codecs and cannot be safely run through
++ a smoother */
++ break;
++ default:
++ if (fmt.inc_ms) {
++ if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) {
++ ast_log(LOG_WARNING, "Unable to create smoother: format %d ms: %d len: %d\n", subclass, fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
++ return -1;
++ }
++ if (fmt.flags) {
++ ast_smoother_set_flags(rtp->smoother, fmt.flags);
++ }
++ ast_debug(1, "Created smoother: format: %d ms: %d len: %d\n", subclass, fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
++ }
++ }
++ }
++
++ /* Feed audio frames into the actual function that will create a frame and send it */
++ if (rtp->smoother) {
++ struct ast_frame *f;
++
++ if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) {
++ ast_smoother_feed_be(rtp->smoother, frame);
++ } else {
++ ast_smoother_feed(rtp->smoother, frame);
++ }
++
++ while ((f = ast_smoother_read(rtp->smoother)) && (f->data.ptr)) {
++ if (f->subclass == AST_FORMAT_G722) {
++ f->samples /= 2;
++ }
++
++ ast_rtp_raw_write(instance, f, codec);
++ }
++ } else {
++ int hdrlen = 12;
++ struct ast_frame *f = NULL;
++
++ if (frame->offset < hdrlen) {
++ f = ast_frdup(frame);
++ } else {
++ f = frame;
++ }
++ if (f->data.ptr) {
++ ast_rtp_raw_write(instance, f, codec);
++ }
++ if (f != frame) {
++ ast_frfree(f);
++ }
++
++ }
++
++ return 0;
++}
++
++static void calc_rxstamp(struct timeval *tv, struct ast_rtp *rtp, unsigned int timestamp, int mark)
++{
++ struct timeval now;
++ double transit;
++ double current_time;
++ double d;
++ double dtv;
++ double prog;
++
++ double normdev_rxjitter_current;
++ if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) {
++ gettimeofday(&rtp->rxcore, NULL);
++ rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000;
++ /* map timestamp to a real time */
++ rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */
++ rtp->rxcore.tv_sec -= timestamp / 8000;
++ rtp->rxcore.tv_usec -= (timestamp % 8000) * 125;
++ /* Round to 0.1ms for nice, pretty timestamps */
++ rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100;
++ if (rtp->rxcore.tv_usec < 0) {
++ /* Adjust appropriately if necessary */
++ rtp->rxcore.tv_usec += 1000000;
++ rtp->rxcore.tv_sec -= 1;
++ }
++ }
++
++ gettimeofday(&now,NULL);
++ /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */
++ tv->tv_sec = rtp->rxcore.tv_sec + timestamp / 8000;
++ tv->tv_usec = rtp->rxcore.tv_usec + (timestamp % 8000) * 125;
++ if (tv->tv_usec >= 1000000) {
++ tv->tv_usec -= 1000000;
++ tv->tv_sec += 1;
++ }
++ prog = (double)((timestamp-rtp->seedrxts)/8000.);
++ dtv = (double)rtp->drxcore + (double)(prog);
++ current_time = (double)now.tv_sec + (double)now.tv_usec/1000000;
++ transit = current_time - dtv;
++ d = transit - rtp->rxtransit;
++ rtp->rxtransit = transit;
++ if (d<0)
++ d=-d;
++ rtp->rxjitter += (1./16.) * (d - rtp->rxjitter);
++
++ if (rtp->rtcp) {
++ if (rtp->rxjitter > rtp->rtcp->maxrxjitter)
++ rtp->rtcp->maxrxjitter = rtp->rxjitter;
++ if (rtp->rtcp->rxjitter_count == 1)
++ rtp->rtcp->minrxjitter = rtp->rxjitter;
++ if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter)
++ rtp->rtcp->minrxjitter = rtp->rxjitter;
++
++ normdev_rxjitter_current = normdev_compute(rtp->rtcp->normdev_rxjitter,rtp->rxjitter,rtp->rtcp->rxjitter_count);
++ rtp->rtcp->stdev_rxjitter = stddev_compute(rtp->rtcp->stdev_rxjitter,rtp->rxjitter,rtp->rtcp->normdev_rxjitter,normdev_rxjitter_current,rtp->rtcp->rxjitter_count);
++
++ rtp->rtcp->normdev_rxjitter = normdev_rxjitter_current;
++ rtp->rtcp->rxjitter_count++;
++ }
++}
++
++static struct ast_frame *send_dtmf(struct ast_rtp_instance *instance, enum ast_frame_type type, int compensate)
++{
++ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
++ struct sockaddr_in remote_address = { 0, };
++
++ ast_rtp_instance_get_remote_address(instance, &remote_address);
++
++ if (((compensate && type == AST_FRAME_DTMF_END) || (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) {
++ ast_debug(1, "Ignore potential DTMF echo from '%s'\n", ast_inet_ntoa(remote_address.sin_addr));
++ rtp->resp = 0;
++ rtp->dtmfsamples = 0;
++ return &ast_null_frame;
++ }
++ ast_debug(1, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, ast_inet_ntoa(remote_address.sin_addr));
++ if (rtp->resp == 'X') {
++ rtp->f.frametype = AST_FRAME_CONTROL;
++ rtp->f.subclass = AST_CONTROL_FLASH;
++ } else {
++ rtp->f.frametype = type;
++ rtp->f.subclass = rtp->resp;
++ }
++ rtp->f.datalen = 0;
++ rtp->f.samples = 0;
++ rtp->f.mallocd = 0;
++ rtp->f.src = "RTP";
++
++ return &rtp->f;
++}
++
++static struct ast_frame *process_dtmf_rfc2833(struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, struct sockaddr_in *sin, int payloadtype, int mark)
++{
++ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
++ struct sockaddr_in remote_address = { 0, };
++ unsigned int event, event_end, samples;
++ char resp = 0;
++ struct ast_frame *f = NULL;
++
++ ast_rtp_instance_get_remote_address(instance, &remote_address);
++
++ /* Figure out event, event end, and samples */
++ event = ntohl(*((unsigned int *)(data)));
++ event >>= 24;
++ event_end = ntohl(*((unsigned int *)(data)));
++ event_end <<= 8;
++ event_end >>= 24;
++ samples = ntohl(*((unsigned int *)(data)));
++ samples &= 0xFFFF;
++
++ if (rtp_debug_test_addr(&remote_address)) {
++ ast_verbose("Got RTP RFC2833 from %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u, mark %d, event %08x, end %d, duration %-5.5d) \n", ast_inet_ntoa(remote_address.sin_addr),
++ ntohs(remote_address.sin_port), payloadtype, seqno, timestamp, len, (mark?1:0), event, ((event_end & 0x80)?1:0), samples);
++ }
++
++ /* Print out debug if turned on */
++ if (rtpdebug || option_debug > 2)
++ ast_debug(0, "- RTP 2833 Event: %08x (len = %d)\n", event, len);
++
++ /* Figure out what digit was pressed */
++ if (event < 10) {
++ resp = '0' + event;
++ } else if (event < 11) {
++ resp = '*';
++ } else if (event < 12) {
++ resp = '#';
++ } else if (event < 16) {
++ resp = 'A' + (event - 12);
++ } else if (event < 17) { /* Event 16: Hook flash */
++ resp = 'X';
++ } else {
++ /* Not a supported event */
++ ast_log(LOG_DEBUG, "Ignoring RTP 2833 Event: %08x. Not a DTMF Digit.\n", event);
++ return &ast_null_frame;
++ }
++
++ if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE)) {
++ if ((rtp->lastevent != timestamp) || (rtp->resp && rtp->resp != resp)) {
++ rtp->resp = resp;
++ rtp->dtmf_timeout = 0;
++ f = send_dtmf(instance, AST_FRAME_DTMF_END, ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE));
++ f->len = 0;
++ rtp->lastevent = timestamp;
++ }
++ } else {
++ /* The duration parameter measures the complete
++ duration of the event (from the beginning) - RFC2833.
++ Account for the fact that duration is only 16 bits long
++ (about 8 seconds at 8000 Hz) and can wrap is digit
++ is hold for too long. */
++ unsigned int new_duration = rtp->dtmf_duration;
++ unsigned int last_duration = new_duration & 0xFFFF;
++
++ if (last_duration > 64000 && samples < last_duration) {
++ new_duration += 0xFFFF + 1;
++ }
++ new_duration = (new_duration & ~0xFFFF) | samples;
++
++ if (event_end & 0x80) {
++ /* End event */
++ if ((rtp->lastevent != seqno) && rtp->resp) {
++ rtp->dtmf_duration = new_duration;
++ f = send_dtmf(instance, AST_FRAME_DTMF_END, 0);
++ f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, 8000), ast_tv(0, 0));
++ rtp->resp = 0;
++ rtp->dtmf_duration = rtp->dtmf_timeout = 0;
++ }
++ } else {
++ /* Begin/continuation */
++
++ if (rtp->resp && rtp->resp != resp) {
++ /* Another digit already began. End it */
++ f = send_dtmf(instance, AST_FRAME_DTMF_END, 0);
++ f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, 8000), ast_tv(0, 0));
++ rtp->resp = 0;
++ rtp->dtmf_duration = rtp->dtmf_timeout = 0;
++ }
++
++ if (rtp->resp) {
++ /* Digit continues */
++ rtp->dtmf_duration = new_duration;
++ } else {
++ /* New digit began */
++ rtp->resp = resp;
++ f = send_dtmf(instance, AST_FRAME_DTMF_BEGIN, 0);
++ rtp->dtmf_duration = samples;
++ }
++
++ rtp->dtmf_timeout = timestamp + rtp->dtmf_duration + dtmftimeout;
++ }
++
++ rtp->lastevent = seqno;
++ }
++
++ rtp->dtmfsamples = samples;
++
++ return f;
++}
++
++static struct ast_frame *process_dtmf_cisco(struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, struct sockaddr_in *sin, int payloadtype, int mark)
++{
++ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
++ unsigned int event, flags, power;
++ char resp = 0;
++ unsigned char seq;
++ struct ast_frame *f = NULL;
++
++ if (len < 4) {
++ return NULL;
++ }
++
++ /* The format of Cisco RTP DTMF packet looks like next:
++ +0 - sequence number of DTMF RTP packet (begins from 1,
++ wrapped to 0)
++ +1 - set of flags
++ +1 (bit 0) - flaps by different DTMF digits delimited by audio
++ or repeated digit without audio???
++ +2 (+4,+6,...) - power level? (rises from 0 to 32 at begin of tone
++ then falls to 0 at its end)
++ +3 (+5,+7,...) - detected DTMF digit (0..9,*,#,A-D,...)
++ Repeated DTMF information (bytes 4/5, 6/7) is history shifted right
++ by each new packet and thus provides some redudancy.
++
++ Sample of Cisco RTP DTMF packet is (all data in hex):
++ 19 07 00 02 12 02 20 02
++ showing end of DTMF digit '2'.
++
++ The packets
++ 27 07 00 02 0A 02 20 02
++ 28 06 20 02 00 02 0A 02
++ shows begin of new digit '2' with very short pause (20 ms) after
++ previous digit '2'. Bit +1.0 flips at begin of new digit.
++
++ Cisco RTP DTMF packets comes as replacement of audio RTP packets
++ so its uses the same sequencing and timestamping rules as replaced
++ audio packets. Repeat interval of DTMF packets is 20 ms and not rely
++ on audio framing parameters. Marker bit isn't used within stream of
++ DTMFs nor audio stream coming immediately after DTMF stream. Timestamps
++ are not sequential at borders between DTMF and audio streams,
++ */
++
++ seq = data[0];
++ flags = data[1];
++ power = data[2];
++ event = data[3] & 0x1f;
++
++ if (option_debug > 2 || rtpdebug)
++ ast_debug(0, "Cisco DTMF Digit: %02x (len=%d, seq=%d, flags=%02x, power=%d, history count=%d)\n", event, len, seq, flags, power, (len - 4) / 2);
++ if (event < 10) {
++ resp = '0' + event;
++ } else if (event < 11) {
++ resp = '*';
++ } else if (event < 12) {
++ resp = '#';
++ } else if (event < 16) {
++ resp = 'A' + (event - 12);
++ } else if (event < 17) {
++ resp = 'X';
++ }
++ if ((!rtp->resp && power) || (rtp->resp && (rtp->resp != resp))) {
++ rtp->resp = resp;
++ /* Why we should care on DTMF compensation at reception? */
++ if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE)) {
++ f = send_dtmf(instance, AST_FRAME_DTMF_BEGIN, 0);
++ rtp->dtmfsamples = 0;
++ }
++ } else if ((rtp->resp == resp) && !power) {
++ f = send_dtmf(instance, AST_FRAME_DTMF_END, ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE));
++ f->samples = rtp->dtmfsamples * 8;
++ rtp->resp = 0;
++ } else if (rtp->resp == resp)
++ rtp->dtmfsamples += 20 * 8;
++ rtp->dtmf_timeout = 0;
++
++ return f;
++}
++
++static struct ast_frame *process_cn_rfc3389(struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, struct sockaddr_in *sin, int payloadtype, int mark)
++{
++ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
++
++ /* Convert comfort noise into audio with various codecs. Unfortunately this doesn't
++ totally help us out becuase we don't have an engine to keep it going and we are not
++ guaranteed to have it every 20ms or anything */
++ if (rtpdebug)
++ ast_debug(0, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", rtp->lastrxformat, len);
++
++ if (ast_test_flag(rtp, FLAG_3389_WARNING)) {
++ struct sockaddr_in remote_address = { 0, };
++
++ ast_rtp_instance_get_remote_address(instance, &remote_address);
++
++ ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client IP: %s\n",
++ ast_inet_ntoa(remote_address.sin_addr));
++ ast_set_flag(rtp, FLAG_3389_WARNING);
++ }
++
++ /* Must have at least one byte */
++ if (!len)
++ return NULL;
++ if (len < 24) {
++ rtp->f.data.ptr = rtp->rawdata + AST_FRIENDLY_OFFSET;
++ rtp->f.datalen = len - 1;
++ rtp->f.offset = AST_FRIENDLY_OFFSET;
++ memcpy(rtp->f.data.ptr, data + 1, len - 1);
++ } else {
++ rtp->f.data.ptr = NULL;
++ rtp->f.offset = 0;
++ rtp->f.datalen = 0;
++ }
++ rtp->f.frametype = AST_FRAME_CNG;
++ rtp->f.subclass = data[0] & 0x7f;
++ rtp->f.datalen = len - 1;
++ rtp->f.samples = 0;
++ rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0;
++
++ return &rtp->f;
++}
++
++static struct ast_frame *ast_rtcp_read(struct ast_rtp_instance *instance)
++{
++ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
++ struct sockaddr_in sin;
++ socklen_t len = sizeof(sin);
++ unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET];
++ unsigned int *rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET);
++ int res, packetwords, position = 0;
++ struct ast_frame *f = &ast_null_frame;
++
++ /* Read in RTCP data from the socket */
++ if ((res = recvfrom(rtp->rtcp->s, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET, 0, (struct sockaddr *)&sin, &len)) < 0) {
++ ast_assert(errno != EBADF);
++ if (errno != EAGAIN) {
++ ast_log(LOG_WARNING, "RTCP Read error: %s. Hanging up.\n", strerror(errno));
++ return NULL;
++ }
++ return &ast_null_frame;
++ }
++
++ packetwords = res / 4;
++
++ if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT)) {
++ /* Send to whoever sent to us */
++ if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
++ (rtp->rtcp->them.sin_port != sin.sin_port)) {
++ memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them));
++ if (option_debug || rtpdebug)
++ ast_debug(0, "RTCP NAT: Got RTCP from other end. Now sending to address %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
++ }
++ }
++
++ ast_debug(1, "Got RTCP report of %d bytes\n", res);
++
++ while (position < packetwords) {
++ int i, pt, rc;
++ unsigned int length, dlsr, lsr, msw, lsw, comp;
++ struct timeval now;
++ double rttsec, reported_jitter, reported_normdev_jitter_current, normdevrtt_current, reported_lost, reported_normdev_lost_current;
++ uint64_t rtt = 0;
++
++ i = position;
++ length = ntohl(rtcpheader[i]);
++ pt = (length & 0xff0000) >> 16;
++ rc = (length & 0x1f000000) >> 24;
++ length &= 0xffff;
++
++ if ((i + length) > packetwords) {
++ if (option_debug || rtpdebug)
++ ast_log(LOG_DEBUG, "RTCP Read too short\n");
++ return &ast_null_frame;
++ }
++
++ if (rtcp_debug_test_addr(&sin)) {
++ ast_verbose("\n\nGot RTCP from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
++ ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown");
++ ast_verbose("Reception reports: %d\n", rc);
++ ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]);
++ }
++
++ i += 2; /* Advance past header and ssrc */
++
++ switch (pt) {
++ case RTCP_PT_SR:
++ gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */
++ rtp->rtcp->spc = ntohl(rtcpheader[i+3]);
++ rtp->rtcp->soc = ntohl(rtcpheader[i + 4]);
++ rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/
++
++ if (rtcp_debug_test_addr(&sin)) {
++ ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096);
++ ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2]));
++ ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4]));
++ }
++ i += 5;
++ if (rc < 1)
++ break;
++ /* Intentional fall through */
++ case RTCP_PT_RR:
++ /* Don't handle multiple reception reports (rc > 1) yet */
++ /* Calculate RTT per RFC */
++ gettimeofday(&now, NULL);
++ timeval2ntp(now, &msw, &lsw);
++ if (ntohl(rtcpheader[i + 4]) && ntohl(rtcpheader[i + 5])) { /* We must have the LSR && DLSR */
++ comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16);
++ lsr = ntohl(rtcpheader[i + 4]);
++ dlsr = ntohl(rtcpheader[i + 5]);
++ rtt = comp - lsr - dlsr;
++
++ /* Convert end to end delay to usec (keeping the calculation in 64bit space)
++ sess->ee_delay = (eedelay * 1000) / 65536; */
++ if (rtt < 4294) {
++ rtt = (rtt * 1000000) >> 16;
++ } else {
++ rtt = (rtt * 1000) >> 16;
++ rtt *= 1000;
++ }
++ rtt = rtt / 1000.;
++ rttsec = rtt / 1000.;
++ rtp->rtcp->rtt = rttsec;
++
++ if (comp - dlsr >= lsr) {
++ rtp->rtcp->accumulated_transit += rttsec;
++
++ if (rtp->rtcp->rtt_count == 0)
++ rtp->rtcp->minrtt = rttsec;
++
++ if (rtp->rtcp->maxrtt<rttsec)
++ rtp->rtcp->maxrtt = rttsec;
++ if (rtp->rtcp->minrtt>rttsec)
++ rtp->rtcp->minrtt = rttsec;
++
++ normdevrtt_current = normdev_compute(rtp->rtcp->normdevrtt, rttsec, rtp->rtcp->rtt_count);
++
++ rtp->rtcp->stdevrtt = stddev_compute(rtp->rtcp->stdevrtt, rttsec, rtp->rtcp->normdevrtt, normdevrtt_current, rtp->rtcp->rtt_count);
++
++ rtp->rtcp->normdevrtt = normdevrtt_current;
++
++ rtp->rtcp->rtt_count++;
++ } else if (rtcp_debug_test_addr(&sin)) {
++ ast_verbose("Internal RTCP NTP clock skew detected: "
++ "lsr=%u, now=%u, dlsr=%u (%d:%03dms), "
++ "diff=%d\n",
++ lsr, comp, dlsr, dlsr / 65536,
++ (dlsr % 65536) * 1000 / 65536,
++ dlsr - (comp - lsr));
++ }
++ }
++
++ rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]);
++ reported_jitter = (double) rtp->rtcp->reported_jitter;
++
++ if (rtp->rtcp->reported_jitter_count == 0)
++ rtp->rtcp->reported_minjitter = reported_jitter;
++
++ if (reported_jitter < rtp->rtcp->reported_minjitter)
++ rtp->rtcp->reported_minjitter = reported_jitter;
++
++ if (reported_jitter > rtp->rtcp->reported_maxjitter)
++ rtp->rtcp->reported_maxjitter = reported_jitter;
++
++ reported_normdev_jitter_current = normdev_compute(rtp->rtcp->reported_normdev_jitter, reported_jitter, rtp->rtcp->reported_jitter_count);
++
++ rtp->rtcp->reported_stdev_jitter = stddev_compute(rtp->rtcp->reported_stdev_jitter, reported_jitter, rtp->rtcp->reported_normdev_jitter, reported_normdev_jitter_current, rtp->rtcp->reported_jitter_count);
++
++ rtp->rtcp->reported_normdev_jitter = reported_normdev_jitter_current;
++
++ rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff;
++
++ reported_lost = (double) rtp->rtcp->reported_lost;
++
++ /* using same counter as for jitter */
++ if (rtp->rtcp->reported_jitter_count == 0)
++ rtp->rtcp->reported_minlost = reported_lost;
++
++ if (reported_lost < rtp->rtcp->reported_minlost)
++ rtp->rtcp->reported_minlost = reported_lost;
++
++ if (reported_lost > rtp->rtcp->reported_maxlost)
++ rtp->rtcp->reported_maxlost = reported_lost;
++ reported_normdev_lost_current = normdev_compute(rtp->rtcp->reported_normdev_lost, reported_lost, rtp->rtcp->reported_jitter_count);
++
++ rtp->rtcp->reported_stdev_lost = stddev_compute(rtp->rtcp->reported_stdev_lost, reported_lost, rtp->rtcp->reported_normdev_lost, reported_normdev_lost_current, rtp->rtcp->reported_jitter_count);
++
++ rtp->rtcp->reported_normdev_lost = reported_normdev_lost_current;
++
++ rtp->rtcp->reported_jitter_count++;
++
++ if (rtcp_debug_test_addr(&sin)) {
++ ast_verbose(" Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24));
++ ast_verbose(" Packets lost so far: %d\n", rtp->rtcp->reported_lost);
++ ast_verbose(" Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff));
++ ast_verbose(" Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16);
++ ast_verbose(" Interarrival jitter: %u\n", rtp->rtcp->reported_jitter);
++ ast_verbose(" Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096);
++ ast_verbose(" DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0);
++ if (rtt)
++ ast_verbose(" RTT: %lu(sec)\n", (unsigned long) rtt);
++ }
++ if (rtt) {
++ manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From %s:%d\r\n"
++ "PT: %d(%s)\r\n"
++ "ReceptionReports: %d\r\n"
++ "SenderSSRC: %u\r\n"
++ "FractionLost: %ld\r\n"
++ "PacketsLost: %d\r\n"
++ "HighestSequence: %ld\r\n"
++ "SequenceNumberCycles: %ld\r\n"
++ "IAJitter: %u\r\n"
++ "LastSR: %lu.%010lu\r\n"
++ "DLSR: %4.4f(sec)\r\n"
++ "RTT: %llu(sec)\r\n",
++ ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port),
++ pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown",
++ rc,
++ rtcpheader[i + 1],
++ (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24),
++ rtp->rtcp->reported_lost,
++ (long) (ntohl(rtcpheader[i + 2]) & 0xffff),
++ (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16,
++ rtp->rtcp->reported_jitter,
++ (unsigned long) ntohl(rtcpheader[i + 4]) >> 16, ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096,
++ ntohl(rtcpheader[i + 5])/65536.0,
++ (unsigned long long)rtt);
++ } else {
++ manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From %s:%d\r\n"
++ "PT: %d(%s)\r\n"
++ "ReceptionReports: %d\r\n"
++ "SenderSSRC: %u\r\n"
++ "FractionLost: %ld\r\n"
++ "PacketsLost: %d\r\n"
++ "HighestSequence: %ld\r\n"
++ "SequenceNumberCycles: %ld\r\n"
++ "IAJitter: %u\r\n"
++ "LastSR: %lu.%010lu\r\n"
++ "DLSR: %4.4f(sec)\r\n",
++ ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port),
++ pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown",
++ rc,
++ rtcpheader[i + 1],
++ (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24),
++ rtp->rtcp->reported_lost,
++ (long) (ntohl(rtcpheader[i + 2]) & 0xffff),
++ (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16,
++ rtp->rtcp->reported_jitter,
++ (unsigned long) ntohl(rtcpheader[i + 4]) >> 16,
++ ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096,
++ ntohl(rtcpheader[i + 5])/65536.0);
++ }
++ break;
++ case RTCP_PT_FUR:
++ if (rtcp_debug_test_addr(&sin))
++ ast_verbose("Received an RTCP Fast Update Request\n");
++ rtp->f.frametype = AST_FRAME_CONTROL;
++ rtp->f.subclass = AST_CONTROL_VIDUPDATE;
++ rtp->f.datalen = 0;
++ rtp->f.samples = 0;
++ rtp->f.mallocd = 0;
++ rtp->f.src = "RTP";
++ f = &rtp->f;
++ break;
++ case RTCP_PT_SDES:
++ if (rtcp_debug_test_addr(&sin))
++ ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
++ break;
++ case RTCP_PT_BYE:
++ if (rtcp_debug_test_addr(&sin))
++ ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
++ break;
++ default:
++ ast_debug(1, "Unknown RTCP packet (pt=%d) received from %s:%d\n", pt, ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
++ break;
++ }
++ position += (length + 1);
++ }
++
++ rtp->rtcp->rtcp_info = 1;
++
++ return f;
++}
++
++static int bridge_p2p_rtp_write(struct ast_rtp_instance *instance, unsigned int *rtpheader, int len, int hdrlen)
++{
++ struct ast_rtp_instance *instance1 = ast_rtp_instance_get_bridged(instance);
++ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance), *bridged = ast_rtp_instance_get_data(instance1);
++ int res = 0, payload = 0, bridged_payload = 0, mark;
++ struct ast_rtp_payload_type payload_type;
++ int reconstruct = ntohl(rtpheader[0]);
++ struct sockaddr_in remote_address = { 0, };
++
++ /* Get fields from packet */
++ payload = (reconstruct & 0x7f0000) >> 16;
++ mark = (((reconstruct & 0x800000) >> 23) != 0);
++
++ /* Check what the payload value should be */
++ payload_type = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(instance), payload);
++
++ /* Otherwise adjust bridged payload to match */
++ bridged_payload = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance1), payload_type.asterisk_format, payload_type.code);
++
++ /* If the payload coming in is not one of the negotiated ones then send it to the core, this will cause formats to change and the bridge to break */
++ if (!(ast_rtp_instance_get_codecs(instance1)->payloads[bridged_payload].code)) {
++ return -1;
++ }
++
++ /* If the marker bit has been explicitly set turn it on */
++ if (ast_test_flag(rtp, FLAG_NEED_MARKER_BIT)) {
++ mark = 1;
++ ast_clear_flag(rtp, FLAG_NEED_MARKER_BIT);
++ }
++
++ /* Reconstruct part of the packet */
++ reconstruct &= 0xFF80FFFF;
++ reconstruct |= (bridged_payload << 16);
++ reconstruct |= (mark << 23);
++ rtpheader[0] = htonl(reconstruct);
++
++ ast_rtp_instance_get_remote_address(instance1, &remote_address);
++
++ /* Send the packet back out */
++ res = sendto(bridged->s, (void *)rtpheader, len, 0, (struct sockaddr *)&remote_address, sizeof(remote_address));
++ if (res < 0) {
++ if (!ast_rtp_instance_get_prop(instance1, AST_RTP_PROPERTY_NAT) || (ast_rtp_instance_get_prop(instance1, AST_RTP_PROPERTY_NAT) && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
++ ast_debug(1, "RTP Transmission error of packet to %s:%d: %s\n", ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port), strerror(errno));
++ } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) {
++ if (option_debug || rtpdebug)
++ ast_debug(0, "RTP NAT: Can't write RTP to private address %s:%d, waiting for other end to send audio...\n", ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port));
++ ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN);
++ }
++ return 0;
++ } else if (rtp_debug_test_addr(&remote_address)) {
++ ast_verbose("Sent RTP P2P packet to %s:%u (type %-2.2d, len %-6.6u)\n", ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port), bridged_payload, len - hdrlen);
++ }
++
++ return 0;
++}
++
++static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtcp)
++{
++ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
++ struct sockaddr_in sin;
++ socklen_t len = sizeof(sin);
++ int res, hdrlen = 12, version, payloadtype, padding, mark, ext, cc, prev_seqno;
++ unsigned int *rtpheader = (unsigned int*)(rtp->rawdata + AST_FRIENDLY_OFFSET), seqno, ssrc, timestamp;
++ struct ast_rtp_payload_type payload;
++ struct sockaddr_in remote_address = { 0, };
++
++ /* If this is actually RTCP let's hop on over and handle it */
++ if (rtcp) {
++ if (rtp->rtcp) {
++ return ast_rtcp_read(instance);
++ }
++ return &ast_null_frame;
++ }
++
++ /* If we are currently sending DTMF to the remote party send a continuation packet */
++ if (rtp->sending_digit) {
++ ast_rtp_dtmf_continuation(instance);
++ }
++
++ /* Actually read in the data from the socket */
++ if ((res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 0, (struct sockaddr*)&sin, &len)) < 0) {
++ ast_assert(errno != EBADF);
++ if (errno != EAGAIN) {
++ ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up.\n", strerror(errno));
++ return NULL;
++ }
++ return &ast_null_frame;
++ }
++
++ /* Make sure the data that was read in is actually enough to make up an RTP packet */
++ if (res < hdrlen) {
++ ast_log(LOG_WARNING, "RTP Read too short\n");
++ return &ast_null_frame;
++ }
++
++ /* If strict RTP protection is enabled see if we need to learn the remote address or if we need to drop the packet */
++ if (rtp->strict_rtp_state == STRICT_RTP_LEARN) {
++ memcpy(&rtp->strict_rtp_address, &sin, sizeof(rtp->strict_rtp_address));
++ rtp->strict_rtp_state = STRICT_RTP_CLOSED;
++ } else if (rtp->strict_rtp_state == STRICT_RTP_CLOSED) {
++ if ((rtp->strict_rtp_address.sin_addr.s_addr != sin.sin_addr.s_addr) || (rtp->strict_rtp_address.sin_port != sin.sin_port)) {
++ /* Hmm, not the strict addres. Perhaps we're getting audio from the alternate? */
++ if ((rtp->alt_rtp_address.sin_addr.s_addr == sin.sin_addr.s_addr) && (rtp->alt_rtp_address.sin_port == sin.sin_port)) {
++ /* ooh, we did! You're now the new expected address, son! */
++ rtp->strict_rtp_address = sin;
++ } else {
++ ast_debug(1, "Received RTP packet from %s:%d, dropping due to strict RTP protection. Expected it to be from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), ast_inet_ntoa(rtp->strict_rtp_address.sin_addr), ntohs(rtp->strict_rtp_address.sin_port));
++ return &ast_null_frame;
++ }
++ }
++ }
++
++ /* Get fields and verify this is an RTP packet */
++ seqno = ntohl(rtpheader[0]);
++
++ ast_rtp_instance_get_remote_address(instance, &remote_address);
++
++ if (!(version = (seqno & 0xC0000000) >> 30)) {
++ if ((ast_stun_handle_packet(rtp->s, &sin, rtp->rawdata + AST_FRIENDLY_OFFSET, res, NULL, NULL) == AST_STUN_ACCEPT) &&
++ (!remote_address.sin_port && !remote_address.sin_addr.s_addr)) {
++ ast_rtp_instance_set_remote_address(instance, &sin);
++ }
++ return &ast_null_frame;
++ }
++
++ /* If symmetric RTP is enabled see if the remote side is not what we expected and change where we are sending audio */
++ if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT)) {
++ if ((remote_address.sin_addr.s_addr != sin.sin_addr.s_addr) ||
++ (remote_address.sin_port != sin.sin_port)) {
++ ast_rtp_instance_set_remote_address(instance, &sin);
++ memcpy(&remote_address, &sin, sizeof(remote_address));
++ if (rtp->rtcp) {
++ memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them));
++ rtp->rtcp->them.sin_port = htons(ntohs(sin.sin_port)+1);
++ }
++ rtp->rxseqno = 0;
++ ast_set_flag(rtp, FLAG_NAT_ACTIVE);
++ if (option_debug || rtpdebug)
++ ast_debug(0, "RTP NAT: Got audio from other end. Now sending to address %s:%d\n", ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port));
++ }
++ }
++
++ /* If we are directly bridged to another instance send the audio directly out */
++ if (ast_rtp_instance_get_bridged(instance) && !bridge_p2p_rtp_write(instance, rtpheader, res, hdrlen)) {
++ return &ast_null_frame;
++ }
++
++ /* If the version is not what we expected by this point then just drop the packet */
++ if (version != 2) {
++ return &ast_null_frame;
++ }
++
++ /* Pull out the various other fields we will need */
++ payloadtype = (seqno & 0x7f0000) >> 16;
++ padding = seqno & (1 << 29);
++ mark = seqno & (1 << 23);
++ ext = seqno & (1 << 28);
++ cc = (seqno & 0xF000000) >> 24;
++ seqno &= 0xffff;
++ timestamp = ntohl(rtpheader[1]);
++ ssrc = ntohl(rtpheader[2]);
++
++ /* Force a marker bit if the SSRC changes */
++ if (!mark && rtp->rxssrc && rtp->rxssrc != ssrc) {
++ if (option_debug || rtpdebug) {
++ ast_debug(1, "Forcing Marker bit, because SSRC has changed\n");
++ }
++ mark = 1;
++ }
++
++ /* Remove any padding bytes that may be present */
++ if (padding) {
++ res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1];
++ }
++
++ /* Skip over any CSRC fields */
++ if (cc) {
++ hdrlen += cc * 4;
++ }
++
++ /* Look for any RTP extensions, currently we do not support any */
++ if (ext) {
++ hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2;
++ hdrlen += 4;
++ if (option_debug) {
++ int profile;
++ profile = (ntohl(rtpheader[3]) & 0xffff0000) >> 16;
++ if (profile == 0x505a)
++ ast_debug(1, "Found Zfone extension in RTP stream - zrtp - not supported.\n");
++ else
++ ast_debug(1, "Found unknown RTP Extensions %x\n", profile);
++ }
++ }
++
++ /* Make sure after we potentially mucked with the header length that it is once again valid */
++ if (res < hdrlen) {
++ ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d\n", res, hdrlen);
++ return &ast_null_frame;
++ }
++
++ rtp->rxcount++;
++ if (rtp->rxcount == 1) {
++ rtp->seedrxseqno = seqno;
++ }
++
++ /* Do not schedule RR if RTCP isn't run */
++ if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) {
++ /* Schedule transmission of Receiver Report */
++ rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
++ }
++ if ((int)rtp->lastrxseqno - (int)seqno > 100) /* if so it would indicate that the sender cycled; allow for misordering */
++ rtp->cycles += RTP_SEQ_MOD;
++
++ prev_seqno = rtp->lastrxseqno;
++ rtp->lastrxseqno = seqno;
++
++ if (!rtp->themssrc) {
++ rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */
++ }
++
++ if (rtp_debug_test_addr(&sin)) {
++ ast_verbose("Got RTP packet from %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
++ ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen);
++ }
++
++ payload = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(instance), payloadtype);
++
++ /* If the payload is not actually an Asterisk one but a special one pass it off to the respective handler */
++ if (!payload.asterisk_format) {
++ struct ast_frame *f = NULL;
++
++ if (payload.code == AST_RTP_DTMF) {
++ f = process_dtmf_rfc2833(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &sin, payloadtype, mark);
++ } else if (payload.code == AST_RTP_CISCO_DTMF) {
++ f = process_dtmf_cisco(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &sin, payloadtype, mark);
++ } else if (payload.code == AST_RTP_CN) {
++ f = process_cn_rfc3389(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &sin, payloadtype, mark);
++ } else {
++ ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", payloadtype, ast_inet_ntoa(remote_address.sin_addr));
++ }
++
++ return f ? f : &ast_null_frame;
++ }
++
++ rtp->lastrxformat = rtp->f.subclass = payload.code;
++ rtp->f.frametype = (rtp->f.subclass & AST_FORMAT_AUDIO_MASK) ? AST_FRAME_VOICE : (rtp->f.subclass & AST_FORMAT_VIDEO_MASK) ? AST_FRAME_VIDEO : AST_FRAME_TEXT;
++
++ rtp->rxseqno = seqno;
++
++ if (rtp->dtmf_timeout && rtp->dtmf_timeout < timestamp) {
++ rtp->dtmf_timeout = 0;
++
++ if (rtp->resp) {
++ struct ast_frame *f;
++ f = send_dtmf(instance, AST_FRAME_DTMF_END, 0);
++ f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, 8000), ast_tv(0, 0));
++ rtp->resp = 0;
++ rtp->dtmf_timeout = rtp->dtmf_duration = 0;
++ return f;
++ }
++ }
++
++ rtp->lastrxts = timestamp;
++
++ rtp->f.src = "RTP";
++ rtp->f.mallocd = 0;
++ rtp->f.datalen = res - hdrlen;
++ rtp->f.data.ptr = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET;
++ rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
++ rtp->f.seqno = seqno;
++
++ if (rtp->f.subclass == AST_FORMAT_T140 && (int)seqno - (prev_seqno+1) > 0 && (int)seqno - (prev_seqno+1) < 10) {
++ unsigned char *data = rtp->f.data.ptr;
++
++ memmove(rtp->f.data.ptr+3, rtp->f.data.ptr, rtp->f.datalen);
++ rtp->f.datalen +=3;
++ *data++ = 0xEF;
++ *data++ = 0xBF;
++ *data = 0xBD;
++ }
++
++ if (rtp->f.subclass == AST_FORMAT_T140RED) {
++ unsigned char *data = rtp->f.data.ptr;
++ unsigned char *header_end;
++ int num_generations;
++ int header_length;
++ int len;
++ int diff =(int)seqno - (prev_seqno+1); /* if diff = 0, no drop*/
++ int x;
++
++ rtp->f.subclass = AST_FORMAT_T140;
++ header_end = memchr(data, ((*data) & 0x7f), rtp->f.datalen);
++ header_end++;
++
++ header_length = header_end - data;
++ num_generations = header_length / 4;
++ len = header_length;
++
++ if (!diff) {
++ for (x = 0; x < num_generations; x++)
++ len += data[x * 4 + 3];
++
++ if (!(rtp->f.datalen - len))
++ return &ast_null_frame;
++
++ rtp->f.data.ptr += len;
++ rtp->f.datalen -= len;
++ } else if (diff > num_generations && diff < 10) {
++ len -= 3;
++ rtp->f.data.ptr += len;
++ rtp->f.datalen -= len;
++
++ data = rtp->f.data.ptr;
++ *data++ = 0xEF;
++ *data++ = 0xBF;
++ *data = 0xBD;
++ } else {
++ for ( x = 0; x < num_generations - diff; x++)
++ len += data[x * 4 + 3];
++
++ rtp->f.data.ptr += len;
++ rtp->f.datalen -= len;
++ }
++ }
++
++ if (rtp->f.subclass & AST_FORMAT_AUDIO_MASK) {
++ rtp->f.samples = ast_codec_get_samples(&rtp->f);
++ if (rtp->f.subclass == AST_FORMAT_SLINEAR)
++ ast_frame_byteswap_be(&rtp->f);
++ calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark);
++ /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */
++ ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO);
++ rtp->f.ts = timestamp / 8;
++ rtp->f.len = rtp->f.samples / ((ast_format_rate(rtp->f.subclass) / 1000));
++ } else if (rtp->f.subclass & AST_FORMAT_VIDEO_MASK) {
++ /* Video -- samples is # of samples vs. 90000 */
++ if (!rtp->lastividtimestamp)
++ rtp->lastividtimestamp = timestamp;
++ rtp->f.samples = timestamp - rtp->lastividtimestamp;
++ rtp->lastividtimestamp = timestamp;
++ rtp->f.delivery.tv_sec = 0;
++ rtp->f.delivery.tv_usec = 0;
++ /* Pass the RTP marker bit as bit 0 in the subclass field.
++ * This is ok because subclass is actually a bitmask, and
++ * the low bits represent audio formats, that are not
++ * involved here since we deal with video.
++ */
++ if (mark)
++ rtp->f.subclass |= 0x1;
++ } else {
++ /* TEXT -- samples is # of samples vs. 1000 */
++ if (!rtp->lastitexttimestamp)
++ rtp->lastitexttimestamp = timestamp;
++ rtp->f.samples = timestamp - rtp->lastitexttimestamp;
++ rtp->lastitexttimestamp = timestamp;
++ rtp->f.delivery.tv_sec = 0;
++ rtp->f.delivery.tv_usec = 0;
++ }
++
++ return &rtp->f;
++}
++
++static void ast_rtp_prop_set(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value)
++{
++ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
++
++ if (property == AST_RTP_PROPERTY_RTCP) {
++ if (rtp->rtcp) {
++ ast_debug(1, "Ignoring duplicate RTCP property on RTP instance '%p'\n", instance);
++ return;
++ }
++ if (!(rtp->rtcp = ast_calloc(1, sizeof(*rtp->rtcp)))) {
++ return;
++ }
++ if ((rtp->rtcp->s = create_new_socket("RTCP")) < 0) {
++ ast_debug(1, "Failed to create a new socket for RTCP on instance '%p'\n", instance);
++ ast_free(rtp->rtcp);
++ rtp->rtcp = NULL;
++ return;
++ }
++
++ /* Grab the IP address and port we are going to use */
++ ast_rtp_instance_get_local_address(instance, &rtp->rtcp->us);
++ rtp->rtcp->us.sin_port = htons(ntohs(rtp->rtcp->us.sin_port) + 1);
++
++ /* Try to actually bind to the IP address and port we are going to use for RTCP, if this fails we have to bail out */
++ if (bind(rtp->rtcp->s, (struct sockaddr*)&rtp->rtcp->us, sizeof(rtp->rtcp->us))) {
++ ast_debug(1, "Failed to setup RTCP on RTP instance '%p'\n", instance);
++ close(rtp->rtcp->s);
++ ast_free(rtp->rtcp);
++ rtp->rtcp = NULL;
++ return;
++ }
++
++ ast_debug(1, "Setup RTCP on RTP instance '%p'\n", instance);
++ rtp->rtcp->schedid = -1;
++
++ return;
++ }
++
++ return;
++}
++
++static int ast_rtp_fd(struct ast_rtp_instance *instance, int rtcp)
++{
++ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
++
++ return rtcp ? (rtp->rtcp ? rtp->rtcp->s : -1) : rtp->s;
++}
++
++static void ast_rtp_remote_address_set(struct ast_rtp_instance *instance, struct sockaddr_in *sin)
++{
++ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
++
++ if (rtp->rtcp) {
++ ast_debug(1, "Setting RTCP address on RTP instance '%p'\n", instance);
++ memcpy(&rtp->rtcp->them, sin, sizeof(rtp->rtcp->them));
++ rtp->rtcp->them.sin_port = htons(ntohs(sin->sin_port) + 1);
++ }
++
++ rtp->rxseqno = 0;
++
++ if (strictrtp) {
++ rtp->strict_rtp_state = STRICT_RTP_LEARN;
++ }
++
++ return;
++}
++
++static void ast_rtp_alt_remote_address_set(struct ast_rtp_instance *instance, struct sockaddr_in *sin)
++{
++ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
++
++ /* No need to futz with rtp->rtcp here because ast_rtcp_read is already able to adjust if receiving
++ * RTCP from an "unexpected" source
++ */
++ rtp->alt_rtp_address = *sin;
++
++ return;
++}
++
++/*! \brief Write t140 redundacy frame
++ * \param data primary data to be buffered
++ */
++static int red_write(const void *data)
++{
++ struct ast_rtp_instance *instance = (struct ast_rtp_instance*) data;
++ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
++
++ ast_rtp_write(instance, &rtp->red->t140);
++
++ return 1;
++}
++
++static int rtp_red_init(struct ast_rtp_instance *instance, int buffer_time, int *payloads, int generations)
++{
++ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
++ int x;
++
++ if (!(rtp->red = ast_calloc(1, sizeof(*rtp->red)))) {
++ return -1;
++ }
++
++ rtp->red->t140.frametype = AST_FRAME_TEXT;
++ rtp->red->t140.subclass = AST_FORMAT_T140RED;
++ rtp->red->t140.data.ptr = &rtp->red->buf_data;
++
++ rtp->red->t140.ts = 0;
++ rtp->red->t140red = rtp->red->t140;
++ rtp->red->t140red.data.ptr = &rtp->red->t140red_data;
++ rtp->red->t140red.datalen = 0;
++ rtp->red->ti = buffer_time;
++ rtp->red->num_gen = generations;
++ rtp->red->hdrlen = generations * 4 + 1;
++ rtp->red->prev_ts = 0;
++
++ for (x = 0; x < generations; x++) {
++ rtp->red->pt[x] = payloads[x];
++ rtp->red->pt[x] |= 1 << 7; /* mark redundant generations pt */
++ rtp->red->t140red_data[x*4] = rtp->red->pt[x];
++ }
++ rtp->red->t140red_data[x*4] = rtp->red->pt[x] = payloads[x]; /* primary pt */
++ rtp->red->schedid = ast_sched_add(rtp->sched, generations, red_write, instance);
++
++ rtp->red->t140.datalen = 0;
++
++ return 0;
++}
++
++static int rtp_red_buffer(struct ast_rtp_instance *instance, struct ast_frame *frame)
++{
++ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
++
++ if (frame->datalen > -1) {
++ struct rtp_red *red = rtp->red;
++ memcpy(&red->buf_data[red->t140.datalen], frame->data.ptr, frame->datalen);
++ red->t140.datalen += frame->datalen;
++ red->t140.ts = frame->ts;
++ }
++
++ return 0;
++}
++
++static int ast_rtp_local_bridge(struct ast_rtp_instance *instance0, struct ast_rtp_instance *instance1)
++{
++ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance0);
++
++ ast_set_flag(rtp, FLAG_NEED_MARKER_BIT);
++
++ return 0;
++}
++
++static int ast_rtp_get_stat(struct ast_rtp_instance *instance, struct ast_rtp_instance_stats *stats, enum ast_rtp_instance_stat stat)
++{
++ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
++
++ if (!rtp->rtcp) {
++ return -1;
++ }
++
++ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_TXCOUNT, -1, stats->txcount, rtp->txcount);
++ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_RXCOUNT, -1, stats->rxcount, rtp->rxcount);
++
++ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_TXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->txploss, rtp->rtcp->reported_lost);
++ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_RXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->rxploss, rtp->rtcp->expected_prior - rtp->rtcp->received_prior);
++ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_MAXRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->remote_maxrxploss, rtp->rtcp->reported_maxlost);
++ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_MINRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->remote_minrxploss, rtp->rtcp->reported_minlost);
++ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->remote_normdevrxploss, rtp->rtcp->reported_normdev_lost);
++ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_STDEVRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->remote_stdevrxploss, rtp->rtcp->reported_stdev_lost);
++ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_MAXRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->local_maxrxploss, rtp->rtcp->maxrxlost);
++ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_MINRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->local_minrxploss, rtp->rtcp->minrxlost);
++ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->local_normdevrxploss, rtp->rtcp->normdev_rxlost);
++ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_STDEVRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->local_stdevrxploss, rtp->rtcp->stdev_rxlost);
++ AST_RTP_STAT_TERMINATOR(AST_RTP_INSTANCE_STAT_COMBINED_LOSS);
++
++ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_TXJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->txjitter, rtp->rxjitter);
++ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_RXJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->rxjitter, rtp->rtcp->reported_jitter / (unsigned int) 65536.0);
++ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_MAXJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->remote_maxjitter, rtp->rtcp->reported_maxjitter);
++ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_MINJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->remote_minjitter, rtp->rtcp->reported_minjitter);
++ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->remote_normdevjitter, rtp->rtcp->reported_normdev_jitter);
++ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_STDEVJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->remote_stdevjitter, rtp->rtcp->reported_stdev_jitter);
++ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_MAXJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->local_maxjitter, rtp->rtcp->maxrxjitter);
++ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_MINJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->local_minjitter, rtp->rtcp->minrxjitter);
++ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->local_normdevjitter, rtp->rtcp->normdev_rxjitter);
++ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_STDEVJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->local_stdevjitter, rtp->rtcp->stdev_rxjitter);
++ AST_RTP_STAT_TERMINATOR(AST_RTP_INSTANCE_STAT_COMBINED_JITTER);
++
++ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_RTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->rtt, rtp->rtcp->rtt);
++ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_MAX_RTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->maxrtt, rtp->rtcp->maxrtt);
++ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_MIN_RTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->minrtt, rtp->rtcp->minrtt);
++ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_NORMDEVRTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->normdevrtt, rtp->rtcp->normdevrtt);
++ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_STDEVRTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->stdevrtt, rtp->rtcp->stdevrtt);
++ AST_RTP_STAT_TERMINATOR(AST_RTP_INSTANCE_STAT_COMBINED_RTT);
++
++ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_SSRC, -1, stats->local_ssrc, rtp->ssrc);
++ AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_SSRC, -1, stats->remote_ssrc, rtp->themssrc);
++
++ return 0;
++}
++
++static int ast_rtp_dtmf_compatible(struct ast_channel *chan0, struct ast_rtp_instance *instance0, struct ast_channel *chan1, struct ast_rtp_instance *instance1)
++{
++ /* If both sides are not using the same method of DTMF transmission
++ * (ie: one is RFC2833, other is INFO... then we can not do direct media.
++ * --------------------------------------------------
++ * | DTMF Mode | HAS_DTMF | Accepts Begin Frames |
++ * |-----------|------------|-----------------------|
++ * | Inband | False | True |
++ * | RFC2833 | True | True |
++ * | SIP INFO | False | False |
++ * --------------------------------------------------
++ */
++ return (((ast_rtp_instance_get_prop(instance0, AST_RTP_PROPERTY_DTMF) != ast_rtp_instance_get_prop(instance1, AST_RTP_PROPERTY_DTMF)) ||
++ (!chan0->tech->send_digit_begin != !chan1->tech->send_digit_begin)) ? 0 : 1);
++}
++
++static void ast_rtp_stun_request(struct ast_rtp_instance *instance, struct sockaddr_in *suggestion, const char *username)
++{
++ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
++
++ ast_stun_request(rtp->s, suggestion, username, NULL);
++}
++
++static void ast_rtp_stop(struct ast_rtp_instance *instance)
++{
++ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
++ struct sockaddr_in sin = { 0, };
++
++ if (rtp->rtcp) {
++ AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
++ }
++ if (rtp->red) {
++ AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
++ free(rtp->red);
++ rtp->red = NULL;
++ }
++
++ ast_rtp_instance_set_remote_address(instance, &sin);
++ if (rtp->rtcp) {
++ memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr));
++ memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port));
++ }
++
++ ast_set_flag(rtp, FLAG_NEED_MARKER_BIT);
++}
++
++static char *rtp_do_debug_ip(struct ast_cli_args *a)
++{
++ struct hostent *hp;
++ struct ast_hostent ahp;
++ int port = 0;
++ char *p, *arg = ast_strdupa(a->argv[3]);
++
++ p = strstr(arg, ":");
++ if (p) {
++ *p = '\0';
++ p++;
++ port = atoi(p);
++ }
++ hp = ast_gethostbyname(arg, &ahp);
++ if (hp == NULL) {
++ ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
++ return CLI_FAILURE;
++ }
++ rtpdebugaddr.sin_family = AF_INET;
++ memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr));
++ rtpdebugaddr.sin_port = htons(port);
++ if (port == 0)
++ ast_cli(a->fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtpdebugaddr.sin_addr));
++ else
++ ast_cli(a->fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtpdebugaddr.sin_addr), port);
++ rtpdebug = 1;
++ return CLI_SUCCESS;
++}
++
++static char *rtcp_do_debug_ip(struct ast_cli_args *a)
++{
++ struct hostent *hp;
++ struct ast_hostent ahp;
++ int port = 0;
++ char *p, *arg = ast_strdupa(a->argv[3]);
++
++ p = strstr(arg, ":");
++ if (p) {
++ *p = '\0';
++ p++;
++ port = atoi(p);
++ }
++ hp = ast_gethostbyname(arg, &ahp);
++ if (hp == NULL) {
++ ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
++ return CLI_FAILURE;
++ }
++ rtcpdebugaddr.sin_family = AF_INET;
++ memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr));
++ rtcpdebugaddr.sin_port = htons(port);
++ if (port == 0)
++ ast_cli(a->fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr));
++ else
++ ast_cli(a->fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port);
++ rtcpdebug = 1;
++ return CLI_SUCCESS;
++}
++
++static char *handle_cli_rtp_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
++{
++ switch (cmd) {
++ case CLI_INIT:
++ e->command = "rtp set debug {on|off|ip}";
++ e->usage =
++ "Usage: rtp set debug {on|off|ip host[:port]}\n"
++ " Enable/Disable dumping of all RTP packets. If 'ip' is\n"
++ " specified, limit the dumped packets to those to and from\n"
++ " the specified 'host' with optional port.\n";
++ return NULL;
++ case CLI_GENERATE:
++ return NULL;
++ }
++
++ if (a->argc == e->args) { /* set on or off */
++ if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
++ rtpdebug = 1;
++ memset(&rtpdebugaddr, 0, sizeof(rtpdebugaddr));
++ ast_cli(a->fd, "RTP Debugging Enabled\n");
++ return CLI_SUCCESS;
++ } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
++ rtpdebug = 0;
++ ast_cli(a->fd, "RTP Debugging Disabled\n");
++ return CLI_SUCCESS;
++ }
++ } else if (a->argc == e->args +1) { /* ip */
++ return rtp_do_debug_ip(a);
++ }
++
++ return CLI_SHOWUSAGE; /* default, failure */
++}
++
++static char *handle_cli_rtcp_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
++{
++ switch (cmd) {
++ case CLI_INIT:
++ e->command = "rtcp set debug {on|off|ip}";
++ e->usage =
++ "Usage: rtcp set debug {on|off|ip host[:port]}\n"
++ " Enable/Disable dumping of all RTCP packets. If 'ip' is\n"
++ " specified, limit the dumped packets to those to and from\n"
++ " the specified 'host' with optional port.\n";
++ return NULL;
++ case CLI_GENERATE:
++ return NULL;
++ }
++
++ if (a->argc == e->args) { /* set on or off */
++ if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
++ rtcpdebug = 1;
++ memset(&rtcpdebugaddr, 0, sizeof(rtcpdebugaddr));
++ ast_cli(a->fd, "RTCP Debugging Enabled\n");
++ return CLI_SUCCESS;
++ } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
++ rtcpdebug = 0;
++ ast_cli(a->fd, "RTCP Debugging Disabled\n");
++ return CLI_SUCCESS;
++ }
++ } else if (a->argc == e->args +1) { /* ip */
++ return rtcp_do_debug_ip(a);
++ }
++
++ return CLI_SHOWUSAGE; /* default, failure */
++}
++
++static char *handle_cli_rtcp_set_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
++{
++ switch (cmd) {
++ case CLI_INIT:
++ e->command = "rtcp set stats {on|off}";
++ e->usage =
++ "Usage: rtcp set stats {on|off}\n"
++ " Enable/Disable dumping of RTCP stats.\n";
++ return NULL;
++ case CLI_GENERATE:
++ return NULL;
++ }
++
++ if (a->argc != e->args)
++ return CLI_SHOWUSAGE;
++
++ if (!strncasecmp(a->argv[e->args-1], "on", 2))
++ rtcpstats = 1;
++ else if (!strncasecmp(a->argv[e->args-1], "off", 3))
++ rtcpstats = 0;
++ else
++ return CLI_SHOWUSAGE;
++
++ ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled");
++ return CLI_SUCCESS;
++}
++
++static struct ast_cli_entry cli_rtp[] = {
++ AST_CLI_DEFINE(handle_cli_rtp_set_debug, "Enable/Disable RTP debugging"),
++ AST_CLI_DEFINE(handle_cli_rtcp_set_debug, "Enable/Disable RTCP debugging"),
++ AST_CLI_DEFINE(handle_cli_rtcp_set_stats, "Enable/Disable RTCP stats"),
++};
++
++static int rtp_reload(int reload)
++{
++ struct ast_config *cfg;
++ const char *s;
++ struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
++
++ cfg = ast_config_load2("rtp.conf", "rtp", config_flags);
++ if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
++ return 0;
++ }
++
++ rtpstart = DEFAULT_RTP_START;
++ rtpend = DEFAULT_RTP_END;
++ dtmftimeout = DEFAULT_DTMF_TIMEOUT;
++ strictrtp = STRICT_RTP_OPEN;
++ if (cfg) {
++ if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
++ rtpstart = atoi(s);
++ if (rtpstart < MINIMUM_RTP_PORT)
++ rtpstart = MINIMUM_RTP_PORT;
++ if (rtpstart > MAXIMUM_RTP_PORT)
++ rtpstart = MAXIMUM_RTP_PORT;
++ }
++ if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
++ rtpend = atoi(s);
++ if (rtpend < MINIMUM_RTP_PORT)
++ rtpend = MINIMUM_RTP_PORT;
++ if (rtpend > MAXIMUM_RTP_PORT)
++ rtpend = MAXIMUM_RTP_PORT;
++ }
++ if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) {
++ rtcpinterval = atoi(s);
++ if (rtcpinterval == 0)
++ rtcpinterval = 0; /* Just so we're clear... it's zero */
++ if (rtcpinterval < RTCP_MIN_INTERVALMS)
++ rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */
++ if (rtcpinterval > RTCP_MAX_INTERVALMS)
++ rtcpinterval = RTCP_MAX_INTERVALMS;
++ }
++ if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
++#ifdef SO_NO_CHECK
++ nochecksums = ast_false(s) ? 1 : 0;
++#else
++ if (ast_false(s))
++ ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
++#endif
++ }
++ if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
++ dtmftimeout = atoi(s);
++ if ((dtmftimeout < 0) || (dtmftimeout > 64000)) {
++ ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
++ dtmftimeout, DEFAULT_DTMF_TIMEOUT);
++ dtmftimeout = DEFAULT_DTMF_TIMEOUT;
++ };
++ }
++ if ((s = ast_variable_retrieve(cfg, "general", "strictrtp"))) {
++ strictrtp = ast_true(s);
++ }
++ ast_config_destroy(cfg);
++ }
++ if (rtpstart >= rtpend) {
++ ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
++ rtpstart = DEFAULT_RTP_START;
++ rtpend = DEFAULT_RTP_END;
++ }
++ ast_verb(2, "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
++ return 0;
++}
++
++static int reload_module(void)
++{
++ rtp_reload(1);
++ return 0;
++}
++
++static int load_module(void)
++{
++ if (ast_rtp_engine_register(&asterisk_rtp_engine)) {
++ return AST_MODULE_LOAD_DECLINE;
++ }
++
++ if (ast_cli_register_multiple(cli_rtp, ARRAY_LEN(cli_rtp))) {
++ ast_rtp_engine_unregister(&asterisk_rtp_engine);
++ return AST_MODULE_LOAD_DECLINE;
++ }
++
++ rtp_reload(0);
++
++ return AST_MODULE_LOAD_SUCCESS;
++}
++
++static int unload_module(void)
++{
++ ast_rtp_engine_unregister(&asterisk_rtp_engine);
++ ast_cli_unregister_multiple(cli_rtp, ARRAY_LEN(cli_rtp));
++
++ return 0;
++}
++
++AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Asterisk RTP Stack",
++ .load = load_module,
++ .unload = unload_module,
++ .reload = reload_module,
++ );
+
+Property changes on: res/res_rtp_asterisk.c
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+
+Index: res/res_config_pgsql.c
+===================================================================
+--- a/res/res_config_pgsql.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/res/res_config_pgsql.c (.../trunk) (revision 202568)
+@@ -49,7 +49,7 @@
+
+ #define RES_CONFIG_PGSQL_CONF "res_pgsql.conf"
+
+-PGconn *pgsqlConn = NULL;
++static PGconn *pgsqlConn = NULL;
+
+ #define MAX_DB_OPTION_SIZE 64
+
+@@ -84,7 +84,7 @@
+ static char *handle_cli_realtime_pgsql_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
+ static char *handle_cli_realtime_pgsql_cache(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
+
+-enum { RQ_WARN, RQ_CREATECLOSE, RQ_CREATECHAR } requirements;
++static enum { RQ_WARN, RQ_CREATECLOSE, RQ_CREATECHAR } requirements;
+
+ static struct ast_cli_entry cli_realtime[] = {
+ AST_CLI_DEFINE(handle_cli_realtime_pgsql_status, "Shows connection information for the PostgreSQL RealTime driver"),
+@@ -1530,7 +1530,7 @@
+ }
+
+ /* needs usecount semantics defined */
+-AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "PostgreSQL RealTime Configuration Driver",
++AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "PostgreSQL RealTime Configuration Driver",
+ .load = load_module,
+ .unload = unload_module,
+ .reload = reload
+Index: res/res_calendar_icalendar.c
+===================================================================
+--- a/res/res_calendar_icalendar.c (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/res/res_calendar_icalendar.c (.../trunk) (revision 202568)
+@@ -0,0 +1,470 @@
++/*
++ * Asterisk -- An open source telephony toolkit.
++ *
++ * Copyright (C) 2008 - 2009, Digium, Inc.
++ *
++ * Terry Wilson <twilson@digium.com>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * 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.
++ */
++
++/*! \file
++ * \brief Resource for handling iCalnedar calendars
++ */
++
++/*** MODULEINFO
++ <depend>neon</depend>
++ <depend>ical</depend>
++***/
++#include "asterisk.h"
++
++ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
++
++#include <libical/ical.h>
++#include <neon/ne_session.h>
++#include <neon/ne_uri.h>
++#include <neon/ne_request.h>
++#include <neon/ne_auth.h>
++
++#include "asterisk/module.h"
++#include "asterisk/calendar.h"
++#include "asterisk/lock.h"
++#include "asterisk/config.h"
++#include "asterisk/astobj2.h"
++
++static void *ical_load_calendar(void *data);
++static void *unref_icalendar(void *obj);
++
++static struct ast_calendar_tech ical_tech = {
++ .type = "ical",
++ .module = AST_MODULE,
++ .description = "iCalendar .ics calendars",
++ .load_calendar = ical_load_calendar,
++ .unref_calendar = unref_icalendar,
++};
++
++struct icalendar_pvt {
++ AST_DECLARE_STRING_FIELDS(
++ AST_STRING_FIELD(url);
++ AST_STRING_FIELD(user);
++ AST_STRING_FIELD(secret);
++ );
++ struct ast_calendar *owner;
++ ne_uri uri;
++ ne_session *session;
++ icalcomponent *data;
++ struct ao2_container *events;
++};
++
++static int cb_true(void *user_data, void *arg, int flags)
++{
++ return CMP_MATCH;
++}
++
++static void icalendar_destructor(void *obj)
++{
++ struct icalendar_pvt *pvt = obj;
++
++ ast_debug(1, "Destroying pvt for iCalendar %s\n", pvt->owner->name);
++ if (pvt->session) {
++ ne_session_destroy(pvt->session);
++ }
++ if (pvt->data) {
++ icalcomponent_free(pvt->data);
++ }
++ ast_string_field_free_memory(pvt);
++
++ ao2_callback(pvt->events, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, cb_true, NULL);
++
++ ao2_ref(pvt->events, -1);
++}
++
++static void *unref_icalendar(void *obj)
++{
++ struct icalendar_pvt *pvt = obj;
++
++ ao2_ref(pvt, -1);
++ return NULL;
++}
++
++static int fetch_response_reader(void *data, const char *block, size_t len)
++{
++ struct ast_str **response = data;
++ unsigned char *tmp;
++
++ if (!(tmp = ast_malloc(len + 1))) {
++ return -1;
++ }
++ memcpy(tmp, block, len);
++ tmp[len] = '\0';
++ ast_str_append(response, 0, "%s", tmp);
++ ast_free(tmp);
++
++ return 0;
++}
++
++static int auth_credentials(void *userdata, const char *realm, int attempts, char *username, char *secret)
++{
++ struct icalendar_pvt *pvt = userdata;
++
++ if (attempts > 1) {
++ ast_log(LOG_WARNING, "Invalid username or password for iCalendar '%s'\n", pvt->owner->name);
++ return -1;
++ }
++
++ ne_strnzcpy(username, pvt->user, NE_ABUFSIZ);
++ ne_strnzcpy(secret, pvt->secret, NE_ABUFSIZ);
++
++ return 0;
++}
++
++static icalcomponent *fetch_icalendar(struct icalendar_pvt *pvt)
++{
++ int ret;
++ struct ast_str *response;
++ ne_request *req;
++ icalcomponent *comp = NULL;
++
++ if (!pvt) {
++ ast_log(LOG_ERROR, "There is no private!\n");
++ }
++
++ if (!(response = ast_str_create(512))) {
++ ast_log(LOG_ERROR, "Could not allocate memory for response.\n");
++ return NULL;
++ }
++
++ req = ne_request_create(pvt->session, "GET", pvt->uri.path);
++ ne_add_response_body_reader(req, ne_accept_2xx, fetch_response_reader, &response);
++
++ ret = ne_request_dispatch(req);
++ if (ret != NE_OK || !ast_str_strlen(response)) {
++ ast_log(LOG_WARNING, "Unable to retrieve iCalendar '%s' from '%s': %s\n", pvt->owner->name, pvt->url, ne_get_error(pvt->session));
++ ast_free(response);
++ return NULL;
++ }
++
++ if (!ast_strlen_zero(ast_str_buffer(response))) {
++ comp = icalparser_parse_string(ast_str_buffer(response));
++ }
++ ast_free(response);
++
++ return comp;
++}
++
++static void icalendar_add_event(icalcomponent *comp, struct icaltime_span *span, void *data)
++{
++ struct icalendar_pvt *pvt = data;
++ struct ast_calendar_event *event;
++ icaltimezone *utc = icaltimezone_get_utc_timezone();
++ icaltimetype start, end, tmp;
++ icalcomponent *valarm;
++ icalproperty *prop;
++ struct icaltriggertype trigger;
++
++ if (!(pvt && pvt->owner)) {
++ ast_log(LOG_ERROR, "Require a private structure with an ownenr\n");
++ return;
++ }
++
++ if (!(event = ast_calendar_event_alloc(pvt->owner))) {
++ ast_log(LOG_ERROR, "Could not allocate an event!\n");
++ return;
++ }
++
++ start = icaltime_from_timet_with_zone(span->start, 0, utc);
++ end = icaltime_from_timet_with_zone(span->end, 0, utc);
++ event->start = span->start;
++ event->end = span->end;
++
++ switch(icalcomponent_get_status(comp)) {
++ case ICAL_STATUS_CONFIRMED:
++ event->busy_state = AST_CALENDAR_BS_BUSY;
++ break;
++
++ case ICAL_STATUS_TENTATIVE:
++ event->busy_state = AST_CALENDAR_BS_BUSY_TENTATIVE;
++ break;
++
++ default:
++ event->busy_state = AST_CALENDAR_BS_FREE;
++ }
++
++ if ((prop = icalcomponent_get_first_property(comp, ICAL_SUMMARY_PROPERTY))) {
++ ast_string_field_set(event, summary, icalproperty_get_value_as_string(prop));
++ }
++
++ if ((prop = icalcomponent_get_first_property(comp, ICAL_DESCRIPTION_PROPERTY))) {
++ ast_string_field_set(event, description, icalproperty_get_value_as_string(prop));
++ }
++
++ if ((prop = icalcomponent_get_first_property(comp, ICAL_ORGANIZER_PROPERTY))) {
++ ast_string_field_set(event, organizer, icalproperty_get_value_as_string(prop));
++ }
++
++ if ((prop = icalcomponent_get_first_property(comp, ICAL_LOCATION_PROPERTY))) {
++ ast_string_field_set(event, location, icalproperty_get_value_as_string(prop));
++ }
++
++ if ((prop = icalcomponent_get_first_property(comp, ICAL_UID_PROPERTY))) {
++ ast_string_field_set(event, uid, icalproperty_get_value_as_string(prop));
++ } else {
++ ast_log(LOG_WARNING, "No UID found, but one is required. Generating, but updates may not be acurate\n");
++ if (!ast_strlen_zero(event->summary)) {
++ ast_string_field_set(event, uid, event->summary);
++ } else {
++ char tmp[100];
++ snprintf(tmp, sizeof(tmp), "%lu", event->start);
++ ast_string_field_set(event, uid, tmp);
++ }
++ }
++
++ /* Get the attendees */
++ for (prop = icalcomponent_get_first_property(comp, ICAL_ATTENDEE_PROPERTY);
++ prop; prop = icalcomponent_get_next_property(comp, ICAL_ATTENDEE_PROPERTY)) {
++ struct ast_calendar_attendee *attendee;
++ const char *data;
++
++ if (!(attendee = ast_calloc(1, sizeof(*attendee)))) {
++ event = ast_calendar_unref_event(event);
++ return;
++ }
++ data = icalproperty_get_attendee(prop);
++ if (!ast_strlen_zero(data)) {
++ attendee->data = ast_strdup(data);;
++ AST_LIST_INSERT_TAIL(&event->attendees, attendee, next);
++ }
++ }
++
++
++ /* Only set values for alarm based on VALARM. Can be overriden in main/calendar.c by autoreminder
++ * therefore, go ahead and add events even if their is no VALARM or it is malformed
++ * Currently we are only getting the first VALARM and are handling repitition in main/calendar.c from calendar.conf */
++ if (!(valarm = icalcomponent_get_first_component(comp, ICAL_VALARM_COMPONENT))) {
++ ao2_link(pvt->events, event);
++ event = ast_calendar_unref_event(event);
++ return;
++ }
++
++ if (!(prop = icalcomponent_get_first_property(valarm, ICAL_TRIGGER_PROPERTY))) {
++ ast_log(LOG_WARNING, "VALARM has no TRIGGER, skipping!\n");
++ ao2_link(pvt->events, event);
++ event = ast_calendar_unref_event(event);
++ return;
++ }
++
++ trigger = icalproperty_get_trigger(prop);
++
++ if (icaltriggertype_is_null_trigger(trigger)) {
++ ast_log(LOG_WARNING, "Bad TRIGGER for VALARM, skipping!\n");
++ ao2_link(pvt->events, event);
++ event = ast_calendar_unref_event(event);
++ return;
++ }
++
++ if (!icaltime_is_null_time(trigger.time)) { /* This is an absolute time */
++ tmp = icaltime_convert_to_zone(trigger.time, utc);
++ event->alarm = icaltime_as_timet_with_zone(tmp, utc);
++ } else { /* Offset from either dtstart or dtend */
++ /* XXX Technically you can check RELATED to see if the event fires from the END of the event
++ * But, I'm not sure I've ever seen anyone implement it in calendaring software, so I'm ignoring for now */
++ tmp = icaltime_add(start, trigger.duration);
++ event->alarm = icaltime_as_timet_with_zone(tmp, utc);
++ }
++
++ ao2_link(pvt->events, event);
++ event = ast_calendar_unref_event(event);
++
++ return;
++}
++
++ static void icalendar_update_events(struct icalendar_pvt *pvt)
++{
++ struct icaltimetype start_time, end_time;
++ icalcomponent *iter;
++
++ if (!pvt) {
++ ast_log(LOG_ERROR, "iCalendar is NULL\n");
++ return;
++ }
++
++ if (!pvt->owner) {
++ ast_log(LOG_ERROR, "iCalendar is an orphan!\n");
++ return;
++ }
++
++ if (!pvt->data) {
++ ast_log(LOG_ERROR, "The iCalendar has not been parsed!\n");
++ return;
++ }
++
++ start_time = icaltime_current_time_with_zone(icaltimezone_get_utc_timezone());
++ end_time = icaltime_current_time_with_zone(icaltimezone_get_utc_timezone());
++ end_time.second += pvt->owner->timeframe * 60;
++ icaltime_normalize(end_time);
++
++ for (iter = icalcomponent_get_first_component(pvt->data, ICAL_VEVENT_COMPONENT);
++ iter;
++ iter = icalcomponent_get_next_component(pvt->data, ICAL_VEVENT_COMPONENT))
++ {
++ icalcomponent_foreach_recurrence(iter, start_time, end_time, icalendar_add_event, pvt);
++ }
++
++ ast_calendar_merge_events(pvt->owner, pvt->events);
++}
++
++static void *ical_load_calendar(void *void_data)
++{
++ struct icalendar_pvt *pvt;
++ struct ast_variable *v;
++ struct ast_calendar *cal = void_data;
++ ast_mutex_t refreshlock;
++
++ if (!(cal && ast_calendar_config)) {
++ ast_log(LOG_ERROR, "You must enable calendar support for res_icalendar to load\n");
++ return NULL;
++ }
++ if (ao2_trylock(cal)) {
++ if (cal->unloading) {
++ ast_log(LOG_WARNING, "Unloading module, load_calendar cancelled.\n");
++ } else {
++ ast_log(LOG_WARNING, "Could not lock calendar, aborting!\n");
++ }
++ return NULL;
++ }
++
++ if (!(pvt = ao2_alloc(sizeof(*pvt), icalendar_destructor))) {
++ ast_log(LOG_ERROR, "Could not allocate icalendar_pvt structure for calendar: %s\n", cal->name);
++ return NULL;
++ }
++
++ pvt->owner = cal;
++
++ if (!(pvt->events = ast_calendar_event_container_alloc())) {
++ ast_log(LOG_ERROR, "Could not allocate space for fetching events for calendar: %s\n", cal->name);
++ pvt = unref_icalendar(pvt);
++ ao2_unlock(cal);
++ return NULL;
++ }
++
++ if (ast_string_field_init(pvt, 32)) {
++ ast_log(LOG_ERROR, "Couldn't allocate string field space for calendar: %s\n", cal->name);
++ pvt = unref_icalendar(pvt);
++ ao2_unlock(cal);
++ return NULL;
++ }
++
++ for (v = ast_variable_browse(ast_calendar_config, cal->name); v; v = v->next) {
++ if (!strcasecmp(v->name, "url")) {
++ ast_string_field_set(pvt, url, v->value);
++ } else if (!strcasecmp(v->name, "user")) {
++ ast_string_field_set(pvt, user, v->value);
++ } else if (!strcasecmp(v->name, "secret")) {
++ ast_string_field_set(pvt, secret, v->value);
++ }
++ }
++
++ if (ast_strlen_zero(pvt->url)) {
++ ast_log(LOG_WARNING, "No URL was specified for iCalendar '%s' - skipping.\n", cal->name);
++ pvt = unref_icalendar(pvt);
++ ao2_unlock(cal);
++ return NULL;
++ }
++
++ if (ne_uri_parse(pvt->url, &pvt->uri) || pvt->uri.host == NULL || pvt->uri.path == NULL) {
++ ast_log(LOG_WARNING, "Could not parse url '%s' for iCalendar '%s' - skipping.\n", pvt->url, cal->name);
++ pvt = unref_icalendar(pvt);
++ ao2_unlock(cal);
++ return NULL;
++ }
++
++ if (pvt->uri.scheme == NULL) {
++ pvt->uri.scheme = "http";
++ }
++
++ if (pvt->uri.port == 0) {
++ pvt->uri.port = ne_uri_defaultport(pvt->uri.scheme);
++ }
++
++ pvt->session = ne_session_create(pvt->uri.scheme, pvt->uri.host, pvt->uri.port);
++ ne_set_server_auth(pvt->session, auth_credentials, pvt);
++ if (!strncasecmp(pvt->uri.scheme, "https", sizeof(pvt->uri.scheme))) {
++ ne_ssl_trust_default_ca(pvt->session);
++ }
++
++ cal->tech_pvt = pvt;
++
++ ast_mutex_init(&refreshlock);
++
++ /* Load it the first time */
++ if (!(pvt->data = fetch_icalendar(pvt))) {
++ ast_log(LOG_WARNING, "Unable to parse iCalendar '%s'\n", cal->name);
++ }
++
++ icalendar_update_events(pvt);
++
++ ao2_unlock(cal);
++
++ /* The only writing from another thread will be if unload is true */
++ for(;;) {
++ struct timeval tv = ast_tvnow();
++ struct timespec ts = {0,};
++
++ ts.tv_sec = tv.tv_sec + (60 * pvt->owner->refresh);
++
++ ast_mutex_lock(&refreshlock);
++ while (!pvt->owner->unloading) {
++ if (ast_cond_timedwait(&pvt->owner->unload, &refreshlock, &ts) == ETIMEDOUT) {
++ break;
++ }
++ }
++ ast_mutex_unlock(&refreshlock);
++
++ if (pvt->owner->unloading) {
++ ast_debug(10, "Skipping refresh since we got a shutdown signal\n");
++ return NULL;
++ }
++
++ ast_debug(10, "Refreshing after %d minute timeout\n", pvt->owner->refresh);
++
++ if (!(pvt->data = fetch_icalendar(pvt))) {
++ ast_log(LOG_WARNING, "Unable to parse iCalendar '%s'\n", pvt->owner->name);
++ continue;
++ }
++
++ icalendar_update_events(pvt);
++ }
++
++ return NULL;
++}
++
++static int load_module(void)
++{
++ ne_sock_init();
++ if (ast_calendar_register(&ical_tech)) {
++ ne_sock_exit();
++ return AST_MODULE_LOAD_DECLINE;
++ }
++
++ return AST_MODULE_LOAD_SUCCESS;
++}
++
++static int unload_module(void)
++{
++ ast_calendar_unregister(&ical_tech);
++ ne_sock_exit();
++ return 0;
++}
++
++AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Asterisk iCalendar .ics file integration",
++ .load = load_module,
++ .unload = unload_module,
++ );
+
+Property changes on: res/res_calendar_icalendar.c
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+
+Index: res/res_smdi.exports
+===================================================================
+--- a/res/res_smdi.exports (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/res/res_smdi.exports (.../trunk) (revision 202568)
+@@ -0,0 +1,18 @@
++{
++ global:
++ *ast_smdi_interface_find;
++ *ast_smdi_interface_unref;
++ *ast_smdi_md_message_destroy;
++ *ast_smdi_md_message_pop;
++ *ast_smdi_md_message_putback;
++ *ast_smdi_md_message_wait;
++ *ast_smdi_mwi_message_destroy;
++ *ast_smdi_mwi_message_pop;
++ *ast_smdi_mwi_message_putback;
++ *ast_smdi_mwi_message_wait;
++ *ast_smdi_mwi_message_wait_station;
++ *ast_smdi_mwi_set;
++ *ast_smdi_mwi_unset;
++ local:
++ *;
++};
+
+Property changes on: res/res_smdi.exports
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+
+Index: res/res_phoneprov.c
+===================================================================
+--- a/res/res_phoneprov.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/res/res_phoneprov.c (.../trunk) (revision 202568)
+@@ -65,6 +65,37 @@
+
+ #define VAR_BUF_SIZE 4096
+
++/*** DOCUMENTATION
++ <function name="PP_EACH_EXTENSION" language="en_US">
++ <synopsis>
++ Execute specified template for each extension.
++ </synopsis>
++ <syntax>
++ <parameter name="mac" required="true" />
++ <parameter name="template" required="true" />
++ </syntax>
++ <description>
++ <para>Output the specified template for each extension associated with the specified MAC address.</para>
++ </description>
++ </function>
++ <function name="PP_EACH_USER" language="en_US">
++ <synopsis>
++ Generate a string for each phoneprov user.
++ </synopsis>
++ <syntax>
++ <parameter name="string" required="true" />
++ <parameter name="exclude_mac" required="true" />
++ </syntax>
++ <description>
++ <para>Pass in a string, with phoneprov variables you want substituted in the format of
++ %{VARNAME}, and you will get the string rendered for each user in phoneprov
++ excluding ones with MAC address <replaceable>exclude_mac</replaceable>. Probably not
++ useful outside of res_phoneprov.</para>
++ <para>Example: ${PP_EACH_USER(&lt;item&gt;&lt;fn&gt;%{DISPLAY_NAME}&lt;/fn&gt;&lt;/item&gt;|${MAC})</para>
++ </description>
++ </function>
++ ***/
++
+ /*! \brief for use in lookup_iface */
+ static struct in_addr __ourip = { .s_addr = 0x00000000, };
+
+@@ -155,19 +186,6 @@
+ static struct ao2_container *http_routes;
+ static struct ao2_container *users;
+
+-/*! \brief Extensions whose mime types we think we know */
+-static struct {
+- char *ext;
+- char *mtype;
+-} mimetypes[] = {
+- { "png", "image/png" },
+- { "xml", "text/xml" },
+- { "jpg", "image/jpeg" },
+- { "js", "application/x-javascript" },
+- { "wav", "audio/x-wav" },
+- { "mp3", "audio/mpeg" },
+-};
+-
+ static char global_server[80] = ""; /*!< Server to substitute into templates */
+ static char global_serverport[6] = ""; /*!< Server port to substitute into templates */
+ static char global_default_profile[80] = ""; /*!< Default profile to use if one isn't specified */
+@@ -176,22 +194,6 @@
+ static struct varshead global_variables;
+ static ast_mutex_t globals_lock;
+
+-/*! \brief Return mime type based on extension */
+-static char *ftype2mtype(const char *ftype)
+-{
+- int x;
+-
+- if (ast_strlen_zero(ftype))
+- return NULL;
+-
+- for (x = 0;x < ARRAY_LEN(mimetypes);x++) {
+- if (!strcasecmp(ftype, mimetypes[x].ext))
+- return mimetypes[x].mtype;
+- }
+-
+- return NULL;
+-}
+-
+ /* iface is the interface (e.g. eth0); address is the return value */
+ static int lookup_iface(const char *iface, struct in_addr *address)
+ {
+@@ -398,21 +400,25 @@
+ }
+
+ /*! \brief Callback that is executed everytime an http request is received by this module */
+-static struct ast_str *phoneprov_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *vars, struct ast_variable *headers, int *status, char **title, int *contentlength)
++static int phoneprov_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_vars, struct ast_variable *headers)
+ {
+ struct http_route *route;
+ struct http_route search_route = {
+ .uri = uri,
+ };
+- struct ast_str *result = ast_str_create(512);
++ struct ast_str *result;
+ char path[PATH_MAX];
+ char *file = NULL;
+ int len;
+ int fd;
+ char buf[256];
+- struct timeval now = ast_tvnow();
+- struct ast_tm tm;
++ struct ast_str *http_header;
+
++ if (method != AST_HTTP_GET && method != AST_HTTP_HEAD) {
++ ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method");
++ return -1;
++ }
++
+ if (!(route = ao2_find(http_routes, &search_route, OBJ_POINTER))) {
+ goto out404;
+ }
+@@ -434,15 +440,9 @@
+ goto out500;
+ }
+
+- ast_strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S %Z", ast_localtime(&now, &tm, "GMT"));
+- fprintf(ser->f, "HTTP/1.1 200 OK\r\n"
+- "Server: Asterisk/%s\r\n"
+- "Date: %s\r\n"
+- "Connection: close\r\n"
+- "Cache-Control: no-cache, no-store\r\n"
+- "Content-Length: %d\r\n"
+- "Content-Type: %s\r\n\r\n",
+- ast_get_version(), buf, len, route->file->mime_type);
++ http_header = ast_str_create(80);
++ ast_str_set(&http_header, 0, "Content-type: %s\r\n",
++ route->file->mime_type);
+
+ while ((len = read(fd, buf, sizeof(buf))) > 0) {
+ if (fwrite(buf, 1, len, ser->f) != len) {
+@@ -455,12 +455,12 @@
+ }
+ }
+
++ ast_http_send(ser, method, 200, NULL, http_header, NULL, fd, 0);
+ close(fd);
+ route = unref_route(route);
+- return NULL;
++ return 0;
+ } else { /* Dynamic file */
+- int bufsize;
+- char *tmp;
++ struct ast_str *tmp;
+
+ len = load_file(path, &file);
+ if (len < 0) {
+@@ -476,12 +476,7 @@
+ goto out500;
+ }
+
+- /* XXX This is a hack -- maybe sum length of all variables in route->user->headp and add that? */
+- bufsize = len + VAR_BUF_SIZE;
+-
+- /* malloc() instead of alloca() here, just in case the file is bigger than
+- * we have enough stack space for. */
+- if (!(tmp = ast_calloc(1, bufsize))) {
++ if (!(tmp = ast_str_create(len))) {
+ if (file) {
+ ast_free(file);
+ }
+@@ -510,39 +505,42 @@
+ }
+ }
+
+- pbx_substitute_variables_varshead(AST_LIST_FIRST(&route->user->extensions)->headp, file, tmp, bufsize);
++ ast_str_substitute_variables_varshead(&tmp, 0, AST_LIST_FIRST(&route->user->extensions)->headp, file);
+
+ if (file) {
+ ast_free(file);
+ }
+
+- ast_str_append(&result, 0,
+- "Content-Type: %s\r\n"
+- "Content-length: %d\r\n"
+- "\r\n"
+- "%s", route->file->mime_type, (int) strlen(tmp), tmp);
++ ast_str_set(&http_header, 0, "Content-type: %s\r\n",
++ route->file->mime_type);
+
++ if (!(result = ast_str_create(512))) {
++ ast_log(LOG_ERROR, "Could not create result string!\n");
++ if (tmp) {
++ ast_free(tmp);
++ }
++ goto out500;
++ }
++ ast_str_append(&result, 0, "%s", ast_str_buffer(tmp));
++
++ ast_http_send(ser, method, 200, NULL, http_header, result, 0, 0);
+ if (tmp) {
+ ast_free(tmp);
+ }
+
+ route = unref_route(route);
+
+- return result;
++ return 0;
+ }
+
+ out404:
+- *status = 404;
+- *title = strdup("Not Found");
+- *contentlength = 0;
+- return ast_http_error(404, "Not Found", NULL, "The requested URL was not found on this server.");
++ ast_http_error(ser, 404, "Not Found", "Nothing to see here. Move along.");
++ return -1;
+
+ out500:
+ route = unref_route(route);
+- *status = 500;
+- *title = strdup("Internal Server Error");
+- *contentlength = 0;
+- return ast_http_error(500, "Internal Error", NULL, "An internal error has occured.");
++ ast_http_error(ser, 500, "Internal Error", "An internal error has occured.");
++ return -1;
+ }
+
+ /*! \brief Build a route structure and add it to the list of available http routes
+@@ -656,7 +654,8 @@
+ * 3) Default mime type specified in profile
+ * 4) text/plain
+ */
+- ast_string_field_set(pp_file, mime_type, S_OR(args.mimetype, (S_OR(S_OR(ftype2mtype(file_extension), profile->default_mime_type), "text/plain"))));
++ ast_string_field_set(pp_file, mime_type, S_OR(args.mimetype,
++ (S_OR(S_OR(ast_http_ftype2mtype(file_extension), profile->default_mime_type), "text/plain"))));
+
+ if (!strcasecmp(v->name, "static_file")) {
+ ast_string_field_set(pp_file, format, args.filename);
+@@ -856,18 +855,25 @@
+ static int add_user_extension(struct user *user, struct extension *exten)
+ {
+ struct ast_var_t *var;
++ struct ast_str *str = ast_str_create(16);
+
++ if (!str) {
++ return -1;
++ }
++
+ /* Append profile variables here, and substitute variables on profile
+ * setvars, so that we can use user specific variables in them */
+ AST_LIST_TRAVERSE(user->profile->headp, var, entries) {
+- char expand_buf[VAR_BUF_SIZE] = {0,};
+ struct ast_var_t *var2;
+
+- pbx_substitute_variables_varshead(exten->headp, var->value, expand_buf, sizeof(expand_buf));
+- if ((var2 = ast_var_assign(var->name, expand_buf)))
++ ast_str_substitute_variables_varshead(&str, 0, exten->headp, var->value);
++ if ((var2 = ast_var_assign(var->name, ast_str_buffer(str)))) {
+ AST_LIST_INSERT_TAIL(exten->headp, var2, entries);
++ }
+ }
+
++ ast_free(str);
++
+ if (AST_LIST_EMPTY(&user->extensions)) {
+ AST_LIST_INSERT_HEAD(&user->extensions, exten, entry);
+ } else {
+@@ -893,14 +899,18 @@
+ static int build_user_routes(struct user *user)
+ {
+ struct phoneprov_file *pp_file;
++ struct ast_str *str;
+
++ if (!(str = ast_str_create(16))) {
++ return -1;
++ }
++
+ AST_LIST_TRAVERSE(&user->profile->dynamic_files, pp_file, entry) {
+- char expand_buf[VAR_BUF_SIZE] = { 0, };
+-
+- pbx_substitute_variables_varshead(AST_LIST_FIRST(&user->extensions)->headp, pp_file->format, expand_buf, sizeof(expand_buf));
+- build_route(pp_file, user, expand_buf);
++ ast_str_substitute_variables_varshead(&str, 0, AST_LIST_FIRST(&user->extensions)->headp, pp_file->format);
++ build_route(pp_file, user, ast_str_buffer(str));
+ }
+
++ ast_free(str);
+ return 0;
+ }
+
+@@ -1079,17 +1089,22 @@
+ }
+
+ /*! \brief A dialplan function that can be used to print a string for each phoneprov user */
+-static int pp_each_user_exec(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
++static int pp_each_user_helper(struct ast_channel *chan, char *data, char *buf, struct ast_str **bufstr, int len)
+ {
+- char *tmp, expand_buf[VAR_BUF_SIZE] = {0,};
++ char *tmp;
+ struct ao2_iterator i;
+ struct user *user;
++ struct ast_str *str;
+ AST_DECLARE_APP_ARGS(args,
+ AST_APP_ARG(string);
+ AST_APP_ARG(exclude_mac);
+ );
+ AST_STANDARD_APP_ARGS(args, data);
+
++ if (!(str = ast_str_create(16))) {
++ return -1;
++ }
++
+ /* Fix data by turning %{ into ${ */
+ while ((tmp = strstr(args.string, "%{")))
+ *tmp = '$';
+@@ -1099,35 +1114,45 @@
+ if (!ast_strlen_zero(args.exclude_mac) && !strcasecmp(user->macaddress, args.exclude_mac)) {
+ continue;
+ }
+- pbx_substitute_variables_varshead(AST_LIST_FIRST(&user->extensions)->headp, args.string, expand_buf, sizeof(expand_buf));
+- ast_build_string(&buf, &len, "%s", expand_buf);
++ ast_str_substitute_variables_varshead(&str, len, AST_LIST_FIRST(&user->extensions)->headp, args.string);
++ if (buf) {
++ size_t slen = len;
++ ast_build_string(&buf, &slen, "%s", ast_str_buffer(str));
++ } else {
++ ast_str_append(bufstr, len, "%s", ast_str_buffer(str));
++ }
+ user = unref_user(user);
+ }
+
++ ast_free(str);
+ return 0;
+ }
+
++static int pp_each_user_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
++{
++ return pp_each_user_helper(chan, data, buf, NULL, len);
++}
++
++static int pp_each_user_read2(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
++{
++ return pp_each_user_helper(chan, data, NULL, buf, len);
++}
++
+ static struct ast_custom_function pp_each_user_function = {
+ .name = "PP_EACH_USER",
+- .synopsis = "Generate a string for each phoneprov user",
+- .syntax = "PP_EACH_USER(<string>|<exclude_mac>)",
+- .desc =
+- "Pass in a string, with phoneprov variables you want substituted in the format of\n"
+- "%{VARNAME}, and you will get the string rendered for each user in phoneprov\n"
+- "excluding ones with MAC address <exclude_mac>. Probably not useful outside of\n"
+- "res_phoneprov.\n"
+- "\nExample: ${PP_EACH_USER(<item><fn>%{DISPLAY_NAME}</fn></item>|${MAC})",
+- .read = pp_each_user_exec,
++ .read = pp_each_user_read,
++ .read2 = pp_each_user_read2,
+ };
+
+ /*! \brief A dialplan function that can be used to output a template for each extension attached to a user */
+-static int pp_each_extension_exec(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
++static int pp_each_extension_helper(struct ast_channel *chan, const char *cmd, char *data, char *buf, struct ast_str **bufstr, int len)
+ {
+ struct user *user;
+ struct extension *exten;
+ char path[PATH_MAX];
+ char *file;
+ int filelen;
++ struct ast_str *str;
+ AST_DECLARE_APP_ARGS(args,
+ AST_APP_ARG(mac);
+ AST_APP_ARG(template);
+@@ -1159,27 +1184,42 @@
+ return 0;
+ }
+
++ if (!(str = ast_str_create(filelen))) {
++ return 0;
++ }
++
+ AST_LIST_TRAVERSE(&user->extensions, exten, entry) {
+- char expand_buf[VAR_BUF_SIZE] = {0,};
+- pbx_substitute_variables_varshead(exten->headp, file, expand_buf, sizeof(expand_buf));
+- ast_build_string(&buf, &len, "%s", expand_buf);
++ ast_str_substitute_variables_varshead(&str, 0, exten->headp, file);
++ if (buf) {
++ size_t slen = len;
++ ast_build_string(&buf, &slen, "%s", ast_str_buffer(str));
++ } else {
++ ast_str_append(bufstr, len, "%s", ast_str_buffer(str));
++ }
+ }
+
+ ast_free(file);
++ ast_free(str);
+
+ user = unref_user(user);
+
+ return 0;
+ }
+
++static int pp_each_extension_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
++{
++ return pp_each_extension_helper(chan, cmd, data, buf, NULL, len);
++}
++
++static int pp_each_extension_read2(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
++{
++ return pp_each_extension_helper(chan, cmd, data, NULL, buf, len);
++}
++
+ static struct ast_custom_function pp_each_extension_function = {
+ .name = "PP_EACH_EXTENSION",
+- .synopsis = "Execute specified template for each extension",
+- .syntax = "PP_EACH_EXTENSION(<mac>|<template>)",
+- .desc =
+- "Output the specified template for each extension associated with the specified\n"
+- "MAC address.",
+- .read = pp_each_extension_exec,
++ .read = pp_each_extension_read,
++ .read2 = pp_each_extension_read2,
+ };
+
+ /*! \brief CLI command to list static and dynamic routes */
+@@ -1233,7 +1273,6 @@
+ .description = "Asterisk HTTP Phone Provisioning Tool",
+ .uri = "phoneprov",
+ .has_subtree = 1,
+- .supports_get = 1,
+ .data = NULL,
+ .key = __FILE__,
+ };
+@@ -1305,7 +1344,7 @@
+ return 0;
+ }
+
+-AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "HTTP Phone Provisioning",
++AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "HTTP Phone Provisioning",
+ .load = load_module,
+ .unload = unload_module,
+ .reload = reload,
+Index: res/res_calendar_caldav.c
+===================================================================
+--- a/res/res_calendar_caldav.c (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/res/res_calendar_caldav.c (.../trunk) (revision 202568)
+@@ -0,0 +1,675 @@
++/*
++ * Asterisk -- An open source telephony toolkit.
++ *
++ * Copyright (C) 2008 - 2009, Digium, Inc.
++ *
++ * Terry Wilson <twilson@digium.com>
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * 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.
++ */
++
++/*! \file
++ * \brief Resource for handling iCalnedar calendars
++ */
++
++/*** MODULEINFO
++ <depend>neon</depend>
++ <depend>ical</depend>
++ <depend>libxml2</depend>
++***/
++#include "asterisk.h"
++
++ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
++
++#include <libical/ical.h>
++#include <neon/ne_session.h>
++#include <neon/ne_uri.h>
++#include <neon/ne_request.h>
++#include <neon/ne_auth.h>
++#include <libxml/xmlmemory.h>
++#include <libxml/parser.h>
++
++#include "asterisk/module.h"
++#include "asterisk/calendar.h"
++#include "asterisk/lock.h"
++#include "asterisk/config.h"
++#include "asterisk/astobj2.h"
++
++static void *caldav_load_calendar(void *data);
++static void *unref_caldav(void *obj);
++static int caldav_write_event(struct ast_calendar_event *event);
++
++static struct ast_calendar_tech caldav_tech = {
++ .type = "caldav",
++ .description = "CalDAV calendars",
++ .module = AST_MODULE,
++ .load_calendar = caldav_load_calendar,
++ .unref_calendar = unref_caldav,
++ .write_event = caldav_write_event,
++};
++
++struct caldav_pvt {
++ AST_DECLARE_STRING_FIELDS(
++ AST_STRING_FIELD(url);
++ AST_STRING_FIELD(user);
++ AST_STRING_FIELD(secret);
++ );
++ struct ast_calendar *owner;
++ ne_uri uri;
++ ne_session *session;
++ struct ao2_container *events;
++};
++
++static int cb_true(void *user_data, void *arg, int flags)
++{
++ return CMP_MATCH;
++}
++
++static void caldav_destructor(void *obj)
++{
++ struct caldav_pvt *pvt = obj;
++
++ ast_debug(1, "Destroying pvt for CalDAV calendar %s\n", pvt->owner->name);
++ if (pvt->session) {
++ ne_session_destroy(pvt->session);
++ }
++ ast_string_field_free_memory(pvt);
++
++ ao2_callback(pvt->events, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, cb_true, NULL);
++
++ ao2_ref(pvt->events, -1);
++}
++
++static void *unref_caldav(void *obj)
++{
++ struct caldav_pvt *pvt = obj;
++
++ ao2_ref(pvt, -1);
++ return NULL;
++}
++
++static int fetch_response_reader(void *data, const char *block, size_t len)
++{
++ struct ast_str **response = data;
++ unsigned char *tmp;
++
++ if (!(tmp = ast_malloc(len + 1))) {
++ return -1;
++ }
++ memcpy(tmp, block, len);
++ tmp[len] = '\0';
++ ast_str_append(response, 0, "%s", tmp);
++ ast_free(tmp);
++
++ return 0;
++}
++
++static int auth_credentials(void *userdata, const char *realm, int attempts, char *username, char *secret)
++{
++ struct caldav_pvt *pvt = userdata;
++
++ if (attempts > 1) {
++ ast_log(LOG_WARNING, "Invalid username or password for CalDAV calendar '%s'\n", pvt->owner->name);
++ return -1;
++ }
++
++ ne_strnzcpy(username, pvt->user, NE_ABUFSIZ);
++ ne_strnzcpy(secret, pvt->secret, NE_ABUFSIZ);
++
++ return 0;
++}
++
++static struct ast_str *caldav_request(struct caldav_pvt *pvt, const char *method, struct ast_str *req_body, struct ast_str *subdir, const char *content_type)
++{
++ struct ast_str *response;
++ ne_request *req;
++ int ret;
++ char buf[1000];
++
++ if (!pvt) {
++ ast_log(LOG_ERROR, "There is no private!\n");
++ return NULL;
++ }
++
++ if (!(response = ast_str_create(512))) {
++ ast_log(LOG_ERROR, "Could not allocate memory for response.\n");
++ return NULL;
++ }
++
++ snprintf(buf, sizeof(buf), "%s%s", pvt->uri.path, subdir ? ast_str_buffer(subdir) : "");
++
++ req = ne_request_create(pvt->session, method, buf);
++ ne_add_response_body_reader(req, ne_accept_2xx, fetch_response_reader, &response);
++ ne_set_request_body_buffer(req, ast_str_buffer(req_body), ast_str_strlen(req_body));
++ ne_add_request_header(req, "Content-type", ast_strlen_zero(content_type) ? "text/xml" : content_type);
++
++ ret = ne_request_dispatch(req);
++ ne_request_destroy(req);
++
++ if (ret != NE_OK || !ast_str_strlen(response)) {
++ ast_log(LOG_WARNING, "Unknown response to CalDAV calendar %s, request %s to %s: %s\n", pvt->owner->name, method, pvt->url, ne_get_error(pvt->session));
++ ast_free(response);
++ return NULL;
++ }
++
++ return response;
++}
++
++static int caldav_write_event(struct ast_calendar_event *event)
++{
++ struct ast_str *body = NULL, *response = NULL, *subdir = NULL;
++ icalcomponent *calendar, *icalevent;
++ icaltimezone *utc = icaltimezone_get_utc_timezone();
++ int ret = -1;
++
++ if (!event) {
++ ast_log(LOG_WARNING, "No event passed!\n");
++ return -1;
++ }
++
++ if (!(event->start && event->end)) {
++ ast_log(LOG_WARNING, "The event must contain a start and an end\n");
++ return -1;
++ }
++ if (!(body = ast_str_create(512)) ||
++ !(subdir = ast_str_create(32)) ||
++ !(response = ast_str_create(512))) {
++ ast_log(LOG_ERROR, "Could not allocate memory for request and response!\n");
++ goto write_cleanup;
++ }
++
++ if (ast_strlen_zero(event->uid)) {
++ unsigned short val[8];
++ int x;
++ for (x = 0; x < 8; x++) {
++ val[x] = ast_random();
++ }
++ ast_string_field_build(event, uid, "%04x%04x-%04x-%04x-%04x-%04x%04x%04x", val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7]);
++ }
++
++ calendar = icalcomponent_new(ICAL_VCALENDAR_COMPONENT);
++ icalcomponent_add_property(calendar, icalproperty_new_version("2.0"));
++ icalcomponent_add_property(calendar, icalproperty_new_prodid("-//Digium, Inc.//res_caldav//EN"));
++
++ icalevent = icalcomponent_new(ICAL_VEVENT_COMPONENT);
++ icalcomponent_add_property(icalevent, icalproperty_new_dtstamp(icaltime_current_time_with_zone(utc)));
++ icalcomponent_add_property(icalevent, icalproperty_new_uid(event->uid));
++ icalcomponent_add_property(icalevent, icalproperty_new_dtstart(icaltime_from_timet_with_zone(event->start, 0, utc)));
++ icalcomponent_add_property(icalevent, icalproperty_new_dtend(icaltime_from_timet_with_zone(event->end, 0, utc)));
++ if (!ast_strlen_zero(event->organizer)) {
++ icalcomponent_add_property(icalevent, icalproperty_new_organizer(event->organizer));
++ }
++ if (!ast_strlen_zero(event->summary)) {
++ icalcomponent_add_property(icalevent, icalproperty_new_summary(event->summary));
++ }
++ if (!ast_strlen_zero(event->description)) {
++ icalcomponent_add_property(icalevent, icalproperty_new_description(event->description));
++ }
++ if (!ast_strlen_zero(event->location)) {
++ icalcomponent_add_property(icalevent, icalproperty_new_location(event->location));
++ }
++
++ switch (event->busy_state) {
++ case AST_CALENDAR_BS_BUSY:
++ icalcomponent_add_property(icalevent, icalproperty_new_status(ICAL_STATUS_CONFIRMED));
++ break;
++
++ case AST_CALENDAR_BS_BUSY_TENTATIVE:
++ icalcomponent_add_property(icalevent, icalproperty_new_status(ICAL_STATUS_TENTATIVE));
++ break;
++
++ default:
++ icalcomponent_add_property(icalevent, icalproperty_new_status(ICAL_STATUS_NONE));
++ }
++
++ icalcomponent_add_component(calendar, icalevent);
++
++ ast_str_append(&body, 0, "%s", icalcomponent_as_ical_string(calendar));
++ ast_str_set(&subdir, 0, "%s%s.ics", ast_str_buffer(body)[ast_str_strlen(body)] == '/' ? "" : "/", event->uid);
++
++ response = caldav_request(event->owner->tech_pvt, "PUT", body, subdir, "text/calendar");
++
++ ret = 0;
++
++write_cleanup:
++ if (body) {
++ ast_free(body);
++ }
++ if (response) {
++ ast_free(response);
++ }
++ if (subdir) {
++ ast_free(subdir);
++ }
++
++ return ret;
++}
++
++static struct ast_str *caldav_get_events_between(struct caldav_pvt *pvt, time_t start_time, time_t end_time)
++{
++ struct ast_str *body, *response;
++ icaltimezone *utc = icaltimezone_get_utc_timezone();
++ icaltimetype start, end;
++ const char *start_str, *end_str;
++
++ if (!(body = ast_str_create(512))) {
++ ast_log(LOG_ERROR, "Could not allocate memory for body of request!\n");
++ return NULL;
++ }
++
++ start = icaltime_from_timet_with_zone(start_time, 0, utc);
++ end = icaltime_from_timet_with_zone(end_time, 0, utc);
++ start_str = icaltime_as_ical_string(start);
++ end_str = icaltime_as_ical_string(end);
++
++ /* If I was really being efficient, I would store a collection of event URIs and etags,
++ * first doing a query of just the etag and seeing if anything had changed. If it had,
++ * then I would do a request for each of the events that had changed, and only bother
++ * updating those. Oh well. */
++ ast_str_append(&body, 0,
++ "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
++ "<C:calendar-query xmlns:D=\"DAV:\" xmlns:C=\"urn:ietf:params:xml:ns:caldav\">\n"
++ " <D:prop>\n"
++ " <C:calendar-data>\n"
++ " <C:expand start=\"%s\" end=\"%s\"/>\n"
++ " </C:calendar-data>\n"
++ " </D:prop>\n"
++ " <C:filter>\n"
++ " <C:comp-filter name=\"VCALENDAR\">\n"
++ " <C:comp-filter name=\"VEVENT\">\n"
++ " <C:time-range start=\"%s\" end=\"%s\"/>\n"
++ " </C:comp-filter>\n"
++ " </C:comp-filter>\n"
++ " </C:filter>\n"
++ "</C:calendar-query>\n", start_str, end_str, start_str, end_str);
++
++ response = caldav_request(pvt, "REPORT", body, NULL, NULL);
++ ast_free(body);
++
++ return response;
++}
++
++static void caldav_add_event(icalcomponent *comp, struct icaltime_span *span, void *data)
++{
++ struct caldav_pvt *pvt = data;
++ struct ast_calendar_event *event;
++ icaltimezone *utc = icaltimezone_get_utc_timezone();
++ icaltimetype start, end, tmp;
++ icalcomponent *valarm;
++ icalproperty *prop;
++ struct icaltriggertype trigger;
++
++ if (!(pvt && pvt->owner)) {
++ ast_log(LOG_ERROR, "Require a private structure with an owner\n");
++ return;
++ }
++
++ if (!(event = ast_calendar_event_alloc(pvt->owner))) {
++ ast_log(LOG_ERROR, "Could not allocate an event!\n");
++ return;
++ }
++
++ start = icaltime_from_timet_with_zone(span->start, 0, utc);
++ end = icaltime_from_timet_with_zone(span->end, 0, utc);
++ event->start = span->start;
++ event->end = span->end;
++
++ switch(icalcomponent_get_status(comp)) {
++ case ICAL_STATUS_CONFIRMED:
++ event->busy_state = AST_CALENDAR_BS_BUSY;
++ break;
++
++ case ICAL_STATUS_TENTATIVE:
++ event->busy_state = AST_CALENDAR_BS_BUSY_TENTATIVE;
++ break;
++
++ default:
++ event->busy_state = AST_CALENDAR_BS_FREE;
++ }
++
++ if ((prop = icalcomponent_get_first_property(comp, ICAL_SUMMARY_PROPERTY))) {
++ ast_string_field_set(event, summary, icalproperty_get_value_as_string(prop));
++ }
++
++ if ((prop = icalcomponent_get_first_property(comp, ICAL_DESCRIPTION_PROPERTY))) {
++ ast_string_field_set(event, description, icalproperty_get_value_as_string(prop));
++ }
++
++ if ((prop = icalcomponent_get_first_property(comp, ICAL_ORGANIZER_PROPERTY))) {
++ ast_string_field_set(event, organizer, icalproperty_get_value_as_string(prop));
++ }
++
++ if ((prop = icalcomponent_get_first_property(comp, ICAL_LOCATION_PROPERTY))) {
++ ast_string_field_set(event, location, icalproperty_get_value_as_string(prop));
++ }
++
++ if ((prop = icalcomponent_get_first_property(comp, ICAL_UID_PROPERTY))) {
++ ast_string_field_set(event, uid, icalproperty_get_value_as_string(prop));
++ } else {
++ ast_log(LOG_WARNING, "No UID found, but one is required. Generating, but updates may not be acurate\n");
++ if (!ast_strlen_zero(event->summary)) {
++ ast_string_field_set(event, uid, event->summary);
++ } else {
++ char tmp[100];
++ snprintf(tmp, sizeof(tmp), "%lu", event->start);
++ ast_string_field_set(event, uid, tmp);
++ }
++ }
++
++ /* Get the attendees */
++ for (prop = icalcomponent_get_first_property(comp, ICAL_ATTENDEE_PROPERTY);
++ prop; prop = icalcomponent_get_next_property(comp, ICAL_ATTENDEE_PROPERTY)) {
++ struct ast_calendar_attendee *attendee;
++ const char *data;
++
++ if (!(attendee = ast_calloc(1, sizeof(*attendee)))) {
++ event = ast_calendar_unref_event(event);
++ return;
++ }
++ data = icalproperty_get_attendee(prop);
++ if (!ast_strlen_zero(data)) {
++ attendee->data = ast_strdup(data);;
++ AST_LIST_INSERT_TAIL(&event->attendees, attendee, next);
++ }
++ }
++
++
++ /* Only set values for alarm based on VALARM. Can be overriden in main/calendar.c by autoreminder
++ * therefore, go ahead and add events even if their is no VALARM or it is malformed
++ * Currently we are only getting the first VALARM and are handling repitition in main/calendar.c from calendar.conf */
++ if (!(valarm = icalcomponent_get_first_component(comp, ICAL_VALARM_COMPONENT))) {
++ ao2_link(pvt->events, event);
++ event = ast_calendar_unref_event(event);
++ return;
++ }
++
++ if (!(prop = icalcomponent_get_first_property(valarm, ICAL_TRIGGER_PROPERTY))) {
++ ast_log(LOG_WARNING, "VALARM has no TRIGGER, skipping!\n");
++ ao2_link(pvt->events, event);
++ event = ast_calendar_unref_event(event);
++ return;
++ }
++
++ trigger = icalproperty_get_trigger(prop);
++
++ if (icaltriggertype_is_null_trigger(trigger)) {
++ ast_log(LOG_WARNING, "Bad TRIGGER for VALARM, skipping!\n");
++ ao2_link(pvt->events, event);
++ event = ast_calendar_unref_event(event);
++ return;
++ }
++
++ if (!icaltime_is_null_time(trigger.time)) { /* This is an absolute time */
++ tmp = icaltime_convert_to_zone(trigger.time, utc);
++ event->alarm = icaltime_as_timet_with_zone(tmp, utc);
++ } else { /* Offset from either dtstart or dtend */
++ /* XXX Technically you can check RELATED to see if the event fires from the END of the event
++ * But, I'm not sure I've ever seen anyone implement it in calendaring software, so I'm ignoring for now */
++ tmp = icaltime_add(start, trigger.duration);
++ event->alarm = icaltime_as_timet_with_zone(tmp, utc);
++ }
++
++ ao2_link(pvt->events, event);
++ event = ast_calendar_unref_event(event);
++
++ return;
++}
++
++struct xmlstate {
++ int in_caldata;
++ struct caldav_pvt *pvt;
++ struct ast_str *cdata;
++ time_t start;
++ time_t end;
++};
++
++static void handle_start_element(void *data, const xmlChar *fullname, const xmlChar **atts)
++{
++ struct xmlstate *state = data;
++
++ if (!xmlStrcasecmp(fullname, BAD_CAST "C:calendar-data")) {
++ state->in_caldata = 1;
++ ast_str_reset(state->cdata);
++ }
++}
++
++static void handle_end_element(void *data, const xmlChar *name)
++{
++ struct xmlstate *state = data;
++ struct icaltimetype start, end;
++ icaltimezone *utc = icaltimezone_get_utc_timezone();
++ icalcomponent *iter;
++ icalcomponent *comp;
++
++ if (xmlStrcasecmp(name, BAD_CAST "C:calendar-data")) {
++ return;
++ }
++
++ state->in_caldata = 0;
++ if (!(state->cdata && ast_str_strlen(state->cdata))) {
++ return;
++ }
++ /* XXX Parse the calendar blurb for recurrence events in the time range,
++ * create an event, and add it to pvt->events */
++ start = icaltime_from_timet_with_zone(state->start, 0, utc);
++ end = icaltime_from_timet_with_zone(state->end, 0, utc);
++ comp = icalparser_parse_string(ast_str_buffer(state->cdata));
++
++ for (iter = icalcomponent_get_first_component(comp, ICAL_VEVENT_COMPONENT);
++ iter;
++ iter = icalcomponent_get_next_component(comp, ICAL_VEVENT_COMPONENT))
++ {
++ icalcomponent_foreach_recurrence(iter, start, end, caldav_add_event, state->pvt);
++ }
++
++ icalcomponent_free(comp);
++}
++
++static void handle_characters(void *data, const xmlChar *ch, int len)
++{
++ struct xmlstate *state = data;
++ xmlChar *tmp;
++
++ if (!state->in_caldata) {
++ return;
++ }
++
++ tmp = xmlStrndup(ch, len);
++ ast_str_append(&state->cdata, 0, "%s", (char *)tmp);
++ xmlFree(tmp);
++}
++
++static int update_caldav(struct caldav_pvt *pvt)
++{
++ struct timeval now = ast_tvnow();
++ time_t start, end;
++ struct ast_str *response;
++ xmlSAXHandler saxHandler;
++ struct xmlstate state = {
++ .in_caldata = 0,
++ .pvt = pvt
++ };
++
++ start = now.tv_sec;
++ end = now.tv_sec + 60 * pvt->owner->timeframe;
++ if (!(response = caldav_get_events_between(pvt, start, end))) {
++ return -1;
++ }
++
++ if (!(state.cdata = ast_str_create(512))) {
++ ast_free(response);
++ return -1;
++ }
++
++ state.start = start;
++ state.end = end;
++
++ memset(&saxHandler, 0, sizeof(saxHandler));
++ saxHandler.startElement = handle_start_element;
++ saxHandler.endElement = handle_end_element;
++ saxHandler.characters = handle_characters;
++
++ xmlSAXUserParseMemory(&saxHandler, &state, ast_str_buffer(response), ast_str_strlen(response));
++
++ ast_calendar_merge_events(pvt->owner, pvt->events);
++
++ ast_free(response);
++ ast_free(state.cdata);
++
++ return 0;
++}
++
++static int verify_cert(void *userdata, int failures, const ne_ssl_certificate *cert)
++{
++ /* Verify all certs */
++ return 0;
++}
++
++static void *caldav_load_calendar(void *void_data)
++{
++ struct caldav_pvt *pvt;
++ struct ast_variable *v;
++ struct ast_calendar *cal = void_data;
++ ast_mutex_t refreshlock;
++
++ if (!(cal && ast_calendar_config)) {
++ ast_log(LOG_ERROR, "You must enable calendar support for res_caldav to load\n");
++ return NULL;
++ }
++
++ if (ao2_trylock(cal)) {
++ if (cal->unloading) {
++ ast_log(LOG_WARNING, "Unloading module, load_calendar cancelled.\n");
++ } else {
++ ast_log(LOG_WARNING, "Could not lock calendar, aborting!\n");
++ }
++ return NULL;
++ }
++
++ if (!(pvt = ao2_alloc(sizeof(*pvt), caldav_destructor))) {
++ ast_log(LOG_ERROR, "Could not allocate caldav_pvt structure for calendar: %s\n", cal->name);
++ return NULL;
++ }
++
++ pvt->owner = cal;
++
++ if (!(pvt->events = ast_calendar_event_container_alloc())) {
++ ast_log(LOG_ERROR, "Could not allocate space for fetching events for calendar: %s\n", cal->name);
++ pvt = unref_caldav(pvt);
++ ao2_unlock(cal);
++ return NULL;
++ }
++
++ if (ast_string_field_init(pvt, 32)) {
++ ast_log(LOG_ERROR, "Couldn't allocate string field space for calendar: %s\n", cal->name);
++ pvt = unref_caldav(pvt);
++ ao2_unlock(cal);
++ return NULL;
++ }
++
++ for (v = ast_variable_browse(ast_calendar_config, cal->name); v; v = v->next) {
++ if (!strcasecmp(v->name, "url")) {
++ ast_string_field_set(pvt, url, v->value);
++ } else if (!strcasecmp(v->name, "user")) {
++ ast_string_field_set(pvt, user, v->value);
++ } else if (!strcasecmp(v->name, "secret")) {
++ ast_string_field_set(pvt, secret, v->value);
++ }
++ }
++
++ if (ast_strlen_zero(pvt->url)) {
++ ast_log(LOG_WARNING, "No URL was specified for CalDAV calendar '%s' - skipping.\n", cal->name);
++ pvt = unref_caldav(pvt);
++ ao2_unlock(cal);
++ return NULL;
++ }
++
++ if (ne_uri_parse(pvt->url, &pvt->uri) || pvt->uri.host == NULL || pvt->uri.path == NULL) {
++ ast_log(LOG_WARNING, "Could not parse url '%s' for CalDAV calendar '%s' - skipping.\n", pvt->url, cal->name);
++ pvt = unref_caldav(pvt);
++ ao2_unlock(cal);
++ return NULL;
++ }
++
++ if (pvt->uri.scheme == NULL) {
++ pvt->uri.scheme = "http";
++ }
++
++ if (pvt->uri.port == 0) {
++ pvt->uri.port = ne_uri_defaultport(pvt->uri.scheme);
++ }
++
++ pvt->session = ne_session_create(pvt->uri.scheme, pvt->uri.host, pvt->uri.port);
++ ne_set_server_auth(pvt->session, auth_credentials, pvt);
++ if (!strncasecmp(pvt->uri.scheme, "https", sizeof(pvt->uri.scheme))) {
++ ne_ssl_trust_default_ca(pvt->session);
++ ne_ssl_set_verify(pvt->session, verify_cert, NULL);
++ }
++
++ cal->tech_pvt = pvt;
++
++ ast_mutex_init(&refreshlock);
++
++ /* Load it the first time */
++ update_caldav(pvt);
++
++ ao2_unlock(cal);
++
++ /* The only writing from another thread will be if unload is true */
++ for (;;) {
++ struct timeval tv = ast_tvnow();
++ struct timespec ts = {0,};
++
++ ts.tv_sec = tv.tv_sec + (60 * pvt->owner->refresh);
++
++ ast_mutex_lock(&refreshlock);
++ while (!pvt->owner->unloading) {
++ if (ast_cond_timedwait(&pvt->owner->unload, &refreshlock, &ts) == ETIMEDOUT) {
++ break;
++ }
++ }
++ ast_mutex_unlock(&refreshlock);
++
++ if (pvt->owner->unloading) {
++ ast_debug(10, "Skipping refresh since we got a shutdown signal\n");
++ return NULL;
++ }
++
++ ast_debug(10, "Refreshing after %d minute timeout\n", pvt->owner->refresh);
++
++ update_caldav(pvt);
++ }
++
++ return NULL;
++}
++
++static int load_module(void)
++{
++ ne_sock_init();
++ if (ast_calendar_register(&caldav_tech)) {
++ ne_sock_exit();
++ return AST_MODULE_LOAD_DECLINE;
++ }
++
++ return AST_MODULE_LOAD_SUCCESS;
++}
++
++static int unload_module(void)
++{
++ ast_calendar_unregister(&caldav_tech);
++ ne_sock_exit();
++ return 0;
++}
++
++AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Asterisk CalDAV Calendar Integration",
++ .load = load_module,
++ .unload = unload_module,
++ );
+
+Property changes on: res/res_calendar_caldav.c
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+
+Index: res/snmp/agent.c
+===================================================================
+--- a/res/snmp/agent.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/res/snmp/agent.c (.../trunk) (revision 202568)
+@@ -236,19 +236,32 @@
+ u_char *ret = NULL;
+ int i, bit;
+ struct ast_str *out = ast_str_alloca(2048);
++ struct ast_channel_iterator *iter;
+
+ if (header_simple_table(vp, name, length, exact, var_len, write_method, ast_active_channels()))
+ return NULL;
+
+ i = name[*length - 1] - 1;
+- for (chan = ast_channel_walk_locked(NULL);
+- chan && i;
+- chan = ast_channel_walk_locked(chan), i--)
+- ast_channel_unlock(chan);
+- if (chan == NULL)
++
++ if (!(iter = ast_channel_iterator_all_new(0))) {
+ return NULL;
++ }
++
++ while ((chan = ast_channel_iterator_next(iter)) && i) {
++ ast_channel_unref(chan);
++ i--;
++ }
++
++ iter = ast_channel_iterator_destroy(iter);
++
++ if (chan == NULL) {
++ return NULL;
++ }
++
+ *var_len = sizeof(long_ret);
+
++ ast_channel_lock(chan);
++
+ switch (vp->magic) {
+ case ASTCHANINDEX:
+ long_ret = name[*length - 1];
+@@ -503,7 +516,10 @@
+ default:
+ break;
+ }
++
+ ast_channel_unlock(chan);
++ chan = ast_channel_unref(chan);
++
+ return ret;
+ }
+
+@@ -567,13 +583,26 @@
+ long_ret = tech->transfer ? 1 : 2;
+ return (u_char *)&long_ret;
+ case ASTCHANTYPECHANNELS:
++ {
++ struct ast_channel_iterator *iter;
++
+ long_ret = 0;
+- for (chan = ast_channel_walk_locked(NULL); chan; chan = ast_channel_walk_locked(chan)) {
+- if (chan->tech == tech)
++
++ if (!(iter = ast_channel_iterator_all_new(0))) {
++ return NULL;
++ }
++
++ while ((chan = ast_channel_iterator_next(iter))) {
++ if (chan->tech == tech) {
+ long_ret++;
+- ast_channel_unlock(chan);
++ }
++ chan = ast_channel_unref(chan);
+ }
++
++ ast_channel_iterator_destroy(iter);
++
+ return (u_char *)&long_ret;
++ }
+ default:
+ break;
+ }
+@@ -585,15 +614,25 @@
+ {
+ static unsigned long long_ret;
+ struct ast_channel *chan = NULL;
++ struct ast_channel_iterator *iter;
+
+ long_ret = 0;
+- if (header_generic(vp, name, length, exact, var_len, write_method))
++
++ if (header_generic(vp, name, length, exact, var_len, write_method)) {
+ return NULL;
++ }
+
+- while ((chan = ast_channel_walk_locked(chan))) {
+- if (ast_bridged_channel(chan))
++ if (!(iter = ast_channel_iterator_all_new(0))) {
++ return NULL;
++ }
++
++ while ((chan = ast_channel_iterator_next(iter))) {
++ ast_channel_lock(chan);
++ if (ast_bridged_channel(chan)) {
+ long_ret++;
++ }
+ ast_channel_unlock(chan);
++ chan = ast_channel_unref(chan);
+ }
+
+ *var_len = sizeof(long_ret);
+Index: res/res_http_post.c
+===================================================================
+--- a/res/res_http_post.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/res/res_http_post.c (.../trunk) (revision 202568)
+@@ -156,7 +156,6 @@
+ return cbinfo.count;
+ }
+
+-
+ /* Find a sequence of bytes within a binary array. */
+ static int find_sequence(char * inbuf, int inlen, char * matchbuf, int matchlen)
+ {
+@@ -292,10 +291,9 @@
+ return 0;
+ }
+
+-
+-static struct ast_str *http_post_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *vars, struct ast_variable *headers, int *status, char **title, int *contentlength)
++static int http_post_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_vars, struct ast_variable *headers)
+ {
+- struct ast_variable *var;
++ struct ast_variable *var, *cookies;
+ unsigned long ident = 0;
+ FILE *f;
+ int content_len = 0;
+@@ -304,41 +302,45 @@
+ int message_count = 0;
+ char * boundary_marker = NULL;
+
+- if (!urih) {
+- return ast_http_error((*status = 400),
+- (*title = ast_strdup("Missing URI handle")),
+- NULL, "There was an error parsing the request");
++ if (method != AST_HTTP_POST) {
++ ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method");
++ return -1;
+ }
+
+- for (var = vars; var; var = var->next) {
+- if (strcasecmp(var->name, "mansession_id")) {
+- continue;
+- }
++ if (!astman_is_authed(ast_http_manid_from_vars(headers))) {
++ ast_http_error(ser, 403, "Access Denied", "Sorry, I cannot let you do that, Dave.");
++ return -1;
++ }
+
+- if (sscanf(var->value, "%lx", &ident) != 1) {
+- return ast_http_error((*status = 400),
+- (*title = ast_strdup("Bad Request")),
+- NULL, "The was an error parsing the request.");
+- }
++ if (!urih) {
++ ast_http_error(ser, 400, "Missing URI handle", "There was an error parsing the request");
++ return -1;
++ }
+
+- if (!astman_verify_session_writepermissions(ident, EVENT_FLAG_CONFIG)) {
+- return ast_http_error((*status = 401),
+- (*title = ast_strdup("Unauthorized")),
+- NULL, "You are not authorized to make this request.");
++ cookies = ast_http_get_cookies(headers);
++ for (var = cookies; var; var = var->next) {
++ if (!strcasecmp(var->name, "mansession_id")) {
++ sscanf(var->value, "%lx", &ident);
++ break;
+ }
+-
+- break;
+ }
++ if (cookies) {
++ ast_variables_destroy(cookies);
++ }
+
+- if (!var) {
+- return ast_http_error((*status = 401),
+- (*title = ast_strdup("Unauthorized")),
+- NULL, "You are not authorized to make this request.");
++ if (ident == 0) {
++ ast_http_error(ser, 401, "Unauthorized", "You are not authorized to make this request.");
++ return -1;
+ }
++ if (!astman_verify_session_writepermissions(ident, EVENT_FLAG_CONFIG)) {
++ ast_http_error(ser, 401, "Unauthorized", "You are not authorized to make this request.");
++ return -1;
++ }
+
+ if (!(f = tmpfile())) {
+ ast_log(LOG_ERROR, "Could not create temp file.\n");
+- return NULL;
++ ast_http_error(ser, 500, "Internal server error", "Could not create temp file.");
++ return -1;
+ }
+
+ for (var = headers; var; var = var->next) {
+@@ -348,8 +350,8 @@
+ if ((sscanf(var->value, "%u", &content_len)) != 1) {
+ ast_log(LOG_ERROR, "Invalid Content-Length in POST request!\n");
+ fclose(f);
+-
+- return NULL;
++ ast_http_error(ser, 500, "Internal server error", "Invalid Content-Length in POST request!");
++ return -1;
+ }
+ ast_debug(1, "Got a Content-Length of %d\n", content_len);
+ } else if (!strcasecmp(var->name, "Content-Type")) {
+@@ -367,15 +369,15 @@
+ ast_log(LOG_DEBUG, "Cannot find boundary marker in POST request.\n");
+ }
+ fclose(f);
+-
+- return NULL;
++
++ return -1;
+ }
+
+ if (fseek(f, SEEK_SET, 0)) {
+ ast_log(LOG_ERROR, "Failed to seek temp file back to beginning.\n");
+ fclose(f);
+-
+- return NULL;
++ ast_http_error(ser, 500, "Internal server error", "Failed to seek temp file back to beginning.");
++ return -1;
+ }
+
+ post_dir = urih->data;
+@@ -385,24 +387,20 @@
+ if (!message) {
+ ast_log(LOG_ERROR, "Error parsing MIME data\n");
+
+- return ast_http_error((*status = 400),
+- (*title = ast_strdup("Bad Request")),
+- NULL, "The was an error parsing the request.");
++ ast_http_error(ser, 400, "Bad Request", "The was an error parsing the request.");
++ return -1;
+ }
+
+ if (!(message_count = process_message(message, ast_str_buffer(post_dir)))) {
+ ast_log(LOG_ERROR, "Invalid MIME data, found no parts!\n");
+ g_object_unref(message);
+- return ast_http_error((*status = 400),
+- (*title = ast_strdup("Bad Request")),
+- NULL, "The was an error parsing the request.");
++ ast_http_error(ser, 400, "Bad Request", "The was an error parsing the request.");
++ return -1;
+ }
+-
+ g_object_unref(message);
+
+- return ast_http_error((*status = 200),
+- (*title = ast_strdup("OK")),
+- NULL, "File successfully uploaded.");
++ ast_http_error(ser, 200, "OK", "File successfully uploaded.");
++ return 0;
+ }
+
+ static int __ast_http_post_load(int reload)
+@@ -450,8 +448,6 @@
+ ast_str_set(&ds, 0, "%s/%s", prefix, v->value);
+ urih->data = ds;
+ urih->has_subtree = 0;
+- urih->supports_get = 0;
+- urih->supports_post = 1;
+ urih->callback = http_post_callback;
+ urih->key = __FILE__;
+ urih->mallocd = urih->dmallocd = 1;
+Index: res/res_musiconhold.c
+===================================================================
+--- a/res/res_musiconhold.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/res/res_musiconhold.c (.../trunk) (revision 202568)
+@@ -70,54 +70,83 @@
+
+ #define INITIAL_NUM_FILES 8
+
+-static char *play_moh = "MusicOnHold";
+-static char *wait_moh = "WaitMusicOnHold";
+-static char *set_moh = "SetMusicOnHold";
+-static char *start_moh = "StartMusicOnHold";
+-static char *stop_moh = "StopMusicOnHold";
++/*** DOCUMENTATION
++ <application name="MusicOnHold" language="en_US">
++ <synopsis>
++ Play Music On Hold indefinitely.
++ </synopsis>
++ <syntax>
++ <parameter name="class" required="true" />
++ <parameter name="duration" />
++ </syntax>
++ <description>
++ <para>Plays hold music specified by class. If omitted, the default music
++ source for the channel will be used. Change the default class with
++ Set(CHANNEL(musicclass)=...). If duration is given, hold music will be played
++ specified number of seconds. If duration is ommited, music plays indefinitely.
++ Returns <literal>0</literal> when done, <literal>-1</literal> on hangup.</para>
++ </description>
++ </application>
++ <application name="WaitMusicOnHold" language="en_US">
++ <synopsis>
++ Wait, playing Music On Hold.
++ </synopsis>
++ <syntax>
++ <parameter name="delay" required="true" />
++ </syntax>
++ <description>
++ <para> !!! DEPRECATED. Use MusicOnHold instead !!!</para>
++ <para>Plays hold music specified number of seconds. Returns <literal>0</literal> when done,
++ or <literal>-1</literal> on hangup. If no hold music is available, the delay will still occur
++ with no sound.</para>
++ <para> !!! DEPRECATED. Use MusicOnHold instead !!!</para>
++ </description>
++ </application>
++ <application name="SetMusicOnHold" language="en_US">
++ <synopsis>
++ Set default Music On Hold class.
++ </synopsis>
++ <syntax>
++ <parameter name="class" required="yes" />
++ </syntax>
++ <description>
++ <para>!!! DEPRECATED. USe Set(CHANNEL(musicclass)=...) instead !!!</para>
++ <para>Sets the default class for music on hold for a given channel.
++ When music on hold is activated, this class will be used to select which
++ music is played.</para>
++ <para>!!! DEPRECATED. USe Set(CHANNEL(musicclass)=...) instead !!!</para>
++ </description>
++ </application>
++ <application name="StartMusicOnHold" language="en_US">
++ <synopsis>
++ Play Music On Hold.
++ </synopsis>
++ <syntax>
++ <parameter name="class" required="true" />
++ </syntax>
++ <description>
++ <para>Starts playing music on hold, uses default music class for channel.
++ Starts playing music specified by class. If omitted, the default music
++ source for the channel will be used. Always returns <literal>0</literal>.</para>
++ </description>
++ </application>
++ <application name="StopMusicOnHold" language="en_US">
++ <synopsis>
++ Stop playing Music On Hold.
++ </synopsis>
++ <syntax />
++ <description>
++ <para>Stops playing music on hold.</para>
++ </description>
++ </application>
++ ***/
+
+-static char *play_moh_syn = "Play Music On Hold indefinitely";
+-static char *wait_moh_syn = "Wait, playing Music On Hold";
+-static char *set_moh_syn = "Set default Music On Hold class";
+-static char *start_moh_syn = "Play Music On Hold";
+-static char *stop_moh_syn = "Stop Playing Music On Hold";
++static const char play_moh[] = "MusicOnHold";
++static const char wait_moh[] = "WaitMusicOnHold";
++static const char set_moh[] = "SetMusicOnHold";
++static const char start_moh[] = "StartMusicOnHold";
++static const char stop_moh[] = "StopMusicOnHold";
+
+-static char *play_moh_desc = " MusicOnHold(class[,duration]):\n"
+-"Plays hold music specified by class. If omitted, the default\n"
+-"music source for the channel will be used. Change the default \n"
+-"class with Set(CHANNEL(musicclass)=...).\n"
+-"If duration is given, hold music will be played specified number\n"
+-"of seconds. If duration is ommited, music plays indefinitely.\n"
+-"Returns 0 when done, -1 on hangup.\n";
+-
+-static char *wait_moh_desc = " WaitMusicOnHold(delay):\n"
+-"\n"
+-" !!! DEPRECATED. Use MusicOnHold instead !!!\n"
+-"\n"
+-"Plays hold music specified number of seconds. Returns 0 when\n"
+-"done, or -1 on hangup. If no hold music is available, the delay will\n"
+-"still occur with no sound.\n"
+-"\n"
+-" !!! DEPRECATED. Use MusicOnHold instead !!!\n";
+-
+-static char *set_moh_desc = " SetMusicOnHold(class):\n"
+-"\n"
+-" !!! DEPRECATED. USe Set(CHANNEL(musicclass)=...) instead !!!\n"
+-"\n"
+-"Sets the default class for music on hold for a given channel. When\n"
+-"music on hold is activated, this class will be used to select which\n"
+-"music is played.\n"
+-"\n"
+-" !!! DEPRECATED. USe Set(CHANNEL(musicclass)=...) instead !!!\n";
+-
+-static char *start_moh_desc = " StartMusicOnHold(class):\n"
+-"Starts playing music on hold, uses default music class for channel.\n"
+-"Starts playing music specified by class. If omitted, the default\n"
+-"music source for the channel will be used. Always returns 0.\n";
+-
+-static char *stop_moh_desc = " StopMusicOnHold(): "
+-"Stops playing music on hold.\n";
+-
+ static int respawn_time = 20;
+
+ struct moh_files_state {
+@@ -606,7 +635,7 @@
+ return NULL;
+ }
+
+-static int play_moh_exec(struct ast_channel *chan, void *data)
++static int play_moh_exec(struct ast_channel *chan, const char *data)
+ {
+ char *parse;
+ char *class;
+@@ -646,7 +675,7 @@
+ return res;
+ }
+
+-static int wait_moh_exec(struct ast_channel *chan, void *data)
++static int wait_moh_exec(struct ast_channel *chan, const char *data)
+ {
+ static int deprecation_warning = 0;
+ int res;
+@@ -669,7 +698,7 @@
+ return res;
+ }
+
+-static int set_moh_exec(struct ast_channel *chan, void *data)
++static int set_moh_exec(struct ast_channel *chan, const char *data)
+ {
+ static int deprecation_warning = 0;
+
+@@ -686,7 +715,7 @@
+ return 0;
+ }
+
+-static int start_moh_exec(struct ast_channel *chan, void *data)
++static int start_moh_exec(struct ast_channel *chan, const char *data)
+ {
+ char *parse;
+ char *class;
+@@ -705,7 +734,7 @@
+ return 0;
+ }
+
+-static int stop_moh_exec(struct ast_channel *chan, void *data)
++static int stop_moh_exec(struct ast_channel *chan, const char *data)
+ {
+ ast_moh_stop(chan);
+
+@@ -1395,9 +1424,10 @@
+ while ((member = AST_LIST_REMOVE_HEAD(&class->members, list))) {
+ free(member);
+ }
+-
++
+ if (class->thread) {
+ pthread_cancel(class->thread);
++ pthread_join(class->thread, NULL);
+ class->thread = AST_PTHREADT_NULL;
+ }
+
+@@ -1667,17 +1697,17 @@
+ local_ast_moh_cleanup);
+ }
+
+- res = ast_register_application(play_moh, play_moh_exec, play_moh_syn, play_moh_desc);
++ res = ast_register_application_xml(play_moh, play_moh_exec);
+ ast_register_atexit(ast_moh_destroy);
+ ast_cli_register_multiple(cli_moh, ARRAY_LEN(cli_moh));
+ if (!res)
+- res = ast_register_application(wait_moh, wait_moh_exec, wait_moh_syn, wait_moh_desc);
++ res = ast_register_application_xml(wait_moh, wait_moh_exec);
+ if (!res)
+- res = ast_register_application(set_moh, set_moh_exec, set_moh_syn, set_moh_desc);
++ res = ast_register_application_xml(set_moh, set_moh_exec);
+ if (!res)
+- res = ast_register_application(start_moh, start_moh_exec, start_moh_syn, start_moh_desc);
++ res = ast_register_application_xml(start_moh, start_moh_exec);
+ if (!res)
+- res = ast_register_application(stop_moh, stop_moh_exec, stop_moh_syn, stop_moh_desc);
++ res = ast_register_application_xml(stop_moh, stop_moh_exec);
+
+ return AST_MODULE_LOAD_SUCCESS;
+ }
+Index: sample.call
+===================================================================
+--- a/sample.call (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/sample.call (.../trunk) (revision 202568)
+@@ -6,7 +6,7 @@
+ # Comments are indicated by a '#' character that begins a line, or follows
+ # a space or tab character. To be consistent with the configuration files
+ # in Asterisk, comments can also be indicated by a semicolon. However, the
+-# multiline comments (;-- --;) used in Asterisk configuration files are not
++# multiline comments (;-- --;) used in Asterisk configuration files are not
+ # supported. Semicolons can be escaped by a backslash.
+ #
+
+@@ -76,8 +76,8 @@
+
+ #
+ # Setting Archive to yes the call file is never deleted, but is moved
+-# in the subdir "outgoing_done" of the spool directory. In this case
+-# will be appended a line with "Status: value", where value can be
++# in the subdir "outgoing_done" of the spool directory. In this case
++# will be appended a line with "Status: value", where value can be
+ # Completed, Expired or Failed.
+ #
+ #Archive: yes
+Index: contrib/init.d/rc.debian.asterisk
+===================================================================
+--- a/contrib/init.d/rc.debian.asterisk (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/contrib/init.d/rc.debian.asterisk (.../trunk) (revision 202568)
+@@ -73,7 +73,7 @@
+ fi
+ if [ $AST_GROUP ] ; then
+ ASTARGS="$ASTARGS -G $AST_GROUP"
+- chown $AST_GROUP $ASTVARRUNDIR
++ chgrp $AST_GROUP $ASTVARRUNDIR
+ fi
+ # "start-stop-daemon --oknodo" returns 0 even if Asterisk was already running (as LSB expects):
+ start-stop-daemon --start --oknodo --exec $DAEMON -- $ASTARGS
+Index: contrib/scripts/asterisk.ldap-schema
+===================================================================
+--- a/contrib/scripts/asterisk.ldap-schema (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/contrib/scripts/asterisk.ldap-schema (.../trunk) (revision 202568)
+@@ -8,7 +8,7 @@
+ # https://issues.asterisk.org/view.php?id=15155
+ # - Added AstAccountLastQualifyMilliseconds - 28/05/2009
+ # https://issues.asterisk.org/view.php?id=15156
+-# - http://bugs.digium.com/view.php?id=12860 - 04/07/2008
++# - https://issues.asterisk.org/view.php?id=12860 - 04/07/2008
+ # - Fixed wrong DESC - 07/05/2008
+ #
+ # Author: Gavin Henry - <ghenry@suretecsystems.com>
+Index: contrib/scripts/asterisk.ldif
+===================================================================
+--- a/contrib/scripts/asterisk.ldif (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/contrib/scripts/asterisk.ldif (.../trunk) (revision 202568)
+@@ -8,7 +8,7 @@
+ # https://issues.asterisk.org/view.php?id=15155
+ # - Added AstAccountLastQualifyMilliseconds - 28/05/2009
+ # https://issues.asterisk.org/view.php?id=15156
+-# - http://bugs.digium.com/view.php?id=12860 - 04/07/2008
++# - https://issues.asterisk.org/view.php?id=12860 - 04/07/2008
+ # - Fixed wrong DESC - 07/05/2008
+ #
+ # Author: Gavin Henry - <ghenry@suretecsystems.com>
+Index: contrib/scripts/ast_grab_core
+===================================================================
+--- a/contrib/scripts/ast_grab_core (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/contrib/scripts/ast_grab_core (.../trunk) (revision 202568)
+@@ -67,4 +67,4 @@
+ echo Done.
+ echo
+ echo Reproducible deadlocks should be posted with a full backtrace and instructions
+-echo to reproduce the issue at http://bugs.digium.com/ Thanks!
++echo to reproduce the issue at https://issues.asterisk.org/ Thanks!
+Index: contrib/scripts/get_ilbc_source.sh
+===================================================================
+--- a/contrib/scripts/get_ilbc_source.sh (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/contrib/scripts/get_ilbc_source.sh (.../trunk) (revision 202568)
+@@ -22,7 +22,7 @@
+
+ wget -P codecs/ilbc http://www.ietf.org/rfc/rfc3951.txt
+
+-wget -q -O - http://www.ilbcfreeware.org/documentation/extract-cfile.awk | sed -e 's/\r//g' > codecs/ilbc/extract-cfile.awk
++wget -q -O - http://www.ilbcfreeware.org/documentation/extract-cfile.awk | tr -d '\r' > codecs/ilbc/extract-cfile.awk
+
+ (cd codecs/ilbc && awk -f extract-cfile.awk rfc3951.txt)
+
+Index: contrib/upstart/asterisk.upstart-0.3.9
+===================================================================
+--- a/contrib/upstart/asterisk.upstart-0.3.9 (.../tags/1.6.2.0-beta3) (revision 0)
++++ b/contrib/upstart/asterisk.upstart-0.3.9 (.../trunk) (revision 202568)
+@@ -0,0 +1,36 @@
++# asterisk
++#
++# Upstart control file for the Asterisk PBX
++#
++# To install, rename this file to 'asterisk' and copy it to /etc/event.d/
++#
++# To start asterisk manually:
++# sudo start asterisk
++#
++# To stop asterisk manually:
++# sudo stop asterisk
++
++description "Asterisk PBX"
++version "1.6.3"
++
++start on runlevel 2
++start on runlevel 3
++start on runlevel 4
++start on runlevel 5
++
++stop on runlevel 0
++stop on runlevel 1
++stop on runlevel 6
++
++pre-start script
++ # Since Ubuntu clears /var/run on reboot, create this before we try to start
++ mkdir -p /var/run/asterisk
++end script
++
++respawn
++exec /usr/sbin/asterisk -vvvvvvvg -cf
++
++post-stop script
++ # Might as well clean up after ourselves, too.
++ rm -rf /var/run/asterisk
++end script
+
+Property changes on: contrib/upstart/asterisk.upstart-0.3.9
+___________________________________________________________________
+Added: svn:mime-type
+ + text/plain
+Added: svn:keywords
+ + Author Date Id Revision
+Added: svn:eol-style
+ + native
+
+Index: contrib/asterisk-ng-doxygen
+===================================================================
+--- a/contrib/asterisk-ng-doxygen (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/contrib/asterisk-ng-doxygen (.../trunk) (revision 202568)
+@@ -475,6 +475,7 @@
+ funcs \
+ include \
+ include/asterisk \
++ include/asterisk/doxygen \
+ main \
+ main/stdtime \
+ pbx \
+Index: codecs/gsm/src/gsm_destroy.c
+===================================================================
+--- a/codecs/gsm/src/gsm_destroy.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/codecs/gsm/src/gsm_destroy.c (.../trunk) (revision 202568)
+@@ -22,5 +22,5 @@
+
+ void gsm_destroy P1((S), gsm S)
+ {
+- if (S) free((char *)S);
++ free((char *)S);
+ }
+Index: utils/ael_main.c
+===================================================================
+--- a/utils/ael_main.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/utils/ael_main.c (.../trunk) (revision 202568)
+@@ -299,8 +299,7 @@
+ }
+
+ /* since add_extension2 is responsible for the malloc'd data stuff */
+- if( data )
+- free(data);
++ free(data);
+ return 0;
+ }
+
+Index: utils/extconf.c
+===================================================================
+--- a/utils/extconf.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/utils/extconf.c (.../trunk) (revision 202568)
+@@ -2993,8 +2993,7 @@
+
+ static void ast_var_delete(struct ast_var_t *var)
+ {
+- if (var)
+- free(var);
++ free(var);
+ }
+
+
+@@ -3090,7 +3089,7 @@
+
+ }
+
+-static int pbx_builtin_setvar(struct ast_channel *chan, void *data)
++static int pbx_builtin_setvar(struct ast_channel *chan, const void *data)
+ {
+ char *name, *value, *mydata;
+ int argc;
+@@ -3125,9 +3124,9 @@
+ return(0);
+ }
+
+-int localized_pbx_builtin_setvar(struct ast_channel *chan, void *data);
++int localized_pbx_builtin_setvar(struct ast_channel *chan, const void *data);
+
+-int localized_pbx_builtin_setvar(struct ast_channel *chan, void *data)
++int localized_pbx_builtin_setvar(struct ast_channel *chan, const void *data)
+ {
+ return pbx_builtin_setvar(chan, data);
+ }
+Index: utils/muted.c
+===================================================================
+--- a/utils/muted.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/utils/muted.c (.../trunk) (revision 202568)
+@@ -684,6 +684,7 @@
+ fclose(astf);
+ exit(1);
+ }
++#if HAVE_WORKING_FORK
+ if (needfork) {
+ #ifndef HAVE_SBIN_LAUNCHD
+ if (daemon(0,0) < 0) {
+@@ -695,6 +696,7 @@
+ exit(1);
+ #endif
+ }
++#endif
+ for(;;) {
+ if (wait_event()) {
+ fclose(astf);
+Index: utils/conf2ael.c
+===================================================================
+--- a/utils/conf2ael.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/utils/conf2ael.c (.../trunk) (revision 202568)
+@@ -471,7 +471,7 @@
+ if (mon) {
+ *mon++ = 0;
+ /* now all 4 fields are set; what do we do? */
+- pvalIncludesAddIncludeWithTimeConstraints(incl, all, hr, dow, dom, mon);
++ pvalIncludesAddIncludeWithTimeConstraints(incl, strdup(all), strdup(hr), strdup(dow), strdup(dom), strdup(mon));
+ /* the original data is always best to keep (no 2-min rounding) */
+ } else {
+ ast_log(LOG_ERROR,"No month spec attached to include!\n");
+@@ -483,6 +483,7 @@
+ ast_log(LOG_ERROR,"No day of week spec attached to include!\n");
+ }
+ }
++ free(all);
+ }
+ tmpi = tmpi->next;
+ }
+@@ -568,7 +569,7 @@
+
+ /* ==================================== for linking internal stuff to external stuff */
+
+-int pbx_builtin_setvar(struct ast_channel *chan, void *data)
++int pbx_builtin_setvar(struct ast_channel *chan, const char *data)
+ {
+ return localized_pbx_builtin_setvar(chan, data);
+ }
+Index: utils/stereorize.c
+===================================================================
+--- a/utils/stereorize.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/utils/stereorize.c (.../trunk) (revision 202568)
+@@ -156,4 +156,7 @@
+ }
+ }
+ /* That was an endless loop. This point is never reached. */
++ free(leftsample);
++ free(rightsample);
++ free(stereosample);
+ }
+Index: Makefile.rules
+===================================================================
+--- a/Makefile.rules (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/Makefile.rules (.../trunk) (revision 202568)
+@@ -51,8 +51,13 @@
+ # per-target settings will be applied
+ CC_CFLAGS=$(PTHREAD_CFLAGS) $(ASTCFLAGS)
+ CXX_CFLAGS=$(PTHREAD_CFLAGS) $(filter-out -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations $(AST_DECLARATION_AFTER_STATEMENT),$(ASTCFLAGS))
+-CC_LDFLAGS_SO=$(PTHREAD_CFLAGS) $(ASTLDFLAGS) $(SOLINK)
+-CXX_LDFLAGS_SO=$(PTHREAD_CFLAGS) $(ASTLDFLAGS) $(SOLINK)
++
++ifeq ($(GNU_LD),1)
++SO_SUPPRESS_SYMBOLS=-Wl,--version-script,$(if $(wildcard $(subst .so,.exports,$@)),$(subst .so,.exports,$@),$(ASTTOPDIR)/default.exports)
++endif
++
++CC_LDFLAGS_SO=$(PTHREAD_CFLAGS) $(ASTLDFLAGS) $(SOLINK) $(SO_SUPPRESS_SYMBOLS)
++CXX_LDFLAGS_SO=$(PTHREAD_CFLAGS) $(ASTLDFLAGS) $(SOLINK) $(SO_SUPPRESS_SYMBOLS)
+ CC_LIBS=$(PTHREAD_LIBS) $(LIBS)
+ CXX_LIBS=$(PTHREAD_LIBS) $(LIBS)
+
+Index: cdr/cdr_pgsql.c
+===================================================================
+--- a/cdr/cdr_pgsql.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/cdr/cdr_pgsql.c (.../trunk) (revision 202568)
+@@ -331,10 +331,9 @@
+ static int unload_module(void)
+ {
+ struct columns *current;
++
+ ast_cdr_unregister(name);
+
+- /* Give all threads time to finish */
+- usleep(1);
+ PQfinish(conn);
+
+ if (pghostname)
+Index: cdr/cdr_custom.c
+===================================================================
+--- a/cdr/cdr_custom.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/cdr/cdr_custom.c (.../trunk) (revision 202568)
+@@ -1,7 +1,7 @@
+ /*
+ * Asterisk -- An open source telephony toolkit.
+ *
+- * Copyright (C) 1999 - 2005, Digium, Inc.
++ * Copyright (C) 1999 - 2009, Digium, Inc.
+ *
+ * Mark Spencer <markster@digium.com>
+ *
+@@ -44,127 +44,171 @@
+ #include "asterisk/pbx.h"
+ #include "asterisk/utils.h"
+ #include "asterisk/lock.h"
++#include "asterisk/threadstorage.h"
++#include "asterisk/strings.h"
+
+ #define CUSTOM_LOG_DIR "/cdr_custom"
++#define CONFIG "cdr_custom.conf"
+
+-#define DATE_FORMAT "%Y-%m-%d %T"
++AST_THREADSTORAGE(custom_buf);
+
+-AST_MUTEX_DEFINE_STATIC(lock);
+-AST_MUTEX_DEFINE_STATIC(mf_lock);
++static const char name[] = "cdr-custom";
+
+-static char *name = "cdr-custom";
++struct cdr_config {
++ AST_DECLARE_STRING_FIELDS(
++ AST_STRING_FIELD(filename);
++ AST_STRING_FIELD(format);
++ );
++ ast_mutex_t lock;
++ AST_RWLIST_ENTRY(cdr_config) list;
++};
+
+-static char master[PATH_MAX];
+-static char format[1024]="";
++static AST_RWLIST_HEAD_STATIC(sinks, cdr_config);
+
+-static int load_config(int reload)
++static void free_config(void)
+ {
++ struct cdr_config *sink;
++ while ((sink = AST_RWLIST_REMOVE_HEAD(&sinks, list))) {
++ ast_mutex_destroy(&sink->lock);
++ ast_free(sink);
++ }
++}
++
++static int load_config(void)
++{
+ struct ast_config *cfg;
+ struct ast_variable *var;
+- struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
+- int res = -1;
++ struct ast_flags config_flags = { 0 };
++ int res = 0;
+
+- if ((cfg = ast_config_load("cdr_custom.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED)
+- return 0;
+-
+- if (cfg == CONFIG_STATUS_FILEINVALID) {
+- ast_log(LOG_ERROR, "Invalid config file\n");
+- return 1;
++ cfg = ast_config_load(CONFIG, config_flags);
++ if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
++ ast_log(LOG_ERROR, "Unable to load " CONFIG ". Not logging custom CSV CDRs.\n");
++ return -1;
+ }
+
+- strcpy(format, "");
+- strcpy(master, "");
+- ast_mutex_lock(&lock);
+- if (cfg) {
+- var = ast_variable_browse(cfg, "mappings");
+- while(var) {
+- if (!ast_strlen_zero(var->name) && !ast_strlen_zero(var->value)) {
+- if (strlen(var->value) > (sizeof(format) - 1))
+- ast_log(LOG_WARNING, "Format string too long, will be truncated, at line %d\n", var->lineno);
+- ast_copy_string(format, var->value, sizeof(format) - 1);
+- strcat(format,"\n");
+- snprintf(master, sizeof(master),"%s/%s/%s", ast_config_AST_LOG_DIR, name, var->name);
+- if (var->next) {
+- ast_log(LOG_NOTICE, "Sorry, only one mapping is supported at this time, mapping '%s' will be ignored at line %d.\n", var->next->name, var->next->lineno);
+- break;
+- }
+- } else
+- ast_log(LOG_NOTICE, "Mapping must have both filename and format at line %d\n", var->lineno);
+- var = var->next;
++ var = ast_variable_browse(cfg, "mappings");
++ while (var) {
++ if (!ast_strlen_zero(var->name) && !ast_strlen_zero(var->value)) {
++ struct cdr_config *sink = ast_calloc_with_stringfields(1, struct cdr_config, 1024);
++
++ if (!sink) {
++ ast_log(LOG_ERROR, "Unable to allocate memory for configuration settings.\n");
++ res = -2;
++ break;
++ }
++
++ ast_string_field_build(sink, format, "%s\n", var->value);
++ ast_string_field_build(sink, filename, "%s/%s/%s", ast_config_AST_LOG_DIR, name, var->name);
++ ast_mutex_init(&sink->lock);
++
++ AST_RWLIST_INSERT_TAIL(&sinks, sink, list);
++ } else {
++ ast_log(LOG_NOTICE, "Mapping must have both a filename and a format at line %d\n", var->lineno);
+ }
+- ast_config_destroy(cfg);
+- res = 0;
+- } else {
+- if (reload)
+- ast_log(LOG_WARNING, "Failed to reload configuration file.\n");
+- else
+- ast_log(LOG_WARNING, "Failed to load configuration file. Module not activated.\n");
++ var = var->next;
+ }
+- ast_mutex_unlock(&lock);
++ ast_config_destroy(cfg);
+
+ return res;
+ }
+
+-
+-
+ static int custom_log(struct ast_cdr *cdr)
+ {
+- FILE *mf = NULL;
++ struct ast_channel *dummy;
++ struct ast_str *str;
++ struct cdr_config *config;
+
+- /* Make sure we have a big enough buf */
+- char buf[2048];
+- struct ast_channel dummy;
++ /* Batching saves memory management here. Otherwise, it's the same as doing an allocation and free each time. */
++ if (!(str = ast_str_thread_get(&custom_buf, 16))) {
++ return -1;
++ }
+
+- /* Abort if no master file is specified */
+- if (ast_strlen_zero(master))
+- return 0;
++ dummy = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Substitution/%p", cdr);
+
+- /* Quite possibly the first use of a static struct ast_channel, we need it so the var funcs will work */
+- memset(&dummy, 0, sizeof(dummy));
+- dummy.cdr = cdr;
+- pbx_substitute_variables_helper(&dummy, format, buf, sizeof(buf) - 1);
++ if (!dummy) {
++ ast_log(LOG_ERROR, "Unable to allocate channel for variable subsitution.\n");
++ return -1;
++ }
+
+- /* because of the absolutely unconditional need for the
+- highest reliability possible in writing billing records,
+- we open write and close the log file each time */
+- ast_mutex_lock(&mf_lock);
+- mf = fopen(master, "a");
+- if (mf) {
+- fputs(buf, mf);
+- fflush(mf); /* be particularly anal here */
+- fclose(mf);
+- mf = NULL;
+- ast_mutex_unlock(&mf_lock);
+- } else {
+- ast_log(LOG_ERROR, "Unable to re-open master file %s : %s\n", master, strerror(errno));
+- ast_mutex_unlock(&mf_lock);
++ /* We need to dup here since the cdr actually belongs to the other channel,
++ so when we release this channel we don't want the CDR getting cleaned
++ up prematurely. */
++ dummy->cdr = ast_cdr_dup(cdr);
++
++ AST_RWLIST_RDLOCK(&sinks);
++
++ AST_LIST_TRAVERSE(&sinks, config, list) {
++ FILE *out;
++
++ ast_str_substitute_variables(&str, 0, dummy, config->format);
++
++ /* Even though we have a lock on the list, we could be being chased by
++ another thread and this lock ensures that we won't step on anyone's
++ toes. Once each CDR backend gets it's own thread, this lock can be
++ removed. */
++ ast_mutex_lock(&config->lock);
++
++ /* Because of the absolutely unconditional need for the
++ highest reliability possible in writing billing records,
++ we open write and close the log file each time */
++ if ((out = fopen(config->filename, "a"))) {
++ fputs(ast_str_buffer(str), out);
++ fflush(out); /* be particularly anal here */
++ fclose(out);
++ } else {
++ ast_log(LOG_ERROR, "Unable to re-open master file %s : %s\n", config->filename, strerror(errno));
++ }
++
++ ast_mutex_unlock(&config->lock);
+ }
+
++ AST_RWLIST_UNLOCK(&sinks);
++
++ ast_channel_release(dummy);
++
+ return 0;
+ }
+
+ static int unload_module(void)
+ {
+ ast_cdr_unregister(name);
++
++ if (AST_RWLIST_WRLOCK(&sinks)) {
++ ast_cdr_register(name, ast_module_info->description, custom_log);
++ ast_log(LOG_ERROR, "Unable to lock sink list. Unload failed.\n");
++ return -1;
++ }
++
++ free_config();
++ AST_RWLIST_UNLOCK(&sinks);
+ return 0;
+ }
+
+-static int load_module(void)
++static enum ast_module_load_result load_module(void)
+ {
+- int res = 0;
++ if (AST_RWLIST_WRLOCK(&sinks)) {
++ ast_log(LOG_ERROR, "Unable to lock sink list. Load failed.\n");
++ return AST_MODULE_LOAD_FAILURE;
++ }
+
+- if (!load_config(0)) {
+- res = ast_cdr_register(name, ast_module_info->description, custom_log);
+- if (res)
+- ast_log(LOG_ERROR, "Unable to register custom CDR handling\n");
+- return res;
+- } else
+- return AST_MODULE_LOAD_DECLINE;
++ load_config();
++ AST_RWLIST_UNLOCK(&sinks);
++ ast_cdr_register(name, ast_module_info->description, custom_log);
++ return AST_MODULE_LOAD_SUCCESS;
+ }
+
+ static int reload(void)
+ {
+- return load_config(1);
++ if (AST_RWLIST_WRLOCK(&sinks)) {
++ ast_log(LOG_ERROR, "Unable to lock sink list. Load failed.\n");
++ return AST_MODULE_LOAD_FAILURE;
++ }
++
++ free_config();
++ load_config();
++ AST_RWLIST_UNLOCK(&sinks);
++ return AST_MODULE_LOAD_SUCCESS;
+ }
+
+ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Customizable Comma Separated Values CDR Backend",
+Index: cdr/cdr_manager.c
+===================================================================
+--- a/cdr/cdr_manager.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/cdr/cdr_manager.c (.../trunk) (revision 202568)
+@@ -46,8 +46,10 @@
+ static char *name = "cdr_manager";
+
+ static int enablecdr = 0;
+-struct ast_str *customfields;
+
++static struct ast_str *customfields;
++AST_RWLOCK_DEFINE_STATIC(customfields_lock);
++
+ static int manager_log(struct ast_cdr *cdr);
+
+ static int load_config(int reload)
+@@ -59,28 +61,33 @@
+ int newenablecdr = 0;
+
+ cfg = ast_config_load(CONF_FILE, config_flags);
+- if (cfg == CONFIG_STATUS_FILEUNCHANGED)
++ if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
+ return 0;
++ }
+
+ if (cfg == CONFIG_STATUS_FILEINVALID) {
+ ast_log(LOG_ERROR, "Config file '%s' could not be parsed\n", CONF_FILE);
+- return 1;
++ return -1;
+ }
+
+- if (reload && customfields) {
+- ast_free(customfields);
+- }
+- customfields = NULL;
+-
+ if (!cfg) {
+ /* Standard configuration */
+ ast_log(LOG_WARNING, "Failed to load configuration file. Module not activated.\n");
+ if (enablecdr)
+ ast_cdr_unregister(name);
+ enablecdr = 0;
+- return 0;
++ return -1;
+ }
+
++ if (reload) {
++ ast_rwlock_wrlock(&customfields_lock);
++ }
++
++ if (reload && customfields) {
++ ast_free(customfields);
++ customfields = NULL;
++ }
++
+ while ( (cat = ast_category_browse(cfg, cat)) ) {
+ if (!strcasecmp(cat, "general")) {
+ v = ast_variable_browse(cfg, cat);
+@@ -109,6 +116,10 @@
+ }
+ }
+
++ if (reload) {
++ ast_rwlock_unlock(&customfields_lock);
++ }
++
+ ast_config_destroy(cfg);
+
+ if (enablecdr && !newenablecdr)
+@@ -117,7 +128,7 @@
+ ast_cdr_register(name, "Asterisk Manager Interface CDR Backend", manager_log);
+ enablecdr = newenablecdr;
+
+- return 1;
++ return 0;
+ }
+
+ static int manager_log(struct ast_cdr *cdr)
+@@ -127,7 +138,6 @@
+ char strAnswerTime[80] = "";
+ char strEndTime[80] = "";
+ char buf[CUSTOM_FIELDS_BUF_SIZE];
+- struct ast_channel dummy;
+
+ if (!enablecdr)
+ return 0;
+@@ -143,13 +153,19 @@
+ ast_localtime(&cdr->end, &timeresult, NULL);
+ ast_strftime(strEndTime, sizeof(strEndTime), DATE_FORMAT, &timeresult);
+
+- buf[0] = 0;
+- /* Custom fields handling */
+- if (customfields != NULL && ast_str_strlen(customfields)) {
+- memset(&dummy, 0, sizeof(dummy));
+- dummy.cdr = cdr;
+- pbx_substitute_variables_helper(&dummy, ast_str_buffer(customfields), buf, sizeof(buf) - 1);
++ buf[0] = '\0';
++ ast_rwlock_rdlock(&customfields_lock);
++ if (customfields && ast_str_strlen(customfields)) {
++ struct ast_channel *dummy = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Substitution/%p", cdr);
++ if (!dummy) {
++ ast_log(LOG_ERROR, "Unable to allocate channel for variable substitution.\n");
++ return 0;
++ }
++ dummy->cdr = ast_cdr_dup(cdr);
++ pbx_substitute_variables_helper(dummy, ast_str_buffer(customfields), buf, sizeof(buf) - 1);
++ ast_channel_release(dummy);
+ }
++ ast_rwlock_unlock(&customfields_lock);
+
+ manager_event(EVENT_FLAG_CDR, "Cdr",
+ "AccountCode: %s\r\n"
+@@ -190,9 +206,9 @@
+
+ static int load_module(void)
+ {
+- /* Configuration file */
+- if (!load_config(0))
++ if (load_config(0)) {
+ return AST_MODULE_LOAD_DECLINE;
++ }
+
+ return AST_MODULE_LOAD_SUCCESS;
+ }
+Index: cdr/cdr_sqlite3_custom.c
+===================================================================
+--- a/cdr/cdr_sqlite3_custom.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/cdr/cdr_sqlite3_custom.c (.../trunk) (revision 202568)
+@@ -56,8 +56,8 @@
+
+ static const char config_file[] = "cdr_sqlite3_custom.conf";
+
+-static char *desc = "Customizable SQLite3 CDR Backend";
+-static char *name = "cdr_sqlite3_custom";
++static const char desc[] = "Customizable SQLite3 CDR Backend";
++static const char name[] = "cdr_sqlite3_custom";
+ static sqlite3 *db = NULL;
+
+ static char table[80];
+@@ -70,7 +70,7 @@
+
+ static AST_LIST_HEAD_STATIC(sql_values, values);
+
+-static int free_config(void);
++static void free_config(void);
+
+ static int load_column_config(const char *tmp)
+ {
+@@ -166,11 +166,8 @@
+ free_config();
+ }
+
+- ast_mutex_lock(&lock);
+-
+ if (!(mappingvar = ast_variable_browse(cfg, "master"))) {
+ /* Nothing configured */
+- ast_mutex_unlock(&lock);
+ ast_config_destroy(cfg);
+ return -1;
+ }
+@@ -185,7 +182,6 @@
+
+ /* Columns */
+ if (load_column_config(ast_variable_retrieve(cfg, "master", "columns"))) {
+- ast_mutex_unlock(&lock);
+ ast_config_destroy(cfg);
+ free_config();
+ return -1;
+@@ -193,7 +189,6 @@
+
+ /* Values */
+ if (load_values_config(ast_variable_retrieve(cfg, "master", "values"))) {
+- ast_mutex_unlock(&lock);
+ ast_config_destroy(cfg);
+ free_config();
+ return -1;
+@@ -201,18 +196,15 @@
+
+ ast_verb(3, "cdr_sqlite3_custom: Logging CDR records to table '%s' in 'master.db'\n", table);
+
+- ast_mutex_unlock(&lock);
+ ast_config_destroy(cfg);
+
+ return 0;
+ }
+
+-static int free_config(void)
++static void free_config(void)
+ {
+ struct values *value;
+
+- ast_mutex_lock(&lock);
+-
+ if (db) {
+ sqlite3_close(db);
+ db = NULL;
+@@ -226,10 +218,6 @@
+ while ((value = AST_LIST_REMOVE_HEAD(&sql_values, list))) {
+ ast_free(value);
+ }
+-
+- ast_mutex_unlock(&lock);
+-
+- return 0;
+ }
+
+ static int sqlite3_log(struct ast_cdr *cdr)
+@@ -237,7 +225,6 @@
+ int res = 0;
+ char *error = NULL;
+ char *sql = NULL;
+- struct ast_channel dummy = { 0, };
+ int count = 0;
+
+ if (db == NULL) {
+@@ -245,25 +232,35 @@
+ return 0;
+ }
+
++ ast_mutex_lock(&lock);
++
+ { /* Make it obvious that only sql should be used outside of this block */
+ char *escaped;
+ char subst_buf[2048];
+ struct values *value;
++ struct ast_channel *dummy;
+ struct ast_str *value_string = ast_str_create(1024);
+- dummy.cdr = cdr;
++
++ dummy = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Substitution/%p", cdr);
++ if (!dummy) {
++ ast_log(LOG_ERROR, "Unable to allocate channel for variable subsitution.\n");
++ ast_free(value_string);
++ ast_mutex_unlock(&lock);
++ return 0;
++ }
++ dummy->cdr = ast_cdr_dup(cdr);
+ AST_LIST_TRAVERSE(&sql_values, value, list) {
+- pbx_substitute_variables_helper(&dummy, value->expression, subst_buf, sizeof(subst_buf) - 1);
++ pbx_substitute_variables_helper(dummy, value->expression, subst_buf, sizeof(subst_buf) - 1);
+ escaped = sqlite3_mprintf("%q", subst_buf);
+ ast_str_append(&value_string, 0, "%s'%s'", ast_str_strlen(value_string) ? "," : "", escaped);
+ sqlite3_free(escaped);
+ }
+ sql = sqlite3_mprintf("INSERT INTO %q (%s) VALUES (%s)", table, columns, ast_str_buffer(value_string));
+ ast_debug(1, "About to log: %s\n", sql);
++ ast_channel_release(dummy);
+ ast_free(value_string);
+ }
+
+- ast_mutex_lock(&lock);
+-
+ /* XXX This seems awful arbitrary... */
+ for (count = 0; count < 5; count++) {
+ res = sqlite3_exec(db, sql, NULL, NULL, &error);
+@@ -289,10 +286,10 @@
+
+ static int unload_module(void)
+ {
++ ast_cdr_unregister(name);
++
+ free_config();
+
+- ast_cdr_unregister(name);
+-
+ return 0;
+ }
+
+@@ -303,14 +300,7 @@
+ int res;
+ char *sql;
+
+- if (!load_config(0)) {
+- res = ast_cdr_register(name, desc, sqlite3_log);
+- if (res) {
+- ast_log(LOG_ERROR, "Unable to register custom SQLite3 CDR handling\n");
+- free_config();
+- return AST_MODULE_LOAD_DECLINE;
+- }
+- } else {
++ if (load_config(0)) {
+ return AST_MODULE_LOAD_DECLINE;
+ }
+
+@@ -340,12 +330,25 @@
+ }
+ }
+
+- return 0;
++ res = ast_cdr_register(name, desc, sqlite3_log);
++ if (res) {
++ ast_log(LOG_ERROR, "Unable to register custom SQLite3 CDR handling\n");
++ free_config();
++ return AST_MODULE_LOAD_DECLINE;
++ }
++
++ return AST_MODULE_LOAD_SUCCESS;
+ }
+
+ static int reload(void)
+ {
+- return load_config(1);
++ int res = 0;
++
++ ast_mutex_lock(&lock);
++ res = load_config(1);
++ ast_mutex_unlock(&lock);
++
++ return res;
+ }
+
+ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "SQLite3 Custom CDR Module",
+Index: cdr/cdr_sqlite.c
+===================================================================
+--- a/cdr/cdr_sqlite.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/cdr/cdr_sqlite.c (.../trunk) (revision 202568)
+@@ -61,7 +61,7 @@
+ AST_MUTEX_DEFINE_STATIC(sqlite_lock);
+
+ /*! \brief SQL table format */
+-static char sql_create_table[] = "CREATE TABLE cdr ("
++static const char sql_create_table[] = "CREATE TABLE cdr ("
+ " AcctId INTEGER PRIMARY KEY,"
+ " clid VARCHAR(80),"
+ " src VARCHAR(80),"
+Index: cdr/cdr_adaptive_odbc.c
+===================================================================
+--- a/cdr/cdr_adaptive_odbc.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/cdr/cdr_adaptive_odbc.c (.../trunk) (revision 202568)
+@@ -282,7 +282,6 @@
+ static SQLHSTMT generic_prepare(struct odbc_obj *obj, void *data)
+ {
+ int res, i;
+- char *sql = data;
+ SQLHSTMT stmt;
+ SQLINTEGER nativeerror = 0, numfields = 0;
+ SQLSMALLINT diagbytes = 0;
+@@ -294,9 +293,9 @@
+ return NULL;
+ }
+
+- res = SQLPrepare(stmt, (unsigned char *)sql, SQL_NTS);
++ res = SQLPrepare(stmt, (unsigned char *) data, SQL_NTS);
+ if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
+- ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql);
++ ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", (char *) data);
+ SQLGetDiagField(SQL_HANDLE_STMT, stmt, 1, SQL_DIAG_NUMBER, &numfields, SQL_IS_INTEGER, &diagbytes);
+ for (i = 0; i < numfields; i++) {
+ SQLGetDiagRec(SQL_HANDLE_STMT, stmt, i + 1, state, &nativeerror, diagnostic, sizeof(diagnostic), &diagbytes);
+@@ -664,7 +663,6 @@
+ static int unload_module(void)
+ {
+ ast_cdr_unregister(name);
+- usleep(1);
+ if (AST_RWLIST_WRLOCK(&odbc_tables)) {
+ ast_cdr_register(name, ast_module_info->description, odbc_log);
+ ast_log(LOG_ERROR, "Unable to lock column list. Unload failed.\n");
+Index: formats/format_gsm.c
+===================================================================
+--- a/formats/format_gsm.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/formats/format_gsm.c (.../trunk) (revision 202568)
+@@ -42,7 +42,7 @@
+
+ /* silent gsm frame */
+ /* begin binary data: */
+-char gsm_silence[] = /* 33 */
++static const char gsm_silence[] = /* 33 */
+ {0xD8,0x20,0xA2,0xE1,0x5A,0x50,0x00,0x49,0x24,0x92,0x49,0x24,0x50,0x00,0x49
+ ,0x24,0x92,0x49,0x24,0x50,0x00,0x49,0x24,0x92,0x49,0x24,0x50,0x00,0x49,0x24
+ ,0x92,0x49,0x24};
+Index: formats/format_wav_gsm.c
+===================================================================
+--- a/formats/format_wav_gsm.c (.../tags/1.6.2.0-beta3) (revision 202568)
++++ b/formats/format_wav_gsm.c (.../trunk) (revision 202568)
+@@ -48,7 +48,7 @@
+ #define MSGSM_SAMPLES (2*GSM_SAMPLES) /* samples in an MSGSM block */
+
+ /* begin binary data: */
+-char msgsm_silence[] = /* 65 */
++static char msgsm_silence[] = /* 65 */
+ {0x48,0x17,0xD6,0x84,0x02,0x80,0x24,0x49,0x92,0x24,0x89,0x02,0x80,0x24,0x49
+ ,0x92,0x24,0x89,0x02,0x80,0x24,0x49,0x92,0x24,0x89,0x02,0x80,0x24,0x49,0x92
+ ,0x24,0x09,0x82,0x74,0x61,0x4D,0x28,0x00,0x48,0x92,0x24,0x49,0x92,0x28,0x00
+
+Property changes on: .
+___________________________________________________________________
+Deleted: trunk-blocked
+ - /trunk:182362,182521,182762,182960,183124,183148,183196,183239,183553-183555,184986,185299,185532,185581,185704,185741,185777,186078,186382,186525,186563,186566,186620,186624,186653,186687,186953,186957,187105,187138,187179,187211,187269,187491,187560,187634-187636,187680,187714,187830,188342,188378,188515,188544,188705,188901,188942,190217,190349,190421,190423,190457,190484,190577,190586,190626,190989,190991,191028,191116,191140,191177,191211,191213,191411,191630,191739,191781,191785,191848,191919,191997,192362,192772,192853,193459,193678,193832,193886,194477,194610,195165,195210,195279,195365,195589,195763,195798,195949,195992,196072,196114,196227,196268,196270,196272,196308,196344,196381,196417,196488,196520,196622,196725,196758,196893,196907,197189,197338,197528,197535,197570,197701,197738,197740,197775,197824,197861,197959,197996,198088,198139,198217,198434,198438,198442,198498,198500,198529-198530,198561,198565,198597,198661,198670,198725,198727,198762,198954,198958,199091,199370,199372,199374,199376,199409,199411,199413,199446,199479,199514,199547,199781,199923,200000
+Deleted: trunk-merged
+ - /trunk:1-182359,182408,182450,182525,182530,182553,182722,182847,183028,183057,183108,183117,183242,183244,183321,183511,183560,183652,183701,183766,183865,183914,184037,184043,184079,184147,184151,184219-184220,184280,184339,184344,184448,184512,184515,184531,184566,184628,184630,184639,184673,184677,184693,184726,184762,184838,184843,184910,184948,185072,185122-185123,185197,185261,185363,185469,185600,185604,185664,185772,185912,185953,186021,186060,186101,186175,186230,186286,186297,186321,186444-186447,186461,186720,186799,186833,186837,186842,186899,186928,186985,187046,187050,187302,187363,187381,187421-187424,187483,187488,187599,187674-187675,187721,187764,187906,188032,188067,188102,188206,188210,188247,188413,188470,188585,188647,188774,188836,188938,188947,189010,189077,189097,189137,189204,189278,189350,189464,189495-189516,189539,189771,189813,189911,189951,189993,190057,190093,190250,190287,190352,190371,190622,190663,190725-190726,190830,190861,190865,190904,190946,190993,191136,191219-191220,191283,191367,191489,191494,191560,191700,191775,191884,191955,192032,192059,192096,192132,192171,192214,192279,192318,192357,192387,192430,192462,192525,192634,192700,192736,192808,192861,192933,192938,193006,193077,193120,193194,193263,193274,193349,193387,193461,193502,193545,193614,193718,193756,193870,193954,193956,194057,194138,194209,194357,194430,194434,194496,194520,194635,194649,194714,194718,194722,194765,194833,194874,194945,194982,195021,195075,195089,195096,195162,195207,195316,195320,195369-195370,195449,195521,195636,195698,195839,195882,195995,196117,196377,196416,196456,196658,196721,196792,196843,196945-196946,196948,196988,197089,197209,197260,197335,197374,197467,197538,197543,197606,197621,197697,197828,197960,198000,198064,198072,198083,198146,198183,198186,198248,198285,198312,198371,198375,198437,198470,198626,198729,198791,198824,198856,199051,199139,199227,199298,199368,199588,199630,199743,199818,199857,199957-199958,200039
+Added: branch-1.4-blocked
+ + /branches/1.4:43484,43510,43582,43626,43703,43756,44023,44080,44109,44407,44409,44567,44650,44660-44662,44665,44746,44760,44776-44777,44805,44992,45246,45313-45314,45381,45464,46114-46117,46165,46214,46253,46255,46401,46431,46583,46716,46883,47107-47108,47323,47329,47344,47348,47369,47444,47542,47553,47558,47564,47573,47576,47613,47736,47762,47856,47892,48046,48147,48162,48195,48234,48270,48281,48561,48583,48931,49022,49024,49032,49035,49070,49096,49189,49212,49282,49388,49710,50186,50921,51245,51755,51895,52000,52158,52373,52535,52809,52856,53077,53086,53099,53818,53878,54026,56006,56922,57591,58939,58955,59042,59069-59070,59230,60709,61220,62095,62299,62739,62913,63283,63656,64280,64565,64605,65394,65452,66068,66160,66244,66312,66602,66637,67018,67372,72453,72462,72493,72554,72597,72599,72665,73143,74262,74628,74839,75437,75439,75447,75712,75980,76054,76176,76178,76227,76891,77871,78146,78416,78620,78826,78860,80086,80088,80167,80497,80689,80747,81375,81492,82198,82276,82398,83400,83653,84163,84437,84544,85397,85536,85548,85687,85717,85852,86028,86371-86372,86406,87067,87340,87534,88471,89111,89191,89254,89339,89616,89727,89999,90147,90546,90798,91032,91501,92200,92510,93000,93183,93420,93764,94466,94543,94765,94769,94831,96020,96022,96024,97206,98025,98082,98265,98734,98849,98972-98973,98982,99127,99878,100418,100673,100934,101820,102653,103503,103556,103607,103698,103701,103703,103709,103713,103768,103807,104026-104027,104111,104332,104591,105591,107472,107582,109057,109171,109393,110880,112689,112709,113507,114032,114072,114167,114173,114180,114211,114248,114297,114299,114522,114542,114545,114550,114649,115257,115517,117523,117809,118055,119076,120061,120371,120671,120731,121992,122208,122314,122613,122663,124743,124908,125530,125893,126395,126680,127069,127501,127754,128029,128637,129158,129208,129505,130042,130298,130317,130373,131480,132042,132784,132787,132974,133237,133709,134652,134704,134976,136238,136304,136348,136404,136458,136560,137348,137527,137529,137580,137677,137850,138309,138516,138569,138938,138949,139145,139521,139769,140050,140115,141217,141267,141678,143204,143270,143475,143674,143964,144420,144758,145839,146129,146244,147941,148990,149840,150557,150816,151100,151167,151763,154724,158306,158629,159158,159571,160570,160764,162071,162670-162671,163785,164082,164204,164343,165537,165991,166157,166262,166592,168598,169581,169797,171120,171122,171452,172639,173248,173770,173900,174644,174885,175407,175698,177160,177450,177696,178640,178838,180010,181133,182652,182963,182965,184980,185298,185531,186057,186565,187135,187865,187962,188149,189537,189991,190187,191041,191096,191422,191628-191629,191778,193880,194356,197024,197124,197264,198665,198891,198957,200037,200185,202022
+Added: branch-1.4-merged
+ + /branches/1.4:1-43376,43383,43386,43388,43392,43396,43405,43410,43422,43441,43445,43450,43454,43456,43464,43466,43469,43477,43482,43486,43489,43492,43518,43524,43553,43564,43616,43635-43702,43704-43755,43757-43800,43802-43846,43852,43861-43862,43864,43873,43877,43893,43898-43899,43913,43915,43918-43919,43933,43944,43952,43978,43993,43996-44012,44022,44034-44043,44053,44055,44057,44068,44078,44090,44111,44125,44135,44166-44167,44169,44186,44199,44215,44283-44286,44298,44312,44322,44378,44390,44393,44433,44436,44450,44476,44486,44502,44559,44561-44563,44581,44605,44628,44631,44684,44759,44764,44786,44788,44806,44808-44809,44819,44888,44911,44921,44942,44945,44956,44971,44982,44994,45026-45027,45031,45040,45049,45051,45066,45079,45088,45104,45106,45125,45196,45213,45262,45280,45327,45378,45408,45410,45439,45441,45452,45517,45595,45622,45646,45678,45692,45694,45741,45775,45817-45818,45916,45928,45999,46065,46067,46078,46080,46082-46113,46118-46141,46143-46154,46200,46216,46237,46249,46252,46276,46298,46329,46347,46351-46353,46358,46363,46367,46370,46377,46382,46389,46398,46403,46407,46433,46474,46506,46511,46526,46554,46558,46561,46563,46606,46628,46631,46714,46744,46775,46778,46780,46822,46845,46847,46857,46901,46930,46937,46965,46992,47015,47051,47053,47192,47195-47196,47199,47239,47250,47268,47279,47284,47287,47309,47327,47331,47333,47352,47366,47372,47375,47377,47380,47391,47398,47405,47414,47418,47432-47433,47436,47454,47457,47463,47466,47474,47476,47492,47494,47497,47507,47509,47511,47513,47523,47526-47527,47540,47551,47572,47581,47584,47597,47617,47621,47625,47628,47632,47635,47639,47641,47645,47656,47684,47690,47693,47698,47701,47707,47709,47712,47733,47744,47748,47751,47755,47758,47764,47777,47782,47823,47843,47845,47850,47852,47860,47864-47865,47897,47944,47959,47989,47992,48002,48015,48017,48031,48038,48049,48054,48088,48095,48101,48105,48107,48113,48115,48129,48135,48143,48152,48155,48158,48166,48168,48177,48179,48186,48190,48193,48199,48219,48223,48228,48230,48248,48252,48254,48264,48279,48317,48323,48326,48349,48357,48363,48372,48375,48377,48379,48381-48382,48391,48396,48399,48401,48427,48461,48472,48478,48481,48487,48502,48504,48506,48513,48521,48525,48528,48548,48554,48564,48571,48577,48586,48592,48596,48637,48783,48870,48888,48906,48944,48948,48956,48960,48964,48966,48975,48977,48980,48982,48985,48987-48988,48993,48995,48997,49006,49009,49024,49028,49046,49061,49063,49066,49073,49098-49099,49102,49145,49165,49237,49259,49313,49355,49413,49457-49461,49465,49523,49536,49551,49553,49581,49600,49636,49680,49705,49712,49714-49715,49742,49831,49834,49866,49890,49925,49945,49983,50006,50032,50073,50098,50124,50151,50228,50266,50298,50346,50377,50405,50433,50466,50468,50562,50602,50647,50674,50727,50754,50782,50820,50867,50895,50957,50994,51030,51057,51087,51146,51148,51150,51159,51162,51165,51167,51170,51172,51176,51182,51186,51195,51198,51204-51205,51211,51213,51233,51236,51241,51243,51251,51256,51262,51265,51272,51274,51311,51326,51328,51331,51339,51341,51343,51348,51350,51407,51409,51513,51558,51615,51683,51716,51750,51781,51788,51829,51848,51931,51989,52016,52049,52052,52107,52160,52163,52208,52210,52265,52335,52370,52416,52462,52494-52506,52523,52572,52611,52645,52647,52679,52688,52695,52717,52763,52807-52808,52904,52952,52997,52999,53001,53035,53037,53040,53042,53046,53050,53052,53057,53062,53064,53070,53072,53075,53079,53081,53085,53088,53093,53097,53104,53109,53114,53118,53120,53131,53136,53138,53143,53150,53152,53246,53294,53324,53355,53358,53399,53429,53434,53464,53497,53530,53532,53601,53715,53749,53779-53781,53783,53810,53850,53879-53881,54002,54066,54103,54204,54218,54235,54290,54375,54481,54623,54714,54772,54787,54884,54886,54888,54898,54924,54969,55002,55006,55050,55052,55086,55129,55154,55217,55219,55278,55397,55435,55483,55553,55555,55590,55634,55670,55688,55717,55741,55758,55799,55834,55869,55914,55947,55949,55951,55954,55957,56008,56011,56055,56094,56125,56231,56277,56341,56372,56407,56457,56505,56569,56685,56740,56783,56785,56805,56839,56847,56856,56888,56975,57049,57053,57055,57089,57093,57139,57144,57146,57203,57207,57318,57364,57396,57426,57473,57477,57556,57649,57768,57770,57798,57826,57870,57872,57914,58023,58053,58119,58121,58165,58240,58243,58320,58351-58352,58354,58389,58436,58474,58479,58510,58512,58584,58604,58638,58669,58705,58779,58783,58825-58826,58843,58845,58848,58902,58906,58923,58931,58933,58935,58937,58941,58946-58947,58953,58957,58992,59035,59037,59040,59049,59064,59076,59078,59081,59087,59089,59145,59180,59182,59188,59195,59200,59202,59206,59213,59215,59217,59223,59225,59228,59254,59256,59259,59261-59262,59273,59275,59278,59281,59284,59289,59302,59304,59341,59358,59361,59363,59452,59486,59522,59573,59654,59688,59724,59774,59804,59853,59887,59936,59939,59963,60069,60088,60112,60137,60214,60265,60268,60323,60325,60361,60399,60459,60485,60521,60565,60603,60661,60712-60713,60762,60798,60847,60850,60936,60984,60989,61183,61342-61443,61477,61641,61644-61645,61648,61651,61656,61658,61674,61676,61678,61681,61683,61686,61690,61694,61697,61705,61707,61763,61765,61772,61774,61779,61787,61799,61805,61863,61870,61914,61959,61961,62005,62038,62137,62171,62174,62218,62331,62369,62371,62414,62419,62497,62545,62548,62624,62689,62692,62738,62789,62797-62807,62842,62883,62912,62942,62986,62989,63047,63099,63152,63254,63286,63329,63360,63403,63445,63448,63478,63532,63534-63535,63566,63608,63611-63612,63698,63749,63804,63830,63872,63886,63905,63982,64044,64086,64114,64157,64193,64240,64276,64278,64306,64324,64353,64426,64515-64516,64543,64578,64602,64686,64720,64754,64756,64759,64761,64820,64868,64904,64974,65039,65076,65123,65200-65201,65250,65342,65408,65501,65541,65589,65677,65679-65680,65683,65685,65768,65836,65839,65841-65842,65853,65863,65866,65965-65967,65978,66026,66029-66030,66070,66074,66076,66157,66159,66363,66398,66404,66414,66437,66474,66503,66538,66671,66768,66770,66775,66821,66879,66881,66897,66916,66919,67020-67021,67026,67061,67064,67066,67068,67071,67073,67119,67121,67156,67158,67162,67210,67270,67304,67308,67329,67334,67360,67420,67457,67492,67526,67558,67594,67597,67626,67631,67650,67716,67804,67862,67872,67924,67941,67993,68027-68028,68030,68071,68157,68192,68198,68211,68249,68280,68313,68326,68354,68370,68401,68450,68527,68595,68644,68683,68733,68781,68814,68922,69010,69012,69014,69016,69069,69071,69128,69144,69181,69183-69184,69221,69259,69358,69392,69434,69470,69518,69558,69579,69625,69660-69661,69668,69689,69702,69708,69744,69775,69794,69796,69805,69847,69895,69944,69987,70003,70062,70084,70164,70198,70360,70397,70445,70494,70552,70554,70560,70612,70656,70677,70726-70727,70808,70841,70866,70883,70899,70949,71003,71063,71096,71106,71118,71120-71123,71214,71230,71289,71291,71362,71371,71412,71422,71430,71519,71522,71576,71657,71751,71796,71877,71915,71953,72006,72042,72112,72125,72148,72257,72260,72272,72328,72331,72335,72381,72383,72556,72705,72766,72806,72850-72852,72888,72926,72933,73005,73053,73208,73253,73316,73319,73355,73398,73400,73467,73512,73548,73551,73555,73598,73629,73675,73679,73696,73727,73769,73849,73930,73980,73985,74043,74045,74047,74082,74120,74122,74159,74162,74211,74265,74314,74317,74323,74374,74379,74388,74428,74476,74515,74572,74642,74722,74767,74815,74864,74866,74888,74922,74955,74997,75053,75067,75078,75108,75253,75306,75401,75403,75405,75441,75445,75450,75529,75583,75619,75621,75623,75658,75707,75711,75732,75749,75759,75807,75928,75969,75978,76067,76087,76132,76139,76174,76211,76485,76519,76561,76618,76620,76654,76656,76708,76801,76803,76937,76983,77071,77154,77176,77191,77318,77348,77350,77380,77410,77424-77429,77460,77490,77536,77540,77571,77768,77771,77778,77780,77783,77785,77788,77794-77795,77824,77827,77831,77844,77852,77854,77863,77865,77867,77869,77883,77886-77887,77890,77894,77939,77943,77945,77947,77949,77993,77996,78028,78063,78095,78101,78103,78242,78275,78371,78375,78415,78437,78450,78488,78569,78575,78646,78717,78749,78778,78859,78891,78907,78936,78951,78955,78995,79044,79049,79142,79174,79207,79214,79255,79397,79436,79470,79523,79527,79553,79642,79665,79690,79748,79756,79778,79792,79833,79857,79902,79904,79906,79912,79947,79998,80044,80047,80049,80130,80132,80166,80183,80255,80257,80302,80304,80330,80360,80362,80390,80424,80426,80469,80499,80501,80539,80547,80573,80661,80717,80722,80750,80789,80820,80849,80895,80932,80974,81010,81012,81042,81065,81074,81120,81158,81189,81226,81291,81331,81340,81342,81346,81349,81367,81369,81373,81379,81381,81383,81392,81395,81397,81401,81403,81405-81406,81410,81412,81415-81416,81418,81426,81433,81435,81437,81439,81442,81448,81453,81455,81520,81523,81525,81569,81599,81650,81682,81713,81743,81776,81778,81826,81832,81886,81923,81952,81997,82028,82091,82155,82236,82238,82240,82243,82245,82250,82252,82261,82263,82265,82267,82274,82278,82280,82285-82286,82291,82296,82309,82326,82335,82337,82339,82344,82346,82358,82376,82385,82394,82396,82435,82444,82514,82590-82592,82594,82644,82676,82751,82802,82834,82865,82867,82929,82961,82992,83023-83024,83070,83074,83121,83175,83177,83179,83230,83232,83246,83316,83348,83432,83558,83589,83637,83695,83773,83879,83910,83941,83943,83974,83976,84018,84049,84078,84133,84146,84158,84160,84166,84170,84206,84236,84239,84271,84274,84291,84370,84410,84474,84511,84581,84637,84690,84692,84742,84783,84818,84851,84890,84902,84957,84990,85023,85057,85093,85158,85195,85242,85276,85280,85316,85356,85515,85517,85523,85532-85533,85540,85543,85545,85552,85556,85559,85561,85571,85604,85647,85649,85684,85686,85720,85818,85850,85896,85921,85958,85994,85997,86032,86063,86066,86117,86149,86202,86237,86296,86328,86330,86405,86469,86471,86502,86598,86630,86661,86663,86694,86726,86750,86754,86756,86787,86836,86880-86881,86902,86936,86982,87069,87120,87168,87262,87294,87342,87373,87396,87460,87567,87571,87650,87686,87739,87775,87849,87852,87906,87908,87970,88026,88078,88116,88210,88283,88328,88366,88539,88585,88624,88671,88709,88719,88765,88768,88805,88826,88862,88931,88994,89032,89036-89037,89042,89045-89046,89053,89079,89088,89090,89093,89095,89097,89099,89101,89103,89105,89115,89119,89125,89169-89173,89184,89194,89205,89239,89241,89246,89248,89260,89275,89280-89281,89286,89288,89296,89298,89301-89302,89323,89325,89416,89419,89450,89457,89491,89493,89495,89527,89534,89536,89540,89545,89559,89571,89577,89580,89586-89587,89592,89594,89599,89610,89618,89622,89624,89630-89631,89634,89701,89709,89790,89837,89839,89844,89886,89893,90059,90098,90101,90142,90145,90154-90155,90160,90163,90166-90545,90547-90753,90876,90967,91070,91074,91192,91237,91273,91292,91366,91439,91450,91637,91675,91677,91693,91737,91777,91780,91783,91826,91828,91830,91890,92158,92202,92204,92323,92363,92443,92463,92617,92696,92803,92807,92809,92815,92875,92933-92934,92937,93180,93182,93250,93291,93336,93377,93381,93625,93668,93949,93955,94077,94122,94251,94256,94418,94420,94464,94468,94538,94540,94660,94763,94767,94789-94790,94793,94797,94801,94808,94824,94828-94829,94905,94924,94977,95024,95095,95191,95470,95577,95890,95946,96102,96198-96199,96318,96394,96449,96525,96573,96575,96644,96884,96932,97077,97093,97152,97192,97194-97195,97304,97308,97350,97410,97448,97450,97489,97491,97529,97575,97618,97622,97640,97645,97697,97734,97753,97847,97849,97889,97925,97973,97976,98164,98219,98315,98317,98325,98372,98390,98467,98733,98774,98894,98934,98943,98946,98951,98955,98958,98960,98964,98966,98991,99004,99079,99081,99187,99301,99341,99426,99540,99592,99594,99643,99652,99718,99775,99777,99923,99975,99977-99978,100138,100164,100264,100378,100465,100581,100624,100626,100629,100672,100675,100740,100793,100835,100882,100922,100930,100932,100973,101035,101080,101152,101216,101219,101222,101413-101414,101433,101480,101482,101531,101601,101649,101693,101772,101818,101822,101894,101942,101989,102090,102142,102214,102323,102378,102450,102453,102576,102651,102725,102807,102858,102968,103070,103120,103197,103315,103324,103385,103683,103688,103690,103722,103726,103728,103741,103763,103770,103780,103786,103790,103795,103801,103812,103821,103823,103845,103904,103953,103956,104015,104037,104082,104084,104086,104092,104094-104095,104102,104106,104119,104132,104135,104139,104141,104334,104536,104593,104596,104598,104625,104665,104704,104783,104787,104841,105059,105113,105116,105261,105326,105409,105557,105560,105563,105565,105568,105570,105572,105674,105676,105932,106015,106038,106235,106237,106328,106437,106552,106606,106635,106704,106788,106842,106895,106945,107016,107099,107102,107158,107161,107173,107230,107290,107352,107405,107408,107461,107464,107637,107646,107713-107714,107826,107877,108031,108083,108086,108135,108227,108288,108469,108530,108583,108682,108737,108792,108796,108961,109012,109107,109226,109309,109386,109575,109648,109713,109763,109838,109908,109973,110019,110035,110083,110163,110336,110395,110474,110614,110628,110635,110779,110962,111014,111020,111024,111049,111121,111126,111129,111245,111280,111341,111391,111442,111605,111658,111720,111856,112068,112125,112138,112204,112209,112393,112468,112599,112711,112766,112820,113012,113065,113117-113118,113296,113348,113399,113402,113454,113504,113596,113681,113784,113874,113927,114021,114029,114035,114045,114051,114063,114083,114100,114103,114106,114112,114117,114120,114133,114138,114148,114184,114191,114195,114198,114204,114207,114226,114230,114242,114257,114275,114278,114284,114322,114537,114558,114571,114579,114584,114587,114591,114594,114597,114600,114603,114608,114621,114624,114628,114632,114662,114673,114689,114695,114708,114823,114829,114848,114875,114880,114890-114891,115017,115102,115196,115276,115279,115282,115285,115304,115308,115312,115320,115327,115333,115341,115415,115418,115422,115512,115545,115551,115554,115557,115561,115565,115568,115579,115884,115944,115990,116038,116088,116230,116296,116352,116409,116463,116466,116799,116978,117081,117086,117135,117462,117479,117507,117514,117519,117574,117582,117899,118048,118052,118163,118251,118358,118365,118465,118509,118551,118558,118646,118858,118953-118954,118956,118961,119009,119012,119071,119156,119238,119301,119354,119404,119478,119530,119533,119585,119636,119687,119742,119838,119926,119929,120001,120168,120173,120226,120282,120285,120425,120513,120675,120863-120885,120908,120959,121078,121229,121280,121442,121495,121596,121751,121804,121861,122046,122127,122130,122137,122259,122311,122713,122869,122919,123110,123113,123271,123274,123333,123391,123485,123710,123769,123869,123883,123909,123930,124112,124182,124315,124372,124395,124450,124540,124910,124965,125132,125218,125276,125327,125384,125585,125587,125740,125793,126056,126516,126573,126735,126789,126844,126899,126902,126999,127068,127133,127244,127560,127663,127892-127895,127973,128639,128737,128795,128812,128856,128912,128950,129047,129149,129343,129436,129567,129741,129803,129907,129966-129967,129970,130039,130102,130169,130173,130236,130514,130573,130634,130735,130792,130889,130959,131012,131242,131299,131357,131369,131421,131491,131790,131915,131921,131970,131985,131988,132107,132112,132311,132571,132641-132642,132645,132704,132712-132713,132826,132872,133038,133101,133104,133169,133295,133488,133572,133578,133649,134161,134254,134352,134475,134480,134536,134540,134595,134649,134758,134883,134915,134983,135055,135058,135473,135479,135482,135536,135597,135747,135799,135841-135850,135899,135915,135949,136062,136190,136241,136484,136488,136726,136946,137138,137405,137530,137679,137731,137847,138023,138027,138119-138238,138258,138360,138886,138942,139015,139074,139213,139347,139387,139456,139466,139553,139621,139635,139764,139869,139909,139927,140051,140056,140060,140421,140488,140605,140670,140690,140747,140751,140816,140850,141028,141094,141156,141366,141503,141565,141741,141806,141809,142063,142079,142218,142354,142358,142416,142474,142575,142675,142740,142744,142807,142865,142927,143140,143337,143404,143534,143736,143903,144066,144238,144356,144677,144924-144925,145479,145751,146026,146448,146643,146711,146799,147193,147517,147681,147997,148257,148611,148736,148912,148916,148987,149061,149130,149200,149204,149207,149266,149452,149683,150124,150304,151240-151241,151905,152059,152215,152286,152368,152463,152535,152538-152539,152811,152922,152958,152992,153114,153337,153651,154060,154066,154263,154266,154365,154685,155011,155398,155553,155803,155861,156164,156167,156178,156229,156289,156294,156297,156386,156688,156755,156816,157104,157162-157163,157305,157365,157859,158053,158071,158126,158483,158539,158600,158603,159025,159246,159269,159316,159476,159808,159897,159900,159976,160003,160207,160297,160480,160551,160558,160703,160770,160943,161013,161287,161426,161725,161948,162013-162014,162136,162188,162204,162264-162265,162273,162286,162341,162348,162413,162463,162653,162659,162663,162738,162804,162874,162926,163080,163084,163088,163092,163253,163316,163383,163448,163511,163761,164201,164350,164416,164422,164605,164634,164672,164736,164806,164876,164881,164977,165317,165591,165661,165767,165796,165889,166093,166297,166380,166509,166568,166772,166953,167095,167179,167260,167299,167432,167541,167545,167554,167566,167714,167840,168128,168191,168198,168267,168480,168507,168516,168546,168551,168561,168593,168603,168608,168614,168622,168628,168716,168721,168745,168828,168975,169210,169364,169485,169722,169867,169943,170050,170147,170158,170239,170392,170504,170568,170588,170648,170671,170719,170836,170979,171187,171264,171527,171621,171837,171963,172030,172169,172438,172962,173066,173070,173211,173392,173396,173559,173592,173692,173696,173917,173967-173968,174082,174148,174218,174282,174369,174583,175029,175124,175187,175294,175311,175590,175777,175792,175825,175921,176029,176216,176249-176252,176254,176354,176426,176661,176701,177096,177225,177383,177536,177540,177701,177786,178141,178205,178373,178445,178508,178804,178956,179395,179461,179468,179532,179536,179608,179671,179741,179807,179840,180006,180194,180372,180380,180464,180532,180567,180941,181029-181031,181295,181328,181340,181423,181436,181655,181659-181660,181664,181768,181898,181990,182208,182281,182449,182808,182810,182882,183115,183123,183126,183145,183238,183241,183291,183319,183342,183386,183559,183700,183913,184078,184188,184388,184447,184565,184842,184947,185031,185120-185121,185196,185362,185468,185599,185771,185845,185952,186059,186081,186174,186229,186320,186415,186445,186458,186719,186775,186832,186841,186984,187045,187209,187300-187301,187362,187428,187482,187484,187763,188582,188646,188773,188833-189134,189203,189277,189391,189462-189463,189465,189601,189664,189849,190286,190356,190661-190662,190721,191220,191488,191559,192213,192429,192454,192524,192633,192858,192932,193050,193119,193193,193262,193544,193613,193755,193955,194028,194137,194208,194484,194509,194557-194685,194764,194873,195020,195095,195206,195366,195448,195520,195635,195688,195881,195991,196116,196657,196826,197194,197466,197537,197562,197588,197998,198068,198251,198311,198370,199022,199138,199297,199626-199628,199856,200360,200513,200875,200991,201261,201380,201423,201450,201600,201828,201993,202336,202341-202342,202414,202496
+Modified: svn:externals
+ - menuselect http://svn.digium.com/svn/menuselect/tags/autotag_for_asterisk/1.6.2.0-beta3
+
+ + menuselect http://svn.digium.com/svn/menuselect/trunk
+
+
diff --git a/testing/asterisk/asterisk-07-issue14068.patch b/testing/asterisk/asterisk-07-issue14068.patch
index 49cad1681..dd57aa692 100644
--- a/testing/asterisk/asterisk-07-issue14068.patch
+++ b/testing/asterisk/asterisk-07-issue14068.patch
@@ -668,756 +668,3 @@ Index: CHANGES
SIP channel driver (chan_sip) changes
-------------------------------------------
-Index: funcs/func_redirecting.c
-===================================================================
---- a/funcs/func_redirecting.c (.../trunk) (revision 0)
-+++ b/funcs/func_redirecting.c (.../team/group/issue14068) (revision 186562)
-@@ -0,0 +1,474 @@
-+/*
-+ * Asterisk -- An open source telephony toolkit.
-+ *
-+ * Copyright (C) 2008 Digium, Inc.
-+ *
-+ * Richard Mudgett <rmudgett@digium.com>
-+ *
-+ * See http://www.asterisk.org for more information about
-+ * the Asterisk project. Please do not directly contact
-+ * any of the maintainers of this project for assistance;
-+ * the project provides a web site, mailing lists and IRC
-+ * channels for your use.
-+ *
-+ * 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.
-+ */
-+
-+/*!
-+ * \file
-+ * \brief Redirecting data dialplan function
-+ * \ingroup functions
-+ *
-+ * \author Richard Mudgett <rmudgett@digium.com>
-+ *
-+ * See Also:
-+ * \arg \ref AstCREDITS
-+ */
-+
-+
-+#include "asterisk.h"
-+
-+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-+
-+/* ------------------------------------------------------------------- */
-+
-+
-+#include <stdlib.h>
-+#include <stdio.h>
-+#include <string.h>
-+#include <sys/types.h>
-+
-+#include "asterisk/module.h"
-+#include "asterisk/channel.h"
-+#include "asterisk/pbx.h"
-+#include "asterisk/logger.h"
-+#include "asterisk/utils.h"
-+#include "asterisk/app.h"
-+#include "asterisk/options.h"
-+#include "asterisk/callerid.h"
-+
-+/*** DOCUMENTATION
-+ <function name="REDIRECTING" language="en_US">
-+ <synopsis>
-+ Gets or sets Redirecting data on the channel.
-+ </synopsis>
-+ <syntax>
-+ <parameter name="datatype" required="true">
-+ <para>The allowable datatypes are:</para>
-+ <enumlist>
-+ <enum name = "from-all" />
-+ <enum name = "from-num" />
-+ <enum name = "from-name" />
-+ <enum name = "from-ton" />
-+ <enum name = "to-all" />
-+ <enum name = "to-num" />
-+ <enum name = "to-name" />
-+ <enum name = "to-ton" />
-+ <enum name = "pres" />
-+ <enum name = "reason" />
-+ <enum name = "count" />
-+ </enumlist>
-+ </parameter>
-+ <parameter name="i">
-+ <para>If set, this will prevent the channel from sending out protocol
-+ messages because of the value being set</para>
-+ </parameter>
-+ </syntax>
-+ <description>
-+ <para>Gets or sets Redirecting data on the channel. The allowable values
-+ for the <replaceable>reason</replaceable> field are the following:</para>
-+ <enumlist>
-+ <enum name = "unknown"><para>Unknown</para></enum>
-+ <enum name = "cfb"><para>Call Forwarding Busy</para></enum>
-+ <enum name = "cfnr"><para>Call Forwarding No Reply</para></enum>
-+ <enum name = "unavailable"><para>Callee is Unavailable</para></enum>
-+ <enum name = "time_of_day"><para>Time of Day</para></enum>
-+ <enum name = "dnd"><para>Do Not Disturb</para></enum>
-+ <enum name = "deflection"><para>Call Deflection</para></enum>
-+ <enum name = "follow_me"><para>Follow Me</para></enum>
-+ <enum name = "out_of_order"><para>Called DTE Out-Of-Order</para></enum>
-+ <enum name = "away"><para>Callee is Away</para></enum>
-+ <enum name = "cf_dte"><para>Call Forwarding By The Called DTE</para></enum>
-+ <enum name = "cfu"><para>Call Forwarding Unconditional</para></enum>
-+ </enumlist>
-+ </description>
-+ </function>
-+ ***/
-+
-+enum ID_FIELD_STATUS {
-+ ID_FIELD_VALID,
-+ ID_FIELD_INVALID,
-+ ID_FIELD_UNKNOWN
-+};
-+
-+
-+
-+
-+/* ******************************************************************* */
-+/*!
-+ * \internal
-+ * \brief Read values from the party id struct.
-+ *
-+ * \param buf Buffer to fill with read value.
-+ * \param len Length of the buffer
-+ * \param data Remaining function datatype string
-+ *
-+ * \retval ID_FIELD_VALID on success.
-+ * \retval ID_FIELD_UNKNOWN on unknown field name.
-+ */
-+static enum ID_FIELD_STATUS redirecting_id_read(char *buf, size_t len, char *data, const struct ast_party_id *id)
-+{
-+ enum ID_FIELD_STATUS status;
-+
-+ status = ID_FIELD_VALID;
-+
-+ if (!strncasecmp("all", data, 3)) {
-+ snprintf(buf, len, "\"%s\" <%s>",
-+ S_OR(id->name, ""),
-+ S_OR(id->number, ""));
-+ } else if (!strncasecmp("name", data, 4)) {
-+ if (id->name) {
-+ ast_copy_string(buf, id->name, len);
-+ }
-+ } else if (!strncasecmp("num", data, 3)) {
-+ if (id->number) {
-+ ast_copy_string(buf, id->number, len);
-+ }
-+ } else if (!strncasecmp("ton", data, 3)) {
-+ snprintf(buf, len, "%d", id->number_type);
-+ } else if (!strncasecmp("pres", data, 4)) {
-+ ast_copy_string(buf, ast_named_caller_presentation(id->number_presentation), len);
-+ } else {
-+ status = ID_FIELD_UNKNOWN;
-+ }
-+
-+ return status;
-+}
-+
-+
-+
-+
-+/* ******************************************************************* */
-+/*!
-+ * \internal
-+ * \brief Read values from the redirecting information struct.
-+ *
-+ * \param chan Asterisk channel to read
-+ * \param cmd Not used
-+ * \param data Redirecting function datatype string
-+ * \param buf Buffer to fill with read value.
-+ * \param len Length of the buffer
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+static int redirecting_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
-+{
-+ /* Ensure that the buffer is empty */
-+ *buf = 0;
-+
-+ if (!chan)
-+ return -1;
-+
-+ ast_channel_lock(chan);
-+
-+ if (!strncasecmp("from-", data, 5)) {
-+ struct ast_party_id from_id;
-+
-+ from_id = chan->redirecting.from;
-+ from_id.number = chan->cid.cid_rdnis;
-+ switch (redirecting_id_read(buf, len, data + 5, &from_id)) {
-+ case ID_FIELD_VALID:
-+ case ID_FIELD_INVALID:
-+ break;
-+
-+ default:
-+ ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
-+ break;
-+ }
-+ } else if (!strncasecmp("to-", data, 3)) {
-+ switch (redirecting_id_read(buf, len, data + 3, &chan->redirecting.to)) {
-+ case ID_FIELD_VALID:
-+ case ID_FIELD_INVALID:
-+ break;
-+
-+ default:
-+ ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
-+ break;
-+ }
-+ } else if (!strncasecmp("pres", data, 4)) {
-+ ast_copy_string(buf, ast_named_caller_presentation(chan->redirecting.from.number_presentation), len);
-+ } else if (!strncasecmp("reason", data, 6)) {
-+ ast_copy_string(buf, ast_redirecting_reason_name(chan->redirecting.reason), len);
-+ } else if (!strncasecmp("count", data, 5)) {
-+ snprintf(buf, len, "%d", chan->redirecting.count);
-+ } else {
-+ ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
-+ }
-+
-+ ast_channel_unlock(chan);
-+
-+ return 0;
-+}
-+
-+
-+
-+
-+/* ******************************************************************* */
-+/*!
-+ * \internal
-+ * \brief Write new values to the party id struct
-+ *
-+ * \param id Party ID struct to write values
-+ * \param data Remaining function datatype string
-+ * \param value Value to assign to the party id.
-+ *
-+ * \retval ID_FIELD_VALID on success.
-+ * \retval ID_FIELD_INVALID on error with field value.
-+ * \retval ID_FIELD_UNKNOWN on unknown field name.
-+ */
-+static enum ID_FIELD_STATUS redirecting_id_write(struct ast_party_id *id, char *data, const char *value)
-+{
-+ char *val;
-+ enum ID_FIELD_STATUS status;
-+
-+ status = ID_FIELD_VALID;
-+
-+ if (!strncasecmp("all", data, 3)) {
-+ char name[256];
-+ char num[256];
-+
-+ ast_callerid_split(value, name, sizeof(name), num, sizeof(num));
-+ if (!(id->name = ast_strdup(name))) {
-+ return ID_FIELD_INVALID;
-+ }
-+ if (!(id->number = ast_strdup(num))) {
-+ return ID_FIELD_INVALID;
-+ }
-+ } else if (!strncasecmp("name", data, 4)) {
-+ id->name = ast_strdup(value);
-+ ast_trim_blanks(id->name);
-+ } else if (!strncasecmp("num", data, 3)) {
-+ id->number = ast_strdup(value);
-+ ast_trim_blanks(id->number);
-+ } else if (!strncasecmp("ton", data, 3)) {
-+ val = ast_strdupa(value);
-+ ast_trim_blanks(val);
-+
-+ if (('0' <= val[0]) && (val[0] <= '9')) {
-+ id->number_type = atoi(val);
-+ } else {
-+ ast_log(LOG_ERROR, "Unknown redirecting type of number '%s', value unchanged\n", val);
-+ status = ID_FIELD_INVALID;
-+ }
-+ } else if (!strncasecmp("pres", data, 4)) {
-+ int pres;
-+
-+ val = ast_strdupa(value);
-+ ast_trim_blanks(val);
-+
-+ if (('0' <= val[0]) && (val[0] <= '9')) {
-+ pres = atoi(val);
-+ } else {
-+ pres = ast_parse_caller_presentation(val);
-+ }
-+
-+ if (pres < 0) {
-+ ast_log(LOG_ERROR, "Unknown redirecting number presentation '%s', value unchanged\n", val);
-+ status = ID_FIELD_INVALID;
-+ } else {
-+ id->number_presentation = pres;
-+ }
-+ } else {
-+ status = ID_FIELD_UNKNOWN;
-+ }
-+
-+ return status;
-+}
-+
-+
-+
-+
-+/* ******************************************************************* */
-+/*!
-+ * \internal
-+ * \brief Write new values to the redirecting information struct.
-+ *
-+ * \param chan Asterisk channel to update
-+ * \param cmd Not used
-+ * \param data Redirecting function datatype string
-+ * \param value Value to assign to the redirecting information struct.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+static int redirecting_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
-+{
-+ struct ast_party_redirecting redirecting;
-+ char *val;
-+ char *option;
-+ void (*set_it)(struct ast_channel *chan, const struct ast_party_redirecting *redirecting);
-+
-+ if (!value || !chan) {
-+ return -1;
-+ }
-+
-+ /* Determine if the update indication inhibit option is present */
-+ option = strchr(data, ',');
-+ if (option) {
-+ option = ast_skip_blanks(option + 1);
-+ switch (*option) {
-+ case 'i':
-+ set_it = ast_channel_set_redirecting;
-+ break;
-+
-+ default:
-+ ast_log(LOG_ERROR, "Unknown redirecting option '%s'.\n", option);
-+ return 0;
-+ }
-+ }
-+ else {
-+ set_it = ast_channel_update_redirecting;
-+ }
-+
-+ ast_channel_lock(chan);
-+ ast_party_redirecting_set_init(&redirecting, &chan->redirecting);
-+ ast_channel_unlock(chan);
-+
-+ value = ast_skip_blanks(value);
-+
-+ if (!strncasecmp("from-", data, 5)) {
-+ switch (redirecting_id_write(&redirecting.from, data + 5, value)) {
-+ case ID_FIELD_VALID:
-+ set_it(chan, &redirecting);
-+ ast_party_redirecting_free(&redirecting);
-+ break;
-+
-+ case ID_FIELD_INVALID:
-+ break;
-+
-+ default:
-+ ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
-+ break;
-+ }
-+ } else if (!strncasecmp("to-", data, 3)) {
-+ switch (redirecting_id_write(&redirecting.to, data + 3, value)) {
-+ case ID_FIELD_VALID:
-+ set_it(chan, &redirecting);
-+ ast_party_redirecting_free(&redirecting);
-+ break;
-+
-+ case ID_FIELD_INVALID:
-+ break;
-+
-+ default:
-+ ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
-+ break;
-+ }
-+ } else if (!strncasecmp("pres", data, 4)) {
-+ int pres;
-+
-+ val = ast_strdupa(value);
-+ ast_trim_blanks(val);
-+
-+ if (('0' <= val[0]) && (val[0] <= '9')) {
-+ pres = atoi(val);
-+ } else {
-+ pres = ast_parse_caller_presentation(val);
-+ }
-+
-+ if (pres < 0) {
-+ ast_log(LOG_ERROR, "Unknown redirecting number presentation '%s', value unchanged\n", val);
-+ } else {
-+ redirecting.from.number_presentation = pres;
-+ redirecting.to.number_presentation = pres;
-+ set_it(chan, &redirecting);
-+ }
-+ } else if (!strncasecmp("reason", data, 6)) {
-+ int reason;
-+
-+ val = ast_strdupa(value);
-+ ast_trim_blanks(val);
-+
-+ if (('0' <= val[0]) && (val[0] <= '9')) {
-+ reason = atoi(val);
-+ } else {
-+ reason = ast_redirecting_reason_parse(val);
-+ }
-+
-+ if (reason < 0) {
-+ ast_log(LOG_ERROR, "Unknown redirecting reason '%s', value unchanged\n", val);
-+ } else {
-+ redirecting.reason = reason;
-+ set_it(chan, &redirecting);
-+ }
-+ } else if (!strncasecmp("count", data, 5)) {
-+ val = ast_strdupa(value);
-+ ast_trim_blanks(val);
-+
-+ if (('0' <= val[0]) && (val[0] <= '9')) {
-+ redirecting.count = atoi(val);
-+ set_it(chan, &redirecting);
-+ } else {
-+ ast_log(LOG_ERROR, "Unknown redirecting count '%s', value unchanged\n", val);
-+ }
-+ } else {
-+ ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
-+ }
-+
-+ return 0;
-+}
-+
-+
-+
-+
-+static struct ast_custom_function redirecting_function = {
-+ .name = "REDIRECTING",
-+ .read = redirecting_read,
-+ .write = redirecting_write,
-+};
-+
-+
-+
-+
-+/* ******************************************************************* */
-+/*!
-+ * \internal
-+ * \brief Unload the function module
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+static int unload_module(void)
-+{
-+ return ast_custom_function_unregister(&redirecting_function);
-+}
-+
-+
-+
-+
-+/* ******************************************************************* */
-+/*!
-+ * \internal
-+ * \brief Load and initialize the function module.
-+ *
-+ * \retval 0 on success.
-+ * \retval -1 on error.
-+ */
-+static int load_module(void)
-+{
-+ return ast_custom_function_register(&redirecting_function)
-+ ? AST_MODULE_LOAD_DECLINE
-+ : AST_MODULE_LOAD_SUCCESS;
-+}
-+
-+
-+
-+
-+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Redirecting data dialplan function");
-+
-+
-+/* ------------------------------------------------------------------- */
-+/* end func_redirecting.c */
-
-Property changes on: funcs/func_redirecting.c
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + Author Date Id Revision
-
-Index: funcs/func_connectedline.c
-===================================================================
---- a/funcs/func_connectedline.c (.../trunk) (revision 0)
-+++ b/funcs/func_connectedline.c (.../team/group/issue14068) (revision 186562)
-@@ -0,0 +1,239 @@
-+/*
-+ * Asterisk -- An open source telephony toolkit.
-+ *
-+ * Copyright (C) 2007, Gareth Palmer
-+ *
-+ * Gareth Palmer <gareth@acsdata.co.nz>
-+ *
-+ * See http://www.asterisk.org for more information about
-+ * the Asterisk project. Please do not directly contact
-+ * any of the maintainers of this project for assistance;
-+ * the project provides a web site, mailing lists and IRC
-+ * channels for your use.
-+ *
-+ * 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.
-+ */
-+
-+/*! \file
-+ *
-+ * \brief Connected Line dialplan function
-+ *
-+ * \ingroup functions
-+ */
-+
-+#include "asterisk.h"
-+
-+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-+
-+#include <stdlib.h>
-+#include <stdio.h>
-+#include <string.h>
-+#include <sys/types.h>
-+
-+#include "asterisk/module.h"
-+#include "asterisk/channel.h"
-+#include "asterisk/pbx.h"
-+#include "asterisk/logger.h"
-+#include "asterisk/utils.h"
-+#include "asterisk/app.h"
-+#include "asterisk/options.h"
-+#include "asterisk/callerid.h"
-+
-+/*** DOCUMENTATION
-+ <function name="CONNECTEDLINE" language="en_US">
-+ <synopsis>
-+ Gets or sets Connected Line data on the channel.
-+ </synopsis>
-+ <syntax>
-+ <parameter name="datatype" required="true">
-+ <para>The allowable datatypes are:</para>
-+ <enumlist>
-+ <enum name = "all" />
-+ <enum name = "num" />
-+ <enum name = "name" />
-+ <enum name = "ton" />
-+ <enum name = "pres" />
-+ <enum name = "source" />
-+ </enumlist>
-+ </parameter>
-+ <parameter name="i">
-+ <para>If set, this will prevent the channel from sending out protocol
-+ messages because of the value being set</para>
-+ </parameter>
-+ </syntax>
-+ <description>
-+ <para>Gets or sets Connected Line data on the channel. Possible values
-+ for the <replaceable>source</replaceable> datatype are:</para>
-+ <enumlist>
-+ <enum name="answer"><para>Normal Call Answering</para></enum>
-+ <enum name="transfer_alerting"><para>Call Transfer(Alerting)</para></enum>
-+ <enum name="transfer_active"><para>Call Transfer(Active)</para></enum>
-+ </enumlist>
-+ </description>
-+ </function>
-+ ***/
-+
-+static int connectedline_read(struct ast_channel *chan, const char *cmd, char *data,
-+ char *buf, size_t len)
-+{
-+ /* Ensure that the buffer is empty */
-+ *buf = 0;
-+
-+ if (!chan)
-+ return -1;
-+
-+ ast_channel_lock(chan);
-+
-+ if (!strncasecmp("all", data, 3)) {
-+ snprintf(buf, len, "\"%s\" <%s>",
-+ S_OR(chan->connected.id.name, ""),
-+ S_OR(chan->connected.id.number, ""));
-+ } else if (!strncasecmp("name", data, 4)) {
-+ if (chan->connected.id.name) {
-+ ast_copy_string(buf, chan->connected.id.name, len);
-+ }
-+ } else if (!strncasecmp("num", data, 3)) {
-+ if (chan->connected.id.number) {
-+ ast_copy_string(buf, chan->connected.id.number, len);
-+ }
-+ } else if (!strncasecmp("ton", data, 3)) {
-+ snprintf(buf, len, "%d", chan->connected.id.number_type);
-+ } else if (!strncasecmp("pres", data, 4)) {
-+ ast_copy_string(buf, ast_named_caller_presentation(chan->connected.id.number_presentation), len);
-+ } else if (!strncasecmp("source", data, 6)) {
-+ ast_copy_string(buf, ast_connected_line_source_name(chan->connected.source), len);
-+ } else {
-+ ast_log(LOG_ERROR, "Unknown connectedline data type '%s'.\n", data);
-+ }
-+
-+ ast_channel_unlock(chan);
-+
-+ return 0;
-+}
-+
-+static int connectedline_write(struct ast_channel *chan, const char *cmd, char *data,
-+ const char *value)
-+{
-+ struct ast_party_connected_line connected;
-+ char *val;
-+ char *option;
-+ void (*set_it)(struct ast_channel *chan, const struct ast_party_connected_line *connected);
-+
-+ if (!value || !chan) {
-+ return -1;
-+ }
-+
-+ /* Determine if the update indication inhibit option is present */
-+ option = strchr(data, ',');
-+ if (option) {
-+ option = ast_skip_blanks(option + 1);
-+ switch (*option) {
-+ case 'i':
-+ set_it = ast_channel_set_connected_line;
-+ break;
-+
-+ default:
-+ ast_log(LOG_ERROR, "Unknown connectedline option '%s'.\n", option);
-+ return 0;
-+ }
-+ }
-+ else {
-+ set_it = ast_channel_update_connected_line;
-+ }
-+
-+ ast_channel_lock(chan);
-+ ast_party_connected_line_set_init(&connected, &chan->connected);
-+ ast_channel_unlock(chan);
-+
-+ value = ast_skip_blanks(value);
-+
-+ if (!strncasecmp("all", data, 3)) {
-+ char name[256];
-+ char num[256];
-+
-+ ast_callerid_split(value, name, sizeof(name), num, sizeof(num));
-+ connected.id.name = name;
-+ connected.id.number = num;
-+ set_it(chan, &connected);
-+ } else if (!strncasecmp("name", data, 4)) {
-+ connected.id.name = ast_strdupa(value);
-+ ast_trim_blanks(connected.id.name);
-+ set_it(chan, &connected);
-+ } else if (!strncasecmp("num", data, 3)) {
-+ connected.id.number = ast_strdupa(value);
-+ ast_trim_blanks(connected.id.number);
-+ set_it(chan, &connected);
-+ } else if (!strncasecmp("ton", data, 3)) {
-+ val = ast_strdupa(value);
-+ ast_trim_blanks(val);
-+
-+ if (('0' <= val[0]) && (val[0] <= '9')) {
-+ connected.id.number_type = atoi(val);
-+ set_it(chan, &connected);
-+ } else {
-+ ast_log(LOG_ERROR, "Unknown connectedline type of number '%s', value unchanged\n", val);
-+ }
-+ } else if (!strncasecmp("pres", data, 4)) {
-+ int pres;
-+
-+ val = ast_strdupa(value);
-+ ast_trim_blanks(val);
-+
-+ if (('0' <= val[0]) && (val[0] <= '9')) {
-+ pres = atoi(val);
-+ } else {
-+ pres = ast_parse_caller_presentation(val);
-+ }
-+
-+ if (pres < 0) {
-+ ast_log(LOG_ERROR, "Unknown connectedline number presentation '%s', value unchanged\n", val);
-+ } else {
-+ connected.id.number_presentation = pres;
-+ set_it(chan, &connected);
-+ }
-+ } else if (!strncasecmp("source", data, 6)) {
-+ int source;
-+
-+ val = ast_strdupa(value);
-+ ast_trim_blanks(val);
-+
-+ if (('0' <= val[0]) && (val[0] <= '9')) {
-+ source = atoi(val);
-+ } else {
-+ source = ast_connected_line_source_parse(val);
-+ }
-+
-+ if (source < 0) {
-+ ast_log(LOG_ERROR, "Unknown connectedline source '%s', value unchanged\n", val);
-+ } else {
-+ connected.source = source;
-+ set_it(chan, &connected);
-+ }
-+ } else {
-+ ast_log(LOG_ERROR, "Unknown connectedline data type '%s'.\n", data);
-+ }
-+
-+ return 0;
-+}
-+
-+static struct ast_custom_function connectedline_function = {
-+ .name = "CONNECTEDLINE",
-+ .read = connectedline_read,
-+ .write = connectedline_write,
-+};
-+
-+static int unload_module(void)
-+{
-+ return ast_custom_function_unregister(&connectedline_function);
-+}
-+
-+static int load_module(void)
-+{
-+ return ast_custom_function_register(&connectedline_function)
-+ ? AST_MODULE_LOAD_DECLINE
-+ : AST_MODULE_LOAD_SUCCESS;
-+}
-+
-+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Connected Line dialplan function");
-
-Property changes on: funcs/func_connectedline.c
-___________________________________________________________________
-Added: svn:eol-style
- + native
-Added: svn:mime-type
- + text/plain
-Added: svn:keywords
- + Author Date Id Revision
-
-
-Property changes on: .
-___________________________________________________________________
-Added: automerge
- + *
-Added: svnmerge-integrated
- + /trunk:1-186557
-Added: automerge-email
- + rmudgett@digium.com
-
diff --git a/testing/kvm/APKBUILD b/testing/kvm/APKBUILD
index 6ee614720..2ffc3f894 100644
--- a/testing/kvm/APKBUILD
+++ b/testing/kvm/APKBUILD
@@ -1,33 +1,33 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=kvm
-pkgver=84
+pkgver=87
pkgrel=0
pkgdesc="kernel-based virtual machine"
-url="http://kvm.qumranet.com"
+url="http://www.linux-kvm.org/"
license='GPL'
-depends="uclibc"
-makedepends="ncurses-dev"
-source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz
- kvm-82-uclibc.patch
- "
+depends=
+makedepends="ncurses-dev linux-grsec-dev pciutils-dev alsa-lib-dev curl-dev
+ zlib-dev"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz"
subpackages=""
build() {
cd "$srcdir/$pkgname-$pkgver"
- for i in ../*.patch; do
- msg "Applying $i"
- patch -p1 < $i || return 1;
- done
+
+ # lets use kernel modules from mainline kernel
+ rm -r kvm/kernel
+
+ # we need -lrt linker flag for uclibc
+ sed -i -e 's/^LIBS+=-lz/LIBS+=-lz -lrt/' Makefile.target || return 1
./configure --prefix=/usr \
- --disable-gfx-check \
- --disable-sdl \
- --qemu-ldflags=-nopie
+ --extra-ldflags=-nopie \
+ --disable-nptl \
+ --audio-drv-list="alsa oss" \
+ --disable-sdl
- make libkvm || return 1
- make qemu || return 1
+ make || return 1
make DESTDIR="$pkgdir"/ kcmd="#" install
}
-md5sums="39b7206ef400845800f081a5b901f757 kvm-84.tar.gz
-c439025cbfe89b35c2ae78aa481eb93f kvm-82-uclibc.patch"
+md5sums="a03ccefb0d096f8efee2b07b56555b33 kvm-87.tar.gz"
diff --git a/testing/kvm/kvm-82-uclibc.patch b/testing/kvm/kvm-82-uclibc.patch
deleted file mode 100644
index 488be77d8..000000000
--- a/testing/kvm/kvm-82-uclibc.patch
+++ /dev/null
@@ -1,14 +0,0 @@
---- kvm-82.orig/qemu/configure Wed Jan 14 13:40:28 2009
-+++ kvm-82/qemu/configure Wed Jan 14 13:41:28 2009
-@@ -1068,7 +1068,10 @@
- cat > $TMPC <<EOF
- #include <signal.h>
- #include <time.h>
--int main(void) { clockid_t id; return clock_gettime(id, NULL); }
-+int main(void) { clockid_t id; timer_t tid;
-+ return clock_gettime(id, NULL) + timer_delete(tid);
-+}
-+
- EOF
-
- rt=no
diff --git a/testing/multipath-tools/APKBUILD b/testing/multipath-tools/APKBUILD
index 9576d7ec3..bf24a4d7d 100644
--- a/testing/multipath-tools/APKBUILD
+++ b/testing/multipath-tools/APKBUILD
@@ -2,11 +2,11 @@
# Maintainer: Leonardo Arena <rnalrd@gmail.com>
pkgname="multipath-tools"
pkgver=0.4.8
-pkgrel=0
+pkgrel=1
pkgdesc="Device Mapper Multipathing Driver"
url="http://christophe.varoqui.free.fr/"
license="GPL"
-depends="uclibc device-mapper libaio readline"
+depends=
makedepends="device-mapper-dev libaio-dev readline-dev"
install=
subpackages="$pkgname-doc"
diff --git a/x11/aterm/APKBUILD b/x11/aterm/APKBUILD
new file mode 100644
index 000000000..e414f4a45
--- /dev/null
+++ b/x11/aterm/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=aterm
+pkgver=1.0.1
+pkgrel=0
+pkgdesc="An xterm replacement with transparency support"
+url="http://aterm.sourceforge.net/"
+license="GPL"
+makedepends="libxext-dev libsm-dev libxt-dev"
+subpackages="$pkgname-doc"
+depends=
+source="http://downloads.sourceforge.net/sourceforge/$pkgname/$pkgname-$pkgver.tar.bz2
+ uclibc.patch"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ patch -p1 < ../uclibc.patch || return 1
+ ./configure --prefix=/usr \
+ --enable-transparency=yes \
+ --enable-background-image \
+ --enable-fading \
+ --enable-menubar \
+ --enable-graphics
+ make || return 1
+ make prefix="$pkgdir"/usr install
+}
+md5sums="c2eede028e1011e0ec7035cf319c9b5a aterm-1.0.1.tar.bz2
+cd942d2639bd32fb9cbf06c94dcd536f uclibc.patch"
diff --git a/x11/aterm/uclibc.patch b/x11/aterm/uclibc.patch
new file mode 100644
index 000000000..1c1428345
--- /dev/null
+++ b/x11/aterm/uclibc.patch
@@ -0,0 +1,16 @@
+--- aterm-1.0.1/src/command.c.orig 2009-06-12 18:04:43.000000000 +0000
++++ aterm-1.0.1/src/command.c 2009-06-12 18:10:23.000000000 +0000
+@@ -91,7 +91,12 @@
+
+ #if defined (__svr4__) || defined (__lnx21__)
+ # include <sys/resource.h> /* for struct rlimit */
+-# include <sys/stropts.h> /* for I_PUSH */
++# if defined (__UCLIBC__)
++# define __SID ('S' << 8)
++# define I_PUSH (__SID | 2)
++# else
++# include <sys/stropts.h> /* for I_PUSH */
++# endif
+ # define _NEW_TTY_CTRL /* to get proper defines in <termios.h> */
+ #endif
+
diff --git a/x11/fontconfig/APKBUILD b/x11/fontconfig/APKBUILD
index 979d62e7b..b315afea1 100644
--- a/x11/fontconfig/APKBUILD
+++ b/x11/fontconfig/APKBUILD
@@ -1,16 +1,17 @@
# Contributor: Mika Havela <mika.havela@gmail.com>
-# Maintainer:
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=fontconfig
pkgver="2.6.0"
-pkgrel=0
+pkgrel=1
pkgdesc="The Fontconfig package is a library for configuring and customizing font access."
url="http://fontconfig.org"
license="GPL"
-depends="uclibc freetype expat zlib"
-makedepends="freetype-dev expat-dev zlib-dev"
+depends=
+makedepends="pkgconfig freetype-dev expat-dev zlib-dev"
install=
subpackages="$pkgname-doc $pkgname-dev"
source="http://fontconfig.org/release/${pkgname}-${pkgver}.tar.gz"
+depends_dev="freetype-dev expat-dev"
build() {
cd "$srcdir/$pkgname-$pkgver"
@@ -19,7 +20,7 @@ build() {
--sysconfdir=/etc \
--disable-docs
make || return 1
- make DESTDIR="$pkgdir" install
+ make -j1 DESTDIR="$pkgdir" install
install -m644 -D COPYING "$pkgdir"/usr/share/licenses/"${pkgname}"/COPYING
}
diff --git a/x11/gamin/APKBUILD b/x11/gamin/APKBUILD
new file mode 100644
index 000000000..730271afb
--- /dev/null
+++ b/x11/gamin/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gamin
+pkgver=0.1.10
+pkgrel=1
+pkgdesc="Gamin is a file and directory monitoring system defined to be a subset of the FAM (File Alteration Monitor) system."
+url="http://www.gnome.org/~veillard/gamin"
+license="GPL"
+subpackages="$pkgname-dev"
+depends=
+makedepends="pkgconfig glib-dev"
+source="http://www.gnome.org/~veillard/$pkgname/sources/$pkgname-$pkgver.tar.gz"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --disable-static \
+ --with-threads \
+ --disable-debug-api \
+ --disable-debug \
+ --disable-dnotify \
+ --libexecdir=/usr/lib/gamin
+ make || return 1
+
+ # some kinde of race in the make install which is not solved with -j
+ export MKDIRPROG="mkdir -p"
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="b4ec549e57da470c04edd5ec2876a028 gamin-0.1.10.tar.gz"
diff --git a/x11/glproto/APKBUILD b/x11/glproto/APKBUILD
index fb41b14c3..7aadaa1ee 100644
--- a/x11/glproto/APKBUILD
+++ b/x11/glproto/APKBUILD
@@ -1,6 +1,6 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=glproto
-pkgver=1.4.9
+pkgver=1.4.10
pkgrel=0
pkgdesc="X11 OpenGL extension wire protocol"
url="http://xorg.freedesktop.org/"
@@ -16,4 +16,4 @@ build ()
make || return 1
make DESTDIR="$pkgdir" install || return 1
}
-md5sums="e60951628422663e60faeb400f27bac1 glproto-1.4.9.tar.bz2"
+md5sums="c9f8cebfba72bfab674bc0170551fb8d glproto-1.4.10.tar.bz2"
diff --git a/x11/gst-plugins-base/APKBUILD b/x11/gst-plugins-base/APKBUILD
new file mode 100644
index 000000000..5e1896776
--- /dev/null
+++ b/x11/gst-plugins-base/APKBUILD
@@ -0,0 +1,33 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gst-plugins-base
+pkgver=0.10.23
+pkgrel=0
+pkgdesc="GStreamer Multimedia Framework Base Plugins"
+url="http://gstreamer.freedesktop.org/"
+license="GPL LGPL"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig gstreamer-dev alsa-lib-dev libvorbis-dev liboil-dev
+ perl libogg-dev gtk+-dev libtheora-dev libice-dev libsm-dev libxv-dev
+ e2fsprogs-dev expat-dev"
+# cdparanoia>=10.2 libvisual libtheora"
+source="http://gstreamer.freedesktop.org/src/$pkgname/$pkgname-$pkgver.tar.bz2"
+
+depends_dev="gstreamer-dev"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --disable-static \
+ --disable-experimental \
+ --with-package-name="GStreamer Base Plugins (Alpine Linux)" \
+ --with-package-origin="http://www.alpinelinux.org/" \
+ || return 1
+ make || return 1
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="641cc7def2d8667b9b4df15e69dba25f gst-plugins-base-0.10.23.tar.bz2"
diff --git a/x11/gstreamer/APKBUILD b/x11/gstreamer/APKBUILD
new file mode 100644
index 000000000..139ab1086
--- /dev/null
+++ b/x11/gstreamer/APKBUILD
@@ -0,0 +1,26 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=gstreamer
+pkgver=0.10.23
+pkgrel=0
+pkgdesc="GStreamer Multimedia Framework"
+url="http://gstreamer.freedesktop.org/"
+license="LGPL"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig libxml2-dev glib-dev bison flex gettext-dev libiconv-dev"
+source="http://gstreamer.freedesktop.org//src/gstreamer/gstreamer-$pkgver.tar.bz2"
+
+depends_dev="glib-dev libxml2-dev"
+
+build ()
+{
+ cd "$srcdir"/gstreamer-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --disable-docs-build || return 1
+ make || return 1
+ make DESTDIR="$pkgdir" install || return 1
+ cd "$pkgdir"/usr/bin
+}
+md5sums="f7b2e300d2d85756407ec529424ab237 gstreamer-0.10.23.tar.bz2"
diff --git a/x11/intltool/APKBUILD b/x11/intltool/APKBUILD
index cc50fcba7..9b817d342 100644
--- a/x11/intltool/APKBUILD
+++ b/x11/intltool/APKBUILD
@@ -1,11 +1,11 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=intltool
pkgver=0.40.6
-pkgrel=0
+pkgrel=1
pkgdesc="The internationalization tool collection"
url="http://freedesktop.org/wiki/Software/intltool"
license="GPL"
-depends="perl perl-xml-parser"
+depends="perl perl-xml-parser gettext"
subpackages="$pkgname-doc"
source="http://ftp.gnome.org/pub/gnome/sources/$pkgname/0.40/$pkgname-$pkgver.tar.bz2"
diff --git a/x11/libdrm/APKBUILD b/x11/libdrm/APKBUILD
index 7cb84e774..8cae38c48 100644
--- a/x11/libdrm/APKBUILD
+++ b/x11/libdrm/APKBUILD
@@ -1,11 +1,11 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=libdrm
-pkgver=2.4.9
+pkgver=2.4.11
pkgrel=0
pkgdesc="Userspace interface to kernel DRM services"
url="http://dri.freedesktop.org/"
license="custom"
-depends="uclibc"
+depends=
makedepends="pkgconfig libpthread-stubs"
subpackages="$pkgname-dev"
source="http://dri.freedesktop.org/$pkgname/$pkgname-$pkgver.tar.bz2"
@@ -16,4 +16,4 @@ build() {
make || return 1
make DESTDIR="$pkgdir" install || return 1
}
-md5sums="a7eacf9d4532391c7a53709da8f34495 libdrm-2.4.9.tar.bz2"
+md5sums="e0e66fae165d0b665b61e9516bf33ade libdrm-2.4.11.tar.bz2"
diff --git a/x11/liboil/APKBUILD b/x11/liboil/APKBUILD
new file mode 100644
index 000000000..d388ca491
--- /dev/null
+++ b/x11/liboil/APKBUILD
@@ -0,0 +1,22 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=liboil
+pkgver=0.3.16
+pkgrel=0
+pkgdesc="Library of simple functions that are optimized for various CPUs."
+url="http://liboil.freedesktop.org/"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+source="http://$pkgname.freedesktop.org/download/$pkgname-$pkgver.tar.gz"
+
+build ()
+{
+ unset CFLAGS
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr || return 1
+ make || return 1
+ make -j1 DESTDIR="$pkgdir" install || return 1
+ install -m755 -d "$pkgdir"/usr/share/licenses/liboil
+ install -m644 COPYING "$pkgdir"/usr/share/licenses/liboil/ || return 1
+}
+md5sums="febb1d9f9bc4c440fcf622dc90f8b6b7 liboil-0.3.16.tar.gz"
diff --git a/x11/libsoup/APKBUILD b/x11/libsoup/APKBUILD
index 25cd81f8a..5bad9edfa 100644
--- a/x11/libsoup/APKBUILD
+++ b/x11/libsoup/APKBUILD
@@ -1,14 +1,14 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=libsoup
-pkgver=2.26.1
+pkgver=2.26.2
pkgrel=0
pkgdesc="Gnome HTTP Library"
url="http://www.gnome.org"
license="LGPL"
subpackages="$pkgname-dev $pkgname-doc"
-depends="glib gnutls libxml2 uclibc libiconv libgcrypt libgpg-error"
+depends=
makedepends="pkgconfig glib-dev gnutls-dev libxml2-dev libiconv-dev gettext-dev
- libgcrypt-dev libgpg-error-dev g++"
+ libgcrypt-dev libgpg-error-dev"
source="http://ftp.gnome.org/pub/gnome/sources/$pkgname/${pkgver%.*}/$pkgname-$pkgver.tar.bz2"
depends_dev="glib-dev libxml2-dev gnutls-dev"
@@ -24,4 +24,4 @@ build ()
make || return 1
make DESTDIR="$pkgdir" install || return 1
}
-md5sums="94c0495dc8bf213709bdb175ab224c7e libsoup-2.26.1.tar.bz2"
+md5sums="61abd9bf1435e37def0956248a03832c libsoup-2.26.2.tar.bz2"
diff --git a/x11/libxau/APKBUILD b/x11/libxau/APKBUILD
index f5295bcea..83e1095bc 100644
--- a/x11/libxau/APKBUILD
+++ b/x11/libxau/APKBUILD
@@ -1,15 +1,17 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=libxau
pkgver=1.0.4
-pkgrel=0
+pkgrel=1
pkgdesc="X11 authorisation library"
url="http://xorg.freedesktop.org/"
license="custom"
-depends="uclibc"
+depends=
makedepends="pkgconfig xproto"
subpackages="$pkgname-dev $pkgname-doc"
source="http://xorg.freedesktop.org/releases/individual/lib/libXau-$pkgver.tar.bz2"
+depends_dev="xproto"
+
build() {
cd "$srcdir"/libXau-$pkgver
./configure --prefix=/usr --sysconfdir=/etc || return 1
diff --git a/x11/libxtst/APKBUILD b/x11/libxtst/APKBUILD
new file mode 100644
index 000000000..69c0a6e29
--- /dev/null
+++ b/x11/libxtst/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=libxtst
+pkgver=1.0.3
+pkgrel=0
+pkgdesc="X11 Testing -- Resource extension library"
+url="http://xorg.freedesktop.org/"
+license="custom"
+subpackages="$pkgname-dev $pkgname-doc"
+depends=
+makedepends="pkgconfig libxext-dev recordproto inputproto"
+source="http://xorg.freedesktop.org/releases/individual/lib/libXtst-$pkgver.tar.bz2"
+depends_dev="recordproto libx11-dev libxext-dev inputproto"
+
+build ()
+{
+ cd "$srcdir"/libXtst-$pkgver
+ ./configure --prefix=/usr \
+ --build=${CHOST} --host=${CHOST}
+ make || return 1
+ make DESTDIR="$pkgdir" install || return 1
+ install -D -m644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/LICENSE
+}
+
+md5sums="090c1ad04e34982eada5cf3b1a0792fd libXtst-1.0.3.tar.bz2"
diff --git a/x11/mesa/APKBUILD b/x11/mesa/APKBUILD
index 0228457e6..493eda91f 100644
--- a/x11/mesa/APKBUILD
+++ b/x11/mesa/APKBUILD
@@ -1,11 +1,11 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=mesa
-pkgver=7.4.1
+pkgver=7.4.4
pkgrel=2
pkgdesc="Mesa DRI OpenGL library and drivers"
url="http://www.mesa3d.org"
license="LGPL"
-depends="libdrm libxxf86vm libxdamage expat libx11"
+depends=
subpackages="$pkgname-dev"
makedepends="pkgconfig libdrm-dev libxxf86vm-dev libxdamage-dev expat-dev
dri2proto xextproto libx11-dev glproto"
@@ -30,11 +30,11 @@ build ()
--with-dri-driverdir=/usr/lib/xorg/modules/dri \
--with-dri-drivers=swrast \
--disable-asm \
- --enable-glx-tls \
+ --disable-glx-tls \
--disable-ttm-api \
--with-driver=dri \
--enable-xcb \
- --disable-glu \
+ --enable-glu \
--disable-glut \
--disable-glw || return 1
make || return 1
@@ -42,6 +42,6 @@ build ()
install -m755 -d "$pkgdir"/usr/lib/xorg/modules/extensions
ln -sf libglx.xorg "$pkgdir"/usr/lib/xorg/modules/extensions/libglx.so || return 1
}
-md5sums="423260578b653818ba66c2fcbde6d7ad MesaLib-7.4.1.tar.bz2
+md5sums="b66528d314c574dccbe0ed963cac5e93 MesaLib-7.4.4.tar.bz2
f0baa948d9810f268413111ee439d24b mesa-7.1-link-shared.patch
75e1bb69f384e9d60544fa03c15cc0ec mesa-7.4-parallel.patch"
diff --git a/x11/pango/APKBUILD b/x11/pango/APKBUILD
index 11d11992e..0ee8baa07 100644
--- a/x11/pango/APKBUILD
+++ b/x11/pango/APKBUILD
@@ -1,12 +1,12 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=pango
-pkgver=1.24.1
+pkgver=1.24.2
pkgrel=0
pkgdesc="A library for layout and rendering of text"
url="http://www.pango.org/"
license="LGPL"
subpackages="$pkgname-dev $pkgname-doc"
-depends="glib cairo libxft uclibc gettext libiconv expat"
+depends=
makedepends="pkgconfig glib-dev cairo-dev libxft-dev gettext-dev libiconv-dev
expat-dev"
install="pango.post-install $pkgname.pre-deinstall"
@@ -23,6 +23,6 @@ build ()
make || return 1
make DESTDIR="$pkgdir" install || return 1
}
-md5sums="af0beac1dd1825e241c5728081f16acd pango-1.24.1.tar.bz2
+md5sums="7bc6c884d847cabc613e4c6d663771f5 pango-1.24.2.tar.bz2
457d66ce8a405fca12009b3c2c06bfa6 pango.post-install
daaca20be2a577d5bcd395ca53d4b4c0 pango.pre-deinstall"
diff --git a/x11/recordproto/APKBUILD b/x11/recordproto/APKBUILD
new file mode 100644
index 000000000..404307236
--- /dev/null
+++ b/x11/recordproto/APKBUILD
@@ -0,0 +1,20 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=recordproto
+pkgver=1.13.2
+pkgrel=0
+pkgdesc="X11 Record extension wire protocol"
+url="http://xorg.freedesktop.org/"
+license="custom"
+depends=""
+makedepends=""
+source="http://xorg.freedesktop.org/releases/individual/proto/$pkgname-$pkgver.tar.bz2"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr
+ make || return 1
+ make DESTDIR="$pkgdir" install || return 1
+ install -D -m644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/LICENSE
+}
+md5sums="0ed4706564a34fc2aff724aa16d3ff00 recordproto-1.13.2.tar.bz2"
diff --git a/x11/ristretto/APKBUILD b/x11/ristretto/APKBUILD
new file mode 100644
index 000000000..5c651efb7
--- /dev/null
+++ b/x11/ristretto/APKBUILD
@@ -0,0 +1,28 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=ristretto
+pkgver=0.0.22
+pkgrel=0
+pkgdesc="Ristretto is a image viewer for Xfce"
+url="http://goodies.xfce.org/projects/applications/ristretto"
+license="GPL-2"
+depends="desktop-file-utils hicolor-icon-theme"
+makedepends="pkgconfig libxfcegui4-dev dbus-glib-dev libexif-dev intltool
+ gettext-dev libiconv-dev thunar-dev"
+install="ristretto.post-install ristretto.post-upgrade ristretto.post-deinstall"
+source="http://goodies.xfce.org/releases/$pkgname/$pkgname-$pkgver.tar.gz
+ $install"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --disable-static || return 1
+ make || return 1
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="978ae19472c5a0b7d4b6622a68234a67 ristretto-0.0.22.tar.gz
+9ba052c0be9f3e3ae52ef7d45083efa3 ristretto.post-install
+9ba052c0be9f3e3ae52ef7d45083efa3 ristretto.post-upgrade
+9ba052c0be9f3e3ae52ef7d45083efa3 ristretto.post-deinstall"
diff --git a/x11/ristretto/ristretto.post-deinstall b/x11/ristretto/ristretto.post-deinstall
new file mode 120000
index 000000000..545052657
--- /dev/null
+++ b/x11/ristretto/ristretto.post-deinstall
@@ -0,0 +1 @@
+ristretto.post-install \ No newline at end of file
diff --git a/x11/ristretto/ristretto.post-install b/x11/ristretto/ristretto.post-install
new file mode 100644
index 000000000..e3be6863e
--- /dev/null
+++ b/x11/ristretto/ristretto.post-install
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+update-desktop-database -q
+gtk-update-icon-cache -q -t -f usr/share/icons/hicolor
+
+
diff --git a/x11/ristretto/ristretto.post-upgrade b/x11/ristretto/ristretto.post-upgrade
new file mode 120000
index 000000000..545052657
--- /dev/null
+++ b/x11/ristretto/ristretto.post-upgrade
@@ -0,0 +1 @@
+ristretto.post-install \ No newline at end of file
diff --git a/x11/Thunar/APKBUILD b/x11/thunar/APKBUILD
index 51b3eef95..e3afae930 100644
--- a/x11/Thunar/APKBUILD
+++ b/x11/thunar/APKBUILD
@@ -1,7 +1,7 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=thunar
pkgver=1.0.1
-pkgrel=0
+pkgrel=2
pkgdesc="File manager for Xfce"
url="http://thunar.xfce.org"
license="GPL2 LGPL2"
@@ -9,11 +9,12 @@ subpackages="$pkgname-dev $pkgname-doc"
depends="desktop-file-utils hicolor-icon-theme"
makedepends="pkgconfig libexif-dev xfce4-panel-dev exo-dev pcre-dev
intltool gettext-dev libiconv-dev expat-dev startup-notification-dev
- libsm-dev e2fsprogs-dev"
+ libsm-dev e2fsprogs-dev gamin-dev"
install="thunar.post-install thunar.post-upgrade thunar.post-deinstall"
source="http://www.xfce.org/archive/xfce-4.6.1/src/Thunar-$pkgver.tar.bz2
$install"
+depends_dev="exo-dev glib-dev"
build ()
{
cd "$srcdir"/Thunar-$pkgver
diff --git a/x11/Thunar/thunar.post-deinstall b/x11/thunar/thunar.post-deinstall
index b2d507f24..b2d507f24 120000
--- a/x11/Thunar/thunar.post-deinstall
+++ b/x11/thunar/thunar.post-deinstall
diff --git a/x11/Thunar/thunar.post-install b/x11/thunar/thunar.post-install
index 591dfaf72..591dfaf72 100644
--- a/x11/Thunar/thunar.post-install
+++ b/x11/thunar/thunar.post-install
diff --git a/x11/Thunar/thunar.post-upgrade b/x11/thunar/thunar.post-upgrade
index b2d507f24..b2d507f24 120000
--- a/x11/Thunar/thunar.post-upgrade
+++ b/x11/thunar/thunar.post-upgrade
diff --git a/x11/vte/APKBUILD b/x11/vte/APKBUILD
index 7d488ddcd..d1e3897e1 100644
--- a/x11/vte/APKBUILD
+++ b/x11/vte/APKBUILD
@@ -1,13 +1,13 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=vte
-pkgver=0.20.2
+pkgver=0.20.5
pkgrel=0
pkgdesc="Virtual Terminal Emulator library"
url="http://www.gnome.org"
license="LGPL"
subpackages="$pkgname-dev $pkgname-doc"
-depends="gtk+ uclibc gettext libiconv"
-makedepends="gtk+-dev intltool python gettext-dev libiconv-dev"
+depends=
+makedepends="pkgconfig gtk+-dev intltool python ncurses-dev"
source="http://ftp.gnome.org/pub/GNOME/sources/$pkgname/0.20/$pkgname-$pkgver.tar.bz2"
depends_dev="glib-dev pango-dev gtk+-dev"
@@ -23,4 +23,4 @@ build ()
make || return 1
make DESTDIR="$pkgdir" install || return 1
}
-md5sums="d38484da2974bb049de8831e294aa7d1 vte-0.20.2.tar.bz2"
+md5sums="90de70ddd1340be308430ded74d6b8d6 vte-0.20.5.tar.bz2"
diff --git a/x11/webkit/APKBUILD b/x11/webkit/APKBUILD
index da5de5f1d..3be205e87 100644
--- a/x11/webkit/APKBUILD
+++ b/x11/webkit/APKBUILD
@@ -1,6 +1,6 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=webkit
-pkgver=1.1.9
+pkgver=1.1.10
pkgrel=0
pkgdesc="portable web rendering engine WebKit for GTK+"
url="http://webkitgtk.org/"
@@ -12,6 +12,7 @@ makedepends="
gnutls-dev sqlite-dev libxslt-dev libxt-dev libiconv-dev gettext-dev
zlib-dev libgcrypt-dev libgpg-error-dev expat-dev e2fsprogs-dev
enchant-dev libxi-dev libxrandr-dev libxcursor-dev libxdamage-dev
+ libxcomposite-dev
"
install=
subpackages="$pkgname-dev gtklauncher"
@@ -39,4 +40,4 @@ gtklauncher() {
"$subpkgdir"/usr/bin/GtkLauncher
}
-md5sums="c9bc52c713b0ab7aefe57022de6eb24b webkit-1.1.9.tar.gz"
+md5sums="b852753b3e21f010f565312132f88311 webkit-1.1.10.tar.gz"
diff --git a/x11/xcb-util/APKBUILD b/x11/xcb-util/APKBUILD
index 22b454dfb..e5d16a247 100644
--- a/x11/xcb-util/APKBUILD
+++ b/x11/xcb-util/APKBUILD
@@ -1,13 +1,13 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=xcb-util
-pkgver=0.3.3
+pkgver=0.3.4
pkgrel=0
pkgdesc="Utility libraries for XC Binding"
url="http://xcb.freedesktop.org"
license="GPL"
subpackages="$pkgname-dev"
-depends="libxcb uclibc"
-makedepends="libxcb-dev gperf pkgconfig"
+depends=
+makedepends="m4 libxcb-dev gperf pkgconfig"
source="http://xcb.freedesktop.org/dist/$pkgname-$pkgver.tar.bz2"
depend_dev="libxcb-dev"
@@ -17,4 +17,4 @@ build() {
make || return 1
make DESTDIR="$pkgdir" install || return 1
}
-md5sums="b1b16c5c1fcf7a6facb346c262cd3513 xcb-util-0.3.3.tar.bz2"
+md5sums="015314fe5e97d9390024275c6a3699a4 xcb-util-0.3.4.tar.bz2"
diff --git a/x11/xdpyinfo/APKBUILD b/x11/xdpyinfo/APKBUILD
new file mode 100644
index 000000000..09f9affcc
--- /dev/null
+++ b/x11/xdpyinfo/APKBUILD
@@ -0,0 +1,21 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xdpyinfo
+pkgver=1.0.3
+pkgrel=0
+pkgdesc="display information utility for X"
+url="http://xorg.freedesktop.org/"
+license="custom"
+subpackages="$pkgname-doc"
+makedepends="pkgconfig libxtst-dev"
+depends=
+source="http://xorg.freedesktop.org/releases/individual/app/$pkgname-$pkgver.tar.bz2"
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man || return 1
+ make || return 1
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="b7cbab6cbcd12bf7ad65dbc12d86e104 xdpyinfo-1.0.3.tar.bz2"
diff --git a/x11/xdriinfo/APKBUILD b/x11/xdriinfo/APKBUILD
new file mode 100644
index 000000000..ff9e76aa6
--- /dev/null
+++ b/x11/xdriinfo/APKBUILD
@@ -0,0 +1,21 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xdriinfo
+pkgver=1.0.2
+pkgrel=0
+pkgdesc="query configuration information of DRI drivers"
+url="http://xorg.freedesktop.org/"
+license="custom"
+subpackages="$pkgname-doc"
+makedepends="pkgconfig libx11-dev glproto mesa-dev"
+depends=
+source="http://xorg.freedesktop.org/releases/individual/app/$pkgname-$pkgver.tar.bz2"
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man || return 1
+ make || return 1
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="a5ec51ed9f0a55dc3462d90d52ff899c xdriinfo-1.0.2.tar.bz2"
diff --git a/x11/xev/APKBUILD b/x11/xev/APKBUILD
new file mode 100644
index 000000000..c30c899aa
--- /dev/null
+++ b/x11/xev/APKBUILD
@@ -0,0 +1,21 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xev
+pkgver=1.0.3
+pkgrel=0
+pkgdesc="print contents of X events"
+url="http://xorg.freedesktop.org/"
+license="custom"
+subpackages="$pkgname-doc"
+makedepends="pkgconfig libx11-dev"
+depends=
+source="http://xorg.freedesktop.org/releases/individual/app/$pkgname-$pkgver.tar.bz2"
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man || return 1
+ make || return 1
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="a9532c3d1683c99bb5df1895cb3a60b1 xev-1.0.3.tar.bz2"
diff --git a/x11/xfce4-appfinder/APKBUILD b/x11/xfce4-appfinder/APKBUILD
new file mode 100644
index 000000000..6f9f6a19a
--- /dev/null
+++ b/x11/xfce4-appfinder/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xfce4-appfinder
+pkgver=4.6.1
+pkgrel=0
+pkgdesc="Xfce application finder"
+url="http://www.xfce.org/"
+license="GPL-2"
+depends="hicolor-icon-theme"
+makedepends="pkgconfig thunar-dev libxfce4menu-dev intltool gtk+-dev
+ libxfce4util-dev libxfcegui4-dev gettext-dev libiconv-dev
+ startup-notification-dev libsm-dev expat-dev e2fsprogs-dev"
+install="$pkgname.post-install $pkgname.post-upgrade $pkgname.post-deinstall"
+source="http://www.xfce.org/archive/xfce-$pkgver/src/$pkgname-$pkgver.tar.bz2
+ $install"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib \
+ --localstatedir=/var \
+ --disable-static || return 1
+ make || return 1
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="a1bc7d88100cfd92714a300be531589b xfce4-appfinder-4.6.1.tar.bz2
+db51db79681eadc47be4932355a77c25 xfce4-appfinder.post-install
+db51db79681eadc47be4932355a77c25 xfce4-appfinder.post-upgrade
+db51db79681eadc47be4932355a77c25 xfce4-appfinder.post-deinstall"
diff --git a/x11/xfce4-appfinder/xfce4-appfinder.post-deinstall b/x11/xfce4-appfinder/xfce4-appfinder.post-deinstall
new file mode 120000
index 000000000..18abfee4f
--- /dev/null
+++ b/x11/xfce4-appfinder/xfce4-appfinder.post-deinstall
@@ -0,0 +1 @@
+xfce4-appfinder.post-install \ No newline at end of file
diff --git a/x11/xfce4-appfinder/xfce4-appfinder.post-install b/x11/xfce4-appfinder/xfce4-appfinder.post-install
new file mode 100644
index 000000000..c523d78da
--- /dev/null
+++ b/x11/xfce4-appfinder/xfce4-appfinder.post-install
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+gtk-update-icon-cache -q -t -f usr/share/icons/hicolor
+
diff --git a/x11/xfce4-appfinder/xfce4-appfinder.post-upgrade b/x11/xfce4-appfinder/xfce4-appfinder.post-upgrade
new file mode 120000
index 000000000..18abfee4f
--- /dev/null
+++ b/x11/xfce4-appfinder/xfce4-appfinder.post-upgrade
@@ -0,0 +1 @@
+xfce4-appfinder.post-install \ No newline at end of file
diff --git a/x11/xfce4-mixer/APKBUILD b/x11/xfce4-mixer/APKBUILD
new file mode 100644
index 000000000..1541cb92b
--- /dev/null
+++ b/x11/xfce4-mixer/APKBUILD
@@ -0,0 +1,30 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xfce4-mixer
+pkgver=4.6.1
+pkgrel=0
+pkgdesc="The volume control plugin for the Xfce panel"
+url="http://www.xfce.org/"
+license="GPL2"
+depends="hicolor-icon-theme"
+makedepends="pkgconfig xfce4-panel-dev gstreamer-dev intltool
+ gst-plugins-base-dev expat-dev libsm-dev e2fsprogs-dev"
+install="$pkgname.post-install $pkgname.post-upgrade $pkgname.post-deinstall"
+source="http://www.xfce.org/archive/xfce-$pkgver/src/$pkgname-$pkgver.tar.bz2
+ $install"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib \
+ --localstatedir=/var \
+ --disable-static \
+ --with-sound=alsa || return 1
+ make || return 1
+ make DESTDIR="$pkgdir" install || return 1
+}
+md5sums="a99e2455445480ef5081fe69454a46fc xfce4-mixer-4.6.1.tar.bz2
+db51db79681eadc47be4932355a77c25 xfce4-mixer.post-install
+db51db79681eadc47be4932355a77c25 xfce4-mixer.post-upgrade
+db51db79681eadc47be4932355a77c25 xfce4-mixer.post-deinstall"
diff --git a/x11/xfce4-mixer/xfce4-mixer.post-deinstall b/x11/xfce4-mixer/xfce4-mixer.post-deinstall
new file mode 120000
index 000000000..59bfac9d7
--- /dev/null
+++ b/x11/xfce4-mixer/xfce4-mixer.post-deinstall
@@ -0,0 +1 @@
+xfce4-mixer.post-install \ No newline at end of file
diff --git a/x11/xfce4-mixer/xfce4-mixer.post-install b/x11/xfce4-mixer/xfce4-mixer.post-install
new file mode 100644
index 000000000..c523d78da
--- /dev/null
+++ b/x11/xfce4-mixer/xfce4-mixer.post-install
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+gtk-update-icon-cache -q -t -f usr/share/icons/hicolor
+
diff --git a/x11/xfce4-mixer/xfce4-mixer.post-upgrade b/x11/xfce4-mixer/xfce4-mixer.post-upgrade
new file mode 120000
index 000000000..59bfac9d7
--- /dev/null
+++ b/x11/xfce4-mixer/xfce4-mixer.post-upgrade
@@ -0,0 +1 @@
+xfce4-mixer.post-install \ No newline at end of file
diff --git a/x11/xfce4-taskmanager/APKBUILD b/x11/xfce4-taskmanager/APKBUILD
new file mode 100644
index 000000000..039ca22d3
--- /dev/null
+++ b/x11/xfce4-taskmanager/APKBUILD
@@ -0,0 +1,24 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xfce4-taskmanager
+pkgver=0.4.1
+pkgrel=0
+pkgdesc="a simple taskmanager for the Xfce Desktop Environment"
+url="http://goodies.xfce.org/projects/applications/xfce4-taskmanager"
+license="GPL-2"
+depends=
+makedepends="pkgconfig intltool libxfcegui4-dev"
+source="http://goodies.xfce.org/releases/$pkgname/$pkgname-$pkgver.tar.bz2"
+
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --libexecdir=/usr/lib/xfce4 \
+ --localstatedir=/var \
+ --disable-static
+ make || return 1
+ make DESTDIR="$pkgdir" install
+}
+
+md5sums="4ed599faf6b734b2d2e7be16adf0b2d9 xfce4-taskmanager-0.4.1.tar.bz2"
diff --git a/x11/xfce4/APKBUILD b/x11/xfce4/APKBUILD
new file mode 100644
index 000000000..9ba27a3c2
--- /dev/null
+++ b/x11/xfce4/APKBUILD
@@ -0,0 +1,22 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xfce4
+pkgver=4.6
+pkgrel=0
+pkgdesc="XFCE 4 meta package"
+url="http://www.xfce.org"
+license="GPL"
+depends="thunar xfce-utils xfce4-panel xfce4-session orage terminal mousepad
+ xfce4-settings xfdesktop xfwm4 xfce4-mixer xfce4-appfinder
+ tango-icon-theme ttf-dejavu"
+
+makedepends=
+install=
+subpackages=
+source=
+
+build() {
+ mkdir -p "$pkgdir"
+}
+
+md5sums="" #generate with 'abuild checksum'
diff --git a/x11/xkeyboard-config/APKBUILD b/x11/xkeyboard-config/APKBUILD
index 07591c672..3816ce62f 100644
--- a/x11/xkeyboard-config/APKBUILD
+++ b/x11/xkeyboard-config/APKBUILD
@@ -1,11 +1,11 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=xkeyboard-config
-pkgver=1.5
+pkgver=1.6
pkgrel=0
pkgdesc="X keyboard configuration files"
url="http://www.freedesktop.org/wiki/Software/XKeyboardConfig"
license="custom"
-depends="uclibc"
+depends=
makedepends="xkbcomp intltool"
source="http://xlibs.freedesktop.org/xkbdesc/$pkgname-$pkgver.tar.bz2"
@@ -22,4 +22,4 @@ build () {
install -m755 -d "$pkgdir"/var/lib/xkb
install -Dm644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/COPYING
}
-md5sums="43c74312d303863b1b929554fa9ed9b3 xkeyboard-config-1.5.tar.bz2"
+md5sums="5ae575a9073af12cd71773e065b38b3a xkeyboard-config-1.6.tar.bz2"
diff --git a/x11/xvinfo/APKBUILD b/x11/xvinfo/APKBUILD
new file mode 100644
index 000000000..7edd4d03c
--- /dev/null
+++ b/x11/xvinfo/APKBUILD
@@ -0,0 +1,21 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=xvinfo
+pkgver=1.0.2
+pkgrel=0
+pkgdesc="Print out X-Video extension adaptor information"
+url="http://xorg.freedesktop.org/"
+license="custom"
+subpackages="$pkgname-doc"
+makedepends="pkgconfig libxv-dev"
+depends=
+source="http://xorg.freedesktop.org/releases/individual/app/$pkgname-$pkgver.tar.bz2"
+build ()
+{
+ cd "$srcdir"/$pkgname-$pkgver
+ ./configure --prefix=/usr \
+ --mandir=/usr/share/man || return 1
+ make || return 1
+ make DESTDIR="$pkgdir" install || return 1
+}
+
+md5sums="e1e318436f49e2f0f3764593dadd9ad2 xvinfo-1.0.2.tar.bz2"